diff --git a/.mockery.yaml b/.mockery.yaml index f6c493589d5..e399cd9a5fb 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -406,9 +406,6 @@ packages: github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer: interfaces: ORM: - github.com/smartcontractkit/chainlink/v2/core/capabilities/targets: - interfaces: - ContractValueGetter: github.com/smartcontractkit/chainlink/v2/core/services/workflows/metering: interfaces: BillingClient: diff --git a/core/capabilities/targets/mocks/contract_value_getter.go b/core/capabilities/targets/mocks/contract_value_getter.go deleted file mode 100644 index d421915b264..00000000000 --- a/core/capabilities/targets/mocks/contract_value_getter.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by mockery v2.53.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - primitives "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ContractValueGetter is an autogenerated mock type for the ContractValueGetter type -type ContractValueGetter struct { - mock.Mock -} - -type ContractValueGetter_Expecter struct { - mock *mock.Mock -} - -func (_m *ContractValueGetter) EXPECT() *ContractValueGetter_Expecter { - return &ContractValueGetter_Expecter{mock: &_m.Mock} -} - -// Bind provides a mock function with given fields: _a0, _a1 -func (_m *ContractValueGetter) Bind(_a0 context.Context, _a1 []types.BoundContract) error { - ret := _m.Called(_a0, _a1) - - if len(ret) == 0 { - panic("no return value specified for Bind") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []types.BoundContract) error); ok { - r0 = rf(_a0, _a1) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractValueGetter_Bind_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bind' -type ContractValueGetter_Bind_Call struct { - *mock.Call -} - -// Bind is a helper method to define mock.On call -// - _a0 context.Context -// - _a1 []types.BoundContract -func (_e *ContractValueGetter_Expecter) Bind(_a0 interface{}, _a1 interface{}) *ContractValueGetter_Bind_Call { - return &ContractValueGetter_Bind_Call{Call: _e.mock.On("Bind", _a0, _a1)} -} - -func (_c *ContractValueGetter_Bind_Call) Run(run func(_a0 context.Context, _a1 []types.BoundContract)) *ContractValueGetter_Bind_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]types.BoundContract)) - }) - return _c -} - -func (_c *ContractValueGetter_Bind_Call) Return(_a0 error) *ContractValueGetter_Bind_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractValueGetter_Bind_Call) RunAndReturn(run func(context.Context, []types.BoundContract) error) *ContractValueGetter_Bind_Call { - _c.Call.Return(run) - return _c -} - -// GetLatestValue provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 -func (_m *ContractValueGetter) GetLatestValue(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 interface{}, _a4 interface{}) error { - ret := _m.Called(_a0, _a1, _a2, _a3, _a4) - - if len(ret) == 0 { - panic("no return value specified for GetLatestValue") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, primitives.ConfidenceLevel, interface{}, interface{}) error); ok { - r0 = rf(_a0, _a1, _a2, _a3, _a4) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractValueGetter_GetLatestValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestValue' -type ContractValueGetter_GetLatestValue_Call struct { - *mock.Call -} - -// GetLatestValue is a helper method to define mock.On call -// - _a0 context.Context -// - _a1 string -// - _a2 primitives.ConfidenceLevel -// - _a3 interface{} -// - _a4 interface{} -func (_e *ContractValueGetter_Expecter) GetLatestValue(_a0 interface{}, _a1 interface{}, _a2 interface{}, _a3 interface{}, _a4 interface{}) *ContractValueGetter_GetLatestValue_Call { - return &ContractValueGetter_GetLatestValue_Call{Call: _e.mock.On("GetLatestValue", _a0, _a1, _a2, _a3, _a4)} -} - -func (_c *ContractValueGetter_GetLatestValue_Call) Run(run func(_a0 context.Context, _a1 string, _a2 primitives.ConfidenceLevel, _a3 interface{}, _a4 interface{})) *ContractValueGetter_GetLatestValue_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(primitives.ConfidenceLevel), args[3].(interface{}), args[4].(interface{})) - }) - return _c -} - -func (_c *ContractValueGetter_GetLatestValue_Call) Return(_a0 error) *ContractValueGetter_GetLatestValue_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractValueGetter_GetLatestValue_Call) RunAndReturn(run func(context.Context, string, primitives.ConfidenceLevel, interface{}, interface{}) error) *ContractValueGetter_GetLatestValue_Call { - _c.Call.Return(run) - return _c -} - -// NewContractValueGetter creates a new instance of ContractValueGetter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewContractValueGetter(t interface { - mock.TestingT - Cleanup(func()) -}) *ContractValueGetter { - mock := &ContractValueGetter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go deleted file mode 100644 index 0bc77138277..00000000000 --- a/core/capabilities/targets/write_target.go +++ /dev/null @@ -1,424 +0,0 @@ -package targets - -import ( - "bytes" - "context" - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "math/big" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - - "github.com/smartcontractkit/chainlink/v2/core/platform" -) - -var ( - _ capabilities.ExecutableCapability = &WriteTarget{} - ErrTxFailed = errors.New("submitted transaction failed") -) - -const transactionStatusCheckInterval = 2 * time.Second - -type WriteTarget struct { - cr ContractValueGetter - cw commontypes.ContractWriter - binding commontypes.BoundContract - forwarderAddress string - // The minimum amount of gas that the receiver contract must get to process the forwarder report - receiverGasMinimum uint64 - capabilities.CapabilityInfo - - emitter custmsg.MessageEmitter - lggr logger.Logger - - bound bool -} - -const ( - TransmissionStateNotAttempted uint8 = iota - TransmissionStateSucceeded - TransmissionStateInvalidReceiver - TransmissionStateFailed -) - -type TransmissionInfo struct { - GasLimit *big.Int - InvalidReceiver bool - State uint8 - Success bool - TransmissionID [32]byte - Transmitter common.Address -} - -// The gas cost of the forwarder contract logic, including state updates and event emission. -// This is a rough estimate and should be updated if the forwarder contract logic changes. -// TODO: Make this part of the on-chain capability configuration -const ForwarderContractLogicGasCost = 100_000 - -type ContractValueGetter interface { - Bind(context.Context, []commontypes.BoundContract) error - GetLatestValue(context.Context, string, primitives.ConfidenceLevel, any, any) error -} - -func NewWriteTarget( - lggr logger.Logger, - id string, - cr ContractValueGetter, - cw commontypes.ContractWriter, - forwarderAddress string, - txGasLimit uint64, -) *WriteTarget { - info := capabilities.MustNewCapabilityInfo( - id, - capabilities.CapabilityTypeTarget, - "Write target.", - ) - - return &WriteTarget{ - cr, - cw, - commontypes.BoundContract{ - Address: forwarderAddress, - Name: "forwarder", - }, - forwarderAddress, - txGasLimit - ForwarderContractLogicGasCost, - info, - custmsg.NewLabeler(), - logger.Named(lggr, "WriteTarget"), - false, - } -} - -// Note: This should be a shared type that the OCR3 package validates as well -type ReportV1Metadata struct { - Version uint8 - WorkflowExecutionID [32]byte - Timestamp uint32 - DonID uint32 - DonConfigVersion uint32 - WorkflowCID [32]byte - WorkflowName [10]byte - WorkflowOwner [20]byte - ReportID [2]byte -} - -func (rm ReportV1Metadata) Encode() ([]byte, error) { - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, rm) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (rm ReportV1Metadata) Length() int { - bytes, err := rm.Encode() - if err != nil { - return 0 - } - return len(bytes) -} - -func decodeReportMetadata(data []byte) (metadata ReportV1Metadata, err error) { - if len(data) < metadata.Length() { - return metadata, fmt.Errorf("data too short: %d bytes", len(data)) - } - return metadata, binary.Read(bytes.NewReader(data[:metadata.Length()]), binary.BigEndian, &metadata) -} - -type Config struct { - // Address of the contract that will get the forwarded report - Address string - // Optional gas limit that overrides the default limit sent to the chain writer - GasLimit *uint64 -} - -type Inputs struct { - SignedReport types.SignedReport -} - -type Request struct { - Metadata capabilities.RequestMetadata - Config Config - Inputs Inputs -} - -func evaluate(rawRequest capabilities.CapabilityRequest) (r Request, err error) { - r.Metadata = rawRequest.Metadata - - if rawRequest.Config == nil { - return r, errors.New("missing config field") - } - - if err = rawRequest.Config.UnwrapTo(&r.Config); err != nil { - return r, err - } - - if !common.IsHexAddress(r.Config.Address) { - return r, fmt.Errorf("'%v' is not a valid address", r.Config.Address) - } - - if rawRequest.Inputs == nil { - return r, errors.New("missing inputs field") - } - - // required field of target's config in the workflow spec - const signedReportField = "signed_report" - signedReport, ok := rawRequest.Inputs.Underlying[signedReportField] - if !ok { - return r, fmt.Errorf("missing required field %s", signedReportField) - } - - if err = signedReport.UnwrapTo(&r.Inputs.SignedReport); err != nil { - return r, err - } - - reportMetadata, err := decodeReportMetadata(r.Inputs.SignedReport.Report) - if err != nil { - return r, err - } - - if reportMetadata.Version != 1 { - return r, fmt.Errorf("unsupported report version: %d", reportMetadata.Version) - } - - 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) - } - - // 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) - } - - // 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.WorkflowCID[:]) != rawRequest.Metadata.WorkflowID { - return r, fmt.Errorf("WorkflowID in the report does not match WorkflowID in the request metadata. Report WorkflowID: %+v, request WorkflowID: %+v", reportMetadata.WorkflowCID, rawRequest.Metadata.WorkflowID) - } - - if !bytes.Equal(reportMetadata.ReportID[:], r.Inputs.SignedReport.ID) { - return r, fmt.Errorf("ReportID in the report does not match ReportID in the inputs. reportMetadata.ReportID: %x, Inputs.SignedReport.ID: %x", reportMetadata.ReportID, r.Inputs.SignedReport.ID) - } - - return r, nil -} - -func (cap *WriteTarget) Execute(ctx context.Context, rawRequest capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - // Bind to the contract address on the write path. - // Bind() requires a connection to the node's RPCs and - // cannot be run during initialization. - if !cap.bound { - cap.lggr.Debugw("Binding to forwarder address") - err := cap.cr.Bind(ctx, []commontypes.BoundContract{cap.binding}) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - cap.bound = true - } - - cap.lggr.Debugw("Execute", "rawRequest", rawRequest) - - request, err := evaluate(rawRequest) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - rawExecutionID, err := hex.DecodeString(request.Metadata.WorkflowExecutionID) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - // Check whether value was already transmitted on chain - transmissionInfo, err := cap.getTransmissionInfo(ctx, request, rawExecutionID) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - switch { - case transmissionInfo.State == TransmissionStateNotAttempted: - cap.lggr.Infow("non-empty report - transmission not attempted - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID) - case transmissionInfo.State == TransmissionStateSucceeded: - cap.lggr.Infow("returning without a transmission attempt - report already onchain ", "executionID", request.Metadata.WorkflowExecutionID) - return capabilities.CapabilityResponse{}, nil - case transmissionInfo.State == TransmissionStateInvalidReceiver: - cap.lggr.Infow("returning without a transmission attempt - transmission already attempted, receiver was marked as invalid", "executionID", request.Metadata.WorkflowExecutionID) - return capabilities.CapabilityResponse{}, ErrTxFailed - case transmissionInfo.State == TransmissionStateFailed: - receiverGasMinimum := cap.receiverGasMinimum - if request.Config.GasLimit != nil { - receiverGasMinimum = *request.Config.GasLimit - ForwarderContractLogicGasCost - } - if transmissionInfo.GasLimit.Uint64() > receiverGasMinimum { - cap.lggr.Infow("returning without a transmission attempt - transmission already attempted and failed, sufficient gas was provided", "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) - return capabilities.CapabilityResponse{}, ErrTxFailed - } - cap.lggr.Infow("non-empty report - retrying a failed transmission - attempting to push to txmgr", "request", request, "reportLen", len(request.Inputs.SignedReport.Report), "reportContextLen", len(request.Inputs.SignedReport.Context), "nSignatures", len(request.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) - - default: - return capabilities.CapabilityResponse{}, fmt.Errorf("unexpected transmission state: %v", transmissionInfo.State) - } - - txID, err := uuid.NewUUID() // NOTE: CW expects us to generate an ID, rather than return one - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - // Note: The codec that ChainWriter uses to encode the parameters for the contract ABI cannot handle - // `nil` values, including for slices. Until the bug is fixed we need to ensure that there are no - // `nil` values passed in the request. - req := struct { - Receiver string - RawReport []byte - ReportContext []byte - Signatures [][]byte - }{request.Config.Address, request.Inputs.SignedReport.Report, request.Inputs.SignedReport.Context, request.Inputs.SignedReport.Signatures} - - if req.RawReport == nil { - req.RawReport = make([]byte, 0) - } - - if req.ReportContext == nil { - req.ReportContext = make([]byte, 0) - } - - if req.Signatures == nil { - req.Signatures = make([][]byte, 0) - } - cap.lggr.Debugw("Transaction raw report", "report", hex.EncodeToString(req.RawReport)) - - meta := commontypes.TxMeta{WorkflowExecutionID: &request.Metadata.WorkflowExecutionID} - if request.Config.GasLimit != nil { - meta.GasLimit = new(big.Int).SetUint64(*request.Config.GasLimit) - } - - value := big.NewInt(0) - if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), cap.forwarderAddress, &meta, value); err != nil { - if !commontypes.ErrSettingTransactionGasLimitNotSupported.Is(err) { - return capabilities.CapabilityResponse{}, fmt.Errorf("failed to submit transaction: %w", err) - } - meta.GasLimit = nil - if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), cap.forwarderAddress, &meta, value); err != nil { - return capabilities.CapabilityResponse{}, fmt.Errorf("failed to submit transaction: %w", err) - } - } - - cap.lggr.Debugw("Transaction submitted", "request", request, "transaction", txID) - - tick := time.NewTicker(transactionStatusCheckInterval) - defer tick.Stop() - for { - select { - case <-ctx.Done(): - return capabilities.CapabilityResponse{}, nil - case <-tick.C: - txStatus, err := cap.cw.GetTransactionStatus(ctx, txID.String()) - if err != nil { - cap.lggr.Errorw("Failed to get transaction status", "request", request, "transaction", txID, "err", err) - continue - } - switch txStatus { - case commontypes.Pending: - cap.lggr.Debugw("Transaction pending, retrying...", "request", request, "transaction", txID) - // TxStatus Unconfirmed actually means "Confirmed" for the transaction manager, i.e. the transaction has landed on chain but isn't finalized. - case commontypes.Unconfirmed: - transmissionInfo, err = cap.getTransmissionInfo(ctx, request, rawExecutionID) - if err != nil { - return capabilities.CapabilityResponse{}, err - } - - // This is counterintuitive, but the tx manager is currently returning unconfirmed whenever the tx is confirmed - // current implementation here: https://github.com/smartcontractkit/chainlink-framework/blob/main/chains/txmgr/txmgr.go#L697 - // so we need to check if we were able to write to the consumer contract to determine if the transaction was successful - switch transmissionInfo.State { - case TransmissionStateSucceeded: - cap.lggr.Debugw("Transaction confirmed", "request", request, "transaction", txID) - return capabilities.CapabilityResponse{}, nil - case TransmissionStateFailed, TransmissionStateInvalidReceiver: - cap.lggr.Errorw("Transaction written to the forwarder, but failed to be written to the consumer contract", "request", request, "transaction", txID, "transmissionState", transmissionInfo.State) - msg := "transaction written to the forwarder, but failed to be written to the consumer contract, transaction ID: " + txID.String() - err = cap.emitter.With( - platform.KeyWorkflowID, request.Metadata.WorkflowID, - platform.KeyWorkflowName, request.Metadata.DecodedWorkflowName, - platform.KeyWorkflowOwner, request.Metadata.WorkflowOwner, - platform.KeyWorkflowExecutionID, request.Metadata.WorkflowExecutionID, - ).Emit(ctx, msg) - if err != nil { - cap.lggr.Errorf("failed to send custom message with msg: %s, err: %v", msg, err) - } - return capabilities.CapabilityResponse{}, ErrTxFailed - } - // TransmissionStateNotAttempted is not expected here, but we'll log it just in case - cap.lggr.Debugw("Transaction confirmed but transmission not attempted, this should never happen", "request", request, "transaction", txID) - return capabilities.CapabilityResponse{}, errors.New("transmission not attempted") - - case commontypes.Finalized: - cap.lggr.Debugw("Transaction finalized", "request", request, "transaction", txID) - return capabilities.CapabilityResponse{}, nil - case commontypes.Failed, commontypes.Fatal: - cap.lggr.Error("Transaction failed", "request", request, "transaction", txID) - - msg := "transaction failed to be written to the forwarder, transaction ID: " + txID.String() - err = cap.emitter.With( - platform.KeyWorkflowID, request.Metadata.WorkflowID, - platform.KeyWorkflowName, request.Metadata.DecodedWorkflowName, - platform.KeyWorkflowOwner, request.Metadata.WorkflowOwner, - platform.KeyWorkflowExecutionID, request.Metadata.WorkflowExecutionID, - ).Emit(ctx, msg) - if err != nil { - cap.lggr.Errorf("failed to send custom message with msg: %s, err: %v", msg, err) - } - return capabilities.CapabilityResponse{}, ErrTxFailed - default: - cap.lggr.Debugw("Unexpected transaction status", "request", request, "transaction", txID, "status", txStatus) - } - } - } -} - -func (cap *WriteTarget) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { - return nil -} - -func (cap *WriteTarget) UnregisterFromWorkflow(ctx context.Context, request capabilities.UnregisterFromWorkflowRequest) error { - return nil -} - -func (cap *WriteTarget) getTransmissionInfo(ctx context.Context, request Request, rawExecutionID []byte) (*TransmissionInfo, error) { - queryInputs := struct { - Receiver string - WorkflowExecutionID []byte - ReportID []byte - }{ - Receiver: request.Config.Address, - WorkflowExecutionID: rawExecutionID, - ReportID: request.Inputs.SignedReport.ID, - } - var transmissionInfo TransmissionInfo - if err := cap.cr.GetLatestValue(ctx, cap.binding.ReadIdentifier("getTransmissionInfo"), primitives.Unconfirmed, queryInputs, &transmissionInfo); err != nil { - return nil, fmt.Errorf("failed to getTransmissionInfo latest value: %w", err) - } - return &transmissionInfo, nil -} diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go deleted file mode 100644 index 1022d58c132..00000000000 --- a/core/capabilities/targets/write_target_test.go +++ /dev/null @@ -1,516 +0,0 @@ -package targets_test - -import ( - "context" - "encoding/hex" - "errors" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "github.com/smartcontractkit/chainlink-common/pkg/values" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" -) - -type testHarness struct { - lggr logger.Logger - cw *mocks.ContractWriter - cr *mocks.ContractValueGetter - config *values.Map - validInputs *values.Map - validMetadata capabilities.RequestMetadata - writeTarget *targets.WriteTarget - forwarderAddr string - binding types.BoundContract - gasLimit uint64 -} - -func setup(t *testing.T) testHarness { - lggr := logger.Test(t) - - cw := mocks.NewContractWriter(t) - cr := mocks.NewContractValueGetter(t) - - forwarderA := testutils.NewAddress() - forwarderAddr := forwarderA.Hex() - - var txGasLimit uint64 = 400_000 - writeTarget := targets.NewWriteTarget(lggr, "test-write-target@1.0.0", cr, cw, forwarderAddr, txGasLimit) - require.NotNil(t, writeTarget) - - config, err := values.NewMap(map[string]any{ - "Address": forwarderAddr, - }) - 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{}, - Timestamp: 0, - DonID: 0, - DonConfigVersion: 0, - WorkflowCID: [32]byte{}, - WorkflowName: workflowName, - WorkflowOwner: workflowOwner, - ReportID: reportID, - } - - reportMetadataBytes, err := reportMetadata.Encode() - require.NoError(t, err) - - validInputs, err := values.NewMap(map[string]any{ - "signed_report": map[string]any{ - "report": reportMetadataBytes, - "signatures": [][]byte{}, - "context": []byte{4, 5}, - "id": reportID[:], - }, - }) - require.NoError(t, err) - - validMetadata := capabilities.RequestMetadata{ - WorkflowID: hex.EncodeToString(reportMetadata.WorkflowCID[:]), - WorkflowOwner: workflowOwnerString, - WorkflowName: hex.EncodeToString(reportMetadata.WorkflowName[:]), - WorkflowExecutionID: hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]), - } - - binding := types.BoundContract{ - Address: forwarderAddr, - Name: "forwarder", - } - - cr.On("Bind", mock.Anything, []types.BoundContract{binding}).Return(nil) - - return testHarness{ - lggr: lggr, - cw: cw, - cr: cr, - config: config, - validInputs: validInputs, - validMetadata: validMetadata, - writeTarget: writeTarget, - forwarderAddr: forwarderAddr, - binding: binding, - gasLimit: txGasLimit - targets.ForwarderContractLogicGasCost, - } -} -func TestWriteTarget(t *testing.T) { - th := setup(t) - th.cr.EXPECT().GetLatestValue(mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(_ context.Context, _ string, _ primitives.ConfidenceLevel, _, retVal any) { - transmissionInfo := retVal.(*targets.TransmissionInfo) - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: 0, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - }) - t.Run("succeeds with valid report", func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Finalized, nil).Once() - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() - - ctx := testutils.Context(t) - response, err2 := th.writeTarget.Execute(ctx, req) - require.NoError(t, err2) - require.NotNil(t, response) - }) - - t.Run("fails when ChainWriter's SubmitTransaction returns error", func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(errors.New("writer error")) - - ctx := testutils.Context(t) - _, err := th.writeTarget.Execute(ctx, req) - require.Error(t, err) - }) - - t.Run("passes gas limit set on config to the chain writer", func(t *testing.T) { - configGasLimit, err2 := values.NewMap(map[string]any{ - "Address": th.forwarderAddr, - "GasLimit": 500000, - }) - require.NoError(t, err2) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: configGasLimit, - Inputs: th.validInputs, - } - - meta := types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID, GasLimit: big.NewInt(500000)} - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, &meta, mock.Anything).Return(types.ErrSettingTransactionGasLimitNotSupported) - - ctx := testutils.Context(t) - _, err2 = th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - }) - - t.Run("retries without gas limit when ChainWriter's SubmitTransaction returns error due to gas limit not supported", func(t *testing.T) { - configGasLimit, err2 := values.NewMap(map[string]any{ - "Address": th.forwarderAddr, - "GasLimit": 500000, - }) - require.NoError(t, err2) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: configGasLimit, - Inputs: th.validInputs, - } - - meta := types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID, GasLimit: big.NewInt(500000)} - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, &meta, mock.Anything).Return(types.ErrSettingTransactionGasLimitNotSupported) - meta = types.TxMeta{WorkflowExecutionID: &req.Metadata.WorkflowExecutionID} - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, &meta, mock.Anything).Return(nil) - - configGasLimit, err := values.NewMap(map[string]any{ - "Address": th.forwarderAddr, - }) - require.NoError(t, err) - req = capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: configGasLimit, - Inputs: th.validInputs, - } - - ctx := testutils.Context(t) - _, err2 = th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - }) - - t.Run("fails when ChainReader's GetLatestValue returns error", func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - th.cr.EXPECT().GetLatestValue(mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(errors.New("reader error")) - - ctx := testutils.Context(t) - _, err := th.writeTarget.Execute(ctx, req) - require.Error(t, err) - }) - - t.Run("fails with invalid config", func(t *testing.T) { - invalidConfig, err2 := values.NewMap(map[string]any{ - "Address": "invalid-address", - }) - require.NoError(t, err2) - - req := capabilities.CapabilityRequest{ - Metadata: capabilities.RequestMetadata{ - WorkflowID: "test-id", - }, - Config: invalidConfig, - Inputs: th.validInputs, - } - ctx := testutils.Context(t) - _, err2 = th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - }) - - t.Run("fails with nil config", func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: nil, - Inputs: th.validInputs, - } - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - }) - - t.Run("fails with nil inputs", func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: nil, - } - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - }) -} - -func TestWriteTarget_ValidateRequest(t *testing.T) { - th := setup(t) - tests := []struct { - name string - modifyRequest func(*capabilities.CapabilityRequest) - 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: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - tt.modifyRequest(&req) - - ctx := testutils.Context(t) - _, err := th.writeTarget.Execute(ctx, req) - if tt.expectedError == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tt.expectedError) - } - }) - } -} - -func TestWriteTarget_UnconfirmedTransaction(t *testing.T) { - t.Run("succeeds when transaction is unconfirmed but transmission succeeded ", func(t *testing.T) { - th := setup(t) - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() - callCount := 0 - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - if callCount == 0 { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: targets.TransmissionStateNotAttempted, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } else { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: targets.TransmissionStateSucceeded, - Success: true, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } - callCount++ - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once() - - ctx := testutils.Context(t) - response, err2 := th.writeTarget.Execute(ctx, req) - require.NoError(t, err2) - require.NotNil(t, response) - }) - - t.Run("getTransmissionInfo twice, transaction written to the forwarder, but failed to be written to the consumer contract because of revert in receiver", func(t *testing.T) { - th := setup(t) - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() - callCount := 0 - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - if callCount == 0 { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: targets.TransmissionStateNotAttempted, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } else { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: targets.TransmissionStateFailed, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } - callCount++ - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once() - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - require.ErrorIs(t, err2, targets.ErrTxFailed) - }) - - t.Run("getTransmissionInfo twice, transaction written to the forwarder, but failed to be written to the consumer contract because of invalid receiver", func(t *testing.T) { - th := setup(t) - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() - callCount := 0 - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - if callCount == 0 { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: false, - State: targets.TransmissionStateNotAttempted, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } else { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: true, - State: targets.TransmissionStateInvalidReceiver, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } - callCount++ - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once() - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - require.ErrorIs(t, err2, targets.ErrTxFailed) - }) - - t.Run("getTransmissionInfo once, transaction written to the forwarder, but failed to be written to the consumer contract because of invalid receiver", func(t *testing.T) { - th := setup(t) - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Once().Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0), - InvalidReceiver: true, - State: targets.TransmissionStateInvalidReceiver, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - require.ErrorIs(t, err2, targets.ErrTxFailed) - }) - - t.Run("getTransmissionInfo once, transaction written to the forwarder, but failed to be written to the consumer contract because of revert in receiver", func(t *testing.T) { - th := setup(t) - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Once().Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0).SetUint64(th.gasLimit + 1), // has sufficient gas - InvalidReceiver: false, - State: targets.TransmissionStateFailed, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - ctx := testutils.Context(t) - _, err2 := th.writeTarget.Execute(ctx, req) - require.Error(t, err2) - require.ErrorIs(t, err2, targets.ErrTxFailed) - }) - - t.Run("getTransmissionInfo twice, first time receiver reverted because of insufficient gas, second time succeeded", func(t *testing.T) { - th := setup(t) - th.cw.On("SubmitTransaction", mock.Anything, "forwarder", "report", mock.Anything, mock.Anything, th.forwarderAddr, mock.Anything, mock.Anything).Return(nil).Once() - callCount := 0 - th.cr.On("GetLatestValue", mock.Anything, th.binding.ReadIdentifier("getTransmissionInfo"), mock.Anything, mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) { - transmissionInfo := args.Get(4).(*targets.TransmissionInfo) - if callCount == 0 { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0).SetUint64(th.gasLimit - 1), // has insufficient gas - InvalidReceiver: false, - State: targets.TransmissionStateFailed, - Success: false, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } else { - *transmissionInfo = targets.TransmissionInfo{ - GasLimit: big.NewInt(0).SetUint64(th.gasLimit + 1), // has sufficient gas - InvalidReceiver: false, - State: targets.TransmissionStateSucceeded, - Success: true, - TransmissionID: [32]byte{}, - Transmitter: common.HexToAddress("0x0"), - } - } - callCount++ - }) - req := capabilities.CapabilityRequest{ - Metadata: th.validMetadata, - Config: th.config, - Inputs: th.validInputs, - } - - th.cw.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(types.Unconfirmed, nil).Once() - - ctx := testutils.Context(t) - response, err2 := th.writeTarget.Execute(ctx, req) - require.NoError(t, err2) - require.NotNil(t, response) - }) -} diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index bacb97a33c1..88dffc49d06 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -545,3 +545,9 @@ FromAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example ForwarderAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example # GasLimitDefault is the default gas limit for workflow transactions. GasLimitDefault = 400_000 # Default +# TxAcceptanceState is the default acceptance state for writer DON tranmissions. +TxAcceptanceState = 2 # Default +# PollPeriod is the default poll period for checking transmission state +PollPeriod = '2s' # Default +# AcceptanceTimeout is the default timeout for a tranmission to be accepted on chain +AcceptanceTimeout = '30s' # Default diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 543cab6ad8c..b1a01e2d635 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -36,10 +36,10 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.60 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-testing-framework/framework v0.9.3 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.0 @@ -396,8 +396,9 @@ require ( github.com/smartcontractkit/chainlink-aptos v0.0.0-20250618082928-9aa8eff952f6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 34b50647e89..37bbd4793d2 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1277,22 +1277,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 3f147b0e353..7fffbbe6d63 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -19,6 +19,7 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-framework/multinode" mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" @@ -733,7 +734,10 @@ func TestConfig_Marshal(t *testing.T) { }, }, Workflow: evmcfg.Workflow{ - GasLimitDefault: ptr[uint64](400000), + GasLimitDefault: ptr[uint64](400000), + TxAcceptanceState: ptr(commontypes.Unconfirmed), + PollPeriod: commoncfg.MustNewDuration(time.Second * 2), + AcceptanceTimeout: commoncfg.MustNewDuration(time.Second * 30), }, }, Nodes: []*evmcfg.Node{ @@ -1221,6 +1225,9 @@ GasLimit = 540 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'foo' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 0e2c4cb8c53..2a47969aabf 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -482,6 +482,9 @@ GasLimit = 540 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'foo' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 25dd09806eb..a9a31fcd9c1 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -431,6 +431,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'primary' @@ -547,6 +550,9 @@ GasLimit = 5400000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'foo' @@ -657,6 +663,9 @@ GasLimit = 5400000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' diff --git a/core/services/relay/evm/target_strategy.go b/core/services/relay/evm/target_strategy.go new file mode 100644 index 00000000000..9d5e3fa1cd6 --- /dev/null +++ b/core/services/relay/evm/target_strategy.go @@ -0,0 +1,230 @@ +package evm + +import ( + "context" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "math/big" + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + + "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget" +) + +var ( + _ writetarget.TargetStrategy = &evmTargetStrategy{} + ErrTxFailed = errors.New("submitted transaction failed") +) + +type evmTargetStrategy struct { + cr commontypes.ContractReader + cw commontypes.ContractWriter + + lggr logger.Logger + forwarder string + + receiverGasMinimum uint64 + binding commontypes.BoundContract + bound *atomic.Bool +} + +type TransmissionInfo struct { + GasLimit *big.Int + InvalidReceiver bool + State uint8 + Success bool + TransmissionID [32]byte + Transmitter common.Address +} + +// The gas cost of the forwarder contract logic, including state updates and event emission. +// This is a rough estimate and should be updated if the forwarder contract logic changes. +// TODO: Make this part of the on-chain capability configuration +const ForwarderContractLogicGasCost = 100_000 + +const ( + TransmissionStateNotAttempted uint8 = iota + TransmissionStateSucceeded + TransmissionStateInvalidReceiver + TransmissionStateFailed +) + +type Config struct { + // Address of the contract that will get the forwarded report + Address string + // Optional gas limit that overrides the default limit sent to the chain writer + GasLimit *uint64 +} + +func NewEVMTargetStrategy(cr commontypes.ContractReader, cw commontypes.ContractWriter, forwarder string, gasLimitDefault uint64, lggr logger.Logger) *evmTargetStrategy { + bound := atomic.Bool{} + return &evmTargetStrategy{ + cr: cr, + cw: cw, + lggr: lggr, + forwarder: forwarder, + receiverGasMinimum: gasLimitDefault - ForwarderContractLogicGasCost, + binding: commontypes.BoundContract{ + Address: forwarder, + Name: "forwarder", + }, + bound: &bound, + } +} + +func (t *evmTargetStrategy) QueryTransmissionState(ctx context.Context, reportID uint16, request capabilities.CapabilityRequest) (*writetarget.TransmissionState, error) { + rawExecutionID, err := hex.DecodeString(request.Metadata.WorkflowExecutionID) + if err != nil { + return nil, fmt.Errorf("failed to decode workflowExecutionID: %w", err) + } + + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, reportID) + + if !t.bound.Load() { + t.lggr.Debugw("Binding to forwarder address") + err = t.cr.Bind(ctx, []commontypes.BoundContract{t.binding}) + if err != nil { + return nil, err + } + t.bound.Store(true) + } + + r, err := getEVMRequest(request) + if err != nil { + return nil, fmt.Errorf("failed to getEVMRequest: %w", err) + } + receiver := r.Config.Address + + queryInputs := struct { + Receiver string + WorkflowExecutionID []byte + ReportID []byte + }{ + Receiver: receiver, + WorkflowExecutionID: rawExecutionID, + ReportID: b, + } + + var transmissionInfo TransmissionInfo + if err := t.cr.GetLatestValue(ctx, t.binding.ReadIdentifier("getTransmissionInfo"), primitives.Unconfirmed, queryInputs, &transmissionInfo); err != nil { + return nil, fmt.Errorf("failed to getTransmissionInfo latest value: %w", err) + } + + // TODO: Want to confirm these states are correct - invalid receiver and failed with sufficient gas are fatal. + switch transmissionInfo.State { + case TransmissionStateNotAttempted: + t.lggr.Infow("non-empty report - transmission not attempted", "request", request, "reportLen", len(r.Inputs.SignedReport.Report), "reportContextLen", len(r.Inputs.SignedReport.Context), "nSignatures", len(r.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID) + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateNotAttempted, + Transmitter: transmissionInfo.Transmitter.String(), + Err: nil, + }, nil + case TransmissionStateSucceeded: + t.lggr.Infow("returning without a transmission attempt - report already onchain ", "executionID", request.Metadata.WorkflowExecutionID) + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateSucceeded, + Transmitter: transmissionInfo.Transmitter.String(), + Err: nil, + }, nil + case TransmissionStateInvalidReceiver: + t.lggr.Infow("returning without a transmission attempt - transmission already attempted, receiver was marked as invalid", "executionID", request.Metadata.WorkflowExecutionID) + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateFatal, + Transmitter: transmissionInfo.Transmitter.String(), + Err: ErrTxFailed, + }, nil + case TransmissionStateFailed: + receiverGasMinimum := t.receiverGasMinimum + if r.Config.GasLimit != nil { + receiverGasMinimum = *r.Config.GasLimit - ForwarderContractLogicGasCost + } + if transmissionInfo.GasLimit.Uint64() > receiverGasMinimum { + t.lggr.Infow("returning without a transmission attempt - transmission already attempted and failed, sufficient gas was provided", "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateFatal, + Transmitter: transmissionInfo.Transmitter.String(), + Err: ErrTxFailed, + }, nil + } + t.lggr.Infow("non-empty report - transmission should be retried", "request", request, "reportLen", len(r.Inputs.SignedReport.Report), "reportContextLen", len(r.Inputs.SignedReport.Context), "nSignatures", len(r.Inputs.SignedReport.Signatures), "executionID", request.Metadata.WorkflowExecutionID, "receiverGasMinimum", receiverGasMinimum, "transmissionGasLimit", transmissionInfo.GasLimit) + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateFailed, + Transmitter: transmissionInfo.Transmitter.String(), + Err: ErrTxFailed, + }, nil + } + + return &writetarget.TransmissionState{ + Status: writetarget.TransmissionStateFatal, + Transmitter: transmissionInfo.Transmitter.String(), + Err: ErrTxFailed, + }, fmt.Errorf("unexpected transmission state: %v", transmissionInfo.State) +} + +// TransmitReport constructs the tx to transmit the report, and defines +// any specific handling for sending the report via ChainWriter. +func (t *evmTargetStrategy) TransmitReport(ctx context.Context, _ []byte, _ []byte, _ [][]byte, request capabilities.CapabilityRequest) (string, error) { + txID, err := uuid.NewUUID() // NOTE: CW expects us to generate an ID, rather than return one + if err != nil { + return "", err + } + + r, err := getEVMRequest(request) + if err != nil { + return txID.String(), fmt.Errorf("failed to getEVMRequest: %w", err) + } + + // Note: The codec that ChainWriter uses to encode the parameters for the contract ABI cannot handle + // `nil` values, including for slices. Until the bug is fixed we need to ensure that there are no + // `nil` values passed in the request. + req := struct { + Receiver string + RawReport []byte + ReportContext []byte + Signatures [][]byte + }{r.Config.Address, r.Inputs.SignedReport.Report, r.Inputs.SignedReport.Context, r.Inputs.SignedReport.Signatures} + + if req.RawReport == nil { + req.RawReport = make([]byte, 0) + } + + if req.ReportContext == nil { + req.ReportContext = make([]byte, 0) + } + + if req.Signatures == nil { + req.Signatures = make([][]byte, 0) + } + t.lggr.Debugw("Transaction raw report", "report", hex.EncodeToString(req.RawReport)) + + meta := commontypes.TxMeta{WorkflowExecutionID: &request.Metadata.WorkflowExecutionID} + if r.Config.GasLimit != nil { + meta.GasLimit = new(big.Int).SetUint64(*r.Config.GasLimit) + } + + value := big.NewInt(0) + if err := t.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), t.forwarder, &meta, value); err != nil { + if !commontypes.ErrSettingTransactionGasLimitNotSupported.Is(err) { + return txID.String(), fmt.Errorf("failed to submit transaction: %w", err) + } + meta.GasLimit = nil + if err := t.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), t.forwarder, &meta, value); err != nil { + return txID.String(), fmt.Errorf("failed to submit transaction: %w", err) + } + } + return txID.String(), nil +} + +func (t *evmTargetStrategy) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { + return t.cw.GetTransactionStatus(ctx, transactionID) +} diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 185b4df8e43..2b39862d316 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -1,21 +1,39 @@ +//nolint:gosec // disable G115 package evm import ( + "bytes" "context" + "encoding/hex" "encoding/json" + "errors" "fmt" + "regexp" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common" chainselectors "github.com/smartcontractkit/chain-selectors" + dfprocessor "github.com/smartcontractkit/chainlink-evm/pkg/report/datafeeds/processor" + porprocessor "github.com/smartcontractkit/chainlink-evm/pkg/report/por/processor" + df "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget/monitoring/pb/data-feeds/on-chain/registry" + processor "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget/report/platform/processor" + + "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget" + monitor "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget/beholder" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + ocr3types "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" forwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, gasLimitDefault uint64, lggr logger.Logger) (*targets.WriteTarget, error) { +func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain, gasLimitDefault uint64, lggr logger.Logger) (capabilities.ExecutableCapability, error) { // generate ID based on chain selector id := GenerateWriteTargetName(chain.ID().Uint64()) @@ -36,7 +54,7 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain }, }) if err != nil { - return nil, fmt.Errorf("failed to marshal contract reader config %v", err) + return nil, fmt.Errorf("failed to marshal contract reader config %w", err) } cr, err := relayer.NewContractReader(ctx, contractReaderConfigEncoded) if err != nil { @@ -69,14 +87,193 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, err } - return targets.NewWriteTarget(logger.Named(lggr, "WriteTarget"), id, cr, cw, config.ForwarderAddress().String(), gasLimitDefault), nil + var chainInfo monitor.ChainInfo + chainInfo, err = getChainInfo(chain.ID().Uint64()) + if err != nil { + return nil, fmt.Errorf("failed to get chain info: %w", err) + } + + registryMetrics, err := df.NewMetrics() + if err != nil { + return nil, fmt.Errorf("failed to create new registry metrics: %w", err) + } + + emitter := writetarget.NewMonitorEmitter(lggr) + + dfProcessor := dfprocessor.NewDataFeedsProcessor(registryMetrics, emitter) + ccipDfProcessor := dfprocessor.NewCCIPDataFeedsProcessor(registryMetrics, emitter) + porProcessor := porprocessor.NewPORProcessor(registryMetrics, emitter) + + processors, err := processor.NewPlatformProcessors(emitter) + if err != nil { + return nil, fmt.Errorf("failed to create EVM platform processors: %w", err) + } + + processors["evm-data-feeds"] = dfProcessor + processors["evm-data-feeds-ccip"] = ccipDfProcessor + processors["evm-por-feeds"] = porProcessor + + beholder, err := writetarget.NewMonitor(writetarget.MonitorOpts{ + Lggr: lggr, + Processors: processors, + EnabledProcessors: processor.PlatformDefaultProcessors, + Emitter: emitter, + }) + if err != nil { + return nil, fmt.Errorf("failed to create Aptos WT monitor client: %+w", err) + } + + opts := writetarget.WriteTargetOpts{ + ID: id, + Logger: lggr, + Config: writetarget.Config{ + PollPeriod: config.PollPeriod(), + AcceptanceTimeout: config.AcceptanceTimeout(), + }, + ChainInfo: chainInfo, + Beholder: beholder, + ChainService: chain, + ConfigValidateFn: evaluate, + NodeAddress: config.FromAddress().String(), + ForwarderAddress: config.ForwarderAddress().String(), + TargetStrategy: NewEVMTargetStrategy(cr, cw, config.ForwarderAddress().String(), gasLimitDefault, lggr), + WriteAcceptanceState: *config.TxAcceptanceState(), + } + + return writetarget.NewWriteTarget(opts), nil +} + +type Inputs struct { + SignedReport ocr3types.SignedReport +} + +type TargetRequest struct { + Metadata capabilities.RequestMetadata + Config Config + Inputs Inputs +} + +func getEVMRequest(rawRequest capabilities.CapabilityRequest) ( + TargetRequest, error) { + var r TargetRequest + r.Metadata = rawRequest.Metadata + + if rawRequest.Config == nil { + return TargetRequest{}, errors.New("missing config field") + } + + if err := rawRequest.Config.UnwrapTo(&r.Config); err != nil { + return TargetRequest{}, err + } + + if !common.IsHexAddress(r.Config.Address) { + return TargetRequest{}, fmt.Errorf("'%v' is not a valid address", r.Config.Address) + } + + if rawRequest.Inputs == nil { + return TargetRequest{}, errors.New("missing inputs field") + } + + // required field of target's config in the workflow spec + signedReport, ok := rawRequest.Inputs.Underlying[writetarget.KeySignedReport] + if !ok { + return TargetRequest{}, fmt.Errorf("missing required field %s", writetarget.KeySignedReport) + } + + if err := signedReport.UnwrapTo(&r.Inputs.SignedReport); err != nil { + return TargetRequest{}, err + } + return r, nil +} + +func evaluate(rawRequest capabilities.CapabilityRequest) (receiver string, err error) { + r, err := getEVMRequest(rawRequest) + if err != nil { + return "", err + } + + // don't need tail in this case + reportMetadata, _, err := ocr3types.Decode(r.Inputs.SignedReport.Report) + if err != nil { + return "", fmt.Errorf("failed to decode report metadata: %w", err) + } + + if reportMetadata.Version != 1 { + return "", fmt.Errorf("unsupported report version: %d", reportMetadata.Version) + } + + if reportMetadata.ExecutionID != rawRequest.Metadata.WorkflowExecutionID { + return "", fmt.Errorf("WorkflowExecutionID in the report does not match WorkflowExecutionID in the request metadata. Report WorkflowExecutionID: %+v, request WorkflowExecutionID: %+v", hex.EncodeToString([]byte(reportMetadata.ExecutionID)), rawRequest.Metadata.WorkflowExecutionID) + } + + // case-insensitive verification of the owner address (so that a check-summed address matches its non-checksummed version). + if !strings.EqualFold(reportMetadata.WorkflowOwner, rawRequest.Metadata.WorkflowOwner) { + return "", fmt.Errorf("WorkflowOwner in the report does not match WorkflowOwner in the request metadata. Report WorkflowOwner: %+v, request WorkflowOwner: %+v", reportMetadata.WorkflowOwner, rawRequest.Metadata.WorkflowOwner) + } + + if !strings.EqualFold(reportMetadata.WorkflowName, rawRequest.Metadata.WorkflowName) { + return "", 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 reportMetadata.WorkflowID != rawRequest.Metadata.WorkflowID { + return "", fmt.Errorf("WorkflowID in the report does not match WorkflowID in the request metadata. Report WorkflowID: %+v, request WorkflowID: %+v", reportMetadata.WorkflowID, rawRequest.Metadata.WorkflowID) + } + + byteID, err := hex.DecodeString(reportMetadata.ReportID) + if err != nil { + return "", fmt.Errorf("failed to decode report ID: %w", err) + } + + if !bytes.Equal(byteID, r.Inputs.SignedReport.ID) { + return "", fmt.Errorf("ReportID in the report does not match ReportID in the inputs. reportMetadata.ReportID: %x, Inputs.SignedReport.ID: %x", reportMetadata.ReportID, r.Inputs.SignedReport.ID) + } + + return r.Config.Address, nil +} + +func getChainInfo(chainID uint64) (monitor.ChainInfo, error) { + chainSelector := chainselectors.EvmChainIdToChainSelector()[chainID] + chainFamily, err := chainselectors.GetSelectorFamily(chainSelector) + if err != nil { + return monitor.ChainInfo{}, fmt.Errorf("failed to get chain family for selector %d: %w", chainSelector, err) + } + chainDetails, err := chainselectors.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(chainID)), chainFamily) + if err != nil { + return monitor.ChainInfo{}, fmt.Errorf("failed to get chain details for chain %d and family %s: %w", chainID, chainFamily, err) + } + + neworkName, err := ExtractNetwork(chainDetails.ChainName) + if err != nil { + return monitor.ChainInfo{}, fmt.Errorf("failed to get network name for chain %d: %w", chainID, err) + } + + return monitor.ChainInfo{ + FamilyName: chainFamily, + ChainID: strconv.Itoa(int(chainID)), + NetworkName: neworkName, + NetworkNameFull: chainDetails.ChainName, + }, nil +} + +func ExtractNetwork(selector string) (string, error) { + // Create a regexp pattern that matches any of the three. + re := regexp.MustCompile(`(mainnet|testnet|devnet)`) + name := re.FindString(selector) + if name == "" { + return "", fmt.Errorf("failed to extract network name from selector: %s", selector) + } + return name, nil } func GenerateWriteTargetName(chainID uint64) string { id := fmt.Sprintf("write_%v@1.0.0", chainID) + chainName, err := chainselectors.NameFromChainId(chainID) if err == nil { - id = fmt.Sprintf("write_%v@1.0.0", chainName) + wtID, err := writetarget.NewWriteTargetID("", chainName, strconv.FormatUint(chainID, 10), "1.0.0") + if err == nil { + id = wtID + } } return id diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index 52ade8f39f0..edcc731d54d 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -6,31 +6,41 @@ import ( "errors" "fmt" "math/big" + "strings" "testing" + "time" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" - forwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" gasmocks "github.com/smartcontractkit/chainlink-evm/pkg/gas/mocks" "github.com/smartcontractkit/chainlink-evm/pkg/heads/headstest" "github.com/smartcontractkit/chainlink-evm/pkg/keys" + "github.com/smartcontractkit/chainlink-evm/pkg/report/datafeeds" + df_processor "github.com/smartcontractkit/chainlink-evm/pkg/report/datafeeds/processor" + por_processor "github.com/smartcontractkit/chainlink-evm/pkg/report/por/processor" "github.com/smartcontractkit/chainlink-evm/pkg/txmgr" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" + "github.com/smartcontractkit/chainlink-framework/capabilities/writetarget/report/platform" + + ocr3types "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" + forwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" evmmocks "github.com/smartcontractkit/chainlink/v2/common/chains/mocks" lpmocks "github.com/smartcontractkit/chainlink/v2/common/logpoller/mocks" txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "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" @@ -39,65 +49,62 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - relayevm "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) var forwardABI = evmtypes.MustGetABI(forwarder.KeystoneForwarderMetaData.ABI) -func newMockedEncodeTransmissionInfo() ([]byte, error) { - info := targets.TransmissionInfo{ +func newMockedEncodeTransmissionInfo(state uint8) ([]byte, error) { + info := evm.TransmissionInfo{ GasLimit: big.NewInt(0), InvalidReceiver: false, - State: 0, + State: state, Success: false, TransmissionID: [32]byte{}, Transmitter: common.HexToAddress("0x0"), } - var buffer bytes.Buffer - gasLimitBytes := info.GasLimit.Bytes() - if len(gasLimitBytes) > 80 { - return nil, fmt.Errorf("GasLimit too large") - } - paddedGasLimit := make([]byte, 80-len(gasLimitBytes)) - buffer.Write(paddedGasLimit) - buffer.Write(gasLimitBytes) - // Encode InvalidReceiver (as uint8) - if info.InvalidReceiver { - buffer.WriteByte(1) - } else { - buffer.WriteByte(0) - } + // 1. Encode TransmissionId (bytes32) + buffer.Write(info.TransmissionID[:]) - // Padding for InvalidReceiver to fit into 32 bytes - padInvalidReceiver := make([]byte, 31) - buffer.Write(padInvalidReceiver) + // 2. Encode State (uint8, ABI pads to 32 bytes: 31 zeros + 1 byte) + stateSlot := make([]byte, 31) + stateSlot = append(stateSlot, info.State) + buffer.Write(stateSlot) - // Encode State (as uint8) - buffer.WriteByte(info.State) + // 3. Encode Transmitter (address): address is 20 bytes; pad left with 12 zeros. + txBytes := info.Transmitter.Bytes() + // Ensure it is 20 bytes; if not, left-pad it (common.HexToAddress always returns 20 bytes). + paddedTx := make([]byte, 32-len(txBytes)) + buffer.Write(paddedTx) + buffer.Write(txBytes) - // Padding for State to fit into 32 bytes - padState := make([]byte, 31) - buffer.Write(padState) + // 4. Encode InvalidReceiver as bool (32 bytes: 31 zeros then byte(0) or byte(1)) + var invReceiverByte byte + if info.InvalidReceiver { + invReceiverByte = 1 + } + invalidReceiverSlot := make([]byte, 31) + invalidReceiverSlot = append(invalidReceiverSlot, invReceiverByte) + buffer.Write(invalidReceiverSlot) - // Encode Success (as uint8) + // 5. Encode Success as bool (32 bytes) + var successByte byte if info.Success { - buffer.WriteByte(1) - } else { - buffer.WriteByte(0) + successByte = 1 } + successSlot := make([]byte, 31) + successSlot = append(successSlot, successByte) + buffer.Write(successSlot) - // Padding for Success to fit into 32 bytes - padSuccess := make([]byte, 31) - buffer.Write(padSuccess) - - // Encode TransmissionID (as bytes32) - buffer.Write(info.TransmissionID[:]) - - // Encode Transmitter (as address) - buffer.Write(info.Transmitter.Bytes()) + // 6. Encode GasLimit as a uint (for uint80, still ABI-encoded in a 32-byte slot) + gasLimitBytes := info.GasLimit.Bytes() + // Left-pad the gas limit to 32 bytes. + paddedGasLimit := make([]byte, 32-len(gasLimitBytes)) + buffer.Write(paddedGasLimit) + buffer.Write(gasLimitBytes) return buffer.Bytes(), nil } @@ -108,23 +115,15 @@ func TestEvmWrite(t *testing.T) { evmClient := clienttest.NewClient(t) poller := lpmocks.NewLogPoller(t) - // This is a very error-prone way to mock an on-chain response to a GetLatestValue("getTransmissionInfo") call - // It's a bit of a hack, but it's the best way to do it without a lot of refactoring - mockCall, err := newMockedEncodeTransmissionInfo() - require.NoError(t, err) - evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockCall, nil).Maybe() - evmClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return([]byte("test"), nil) - - txManager.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(commonTypes.Finalized, nil) - chain.On("Start", mock.Anything).Return(nil) chain.On("Close").Return(nil) chain.On("ID").Return(big.NewInt(11155111)) chain.On("TxManager").Return(txManager) chain.On("LogPoller").Return(poller) + chain.On("LatestHead", mock.Anything).Return(commontypes.Head{Height: "99"}, nil) - ht := headstest.NewTracker[*evmtypes.Head, common.Hash](t) - ht.On("LatestAndFinalizedBlock", mock.Anything).Return(&evmtypes.Head{}, &evmtypes.Head{}, nil) + ht := headstest.NewTracker[*evmtypes.Head](t) + ht.On("LatestAndFinalizedBlock", mock.Anything).Return(&evmtypes.Head{Number: 99}, &evmtypes.Head{}, nil) chain.On("HeadTracker").Return(ht) chain.On("Client").Return(evmClient) @@ -149,9 +148,9 @@ func TestEvmWrite(t *testing.T) { db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) - lggr := logger.TestLogger(t) + lggr := logger.TestLogger(t, zapcore.DebugLevel) cRegistry := evmcapabilities.NewRegistry(lggr) - relayer, err := relayevm.NewRelayer(lggr, chain, relayevm.RelayerOpts{ + relayer, err := evm.NewRelayer(lggr, chain, evm.RelayerOpts{ DS: db, EVMKeystore: keys.NewChainStore(keystore.NewEthSigner(keyStore.Eth(), chain.ID()), chain.ID()), CSAKeystore: &keystore.CSASigner{CSA: keyStore.CSA()}, @@ -164,58 +163,236 @@ func TestEvmWrite(t *testing.T) { require.Len(t, registeredCapabilities, 1) // WriteTarget should be added to the registry reportID := [2]byte{0x00, 0x01} - reportMetadata := targets.ReportV1Metadata{ - Version: 1, - WorkflowExecutionID: [32]byte{}, - Timestamp: 0, - DonID: 0, - DonConfigVersion: 0, - WorkflowCID: [32]byte{}, - WorkflowName: [10]byte{}, - WorkflowOwner: [20]byte{}, - ReportID: reportID, + + reportMetadata := ocr3types.Metadata{ + Version: 1, + ExecutionID: "0102030405060708090a0b0c0d0e0f1000000000000000000000000000000000", + Timestamp: 1620000000, + DONID: 1, + DONConfigVersion: 1, + WorkflowID: "1234567890123456789012345678901234567890123456789012345678901234", + WorkflowName: "12345678901234567890", + WorkflowOwner: "1234567890123456789012345678901234567890", + ReportID: hex.EncodeToString(reportID[:]), } - reportMetadataBytes, err := reportMetadata.Encode() - require.NoError(t, err) + generateReportEncoded := func(reportType string) []byte { + feedReports := datafeeds.Reports{ + { + FeedID: [32]byte{0x01}, + Price: big.NewInt(1234567890123456789), + Timestamp: 1620000000, + }, + } + + ccipFeedReports := datafeeds.CCIPReports{ + { + FeedID: [32]byte{0x01}, + Timestamp: 1620000000, + Price: big.NewInt(1234567890123456789), + }, + } + + porFeedReports := datafeeds.PORReports{ + { + DataID: [32]byte{0x01}, + Timestamp: 1620000000, + Bundle: []byte{0x01, 0x02, 0x03}, + }, + } + + var feedReportsEncoded []byte + + switch reportType { + case "ccip": + feedReportsEncoded, err = df_processor.GetCCIPDataFeedsSchema().Pack(ccipFeedReports) + require.NoError(t, err) + case "por": + feedReportsEncoded, err = por_processor.GetPORSchema().Pack(porFeedReports) + require.NoError(t, err) + // normal non-ccip / POR report + default: + feedReportsEncoded, err = df_processor.GetDataFeedsSchema().Pack(feedReports) + require.NoError(t, err) + } + + report := platform.Report{ + Metadata: reportMetadata, + Data: feedReportsEncoded, + } + + reportEncoded, encodeErr := report.Encode() + require.NoError(t, encodeErr) + + return reportEncoded + } signatures := [][]byte{} - validInputs, err := values.NewMap(map[string]any{ - "signed_report": map[string]any{ - "report": reportMetadataBytes, - "signatures": signatures, - "context": []byte{4, 5}, - "id": reportID[:], - }, - }) - require.NoError(t, err) + mockSuccessfulTransmission := func(reportType string) { + // This is a very error-prone way to mock an on-chain response to a GetLatestValue("getTransmissionInfo") call + // It's a bit of a hack, but it's the best way to do it without a lot of refactoring + mockNotStarted, mockErr := newMockedEncodeTransmissionInfo(0) + require.NoError(t, mockErr) + + evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockNotStarted, nil).Once() + evmClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return([]byte("test"), nil) + + txManager.On("GetTransactionStatus", mock.Anything, mock.Anything).Return(commontypes.Finalized, nil).Maybe() + + mockSucceeded, mockErr2 := newMockedEncodeTransmissionInfo(1) + require.NoError(t, mockErr2) + evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockSucceeded, nil).Maybe().Once() + + txManager.On("CreateTransaction", mock.Anything, mock.Anything).Return(txmgr.Tx{}, nil).Run(func(args mock.Arguments) { + req := args.Get(1).(txmgr.TxRequest) + payload := make(map[string]any) + method := forwardABI.Methods["report"] + err = method.Inputs.UnpackIntoMap(payload, req.EncodedPayload[4:]) + require.NoError(t, err) + require.Equal(t, generateReportEncoded(reportType), payload["rawReport"]) + require.Equal(t, signatures, payload["signatures"]) + }).Once() + } + + generateValidInputs := func(reportType string) *values.Map { + validInputs, inputErr := values.NewMap(map[string]any{ + "signed_report": map[string]any{ + "report": generateReportEncoded(reportType), + "signatures": signatures, + "context": []byte{4, 5}, + "id": reportID[:], + }, + }) + require.NoError(t, inputErr) + return validInputs + } + + // default inputs/report are not CCIP / POR + validInputs := generateValidInputs("") validMetadata := capabilities.RequestMetadata{ - WorkflowID: hex.EncodeToString(reportMetadata.WorkflowCID[:]), - WorkflowOwner: hex.EncodeToString(reportMetadata.WorkflowOwner[:]), - WorkflowName: hex.EncodeToString(reportMetadata.WorkflowName[:]), - WorkflowExecutionID: hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]), + WorkflowID: reportMetadata.WorkflowID, + WorkflowOwner: reportMetadata.WorkflowOwner, + WorkflowName: reportMetadata.WorkflowName, + WorkflowExecutionID: reportMetadata.ExecutionID, } validConfig, err := values.NewMap(map[string]any{ - "Address": evmCfg.EVM().Workflow().ForwarderAddress().String(), + "address": evmCfg.EVM().Workflow().ForwarderAddress().String(), + "processor": "evm-data-feeds", }) require.NoError(t, err) - txManager.On("CreateTransaction", mock.Anything, mock.Anything).Return(txmgr.Tx{}, nil).Run(func(args mock.Arguments) { - req := args.Get(1).(txmgr.TxRequest) - payload := make(map[string]any) - method := forwardABI.Methods["report"] - err = method.Inputs.UnpackIntoMap(payload, req.EncodedPayload[4:]) - require.NoError(t, err) - require.Equal(t, reportMetadataBytes, payload["rawReport"]) - require.Equal(t, signatures, payload["signatures"]) - }).Once() - gasLimitDefault := uint64(400_000) t.Run("succeeds with valid report", func(t *testing.T) { + mockSuccessfulTransmission("") + ctx := testutils.Context(t) + lggr, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) + + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) + require.NoError(t, err) + + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: validConfig, + Inputs: validInputs, + } + + _, err = capability.Execute(ctx, req) + require.NoError(t, err) + + findLogMatch(t, observed, "[Beholder.emit]", "attributes", "FeedUpdated") + }) + + t.Run("succeeds with valid CCIP report", func(t *testing.T) { + mockSuccessfulTransmission("ccip") + ctx := testutils.Context(t) + lggr, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) + + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) + require.NoError(t, err) + + config, err := values.NewMap(map[string]any{ + "address": evmCfg.EVM().Workflow().ForwarderAddress().String(), + "processor": "evm-data-feeds-ccip", + }) + require.NoError(t, err) + + // special request with properly encoded CCIP report using ccip processor + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: config, + Inputs: generateValidInputs("ccip"), + } + + _, err = capability.Execute(ctx, req) + require.NoError(t, err) + + findLogMatch(t, observed, "[Beholder.emit]", "attributes", "FeedUpdated") + }) + + t.Run("succeeds with valid POR report", func(t *testing.T) { + mockSuccessfulTransmission("por") + ctx := testutils.Context(t) + lggr, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) + + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) + require.NoError(t, err) + + config, err := values.NewMap(map[string]any{ + "address": evmCfg.EVM().Workflow().ForwarderAddress().String(), + "processor": "evm-por-feeds", + }) + require.NoError(t, err) + + // special request with properly encoded CCIP report using ccip processor + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: config, + Inputs: generateValidInputs("por"), + } + + _, err = capability.Execute(ctx, req) + require.NoError(t, err) + + findLogMatch(t, observed, "[Beholder.emit]", "attributes", "FeedUpdated") + }) + + t.Run("succeeds with valid report, but logs error for missing processor", func(t *testing.T) { + mockSuccessfulTransmission("") + + ctx := testutils.Context(t) + lggr, observed := logger.TestLoggerObserved(t, zapcore.DebugLevel) + + capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) + require.NoError(t, err) + + config, err := values.NewMap(map[string]any{ + "address": evmCfg.EVM().Workflow().ForwarderAddress().String(), + "processor": "invalid-name", + }) + require.NoError(t, err) + + req := capabilities.CapabilityRequest{ + Metadata: validMetadata, + Config: config, + Inputs: validInputs, + } + + _, err = capability.Execute(ctx, req) + require.NoError(t, err) + + tests.RequireLogMessage(t, observed, "no matching processor for MetaCapabilityProcessor=invalid-name") + }) + + t.Run("succeeds when report already succeeded", func(t *testing.T) { + mockCall, err := newMockedEncodeTransmissionInfo(1) + require.NoError(t, err) + + evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockCall, nil).Once() + ctx := testutils.Context(t) capability, err := evm.NewWriteTarget(ctx, relayer, chain, gasLimitDefault, lggr) require.NoError(t, err) @@ -260,8 +437,10 @@ func TestEvmWrite(t *testing.T) { Config: validConfig, Inputs: validInputs, } - - txManager.On("CreateTransaction", mock.Anything, mock.Anything).Return(txmgr.Tx{}, errors.New("TXM error")) + mockCall, err := newMockedEncodeTransmissionInfo(0) + require.NoError(t, err) + evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockCall, nil).Once() + txManager.On("CreateTransaction", mock.Anything, mock.Anything).Return(txmgr.Tx{}, errors.New("TXM error")).Once() _, err = capability.Execute(ctx, req) require.Error(t, err) @@ -283,7 +462,7 @@ func TestEvmWrite(t *testing.T) { testChain.On("Config").Return(evmtest.NewChainScopedConfig(t, testCfg)) capabilityRegistry := evmcapabilities.NewRegistry(lggr) - relayer, err := relayevm.NewRelayer(lggr, testChain, relayevm.RelayerOpts{ + relayer, err := evm.NewRelayer(lggr, testChain, evm.RelayerOpts{ DS: db, EVMKeystore: keys.NewChainStore(keystore.NewEthSigner(keyStore.Eth(), chain.ID()), chain.ID()), CSAKeystore: &keystore.CSASigner{CSA: keyStore.CSA()}, @@ -298,3 +477,67 @@ func TestEvmWrite(t *testing.T) { assert.Empty(t, l) }) } + +func findLogMatch(t *testing.T, observed *observer.ObservedLogs, msg string, key string, value string) { + require.Eventually(t, func() bool { + filteredByMsg := observed.FilterMessage(msg) + matches := filteredByMsg. + Filter(func(le observer.LoggedEntry) bool { + for _, field := range le.Context { + if field.Key == key && + strings.Contains(fmt.Sprint(field.Interface), + value) { + return true + } + } + return false + }). + All() // => []observer.LoggedEntry + return len(matches) > 0 + }, 30*time.Second, 1*time.Second) +} +func TestExtractNetwork(t *testing.T) { + testCases := []struct { + networkName string + expectedName string + expectedErr bool + }{ + { + networkName: "ethereum-testnet-goerli", + expectedName: "testnet", + expectedErr: false, + }, + { + networkName: "ethereum-mainnet", + expectedName: "mainnet", + expectedErr: false, + }, + { + networkName: "polygon-devnet", + expectedName: "devnet", + expectedErr: false, + }, + { + networkName: "ethereum_test", + expectedName: "", + expectedErr: true, + }, + { + networkName: "ethereum", + expectedName: "", + expectedErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.networkName, func(t *testing.T) { + networkName, err := evm.ExtractNetwork(tc.networkName) + if tc.expectedErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tc.expectedName, networkName) + }) + } +} diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index a3bb5124280..1185ba68440 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -481,6 +481,9 @@ GasLimit = 540 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'foo' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index c44a71f9a0f..67b73430640 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -431,6 +431,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'primary' @@ -547,6 +550,9 @@ GasLimit = 5400000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'foo' @@ -657,6 +663,9 @@ GasLimit = 5400000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' diff --git a/deployment/go.mod b/deployment/go.mod index 753cfc5a69d..808f48d055f 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -35,9 +35,9 @@ require ( github.com/smartcontractkit/chainlink-aptos v0.0.0-20250618082928-9aa8eff952f6 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 github.com/smartcontractkit/chainlink-protos/orchestrator v0.7.0 @@ -379,8 +379,9 @@ require ( github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.0 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index bcf42ccb891..1be35031b9b 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1253,22 +1253,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 2deda648072..19283aa2de1 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2293,6 +2293,9 @@ GasLimit = 10500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2403,6 +2406,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2513,6 +2519,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2623,6 +2632,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2738,6 +2750,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2849,6 +2864,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -2959,6 +2977,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3068,6 +3089,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3177,6 +3201,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3287,6 +3314,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3397,6 +3427,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3508,6 +3541,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3618,6 +3654,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3728,6 +3767,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3843,6 +3885,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -3953,6 +3998,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4063,6 +4111,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4173,6 +4224,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4288,6 +4342,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4400,6 +4457,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4512,6 +4572,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4627,6 +4690,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4740,6 +4806,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4854,6 +4923,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -4964,6 +5036,9 @@ GasLimit = 3800000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5073,6 +5148,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5188,6 +5266,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5302,6 +5383,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5413,6 +5497,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5524,6 +5611,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5638,6 +5728,9 @@ GasLimit = 11000000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5752,6 +5845,9 @@ GasLimit = 11000000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5867,6 +5963,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -5982,6 +6081,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6092,6 +6194,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6203,6 +6308,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6318,6 +6426,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6427,6 +6538,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6542,6 +6656,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6654,6 +6771,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6765,6 +6885,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6876,6 +6999,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -6986,6 +7112,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7095,6 +7224,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7210,6 +7342,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7325,6 +7460,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7434,6 +7572,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7549,6 +7690,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7664,6 +7808,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7774,6 +7921,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7884,6 +8034,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -7999,6 +8152,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8111,6 +8267,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8220,6 +8379,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8330,6 +8492,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8440,6 +8605,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8550,6 +8718,9 @@ GasLimit = 3800000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8661,6 +8832,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8776,6 +8950,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -8892,6 +9069,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9008,6 +9188,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9117,6 +9300,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9232,6 +9418,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9341,6 +9530,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9452,6 +9644,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9566,6 +9761,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9680,6 +9878,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9790,6 +9991,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -9905,6 +10109,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10022,6 +10229,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10136,6 +10346,9 @@ GasLimit = 14500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10247,6 +10460,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10361,6 +10577,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10471,6 +10690,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10581,6 +10803,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10692,6 +10917,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10809,6 +11037,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -10926,6 +11157,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11036,6 +11270,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11151,6 +11388,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11260,6 +11500,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11372,6 +11615,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11484,6 +11730,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11599,6 +11848,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11714,6 +11966,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11827,6 +12082,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -11937,6 +12195,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12047,6 +12308,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12157,6 +12421,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12267,6 +12534,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12382,6 +12652,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12496,6 +12769,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12611,6 +12887,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12720,6 +12999,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12829,6 +13111,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -12943,6 +13228,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13052,6 +13340,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13161,6 +13452,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13275,6 +13569,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13385,6 +13682,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13495,6 +13795,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13609,6 +13912,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13723,6 +14029,9 @@ GasLimit = 14500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13837,6 +14146,9 @@ GasLimit = 14500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -13953,6 +14265,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14069,6 +14384,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14180,6 +14498,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14294,6 +14615,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14408,6 +14732,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14523,6 +14850,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14638,6 +14968,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14751,6 +15084,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14861,6 +15197,9 @@ GasLimit = 10500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -14976,6 +15315,9 @@ GasLimit = 6500000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -15090,6 +15432,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -15204,6 +15549,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -15319,6 +15667,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -15429,6 +15780,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -15539,6 +15893,9 @@ GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' ```

@@ -16739,6 +17096,9 @@ GasLimit controls the gas limit for transmit transactions from ocr2automation jo FromAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example ForwarderAddress = '0x2a3e23c6f242F5345320814aC8a1b4E58707D292' # Example GasLimitDefault = 400_000 # Default +TxAcceptanceState = 2 # Default +PollPeriod = '2s' # Default +AcceptanceTimeout = '30s' # Default ``` @@ -16760,6 +17120,24 @@ GasLimitDefault = 400_000 # Default ``` GasLimitDefault is the default gas limit for workflow transactions. +### TxAcceptanceState +```toml +TxAcceptanceState = 2 # Default +``` +TxAcceptanceState is the default acceptance state for writer DON tranmissions. + +### PollPeriod +```toml +PollPeriod = '2s' # Default +``` +PollPeriod is the default poll period for checking transmission state + +### AcceptanceTimeout +```toml +AcceptanceTimeout = '30s' # Default +``` +AcceptanceTimeout is the default timeout for a tranmission to be accepted on chain + ## Cosmos ```toml [[Cosmos]] diff --git a/go.md b/go.md index 93803087082..7158e81a819 100644 --- a/go.md +++ b/go.md @@ -50,7 +50,7 @@ flowchart LR click chainlink-evm href "https://github.com/smartcontractkit/chainlink-evm" chainlink-feeds --> chainlink-common click chainlink-feeds href "https://github.com/smartcontractkit/chainlink-feeds" - chainlink-framework/capabilities + chainlink-framework/capabilities --> chainlink-common click chainlink-framework/capabilities href "https://github.com/smartcontractkit/chainlink-framework" chainlink-framework/chains --> chainlink-framework/multinode click chainlink-framework/chains href "https://github.com/smartcontractkit/chainlink-framework" @@ -191,7 +191,7 @@ flowchart LR click chainlink-evm href "https://github.com/smartcontractkit/chainlink-evm" chainlink-feeds --> chainlink-common click chainlink-feeds href "https://github.com/smartcontractkit/chainlink-feeds" - chainlink-framework/capabilities + chainlink-framework/capabilities --> chainlink-common click chainlink-framework/capabilities href "https://github.com/smartcontractkit/chainlink-framework" chainlink-framework/chains --> chainlink-framework/multinode click chainlink-framework/chains href "https://github.com/smartcontractkit/chainlink-framework" diff --git a/go.mod b/go.mod index 5af103b82bc..206e878191b 100644 --- a/go.mod +++ b/go.mod @@ -79,10 +79,11 @@ require ( github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f @@ -322,7 +323,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect diff --git a/go.sum b/go.sum index 83193af1d04..44089998ce9 100644 --- a/go.sum +++ b/go.sum @@ -1071,20 +1071,22 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e38d1784f03..dcddd83fa1e 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -47,9 +47,9 @@ require ( github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -460,8 +460,9 @@ require ( github.com/smartcontractkit/chainlink-aptos v0.0.0-20250618082928-9aa8eff952f6 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.7.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c4292ff0dbd..1f0fa1624f0 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1484,22 +1484,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 3415ae6f6a8..77f8bf8312c 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -29,9 +29,9 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.60 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-testing-framework/framework v0.9.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -449,8 +449,9 @@ require ( github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index b04a2b417f4..8d46e17bb55 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1466,22 +1466,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/system-tests/lib/cre/don/config/definitions.go b/system-tests/lib/cre/don/config/definitions.go index e682ebb4b5d..7e8f79c0efe 100644 --- a/system-tests/lib/cre/don/config/definitions.go +++ b/system-tests/lib/cre/don/config/definitions.go @@ -100,10 +100,12 @@ func WorkerEVM(donBootstrapNodePeerID, donBootstrapNodeHost string, peeringData FromAddress = '%s' ForwarderAddress = '%s' GasLimitDefault = 400_000 + TxAcceptanceState = 2 + PollPeriod = '2s' + AcceptanceTimeout = '30s' [EVM.Transactions] ForwardersEnabled = true - `, chain.ChainID, chain.Name, diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 6ed917a3671..2104310142d 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -20,9 +20,9 @@ require ( github.com/rs/zerolog v1.33.0 github.com/scylladb/go-reflectx v1.0.1 github.com/smartcontractkit/chain-selectors v1.0.60 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 github.com/smartcontractkit/chainlink-testing-framework/framework v0.9.3 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -365,8 +365,9 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.7.0 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 946e5038476..f34c5b960d9 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1240,22 +1240,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 41835b8252b..c22c9afc4e9 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -22,10 +22,10 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 + github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e github.com/smartcontractkit/chainlink-protos/job-distributor v0.11.0 github.com/smartcontractkit/chainlink-testing-framework/framework v0.9.3 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.7 @@ -437,8 +437,9 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect + github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 // indirect - github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a // indirect + github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e // indirect github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f // indirect github.com/smartcontractkit/chainlink-protos/orchestrator v0.7.0 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index a841ccc4c9b..27bda6addfb 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1440,22 +1440,24 @@ github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028 h1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250613181244-830358e67028/go.mod h1:uhUQUnJA5DkBtJ/0SuBJwD+DuwiK+kRBTyz9IlSY1k0= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed h1:rjtXQLTCLa/+AmMwMTP5WwJUdPBeBAF3Ivwc1GXetBw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250609091505-5c8cd74b92ed/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098 h1:cFdpGFQ2YhgsPBIW2CPs78OOsnL/+EOIUdE7GnaBUQo= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250616165219-db6559760098/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b h1:nS5njF5W9lY1LnTITt3V2M35dT19JPpuVg6//vlzFiU= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250618162808-a5a42ee8701b/go.mod h1:1ntZ0rtQpPx6h+xlcOJp0ccqHFaxTzW2Z62FJG358q0= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae h1:BmqiIDbA9FB/uOCOHi/shgL7P0XmjFxhfRtJHdKPLE4= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250604171706-a98fa6515eae/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1 h1:YRuzDFIbIW2zGVqzid+PhTit6dmNaexLCfv76Aney3k= github.com/smartcontractkit/chainlink-deployments-framework v0.12.1/go.mod h1:mxiSmxY5dy94jZ1j9ciu9tzdVKNjo57dYTVecbwYktg= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371 h1:IhYpVmSIfmitmTn86E/LLnd35i0j4xVUJm5qv7I65FI= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250617143435-e92bf0b88371/go.mod h1:rxElHAzSKanIEpLVtbs7ynQCiI67VmJuAgV0BGhVY4M= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e h1:QBua0Vz42fC3nwzGnaAcUwTp+EnJp5sqiUDjud1UnwE= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250618173856-d731d7e7468e/go.mod h1:GlSY0cLuXOdaZP8+7pQTezPUwJBW+ExMb5CGby4GGSU= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135/go.mod h1:NkvE4iQgiT7dMCP6U3xPELHhWhN5Xr6rHC0axRebyMU= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502 h1:WLgEB8/lIfA1vI+7O4RE/PYitO57TRkKUqVllDIgJD4= +github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250618164021-9b34289a9502/go.mod h1:Kb8f+wt2YmBdD0PfbsC9bDhdUG/Y8sqUkzAvC2Dn8/M= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0 h1:OpFlG2f+LXsDp3cejSQju2rmoNsxBlhgrwXMIsk72IA= github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250616180023-87b70c08d7c0/go.mod h1:X+a4k2a+2G2/yeAaRQMCTLmlhNdQYAeN6v+ZpLzRZww= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a h1:bFYBcW0cmhq0G8NSjPxSFfL/fVODuhEGluyWOxJTqqk= -github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250522110034-65c54665034a/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e h1:LRT+PltY99+hxZAJn+4nyTfqGVNEM1S6FJ675B9BtJo= +github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250618135814-7e3f79ab707e/go.mod h1:jo+cUqNcHwN8IF7SInQNXDZ8qzBsyMpnLdYbDswviFc= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a h1:O28vgyHM7QF1YLg1BwkQSIbOYA+t0RiH9+b+k90GPG8= github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250522110034-65c54665034a/go.mod h1:zYqPBBRUXUQ/L+aD4Q7phnYsfVeC5rDBXtPt1VYwtws= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250612182447-1c32d2efe48f h1:OYOifWMKVL54uM+sxrY7oPVTZptTXK45tA8dXN5nZSE= diff --git a/system-tests/tests/load/cre/workflow_don_load_test.go b/system-tests/tests/load/cre/workflow_don_load_test.go index 1c029663c92..5f84465712d 100644 --- a/system-tests/tests/load/cre/workflow_don_load_test.go +++ b/system-tests/tests/load/cre/workflow_don_load_test.go @@ -47,10 +47,10 @@ import ( mock_capability "github.com/smartcontractkit/chainlink/system-tests/lib/cre/mock" keystonetypes "github.com/smartcontractkit/chainlink/system-tests/lib/cre/types" libtypes "github.com/smartcontractkit/chainlink/system-tests/lib/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/llo/cre" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink-testing-framework/framework" "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" @@ -702,8 +702,8 @@ func createFeedReport(lggr logger.Logger, price decimal.Decimal, timestamp uint6 return event, eventID, nil } -func decodeTargetInput(inputs *values.Map) (targets.Request, error) { - var r targets.Request +func decodeTargetInput(inputs *values.Map) (evm.TargetRequest, error) { + var r evm.TargetRequest const signedReportField = "signed_report" signedReport, ok := inputs.Underlying[signedReportField] if !ok { diff --git a/system-tests/tests/smoke/cre/por_test.go b/system-tests/tests/smoke/cre/por_test.go index 406e2f1b3e8..3d4bfe10aa6 100644 --- a/system-tests/tests/smoke/cre/por_test.go +++ b/system-tests/tests/smoke/cre/por_test.go @@ -578,6 +578,8 @@ func setupPoRTestEnvironment( require.NoError(t, syncerErr, "failed to wait for workflow registry syncer") testLogger.Info().Msg("Proceeding to register PoR workflow...") + wtName := corevm.GenerateWriteTargetName(bo.ChainID) + workflowInput := managePoRWorkflowInput{ WorkflowConfig: in.WorkflowConfigs[idx], homeChainSelector: homeChainOutput.ChainSelector, @@ -590,7 +592,7 @@ func setupPoRTestEnvironment( deployerPrivateKey: bo.DeployerPrivateKey, creCLIAbsPath: creCLIAbsPath, creCLIsettingsFile: creCLISettingsFile, - writeTargetName: corevm.GenerateWriteTargetName(bo.ChainID), + writeTargetName: wtName, creCLIProfile: libcrecli.CRECLIProfile, } diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index 0858b3900ef..db105c17235 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -504,6 +504,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 9ad184d6437..cb7fe35b8b7 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -487,6 +487,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' 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 316d9d3f774..e6a22b15340 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -487,6 +487,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 6a7558016b9..da0b7a86496 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -487,6 +487,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' diff --git a/testdata/scripts/node/validate/fallback-override.txtar b/testdata/scripts/node/validate/fallback-override.txtar index f4bc46aa3fe..c68119f25f0 100644 --- a/testdata/scripts/node/validate/fallback-override.txtar +++ b/testdata/scripts/node/validate/fallback-override.txtar @@ -583,6 +583,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index ddd6007a8a8..2d6ca6d1602 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -477,6 +477,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake' diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 95b73764c75..f7839455094 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -484,6 +484,9 @@ GasLimit = 10500000 [EVM.Workflow] GasLimitDefault = 400000 +TxAcceptanceState = 2 +PollPeriod = '2s' +AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'fake'