Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-cl-smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
test: [
{ name: "TestE2ESmoke", config: "env.toml,env-cl-ci.toml" },
{ name: "Test(E2ESmoke|RMNCurseLaneVerifierSide|RMNGlobalCurseVerifierSide)", config: "env.toml,env-cl-ci.toml" },
]
fail-fast: false
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
working-directory: build/devenv/tests/e2e
run: |
set -o pipefail
go test -v -timeout 15m -count=1 -run 'TestE2ESmoke' -json \
go test -v -timeout 15m -count=1 -run 'Test(E2ESmoke|RMNCurseLaneVerifierSide|RMNGlobalCurseVerifierSide)' -json \
| tee test-results.json \
| jq -r '
select(.Action != null) |
Expand Down
6 changes: 6 additions & 0 deletions build/devenv/cciptestinterfaces/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ type Chains interface {
GetTokenBalance(ctx context.Context, chainSelector uint64, address, tokenAddress protocol.UnknownAddress) (*big.Int, error)
// GetMaxDataBytes gets the maximum data size for a CCIP message to a remote chain.
GetMaxDataBytes(ctx context.Context, remoteChainSelector uint64) (uint32, error)

// ApplyCurse applies a curse to the specified subjects on the given chain.
ApplyCurse(ctx context.Context, chainSelector uint64, subjects [][16]byte) error

// ApplyUncurse removes a curse from the specified subjects on the given chain.
ApplyUncurse(ctx context.Context, chainSelector uint64, subjects [][16]byte) error
Comment on lines +135 to +139
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can just be Curse and Uncurse as they are already verbs

}

// OnChainConfigurable defines methods that allows devenv to
Expand Down
123 changes: 122 additions & 1 deletion build/devenv/evm/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_0_0/operations/weth"
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_5_0/operations/token_admin_registry"
"github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment/v1_6_0/operations/rmn_remote"
rmn_remote_binding "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote"
"github.com/smartcontractkit/chainlink-ccip/deployment/v1_7_0/adapters"
"github.com/smartcontractkit/chainlink-ccip/deployment/v1_7_0/changesets"
"github.com/smartcontractkit/chainlink-ccv/devenv/cciptestinterfaces"
Expand Down Expand Up @@ -503,7 +504,7 @@ func (m *CCIP17EVM) WaitOneExecEventBySeqNo(ctx context.Context, from, to, seq u
return cciptestinterfaces.ExecutionStateChangedEvent{}, fmt.Errorf("no off ramp for selector %d", to)
}

l.Info().Msg("Awaiting ExecutionStateChanged event")
l.Info().Uint64("srcChain", from).Uint64("destChain", to).Uint64("seqNo", seq).Msg("Awaiting ExecutionStateChanged event")

for {
select {
Expand Down Expand Up @@ -1673,3 +1674,123 @@ func (m *CCIP17EVM) fundLockReleaseTokenPool(

return nil
}

// ============================================================================
// RMN Curse Operations
// ============================================================================

// getRMNRemoteAddress returns the RMN Remote contract address for a given chain.
func (m *CCIP17EVM) getRMNRemoteAddress(chainSelector uint64) (common.Address, error) {
rmnRemoteRef, err := m.e.DataStore.Addresses().Get(
datastore.NewAddressRefKey(
chainSelector,
datastore.ContractType(rmn_remote.ContractType),
rmn_remote.Version,
"",
),
)
if err != nil {
return common.Address{}, fmt.Errorf("failed to get RMN Remote address for chain %d: %w", chainSelector, err)
}
return common.HexToAddress(rmnRemoteRef.Address), nil
}

// ApplyCurse applies curses to the RMN Remote contract on a given chain.
// The subjects parameter contains the curse subjects (either chain selectors or global curse).
func (m *CCIP17EVM) ApplyCurse(ctx context.Context, chainSelector uint64, subjects [][16]byte) error {
rmnRemoteAddr, err := m.getRMNRemoteAddress(chainSelector)
if err != nil {
return err
}

ethClient, ok := m.ethClients[chainSelector]
if !ok {
return fmt.Errorf("eth client not found for chain %d", chainSelector)
}

rmnRemote, err := rmn_remote_binding.NewRMNRemote(rmnRemoteAddr, ethClient)
if err != nil {
return fmt.Errorf("failed to create RMN Remote contract binding: %w", err)
}
Comment on lines +1701 to +1714
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull this out into a private helper method getRMNRemote so that you can use from the Curse and Uncurse methods


// Get deployer key for transaction signing
txOpts := m.e.BlockChains.EVMChains()[chainSelector].DeployerKey
if txOpts == nil {
return fmt.Errorf("deployer key not found for chain %d", chainSelector)
}

// Set context for transaction

// Call Curse method
tx, err := rmnRemote.Curse0(txOpts, subjects)
if err != nil {
return fmt.Errorf("failed to call Curse on RMN Remote at %s: %w", rmnRemoteAddr.Hex(), err)
}

// Wait for transaction receipt
receipt, err := bind.WaitMined(ctx, ethClient, tx.Hash())
if err != nil {
return fmt.Errorf("failed to wait for curse transaction: %w", err)
}
if receipt.Status != types.ReceiptStatusSuccessful {
return fmt.Errorf("curse transaction failed")
}

m.logger.Info().
Uint64("chain", chainSelector).
Str("tx", tx.Hash().Hex()).
Int("numSubjects", len(subjects)).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The subjects are pertinent to this function, would be nice to see them (maybe as uint64's and not [16]byte)

Msg("Applied curse on chain")

return nil
}

// ApplyUncurse removes curses from the RMN Remote contract on a given chain.
// The subjects parameter contains the curse subjects to remove (either chain selectors or global curse).
func (m *CCIP17EVM) ApplyUncurse(ctx context.Context, chainSelector uint64, subjects [][16]byte) error {
rmnRemoteAddr, err := m.getRMNRemoteAddress(chainSelector)
if err != nil {
return err
}

ethClient, ok := m.ethClients[chainSelector]
if !ok {
return fmt.Errorf("eth client not found for chain %d", chainSelector)
}

rmnRemote, err := rmn_remote_binding.NewRMNRemote(rmnRemoteAddr, ethClient)
if err != nil {
return fmt.Errorf("failed to create RMN Remote contract binding: %w", err)
}

// Get deployer key for transaction signing
txOpts := m.e.BlockChains.EVMChains()[chainSelector].DeployerKey
if txOpts == nil {
return fmt.Errorf("deployer key not found for chain %d", chainSelector)
}

// Set context for transaction

// Call Uncurse method
tx, err := rmnRemote.Uncurse0(txOpts, subjects)
if err != nil {
return fmt.Errorf("failed to call Uncurse on RMN Remote at %s: %w", rmnRemoteAddr.Hex(), err)
}

// Wait for transaction receipt
receipt, err := bind.WaitMined(ctx, ethClient, tx.Hash())
if err != nil {
return fmt.Errorf("failed to wait for uncurse transaction: %w", err)
}
if receipt.Status != types.ReceiptStatusSuccessful {
return fmt.Errorf("uncurse transaction failed")
}

m.logger.Info().
Uint64("chain", chainSelector).
Str("tx", tx.Hash().Hex()).
Int("numSubjects", len(subjects)).
Msg("Applied uncurse on chain")

return nil
}
51 changes: 27 additions & 24 deletions build/devenv/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ require (
github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20251107170647-25947f0bb4cb
github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment v0.0.0-20251107170647-25947f0bb4cb
github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20251107170647-25947f0bb4cb
github.com/smartcontractkit/chainlink-common v0.9.6-0.20250929154511-1f5fbda7ae76
github.com/smartcontractkit/chainlink-common v0.9.6-0.20251107181740-8b842a2f1192
github.com/smartcontractkit/chainlink-deployments-framework v0.66.0
github.com/smartcontractkit/chainlink-testing-framework/framework v0.11.10
github.com/smartcontractkit/chainlink/deployment v0.0.0-20251112112310-cf52963f0878
github.com/spf13/cobra v1.10.1
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.39.0
Expand All @@ -36,7 +37,7 @@ require (
github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm v0.0.0-20251107170647-25947f0bb4cb
github.com/smartcontractkit/chainlink-ccip/ccv/chains/evm/deployment v0.0.0-20251107170647-25947f0bb4cb
github.com/smartcontractkit/chainlink-ccv v0.0.0-00010101000000-000000000000
github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20250826201006-c81344a26fc3
github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20251022075638-49d961001d1b
github.com/smartcontractkit/chainlink-protos/chainlink-ccv/go v0.0.0-20251110113103-29ff7c1d872a
github.com/smartcontractkit/chainlink-testing-framework/wasp v1.51.1
google.golang.org/grpc v1.76.0
Expand Down Expand Up @@ -79,7 +80,7 @@ require (
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/btcsuite/btcd/btcutil v1.1.6 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/btcsuite/btcutil v1.0.2 // indirect
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.14.1 // indirect
Expand Down Expand Up @@ -121,7 +122,7 @@ require (
github.com/ebitengine/purego v0.9.0 // indirect
github.com/edsrzf/mmap-go v1.2.0 // indirect
github.com/emicklei/dot v1.6.2 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/ethereum/c-kzg-4844/v2 v2.1.3 // indirect
github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect
github.com/ethereum/go-verkle v0.2.2 // indirect
Expand Down Expand Up @@ -169,9 +170,8 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
Expand All @@ -196,7 +196,7 @@ require (
github.com/hashicorp/go-metrics v0.5.4 // indirect
github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.3 // indirect
github.com/hashicorp/go-plugin v1.7.0 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
Expand Down Expand Up @@ -314,19 +314,21 @@ require (
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartcontractkit/chainlink-aptos v0.0.0-20251024142440-51f2ad2652a2 // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250908144012-8184001834b5 // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250908144012-8184001834b5 // indirect
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 // indirect
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 // indirect
github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect
github.com/smartcontractkit/chainlink-aptos v0.0.0-20251027153600-2b072ff3618e // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250912190424-fd2e35d7deb5 // indirect
github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250912190424-fd2e35d7deb5 // indirect
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20251021010742-3f8d3dba17d8 // indirect
github.com/smartcontractkit/chainlink-protos/job-distributor v0.17.0 // indirect
github.com/smartcontractkit/chainlink-sui v0.0.0-20251104205009-00bd79b81471 // indirect
github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect
github.com/smartcontractkit/chainlink-sui v0.0.0-20251105220250-f8d7f06e3b8d // indirect
github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect
github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.2 // indirect
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250908203554-5bd9d2fe9513 // indirect
github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9 // indirect
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect
github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect
github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d // indirect
github.com/smartcontractkit/libocr v0.0.0-20251031190958-7324c200a6b0 // indirect
github.com/smartcontractkit/mcms v0.30.2 // indirect
github.com/sony/gobreaker/v2 v2.1.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
Expand Down Expand Up @@ -367,7 +369,7 @@ require (
go.opentelemetry.io/collector/pipeline v0.118.0 // indirect
go.opentelemetry.io/collector/processor v0.118.0 // indirect
go.opentelemetry.io/collector/semconv v0.118.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.59.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
Expand Down Expand Up @@ -406,23 +408,24 @@ require (
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.37.0 // indirect
google.golang.org/api v0.221.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251007200510-49b9836ed3ff // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/guregu/null.v4 v4.0.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.32.2 // indirect
k8s.io/apimachinery v0.32.2 // indirect
k8s.io/client-go v0.32.2 // indirect
k8s.io/api v0.32.3 // indirect
k8s.io/apimachinery v0.33.2 // indirect
k8s.io/client-go v0.32.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

Expand Down
Loading
Loading