From 35203c5dc61791a35c6871c68b7173fe2a7e8ba7 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:48:53 +0400 Subject: [PATCH 001/136] core/capabilities/ccip/ccipaptos: add initial ccipaptos implementation --- .../ccip/ccipaptos/addresscodec.go | 69 ++++ .../ccip/ccipaptos/addresscodec_test.go | 121 ++++++ .../ccip/ccipaptos/commitcodec.go | 168 ++++++++ .../ccip/ccipaptos/commitcodec_test.go | 163 ++++++++ .../ccip/ccipaptos/executecodec.go | 343 ++++++++++++++++ .../ccip/ccipaptos/executecodec_test.go | 179 +++++++++ .../ccip/ccipaptos/extradatadecoder.go | 150 +++++++ .../ccip/ccipaptos/extradatadecoder_test.go | 110 ++++++ .../ccip/ccipaptos/gas_helpers.go | 22 ++ core/capabilities/ccip/ccipaptos/msghasher.go | 367 ++++++++++++++++++ .../ccip/ccipaptos/msghasher_test.go | 93 +++++ core/capabilities/ccip/ccipaptos/rmncrypto.go | 20 + core/capabilities/ccip/ccipaptos/tokendata.go | 18 + core/capabilities/ccip/ccipaptos/utils.go | 23 ++ 14 files changed, 1846 insertions(+) create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec.go create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder_test.go create mode 100644 core/capabilities/ccip/ccipaptos/gas_helpers.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher_test.go create mode 100644 core/capabilities/ccip/ccipaptos/rmncrypto.go create mode 100644 core/capabilities/ccip/ccipaptos/tokendata.go create mode 100644 core/capabilities/ccip/ccipaptos/utils.go diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go new file mode 100644 index 00000000000..73ee4bb79c0 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -0,0 +1,69 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" +) + +type AddressCodec struct{} + +func (a AddressCodec) AddressBytesToString(addr []byte) (string, error) { + return addressBytesToString(addr) +} + +func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { + return addressStringToBytes(addr) +} + +func addressBytesToString(addr []byte) (string, error) { + if len(addr) != 32 { + return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + + accAddress := aptos.AccountAddress(addr) + return accAddress.String(), nil +} + +func addressStringToBytes(addr string) ([]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress[:], nil +} + +func addressStringToBytes32(addr string) ([32]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress, nil +} + +func addressBytesToBytes32(addr []byte) ([32]byte, error) { + if len(addr) > 32 { + return [32]byte{}, fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + var result [32]byte + // Left pad by copying to the end of the 32 byte array + copy(result[32-len(addr):], addr) + return result, nil +} + +// takes a valid Aptos address string and converts it into canonical format. +func addressStringToString(addr string) (string, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress.String(), nil +} + +func addressIsValid(addr string) bool { + _, err := addressStringToBytes(addr) + return err == nil +} diff --git a/core/capabilities/ccip/ccipaptos/addresscodec_test.go b/core/capabilities/ccip/ccipaptos/addresscodec_test.go new file mode 100644 index 00000000000..b40c52ce522 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec_test.go @@ -0,0 +1,121 @@ +package ccipaptos + +import ( + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func generateAddressBytes32() [32]byte { + var result [32]byte + _, err := rand.Read(result[:]) + if err != nil { + panic(fmt.Sprintf("failed to generate random address bytes: %v", err)) + } + return result +} + +func generateAddressBytes() []byte { + a := generateAddressBytes32() + return a[:] +} + +func generateAddressString() string { + addressBytes := generateAddressBytes() + addressString, err := addressBytesToString(addressBytes) + if err != nil { + panic(fmt.Sprintf("failed to generate random address string: %v", err)) + } + return addressString +} + +func TestAddressBytesToString(t *testing.T) { + tests := []struct { + name string + inHex string + isErr bool + expected string + }{ + { + "empty", + "", + true, + "", + }, + { + "equal to 32 bytes", + "0102030405060102030405060102030405060102030405060102030405060101", + false, + "0x0102030405060102030405060102030405060102030405060102030405060101", + }, + { + "longer than required", + "0102030405060102030405060102030405060102030405060102030405060101FFFFFFFFFF", + true, + "", + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + bytes, err := hex.DecodeString(test.inHex) + require.NoError(t, err) + + if test.isErr { + _, err := codec.AddressBytesToString(bytes) + require.Error(t, err, fmt.Sprintf("expected error for %s, input %s", test.name, test.inHex)) + } else { + actual, err := codec.AddressBytesToString(bytes) + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } + }) + } +} + +func TestAddressStringToBytes(t *testing.T) { + tests := []struct { + name string + in string + expected []byte + expectedErr error + }{ + { + "hand crafted", + "0x0102030405060102030405060102030405060102030405060102030405060101", + []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x01, + }, + nil, + }, + { + "hand crafted error", + "invalidAddress", + nil, + errors.New("failed to decode Aptos address 'invalidAddress': invalid address"), + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual, err := codec.AddressStringToBytes(test.in) + if test.expectedErr == nil { + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go new file mode 100644 index 00000000000..0fc28059a38 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -0,0 +1,168 @@ +package ccipaptos + +import ( + "context" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. +// Compatible with ccip::offramp version 1.6.0 +type CommitPluginCodecV1 struct{} + +func NewCommitPluginCodecV1() *CommitPluginCodecV1 { + return &CommitPluginCodecV1{} +} + +func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { + s := &bcs.Serializer{} + bcs.SerializeSequenceWithFunction(report.PriceUpdates.TokenPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.TokenPrice) { + sourceToken := aptos.AccountAddress{} + err := sourceToken.ParseStringRelaxed(string(item.TokenID)) + if err != nil { + s.SetError(fmt.Errorf("failed to parse source token address: %w", err)) + return + } + s.Struct(&sourceToken) + s.U256(*item.Price.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { + s.U64(uint64(item.ChainSel)) + s.U256(*item.GasPrice.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.BlessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize BlessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.UnblessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize UnblessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.RMNSignatures, s, func(s *bcs.Serializer, item cciptypes.RMNECDSASignature) { + s.FixedBytes(item.R[:]) + s.FixedBytes(item.S[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize RMNSignatures: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptypes.CommitPluginReport, error) { + des := bcs.NewDeserializer(data) + report := cciptypes.CommitPluginReport{} + + report.PriceUpdates.TokenPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.TokenPrice) { + var sourceToken aptos.AccountAddress + des.Struct(&sourceToken) + if des.Error() != nil { + return + } + item.TokenID = cciptypes.UnknownEncodedAddress(sourceToken.String()) + price := des.U256() + if des.Error() != nil { + return + } + item.Price = cciptypes.NewBigInt(&price) + }) + + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize TokenPriceUpdates: %w", des.Error()) + } + + report.PriceUpdates.GasPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.GasPriceChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + gasPrice := des.U256() + if des.Error() != nil { + return + } + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) + } + + deserializeMerkleRootChain := func(des *bcs.Deserializer, item *cciptypes.MerkleRootChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + onRampAddrBytes := des.ReadBytes() + if des.Error() != nil { + return + } + item.OnRampAddress = onRampAddrBytes + startSeqNum := des.U64() + if des.Error() != nil { + return + } + endSeqNum := des.U64() + if des.Error() != nil { + return + } + item.SeqNumsRange = cciptypes.NewSeqNumRange(cciptypes.SeqNum(startSeqNum), cciptypes.SeqNum(endSeqNum)) + des.ReadFixedBytesInto(item.MerkleRoot[:]) + if des.Error() != nil { + return + } + } + + report.BlessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize BlessedMerkleRoots: %w", des.Error()) + } + + report.UnblessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize UnblessedMerkleRoots: %w", des.Error()) + } + + report.RMNSignatures = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RMNECDSASignature) { + des.ReadFixedBytesInto(item.R[:]) + if des.Error() != nil { + return + } + des.ReadFixedBytesInto(item.S[:]) + if des.Error() != nil { + return + } + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize RMNSignatures: %w", des.Error()) + } + + if des.Remaining() > 0 { + return cciptypes.CommitPluginReport{}, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + return report, nil +} + +// Ensure CommitPluginCodec implements the CommitPluginCodec interface +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go new file mode 100644 index 00000000000..3f05cb75d52 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -0,0 +1,163 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomCommitReport = func() cciptypes.CommitPluginReport { + return cciptypes.CommitPluginReport{ + BlessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + UnblessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + PriceUpdates: cciptypes.PriceUpdates{ + TokenPriceUpdates: []cciptypes.TokenPrice{ + { + TokenID: cciptypes.UnknownEncodedAddress(generateAddressString()), + Price: cciptypes.NewBigInt(utils.RandUint256()), + }, + }, + GasPriceUpdates: []cciptypes.GasPriceChain{ + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + }, + }, + RMNSignatures: []cciptypes.RMNECDSASignature{ + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + }, + } +} + +func TestCommitPluginCodecV1(t *testing.T) { + testCases := []struct { + name string + report func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport + expErr bool + }{ + { + name: "base report", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + return report + }, + }, + { + name: "empty token address", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].TokenID = "" + return report + }, + expErr: true, + }, + { + name: "empty merkle root", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.BlessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + report.UnblessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + return report + }, + }, + { + name: "zero token price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].Price = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + { + name: "zero gas price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.GasPriceUpdates[0].GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + report := tc.report(randomCommitReport()) + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(t) + encodedReport, err := commitCodec.Encode(ctx, report) + if tc.expErr { + assert.Error(t, err) + return + } + require.NoError(t, err) + decodedReport, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(t, err) + require.Equal(t, report, decodedReport) + }) + } +} + +func BenchmarkCommitPluginCodecV1_Encode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + + rep := randomCommitReport() + for i := 0; i < b.N; i++ { + _, err := commitCodec.Encode(ctx, rep) + require.NoError(b, err) + } +} + +func BenchmarkCommitPluginCodecV1_Decode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + encodedReport, err := commitCodec.Encode(ctx, randomCommitReport()) + require.NoError(b, err) + + for i := 0; i < b.N; i++ { + _, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(b, err) + } +} diff --git a/core/capabilities/ccip/ccipaptos/executecodec.go b/core/capabilities/ccip/ccipaptos/executecodec.go new file mode 100644 index 00000000000..62c53e21fee --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec.go @@ -0,0 +1,343 @@ +package ccipaptos + +import ( + "context" + "fmt" + "math/big" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. +// Compatible with ccip_offramp::offramp version 1.6.0 +type ExecutePluginCodecV1 struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +func NewExecutePluginCodecV1(extraDataCodec ccipcommon.ExtraDataCodec) *ExecutePluginCodecV1 { + return &ExecutePluginCodecV1{ + extraDataCodec: extraDataCodec, + } +} + +func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.ExecutePluginReport) ([]byte, error) { + if len(report.ChainReports) == 0 { + return nil, nil + } + + if len(report.ChainReports) != 1 { + return nil, fmt.Errorf("ExecutePluginCodecV1 expects exactly one ChainReport, found %d", len(report.ChainReports)) + } + + chainReport := report.ChainReports[0] + + if len(chainReport.Messages) != 1 { + return nil, fmt.Errorf("only single report message expected, got %d", len(chainReport.Messages)) + } + + if len(chainReport.OffchainTokenData) != 1 { + return nil, fmt.Errorf("only single group of offchain token data expected, got %d", len(chainReport.OffchainTokenData)) + } + + message := chainReport.Messages[0] + offchainTokenData := chainReport.OffchainTokenData[0] + + s := &bcs.Serializer{} + + // 1. source_chain_selector: u64 + s.U64(uint64(chainReport.SourceChainSelector)) + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + if len(message.Header.MessageID) != 32 { + return nil, fmt.Errorf("invalid message ID length: expected 32, got %d", len(message.Header.MessageID)) + } + s.FixedBytes(message.Header.MessageID[:]) + + // 3. header_source_chain_selector: u64 + s.U64(uint64(message.Header.SourceChainSelector)) + + // 4. dest_chain_selector: u64 + s.U64(uint64(message.Header.DestChainSelector)) + + // 5. sequence_number: u64 + s.U64(uint64(message.Header.SequenceNumber)) + + // 6. nonce: u64 + s.U64(message.Header.Nonce) + // --- End Message Header --- + + // 7. sender: vector + s.WriteBytes(message.Sender) + + // 8. data: vector + s.WriteBytes(message.Data) + + // 9. receiver: address (Aptos address, 32 bytes) + var receiverAddr aptos.AccountAddress + if err := receiverAddr.ParseStringRelaxed(message.Receiver.String()); err != nil { + return nil, fmt.Errorf("failed to parse receiver address '%s': %w", message.Receiver.String(), err) + } + s.Struct(&receiverAddr) + + // 10. gas_limit: u256 + // Extract gas limit from ExtraArgs + decodedExtraArgsMap, err := e.extraDataCodec.DecodeExtraArgs(message.ExtraArgs, chainReport.SourceChainSelector) + if err != nil { + return nil, fmt.Errorf("failed to decode ExtraArgs: %w", err) + } + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) // Use a helper to extract the gas limit + if err != nil { + return nil, fmt.Errorf("failed to extract gas limit from decoded ExtraArgs map: %w", err) + } + s.U256(*gasLimit) + + // 11. token_amounts: vector + bcs.SerializeSequenceWithFunction(message.TokenAmounts, s, func(s *bcs.Serializer, item cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + s.WriteBytes(item.SourcePoolAddress) + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + if err := destTokenAddr.ParseStringRelaxed(item.DestTokenAddress.String()); err != nil { + s.SetError(fmt.Errorf("failed to parse dest_token_address '%s': %w", item.DestTokenAddress.String(), err)) + } + s.Struct(&destTokenAddr) + + // 11c. dest_gas_amount: u32 + // Extract dest gas amount from DestExecData + destExecDataDecodedMap, err := e.extraDataCodec.DecodeTokenAmountDestExecData(item.DestExecData, chainReport.SourceChainSelector) + if err != nil { + s.SetError(fmt.Errorf("failed to decode DestExecData for token %s: %w", destTokenAddr.String(), err)) + return + } + destGasAmount, err := extractDestGasAmountFromMap(destExecDataDecodedMap) // Use a helper + if err != nil { + s.SetError(fmt.Errorf("failed to extract dest gas amount from decoded DestExecData map for token %s: %w", destTokenAddr.String(), err)) + return + } + s.U32(destGasAmount) + + // 11d. extra_data: vector + s.WriteBytes(item.ExtraData) + + // 11e. amount: u256 + if item.Amount.Int == nil { + s.SetError(fmt.Errorf("token amount is nil for token %s", destTokenAddr.String())) + return + } + s.U256(*item.Amount.Int) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during token_amounts serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize token_amounts: %w", s.Error()) + } + + // 12. offchain_token_data: vector> + bcs.SerializeSequenceWithFunction(offchainTokenData, s, func(s *bcs.Serializer, item []byte) { + s.WriteBytes(item) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during offchain_token_data serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda (though unlikely here) + return nil, fmt.Errorf("failed to serialize offchain_token_data: %w", s.Error()) + } + + // 13. proofs: vector + bcs.SerializeSequenceWithFunction(chainReport.Proofs, s, func(s *bcs.Serializer, item cciptypes.Bytes32) { + if len(item) != 32 { + s.SetError(fmt.Errorf("invalid proof length: expected 32, got %d", len(item))) + return + } + s.FixedBytes(item[:]) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during proofs serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize proofs: %w", s.Error()) + } + + // Final check and return + if s.Error() != nil { + return nil, fmt.Errorf("BCS serialization failed: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) (cciptypes.ExecutePluginReport, error) { + des := bcs.NewDeserializer(encodedReport) + report := cciptypes.ExecutePluginReport{} + var chainReport cciptypes.ExecutePluginReportSingleChain + var message cciptypes.Message + + // 1. source_chain_selector: u64 + chainReport.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize source_chain_selector: %w", des.Error()) + } + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + messageIDBytes := des.ReadFixedBytes(32) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize message_id: %w", des.Error()) + } + copy(message.Header.MessageID[:], messageIDBytes) + + // 3. header_source_chain_selector: u64 + message.Header.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize header_source_chain_selector: %w", des.Error()) + } + + // 4. dest_chain_selector: u64 + message.Header.DestChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize dest_chain_selector: %w", des.Error()) + } + + // 5. sequence_number: u64 + message.Header.SequenceNumber = cciptypes.SeqNum(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sequence_number: %w", des.Error()) + } + + // 6. nonce: u64 + message.Header.Nonce = des.U64() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize nonce: %w", des.Error()) + } + + // --- End Message Header --- + + // 7. sender: vector + message.Sender = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sender: %w", des.Error()) + } + + // 8. data: vector + message.Data = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize data: %w", des.Error()) + } + + // 9. receiver: address + var receiverAddr aptos.AccountAddress + des.Struct(&receiverAddr) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize receiver: %w", des.Error()) + } + message.Receiver = receiverAddr[:] + + // 10. gas_limit: u256 + _ = des.U256() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize gas_limit: %w", des.Error()) + } + + // 11. token_amounts: vector + message.TokenAmounts = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + item.SourcePoolAddress = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + des.Struct(&destTokenAddr) + if des.Error() != nil { + return // Error handled by caller + } + item.DestTokenAddress = destTokenAddr[:] + + // 11c. dest_gas_amount: u32 + destGasAmount := des.U32() + if des.Error() != nil { + return // Error handled by caller + } + // Encode dest gas amount back into DestExecData + destData, err := abiEncodeUint32(destGasAmount) + if err != nil { + des.SetError(fmt.Errorf("abi encode dest gas amount: %w", err)) + return + } + item.DestExecData = destData + + // 11d. extra_data: vector + item.ExtraData = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11e. amount: u256 + amountU256 := des.U256() + if des.Error() != nil { + return // Error handled by caller + } + item.Amount = cciptypes.NewBigInt(&amountU256) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize token_amounts: %w", des.Error()) + } + + // 12. offchain_token_data: vector> + offchainTokenDataGroup := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadBytes() + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize offchain_token_data: %w", des.Error()) + } + // Wrap it in the expected [][][]byte structure + chainReport.OffchainTokenData = [][][]byte{offchainTokenDataGroup} + + // 13. proofs: vector + proofsBytes := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadFixedBytes(32) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize proofs: %w", des.Error()) + } + // Convert [][]byte to [][32]byte + chainReport.Proofs = make([]cciptypes.Bytes32, len(proofsBytes)) + for i, proofB := range proofsBytes { + if len(proofB) != 32 { + // This shouldn't happen if ReadFixedBytes worked correctly + return report, fmt.Errorf("internal error: deserialized proof %d has length %d, expected 32", i, len(proofB)) + } + copy(chainReport.Proofs[i][:], proofB) + } + + // Check if all bytes were consumed + if des.Remaining() > 0 { + return report, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + // Set empty fields + message.Header.MsgHash = cciptypes.Bytes32{} + message.Header.OnRamp = cciptypes.UnknownAddress{} + message.FeeToken = cciptypes.UnknownAddress{} + message.ExtraArgs = cciptypes.Bytes{} + message.FeeTokenAmount = cciptypes.BigInt{} + + // Assemble the final report + chainReport.Messages = []cciptypes.Message{message} + // ProofFlagBits is not part of the Aptos report, initialize it empty/zero. + chainReport.ProofFlagBits = cciptypes.NewBigInt(big.NewInt(0)) + report.ChainReports = []cciptypes.ExecutePluginReportSingleChain{chainReport} + + return report, nil +} + +// Ensure ExecutePluginCodec implements the ExecutePluginCodec interface +var _ cciptypes.ExecutePluginCodec = (*ExecutePluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go new file mode 100644 index 00000000000..f4500ef679a --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -0,0 +1,179 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big.Int, destGasAmount uint32) cciptypes.ExecutePluginReport { + const numChainReports = 1 + const msgsPerReport = 1 + const numTokensPerMsg = 3 + + chainReports := make([]cciptypes.ExecutePluginReportSingleChain, numChainReports) + for i := 0; i < numChainReports; i++ { + reportMessages := make([]cciptypes.Message, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + data, err := cciptypes.NewBytesFromString(utils.RandomAddress().String()) + require.NoError(t, err) + + tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) + for z := 0; z < numTokensPerMsg; z++ { + encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + require.NoError(t, err2) + + tokenAmounts[z] = cciptypes.RampTokenAmount{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: generateAddressBytes(), + ExtraData: data, + Amount: cciptypes.NewBigInt(utils.RandUint256()), + DestExecData: encodedDestExecData, + } + } + + extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + if err != nil { + t.Fatalf("failed to pack extra args: %v", err) + } + extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + + reportMessages[j] = cciptypes.Message{ + Header: cciptypes.RampMessageHeader{ + MessageID: utils.RandomBytes32(), + SourceChainSelector: cciptypes.ChainSelector(rand.Uint64()), + DestChainSelector: cciptypes.ChainSelector(rand.Uint64()), + SequenceNumber: cciptypes.SeqNum(rand.Uint64()), + Nonce: rand.Uint64(), + MsgHash: utils.RandomBytes32(), + OnRamp: utils.RandomAddress().Bytes(), + }, + Sender: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + Data: data, + Receiver: generateAddressBytes(), + ExtraArgs: extraArgs, + FeeToken: generateAddressBytes(), + FeeTokenAmount: cciptypes.NewBigInt(utils.RandUint256()), + TokenAmounts: tokenAmounts, + } + } + + tokenData := make([][][]byte, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + tokenData[j] = [][]byte{{0x1}, {0x2, 0x3}} + } + + chainReports[i] = cciptypes.ExecutePluginReportSingleChain{ + SourceChainSelector: cciptypes.ChainSelector(chainSelector), + Messages: reportMessages, + OffchainTokenData: tokenData, + Proofs: []cciptypes.Bytes32{utils.RandomBytes32(), utils.RandomBytes32()}, + ProofFlagBits: cciptypes.NewBigInt(big.NewInt(0)), + } + } + + return cciptypes.ExecutePluginReport{ChainReports: chainReports} +} + +func TestExecutePluginCodecV1(t *testing.T) { + ctx := testutils.Context(t) + mockExtraDataCodec := &mocks.ExtraDataCodec{} + destGasAmount := rand.Uint32() + gasLimit := utils.RandUint256() + mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + "destgasamount": destGasAmount, + }, nil) + mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + "gasLimit": utils.RandUint256(), + "accountIsWritableBitmap": gasLimit, + }, nil) + + testCases := []struct { + name string + report func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport + expErr bool + chainSelector uint64 + destGasAmount uint32 + gasLimit *big.Int + }{ + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 124615329519749607, // Solana mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty msgs", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].Messages = []cciptypes.Message{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty offchain token data", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].OffchainTokenData = [][][]byte{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + codec := NewExecutePluginCodecV1(mockExtraDataCodec) + report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) + bytes, err := codec.Encode(ctx, report) + if tc.expErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + // ignore unavailable fields in comparison + for i := range report.ChainReports { + for j := range report.ChainReports[i].Messages { + report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} + report.ChainReports[i].Messages[j].Header.OnRamp = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].FeeToken = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].ExtraArgs = cciptypes.Bytes{} + report.ChainReports[i].Messages[j].FeeTokenAmount = cciptypes.BigInt{} + } + } + + // decode using the codec + codecDecoded, err := codec.Decode(ctx, bytes) + require.NoError(t, err) + require.Equal(t, report, codecDecoded) + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go new file mode 100644 index 00000000000..5c600f266bd --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -0,0 +1,150 @@ +package ccipaptos + +import ( + "fmt" + "reflect" + + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +// ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder +// Compatible with ccip::fee_quoter version 1.6.0 +type ExtraDataDecoder struct{} + +const ( + aptosDestExecDataKey = "destGasAmount" +) + +var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) + +var ( + // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") + + // bytes4 public constant GENERIC_EXTRA_ARGS_V2_TAG = 0x181dcf10; + genericExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") + + // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba + svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") +) + +// DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data +func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { + destGasAmount, err := abiDecodeUint32(destExecData) + if err != nil { + return nil, fmt.Errorf("decode dest gas amount: %w", err) + } + + return map[string]any{ + aptosDestExecDataKey: destGasAmount, + }, nil +} + +// DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args +func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { + if len(extraArgs) < 4 { + return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) + } + + var method string + var argName string + switch string(extraArgs[:4]) { + case string(evmExtraArgsV1Tag): + method = "exposeEVMExtraArgsV1" + argName = "evmExtraArgsV1" + case string(genericExtraArgsV2Tag): + method = "exposeGenericExtraArgsV2" + argName = "evmExtraArgsV2" + case string(svmExtraArgsV1Tag): + method = "exposeSVMExtraArgsV1" + argName = "svmExtraArgsV1" + default: + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + } + + output := make(map[string]any) + args := make(map[string]any) + err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + if err != nil { + return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + } + + argValue, exists := args[argName] + if !exists { + return nil, fmt.Errorf("failed to get arg value for %s", argName) + } + + val := reflect.ValueOf(argValue) + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) + } + + switch argName { + case "evmExtraArgsV1": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + case "evmExtraArgsV2": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + case "svmExtraArgsV1": + computeUnitsField := val.FieldByName("ComputeUnits") + if computeUnitsField.IsValid() { + output["computeUnits"] = computeUnitsField.Interface() + } else { + output["computeUnits"] = nil + } + + bitmapField := val.FieldByName("AccountIsWritableBitmap") + if bitmapField.IsValid() { + output["accountIsWritableBitmap"] = bitmapField.Interface() + } else { + output["accountIsWritableBitmap"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + + tokenReceiverField := val.FieldByName("TokenReceiver") + if tokenReceiverField.IsValid() { + output["tokenReceiver"] = tokenReceiverField.Interface() + } else { + output["tokenReceiver"] = nil + } + + accountsField := val.FieldByName("Accounts") + if accountsField.IsValid() { + output["accounts"] = accountsField.Interface() + } else { + output["accounts"] = nil + } + } + return output, nil +} + +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go new file mode 100644 index 00000000000..234d2f29981 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -0,0 +1,110 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +func Test_decodeExtraData(t *testing.T) { + gasLimit := big.NewInt(rand.Int63()) + extraDataDecoder := &ExtraDataDecoder{} + + t.Run("decode extra args into map evm v1", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + }) + + t.Run("decode extra args into map evm v2", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ + GasLimit: gasLimit, + AllowOutOfOrderExecution: true, + }) + encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 2) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + + ooe, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, true, ooe) + }) + + t.Run("decode extra args into map svm", func(t *testing.T) { + key, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + cu := uint32(10000) + bitmap := uint64(4) + ooe := false + tokenReceiver := [32]byte(key.PublicKey().Bytes()) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} + encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ + ComputeUnits: cu, + AccountIsWritableBitmap: bitmap, + AllowOutOfOrderExecution: ooe, + TokenReceiver: tokenReceiver, + Accounts: accounts, + }) + encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 5) + + cuDecoded, exist := m["computeUnits"] + require.True(t, exist) + require.Equal(t, cuDecoded, cu) + + bitmapDecoded, exist := m["accountIsWritableBitmap"] + require.True(t, exist) + require.Equal(t, bitmapDecoded, bitmap) + + ooeDecoded, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, ooeDecoded, ooe) + + tokenReceiverDecoded, exist := m["tokenReceiver"] + require.True(t, exist) + require.Equal(t, tokenReceiverDecoded, tokenReceiver) + + accountsDecoded, exist := m["accounts"] + require.True(t, exist) + require.Equal(t, accountsDecoded, accounts) + }) + + t.Run("decode dest exec data into map", func(t *testing.T) { + destGasAmount := uint32(10000) + encoded, err := abiEncodeUint32(destGasAmount) + require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + decoded, exist := m[aptosDestExecDataKey] + require.True(t, exist) + require.Equal(t, destGasAmount, decoded) + }) +} diff --git a/core/capabilities/ccip/ccipaptos/gas_helpers.go b/core/capabilities/ccip/ccipaptos/gas_helpers.go new file mode 100644 index 00000000000..7f3922e5c6c --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/gas_helpers.go @@ -0,0 +1,22 @@ +package ccipaptos + +import ( + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +func NewGasEstimateProvider() EstimateProvider { + return EstimateProvider{} +} + +type EstimateProvider struct { +} + +// CalculateMerkleTreeGas is not implemented +func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { + return 0 +} + +// CalculateMessageMaxGas is not implemented. +func (gp EstimateProvider) CalculateMessageMaxGas(msg cciptypes.Message) uint64 { + return 0 +} diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go new file mode 100644 index 00000000000..995e7e0112e --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -0,0 +1,367 @@ +package ccipaptos + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink-ccip/pkg/logutil" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +var ( + // const LEAF_DOMAIN_SEPARATOR: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; + leafDomainSeparator = [32]byte{} + + // see aptos_hash::keccak256(b"Any2AptosMessageHashV1") in calculate_metadata_hash + any2AptosMessageHash = utils.Keccak256Fixed([]byte("Any2AptosMessageHashV1")) +) + +// MessageHasherV1 implements the MessageHasher interface. +// Compatible with ccip::offramp version 1.6.0 +type MessageHasherV1 struct { + lggr logger.Logger + extraDataCodec ccipcommon.ExtraDataCodec +} + +type any2AptosTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int +} + +func NewMessageHasherV1(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) *MessageHasherV1 { + return &MessageHasherV1{ + lggr: lggr, + extraDataCodec: extraDataCodec, + } +} + +// Hash implements the MessageHasher interface. +// It constructs all of the inputs to the final keccak256 hash in Internal._hash(Any2EVMRampMessage). +// The main structure of the hash is as follows: +// Fixed-size message fields are included in nested hash to reduce stack pressure. +// This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. +func (h *MessageHasherV1) Hash(ctx context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) { + lggr := logutil.WithContextValues(ctx, h.lggr) + lggr = logger.With( + lggr, + "msgID", msg.Header.MessageID.String(), + "ANY_2_APTOS_MESSAGE_HASH", hexutil.Encode(any2AptosMessageHash[:]), + "onrampAddress", msg.Header.OnRamp, + ) + lggr.Debugw("hashing message", "msg", msg) + + rampTokenAmounts := make([]any2AptosTokenTransfer, len(msg.TokenAmounts)) + for _, rta := range msg.TokenAmounts { + destGasAmount, err := abiDecodeUint32(rta.DestExecData) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest gas amount: %w", err) + } + + lggr.Debugw("decoded dest gas amount", + "destGasAmount", destGasAmount) + + destTokenAddress, err := addressBytesToBytes32(rta.DestTokenAddress) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest token address: %w", err) + } + + lggr.Debugw("abi decoded dest token address", + "destTokenAddress", destTokenAddress) + + rampTokenAmounts = append(rampTokenAmounts, any2AptosTokenTransfer{ + SourcePoolAddress: rta.SourcePoolAddress, + DestTokenAddress: destTokenAddress, + DestGasAmount: destGasAmount, + ExtraData: rta.ExtraData, + Amount: rta.Amount.Int, + }) + } + + // one difference from EVM is that we don't left pad the OnRamp to 32 bytes here, we use the source chain's canonical bytes encoding directly. + metaDataHashInput, err := computeMetadataHash(uint64(msg.Header.SourceChainSelector), uint64(msg.Header.DestChainSelector), msg.Header.OnRamp) + if err != nil { + return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) + } + + lggr.Debugw("metadata hash preimage", + "metaDataHashInput", hexutil.Encode(metaDataHashInput[:])) + + // Need to decode the extra args to get the gas limit. + // TODO: we assume that extra args is always abi-encoded for now, but we need + // to decode according to source chain selector family. We should add a family + // lookup API to the chain-selectors library. + + decodedExtraArgsMap, err := h.extraDataCodec.DecodeExtraArgs(msg.ExtraArgs, msg.Header.SourceChainSelector) + if err != nil { + return [32]byte{}, err + } + + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) + if err != nil { + return [32]byte{}, fmt.Errorf("decode extra args to get gas limit: %w", err) + } + + lggr.Debugw("decoded msg gas limit", "gasLimit", gasLimit) + + receiverAddress, err := addressBytesToBytes32(msg.Receiver) + if err != nil { + return [32]byte{}, err + } + + msgHash, err := computeMessageDataHash(metaDataHashInput, msg.Header.MessageID, receiverAddress, uint64(msg.Header.SequenceNumber), gasLimit, msg.Header.Nonce, msg.Sender, msg.Data, rampTokenAmounts) + if err != nil { + return [32]byte{}, err + } + + lggr.Debugw("final message hash result", + "msgHash", hexutil.Encode(msgHash[:]), + ) + + return msgHash, nil +} + +// This is the equivalent of offramp::calculate_message_hash. +// This is very similar to the EVM version, except for 32-byte addresses: +// +// bytes32 messageDataHash = keccak256( +// abi.encode( +// LEAF_DOMAIN_SEPARATOR, +// metadataHash, +// keccak256( +// abi.encode( +// original.header.originalId, +// original.receiver, +// original.header.sequenceNumber, +// original.gasLimit, +// original.header.nonce +// ) +// ), +// keccak256(original.sender), +// keccak256(original.data), +// keccak256(abi.encode(original.tokenAmounts)) +// ) +// ); +func computeMessageDataHash( + metadataHash [32]byte, + messageID [32]byte, + receiver [32]byte, + sequenceNumber uint64, + gasLimit *big.Int, + nonce uint64, + sender []byte, + data []byte, + tokenAmounts []any2AptosTokenTransfer, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + uint256Type, err := abi.NewType("uint256", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint256 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + headerArgs := abi.Arguments{ + {Type: bytes32Type}, // messageID + {Type: bytes32Type}, // receiver as bytes32 + {Type: uint64Type}, // sequenceNumber + {Type: uint256Type}, // gasLimit + {Type: uint64Type}, // nonce + } + headerEncoded, err := headerArgs.Pack( + messageID, + receiver, + sequenceNumber, + gasLimit, + nonce, + ) + if err != nil { + return [32]byte{}, err + } + headerHash := crypto.Keccak256Hash(headerEncoded) + + senderHash := crypto.Keccak256Hash(sender) + + dataHash := crypto.Keccak256Hash(data) + + type tokenTuple struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int + } + tokens := make([]tokenTuple, len(tokenAmounts)) + for i, token := range tokenAmounts { + tokens[i] = tokenTuple{ + SourcePoolAddress: token.SourcePoolAddress, + DestTokenAddress: token.DestTokenAddress, + DestGasAmount: token.DestGasAmount, + ExtraData: token.ExtraData, + Amount: token.Amount, + } + } + + // Manually encode tokens to match the Move implementation, because abi.Pack has different behavior + // for dynamic types. + var tokenHashData []byte + tokenHashData = append(tokenHashData, encodeUint256(big.NewInt(int64(len(tokens))))...) + for _, token := range tokens { + tokenHashData = append(tokenHashData, encodeBytes(token.SourcePoolAddress)...) + tokenHashData = append(tokenHashData, token.DestTokenAddress[:]...) + tokenHashData = append(tokenHashData, encodeUint32(token.DestGasAmount)...) + tokenHashData = append(tokenHashData, encodeBytes(token.ExtraData)...) + tokenHashData = append(tokenHashData, encodeUint256(token.Amount)...) + } + tokenAmountsHash := crypto.Keccak256Hash(tokenHashData) + + finalArgs := abi.Arguments{ + {Type: bytes32Type}, // LEAF_DOMAIN_SEPARATOR + {Type: bytes32Type}, // metadataHash + {Type: bytes32Type}, // headerHash + {Type: bytes32Type}, // senderHash + {Type: bytes32Type}, // dataHash + {Type: bytes32Type}, // tokenAmountsHash + } + + finalEncoded, err := finalArgs.Pack( + leafDomainSeparator, + metadataHash, + headerHash, + senderHash, + dataHash, + tokenAmountsHash, + ) + if err != nil { + return [32]byte{}, err + } + + return crypto.Keccak256Hash(finalEncoded), nil +} + +// ComputeMetadataHash calculates the metadataHash as per offramp::calculate_metadata_hash +// This is the same as the EVM version minus the separator: +// +// bytes32 metaDataHash = keccak256( +// abi.encode( +// Internal.ANY_2_APTOS_MESSAGE_HASH, +// sourceChainSelector, +// i_chainSelector, +// keccak256(_getEnabledSourceChainConfig(sourceChainSelector).onRamp) +// ) +// ); +func computeMetadataHash( + sourceChainSelector uint64, + destinationChainSelector uint64, + onRamp []byte, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + onRampHash := crypto.Keccak256Hash(onRamp) + + args := abi.Arguments{ + {Type: bytes32Type}, // ANY_2_APTOS_MESSAGE_HASH + {Type: uint64Type}, // sourceChainSelector + {Type: uint64Type}, // destinationChainSelector (i_chainSelector) + {Type: bytes32Type}, // onRamp + } + + encoded, err := args.Pack( + any2AptosMessageHash, + sourceChainSelector, + destinationChainSelector, + onRampHash, + ) + if err != nil { + return [32]byte{}, err + } + + metadataHash := crypto.Keccak256Hash(encoded) + return metadataHash, nil +} + +func encodeUint256(n *big.Int) []byte { + return common.LeftPadBytes(n.Bytes(), 32) +} + +func encodeUint32(n uint32) []byte { + return common.LeftPadBytes(new(big.Int).SetUint64(uint64(n)).Bytes(), 32) +} + +func encodeBytes(b []byte) []byte { + encodedLength := common.LeftPadBytes(big.NewInt(int64(len(b))).Bytes(), 32) + padLen := (32 - (len(b) % 32)) % 32 + result := make([]byte, 32+len(b)+padLen) + copy(result[:32], encodedLength) + copy(result[32:], b) + return result +} + +func parseExtraDataMap(input map[string]any) (*big.Int, error) { + var outputGas *big.Int + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "gaslimit": + // Expect [][32]byte + if val, ok := fieldValue.(*big.Int); ok { + outputGas = val + return outputGas, nil + } + return nil, fmt.Errorf("unexpected type for gas limit: %T", fieldValue) + default: + // no error here, as we only need the keys to gasLimit, other keys can be skipped without like AllowOutOfOrderExecution etc. + } + } + return outputGas, errors.New("gas limit not found in extra data map") +} + +func extractDestGasAmountFromMap(input map[string]any) (uint32, error) { + // Iterate through the expected fields in the struct + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "destgasamount": + // Expect uint32 + if val, ok := fieldValue.(uint32); ok { + return val, nil + } + return 0, errors.New("invalid type for destgasamount, expected uint32") + default: + } + } + + return 0, errors.New("invalid token message, dest gas amount not found in the DestExecDataDecoded map") +} + +// Interface compliance check +var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/msghasher_test.go b/core/capabilities/ccip/ccipaptos/msghasher_test.go new file mode 100644 index 00000000000..fa06a9fb2b7 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher_test.go @@ -0,0 +1,93 @@ +package ccipaptos + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_message_hash +func TestComputeMessageDataHash(t *testing.T) { + expectedHashStr := "0xc8d6cf666864a60dd6ecd89e5c294734c53b3218d3f83d2d19a3c3f9e200e00d" + + metadataHashBytes, err := hexutil.Decode("0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899") + require.NoError(t, err) + var metadataHash [32]byte + copy(metadataHash[:], metadataHashBytes) + + messageIDBytes, err := hexutil.Decode("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + require.NoError(t, err) + var messageID [32]byte + copy(messageID[:], messageIDBytes) + + receiverBytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000001234") + require.NoError(t, err) + var receiver [32]byte + copy(receiver[:], receiverBytes) + + sequenceNumber := uint64(42) + nonce := uint64(123) + gasLimit := big.NewInt(500000) + + sender, err := hexutil.Decode("0x8765432109fedcba8765432109fedcba87654321") + require.NoError(t, err) + + data := []byte("sample message data") + srcPool1, err := hexutil.Decode("0xabcdef1234567890abcdef1234567890abcdef12") + require.NoError(t, err) + destToken1Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000005678") + require.NoError(t, err) + var destToken1 [32]byte + copy(destToken1[:], destToken1Bytes) + extraData1, err := hexutil.Decode("0x00112233") + require.NoError(t, err) + token1 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool1, + DestTokenAddress: destToken1, + DestGasAmount: 10000, + ExtraData: extraData1, + Amount: big.NewInt(1000000), + } + srcPool2, err := hexutil.Decode("0x123456789abcdef123456789abcdef123456789a") + require.NoError(t, err) + destToken2Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000009abc") + require.NoError(t, err) + var destToken2 [32]byte + copy(destToken2[:], destToken2Bytes) + extraData2, err := hexutil.Decode("0xffeeddcc") + require.NoError(t, err) + token2 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool2, + DestTokenAddress: destToken2, + DestGasAmount: 20000, + ExtraData: extraData2, + Amount: big.NewInt(5000000), + } + + tokens := []any2AptosTokenTransfer{token1, token2} + + computedHash, err := computeMessageDataHash(metadataHash, messageID, receiver, sequenceNumber, gasLimit, nonce, sender, data, tokens) + require.NoError(t, err) + + require.Equal(t, expectedHashStr, hexutil.Encode(computedHash[:]), "Computed hash does not match expected hash") +} + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_metadata_hash +func TestComputeMetadataHash(t *testing.T) { + expectedHashStr := "0x812acb01df318f85be452cf6664891cf5481a69dac01e0df67102a295218dd17" + expectedHashAlternateStr := "0x6caf8756ae02ee4f12b83b38e0f21b5e43e90d203bd06729486fd4a0fc8bcc5e" + + sourceChainSelector := uint64(123456789) + destinationChainSelector := uint64(987654321) + onRamp := []byte("source-onramp-address") + + metadataHash, err := computeMetadataHash(sourceChainSelector, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashStr, hexutil.Encode(metadataHash[:]), "Computed hash does not match expected hash") + + metadataHashAlternate, err := computeMetadataHash(sourceChainSelector+1, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashAlternateStr, hexutil.Encode(metadataHashAlternate[:]), "Alternate computed hash does not match expected alternate hash") +} diff --git a/core/capabilities/ccip/ccipaptos/rmncrypto.go b/core/capabilities/ccip/ccipaptos/rmncrypto.go new file mode 100644 index 00000000000..986ebe90f36 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/rmncrypto.go @@ -0,0 +1,20 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// AptosRMNCrypto is the RMNCrypto implementation for Aptos chains. +type AptosRMNCrypto struct{} + +func (r *AptosRMNCrypto) VerifyReportSignatures( + _ context.Context, + _ []cciptypes.RMNECDSASignature, + _ cciptypes.RMNReport, + _ []cciptypes.UnknownAddress, +) error { + return errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/tokendata.go b/core/capabilities/ccip/ccipaptos/tokendata.go new file mode 100644 index 00000000000..4f18399c5f6 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/tokendata.go @@ -0,0 +1,18 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +type AptosTokenDataEncoder struct{} + +func NewAptosTokenDataEncoder() AptosTokenDataEncoder { + return AptosTokenDataEncoder{} +} + +func (e AptosTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) { + return nil, errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go new file mode 100644 index 00000000000..5488f3903d2 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -0,0 +1,23 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +func abiEncodeUint32(data uint32) ([]byte, error) { + return utils.ABIEncode(`[{ "type": "uint32" }]`, data) +} + +func abiDecodeUint32(data []byte) (uint32, error) { + raw, err := utils.ABIDecode(`[{ "type": "uint32" }]`, data) + if err != nil { + return 0, fmt.Errorf("abi decode uint32: %w", err) + } + + val := *abi.ConvertType(raw[0], new(uint32)).(*uint32) + return val, nil +} From eec2ee63d9dd261f407a78fd0570c6e9b0713249 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:49:14 +0400 Subject: [PATCH 002/136] core/capabilities/ccip/common/addresscodec.go: add aptos address codec --- .../ccip/ccipaptos/addresscodec.go | 44 +++++++++---------- core/capabilities/ccip/common/addresscodec.go | 12 ++++- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go index 73ee4bb79c0..6297b220279 100644 --- a/core/capabilities/ccip/ccipaptos/addresscodec.go +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -1,9 +1,9 @@ package ccipaptos import ( + "encoding/hex" "fmt" - - "github.com/aptos-labs/aptos-go-sdk" + "strings" ) type AddressCodec struct{} @@ -17,30 +17,30 @@ func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { } func addressBytesToString(addr []byte) (string, error) { - if len(addr) != 32 { - return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + if len(addr) < 1 || len(addr) > 32 { + return "", fmt.Errorf("invalid Aptos address length (%d)", len(addr)) } - accAddress := aptos.AccountAddress(addr) - return accAddress.String(), nil + return fmt.Sprintf("0x%064x", addr), nil } func addressStringToBytes(addr string) ([]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) - if err != nil { - return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + a := strings.TrimPrefix(addr, "0x") + if len(a) == 0 { + return nil, fmt.Errorf("invalid Aptos address length, expected at least 1 character: %s", addr) + } + if len(a) > 64 { + return nil, fmt.Errorf("invalid Aptos address length, expected at most 64 characters: %s", addr) + } + for len(a) < 64 { + a = "0" + a } - return accAddress[:], nil -} -func addressStringToBytes32(addr string) ([32]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) + bytes, err := hex.DecodeString(a) if err != nil { - return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) } - return accAddress, nil + return bytes, nil } func addressBytesToBytes32(addr []byte) ([32]byte, error) { @@ -53,14 +53,12 @@ func addressBytesToBytes32(addr []byte) ([32]byte, error) { return result, nil } -// takes a valid Aptos address string and converts it into canonical format. -func addressStringToString(addr string) (string, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) +func addressStringToBytes32(addr string) ([32]byte, error) { + bytes, err := addressStringToBytes(addr) if err != nil { - return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return [32]byte{}, err } - return accAddress.String(), nil + return addressBytesToBytes32(bytes) } func addressIsValid(addr string) bool { diff --git a/core/capabilities/ccip/common/addresscodec.go b/core/capabilities/ccip/common/addresscodec.go index 3440ec4c391..b72666b906f 100644 --- a/core/capabilities/ccip/common/addresscodec.go +++ b/core/capabilities/ccip/common/addresscodec.go @@ -18,19 +18,22 @@ type ChainSpecificAddressCodec interface { type AddressCodec struct { EVMAddressCodec ChainSpecificAddressCodec SolanaAddressCodec ChainSpecificAddressCodec + AptosAddressCodec ChainSpecificAddressCodec } // AddressCodecParams is a struct that holds the parameters for creating a AddressCodec type AddressCodecParams struct { evmAddressCodec ChainSpecificAddressCodec solanaAddressCodec ChainSpecificAddressCodec + aptosAddressCodec ChainSpecificAddressCodec } // NewAddressCodecParams is a constructor for AddressCodecParams -func NewAddressCodecParams(evmAddressCodec ChainSpecificAddressCodec, solanaAddressCodec ChainSpecificAddressCodec) AddressCodecParams { +func NewAddressCodecParams(evmAddressCodec ChainSpecificAddressCodec, solanaAddressCodec ChainSpecificAddressCodec, aptosAddressCodec ChainSpecificAddressCodec) AddressCodecParams { return AddressCodecParams{ evmAddressCodec: evmAddressCodec, solanaAddressCodec: solanaAddressCodec, + aptosAddressCodec: aptosAddressCodec, } } @@ -39,6 +42,7 @@ func NewAddressCodec(params AddressCodecParams) AddressCodec { return AddressCodec{ EVMAddressCodec: params.evmAddressCodec, SolanaAddressCodec: params.solanaAddressCodec, + AptosAddressCodec: params.aptosAddressCodec, } } @@ -56,6 +60,9 @@ func (ac AddressCodec) AddressBytesToString(addr cciptypes.UnknownAddress, chain case chainsel.FamilySolana: return ac.SolanaAddressCodec.AddressBytesToString(addr) + case chainsel.FamilyAptos: + return ac.AptosAddressCodec.AddressBytesToString(addr) + default: return "", fmt.Errorf("unsupported family for address encode type %s", family) } @@ -75,6 +82,9 @@ func (ac AddressCodec) AddressStringToBytes(addr string, chainSelector cciptypes case chainsel.FamilySolana: return ac.SolanaAddressCodec.AddressStringToBytes(addr) + case chainsel.FamilyAptos: + return ac.AptosAddressCodec.AddressStringToBytes(addr) + default: return nil, fmt.Errorf("unsupported family for address decode type %s", family) } From c682b39575a2875c6d6ca234e94d30b44c203b68 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:49:28 +0400 Subject: [PATCH 003/136] core/capabilities/ccip/delegate.go: initialize with aptos address codec --- core/capabilities/ccip/delegate.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 1b15180da0d..05e016f5514 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -9,6 +9,7 @@ import ( "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" @@ -210,6 +211,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services common.NewAddressCodecParams( ccipevm.AddressCodec{}, ccipsolana.AddressCodec{}, + ccipaptos.AddressCodec{}, )) // if bootstrappers are provided we assume that the node is a plugin oracle. From adc9b9993f09150b0bfb909c562111b2a839c26c Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:20 +0400 Subject: [PATCH 004/136] core/capabilities/ccip/ccipevm/executecodec_test.go: initialize extra data codec with aptos decoder --- core/capabilities/ccip/ccipevm/executecodec_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go index db0619ca58f..1b57b750c83 100644 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ b/core/capabilities/ccip/ccipevm/executecodec_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" @@ -227,7 +228,7 @@ func TestExecutePluginCodecV1(t *testing.T) { } func Test_DecodeReport(t *testing.T) { - ExtraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) + ExtraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) offRampABI, err := offramp.OffRampMetaData.GetAbi() require.NoError(t, err) From ede855b4af0c53005452f7925cc2e53964ed9b65 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:40 +0400 Subject: [PATCH 005/136] core/capabilities/ccip/common/extradatacodec.go: add Aptos --- core/capabilities/ccip/common/extradatacodec.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/common/extradatacodec.go b/core/capabilities/ccip/common/extradatacodec.go index 33f209f6e4c..3382d46415e 100644 --- a/core/capabilities/ccip/common/extradatacodec.go +++ b/core/capabilities/ccip/common/extradatacodec.go @@ -26,19 +26,22 @@ type ExtraDataDecoder interface { type RealExtraDataCodec struct { EVMExtraDataDecoder ExtraDataDecoder SolanaExtraDataDecoder ExtraDataDecoder + AptosExtraDataDecoder ExtraDataDecoder } // ExtraDataCodecParams is a struct that holds the parameters for creating a RealExtraDataCodec type ExtraDataCodecParams struct { evmExtraDataDecoder ExtraDataDecoder solanaExtraDataDecoder ExtraDataDecoder + aptosExtraDataDecoder ExtraDataDecoder } // NewExtraDataCodecParams is a constructor for ExtraDataCodecParams -func NewExtraDataCodecParams(evmDecoder ExtraDataDecoder, solanaDecoder ExtraDataDecoder) ExtraDataCodecParams { +func NewExtraDataCodecParams(evmDecoder ExtraDataDecoder, solanaDecoder ExtraDataDecoder, aptosDecoder ExtraDataDecoder) ExtraDataCodecParams { return ExtraDataCodecParams{ evmExtraDataDecoder: evmDecoder, solanaExtraDataDecoder: solanaDecoder, + aptosExtraDataDecoder: aptosDecoder, } } @@ -47,6 +50,7 @@ func NewExtraDataCodec(params ExtraDataCodecParams) RealExtraDataCodec { return RealExtraDataCodec{ EVMExtraDataDecoder: params.evmExtraDataDecoder, SolanaExtraDataDecoder: params.solanaExtraDataDecoder, + AptosExtraDataDecoder: params.aptosExtraDataDecoder, } } @@ -69,6 +73,9 @@ func (c RealExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceCha case chainsel.FamilySolana: return c.SolanaExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + case chainsel.FamilyAptos: + return c.AptosExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) } @@ -93,6 +100,9 @@ func (c RealExtraDataCodec) DecodeTokenAmountDestExecData(destExecData cciptypes case chainsel.FamilySolana: return c.SolanaExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + case chainsel.FamilyAptos: + return c.AptosExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) } From 060b1c2e822c27e4efe481825370ee6521d8c1d7 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:54 +0400 Subject: [PATCH 006/136] core/capabilities/ccip/oraclecreator/plugin.go: initialize extra data codec with Aptos decoder --- core/capabilities/ccip/oraclecreator/plugin.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index f510eb6cce0..336b5f89541 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" @@ -59,6 +60,7 @@ var extraDataCodec = ccipcommon.NewExtraDataCodec( ccipcommon.NewExtraDataCodecParams( ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, + ccipaptos.ExtraDataDecoder{}, ), ) From 56abcadbeacecd768dc62c9201e64c457fec443e Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:49:11 +0400 Subject: [PATCH 007/136] core/capabilities/ccip/ccipevm/msghasher_test.go: initialize extra data codec with Aptos decoder --- core/capabilities/ccip/ccipevm/msghasher_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go index 1dd329563dd..c5493a388a1 100644 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ b/core/capabilities/ccip/ccipevm/msghasher_test.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" @@ -39,7 +40,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) +var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) // NOTE: these test cases are only EVM <-> EVM. // Update these cases once we have non-EVM examples. From 51a413894ce8430e9a99e3bc1d5110bab9fbb667 Mon Sep 17 00:00:00 2001 From: cfal Date: Thu, 27 Feb 2025 15:03:30 +0400 Subject: [PATCH 008/136] .changeset/warm-toys-give.md: add changeset --- .changeset/warm-toys-give.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/warm-toys-give.md diff --git a/.changeset/warm-toys-give.md b/.changeset/warm-toys-give.md new file mode 100644 index 00000000000..32417a44c80 --- /dev/null +++ b/.changeset/warm-toys-give.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +add support for Aptos CCIP #added + From 8c15dfcf3136885e7b0f18a2aad98dcc6d692169 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 16 Apr 2025 01:24:00 +0400 Subject: [PATCH 009/136] core/capabilities/ccip/ccipaptos: update for contract changes, dont depend on generated bindings --- .../ccip/ccipaptos/commitcodec.go | 38 +++- .../ccip/ccipaptos/executecodec_test.go | 39 ++-- .../ccip/ccipaptos/extradatadecoder.go | 181 +++++++++++------- .../ccip/ccipaptos/extradatadecoder_test.go | 106 +++++++--- 4 files changed, 243 insertions(+), 121 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go index 0fc28059a38..8dbd9f4550e 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -3,6 +3,7 @@ package ccipaptos import ( "context" "fmt" + "math/big" "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" @@ -14,6 +15,8 @@ import ( // Compatible with ccip::offramp version 1.6.0 type CommitPluginCodecV1 struct{} +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) + func NewCommitPluginCodecV1() *CommitPluginCodecV1 { return &CommitPluginCodecV1{} } @@ -28,14 +31,22 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi return } s.Struct(&sourceToken) - s.U256(*item.Price.Int) + if item.Price.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.Price.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) } bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { s.U64(uint64(item.ChainSel)) - s.U256(*item.GasPrice.Int) + if item.GasPrice.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.GasPrice.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) @@ -86,7 +97,19 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.Price = cciptypes.NewBigInt(&price) + + // we need this clause because the zero token price test fails otherwise: + // - abs: (big.nat) + // + abs: (big.nat) { + // + } + // the reason is because big.NewInt(0) ends up not setting the `abs` field at all, while big.NewInt().SetBytes(..) will + // set the `abs` value to 0. + // ref: https://cs.opensource.google/go/go/+/master:src/math/big/int.go;drc=432fd9c60fac4485d0473173171206f1ef558829;l=85 + if price.Sign() == 0 { + item.Price = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.Price = cciptypes.NewBigInt(&price) + } }) if des.Error() != nil { @@ -102,7 +125,11 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.GasPrice = cciptypes.NewBigInt(&gasPrice) + if gasPrice.Sign() == 0 { + item.GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + } }) if des.Error() != nil { return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) @@ -163,6 +190,3 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype return report, nil } - -// Ensure CommitPluginCodec implements the CommitPluginCodec interface -var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index f4500ef679a..0bd3b19d4bf 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -12,7 +12,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-integrations/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -30,7 +29,8 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) for z := 0; z < numTokensPerMsg; z++ { - encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + // Use the predefined ABI arguments to pack destGasAmount + encodedDestExecData, err2 := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err2) tokenAmounts[z] = cciptypes.RampTokenAmount{ @@ -42,13 +42,12 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big } } - extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - if err != nil { - t.Fatalf("failed to pack extra args: %v", err) - } - extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + // Use the predefined ABI arguments to pack EVM V1 fields + encodedExtraArgsFields, err := evmExtraArgsV1Fields.Pack(gasLimit) + require.NoError(t, err, "failed to pack extra args fields") + + // Prepend the tag + extraArgs := append(evmExtraArgsV1Tag, encodedExtraArgsFields...) reportMessages[j] = cciptypes.Message{ Header: cciptypes.RampMessageHeader{ @@ -92,12 +91,15 @@ func TestExecutePluginCodecV1(t *testing.T) { mockExtraDataCodec := &mocks.ExtraDataCodec{} destGasAmount := rand.Uint32() gasLimit := utils.RandUint256() + + // Update mock return values to use the correct keys expected by the codec + // The codec uses the ExtraDataDecoder internally, which returns maps like these. mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ - "destgasamount": destGasAmount, + aptosDestExecDataKey: destGasAmount, // Use the constant defined in the decoder }, nil) mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ - "gasLimit": utils.RandUint256(), - "accountIsWritableBitmap": gasLimit, + "gasLimit": gasLimit, // Match the key used in the decoder for EVM V1/V2 gasLimit + // "allowOutOfOrderExecution": false, // Optionally mock other fields if needed by codec logic }, nil) testCases := []struct { @@ -109,7 +111,7 @@ func TestExecutePluginCodecV1(t *testing.T) { gasLimit *big.Int }{ { - name: "base report", + name: "base report EVM chain", report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 5009297550715157269, // ETH mainnet chain selector @@ -117,7 +119,7 @@ func TestExecutePluginCodecV1(t *testing.T) { destGasAmount: destGasAmount, }, { - name: "base report", + name: "base report non-EVM chain", // Name updated for clarity report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 124615329519749607, // Solana mainnet chain selector @@ -131,7 +133,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -142,7 +144,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -151,6 +153,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { codec := NewExecutePluginCodecV1(mockExtraDataCodec) + // randomExecuteReport now uses the new encoding internally report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) if tc.expErr { @@ -159,7 +162,7 @@ func TestExecutePluginCodecV1(t *testing.T) { } require.NoError(t, err) - // ignore unavailable fields in comparison + // ignore unavailable fields in comparison - This part remains the same for i := range report.ChainReports { for j := range report.ChainReports[i].Messages { report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} @@ -173,7 +176,7 @@ func TestExecutePluginCodecV1(t *testing.T) { // decode using the codec codecDecoded, err := codec.Decode(ctx, bytes) require.NoError(t, err) - require.Equal(t, report, codecDecoded) + require.Equal(t, report, codecDecoded) // Comparison should still work }) } } diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go index 5c600f266bd..2f59d9bed17 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -2,28 +2,25 @@ package ccipaptos import ( "fmt" - "reflect" + "math/big" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) // ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder // Compatible with ccip::fee_quoter version 1.6.0 type ExtraDataDecoder struct{} +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) + const ( aptosDestExecDataKey = "destGasAmount" ) -var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) - var ( // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") @@ -33,18 +30,71 @@ var ( // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") + + uint32Type = mustNewType("uint32") + uint64Type = mustNewType("uint64") + uint256Type = mustNewType("uint256") + boolType = mustNewType("bool") + bytes32Type = mustNewType("bytes32") + bytes32ArrType = mustNewType("bytes32[]") + + // Arguments for decoding destGasAmount + destGasAmountArguments = abi.Arguments{ + {Name: aptosDestExecDataKey, Type: uint32Type}, + } + + // Arguments matching the fields of EVMExtraArgsV1 struct + evmExtraArgsV1Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + } + + // Arguments matching the fields of GenericExtraArgsV2 struct + genericExtraArgsV2Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + } + + // Arguments matching the fields of SVMExtraArgsV1 struct + svmExtraArgsV1Fields = abi.Arguments{ + {Name: "computeUnits", Type: uint32Type}, + {Name: "accountIsWritableBitmap", Type: uint64Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + {Name: "tokenReceiver", Type: bytes32Type}, + {Name: "accounts", Type: bytes32ArrType}, + } ) +func mustNewType(typeStr string) abi.Type { + t, err := abi.NewType(typeStr, "", nil) + if err != nil { + panic(fmt.Sprintf("failed to create ABI type %s: %v", typeStr, err)) + } + return t +} + // DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { - destGasAmount, err := abiDecodeUint32(destExecData) + args := make(map[string]any) + err := destGasAmountArguments.UnpackIntoMap(args, destExecData) if err != nil { + if len(destExecData) != 32 { + return nil, fmt.Errorf("decode dest gas amount: expected 32 bytes for uint32, got %d: %w", len(destExecData), err) + } + + var val big.Int + val.SetBytes(destExecData) + if val.Cmp(big.NewInt(0xFFFFFFFF)) > 0 { + return nil, fmt.Errorf("decode dest gas amount: value %s exceeds uint32 max: %w", val.String(), err) + } + return nil, fmt.Errorf("decode dest gas amount: %w", err) } - return map[string]any{ - aptosDestExecDataKey: destGasAmount, - }, nil + if _, ok := args[aptosDestExecDataKey]; !ok { + return nil, fmt.Errorf("failed to unpack key '%s' for dest gas amount", aptosDestExecDataKey) + } + + return args, nil } // DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args @@ -53,98 +103,99 @@ func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[s return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) } - var method string - var argName string - switch string(extraArgs[:4]) { + var decoderArgs abi.Arguments + tag := string(extraArgs[:4]) + argsData := extraArgs[4:] + + switch tag { case string(evmExtraArgsV1Tag): - method = "exposeEVMExtraArgsV1" - argName = "evmExtraArgsV1" + decoderArgs = evmExtraArgsV1Fields case string(genericExtraArgsV2Tag): - method = "exposeGenericExtraArgsV2" - argName = "evmExtraArgsV2" + decoderArgs = genericExtraArgsV2Fields case string(svmExtraArgsV1Tag): - method = "exposeSVMExtraArgsV1" - argName = "svmExtraArgsV1" + decoderArgs = svmExtraArgsV1Fields default: - return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs[:4]) } - output := make(map[string]any) - args := make(map[string]any) - err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + unpackedArgs := make(map[string]any) + err := decoderArgs.UnpackIntoMap(unpackedArgs, argsData) if err != nil { - return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + return nil, fmt.Errorf("abi decode extra args (tag %x): %w", extraArgs[:4], err) } - argValue, exists := args[argName] - if !exists { - return nil, fmt.Errorf("failed to get arg value for %s", argName) - } - - val := reflect.ValueOf(argValue) - if val.Kind() != reflect.Struct { - return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) - } + output := make(map[string]any) - switch argName { - case "evmExtraArgsV1": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + switch tag { + case string(evmExtraArgsV1Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in EVMExtraArgsV1: %T", unpackedArgs["gasLimit"]) } else { - output["gasLimit"] = nil + output["gasLimit"] = nil // Field not present or nil } - case "evmExtraArgsV2": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + + case string(genericExtraArgsV2Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in GenericExtraArgsV2: %T", unpackedArgs["gasLimit"]) } else { output["gasLimit"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in GenericExtraArgsV2: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { + // Default to false if not present, consistent with original code. + // Note: ABI decoding of bool usually doesn't result in nil, but checking doesn't hurt. output["allowOutOfOrderExecution"] = false } - case "svmExtraArgsV1": - computeUnitsField := val.FieldByName("ComputeUnits") - if computeUnitsField.IsValid() { - output["computeUnits"] = computeUnitsField.Interface() + + case string(svmExtraArgsV1Tag): + if computeUnits, ok := unpackedArgs["computeUnits"].(uint32); ok { + output["computeUnits"] = computeUnits + } else if unpackedArgs["computeUnits"] != nil { + return nil, fmt.Errorf("unexpected type for computeUnits in SVMExtraArgsV1: %T", unpackedArgs["computeUnits"]) } else { output["computeUnits"] = nil } - bitmapField := val.FieldByName("AccountIsWritableBitmap") - if bitmapField.IsValid() { - output["accountIsWritableBitmap"] = bitmapField.Interface() + if bitmap, ok := unpackedArgs["accountIsWritableBitmap"].(uint64); ok { + output["accountIsWritableBitmap"] = bitmap + } else if unpackedArgs["accountIsWritableBitmap"] != nil { + return nil, fmt.Errorf("unexpected type for accountIsWritableBitmap in SVMExtraArgsV1: %T", unpackedArgs["accountIsWritableBitmap"]) } else { output["accountIsWritableBitmap"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in SVMExtraArgsV1: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { output["allowOutOfOrderExecution"] = false } - tokenReceiverField := val.FieldByName("TokenReceiver") - if tokenReceiverField.IsValid() { - output["tokenReceiver"] = tokenReceiverField.Interface() + if tokenReceiver, ok := unpackedArgs["tokenReceiver"].([32]byte); ok { + output["tokenReceiver"] = tokenReceiver + } else if unpackedArgs["tokenReceiver"] != nil { + return nil, fmt.Errorf("unexpected type for tokenReceiver in SVMExtraArgsV1: %T", unpackedArgs["tokenReceiver"]) } else { output["tokenReceiver"] = nil } - accountsField := val.FieldByName("Accounts") - if accountsField.IsValid() { - output["accounts"] = accountsField.Interface() + if accounts, ok := unpackedArgs["accounts"].([][32]byte); ok { + output["accounts"] = accounts + } else if unpackedArgs["accounts"] != nil { + return nil, fmt.Errorf("unexpected type for accounts in SVMExtraArgsV1: %T", unpackedArgs["accounts"]) } else { output["accounts"] = nil } } + return output, nil } - -var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go index 234d2f29981..d8188010362 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -5,10 +5,9 @@ import ( "math/rand" "testing" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) func Test_decodeExtraData(t *testing.T) { @@ -16,40 +15,38 @@ func Test_decodeExtraData(t *testing.T) { extraDataDecoder := &ExtraDataDecoder{} t.Run("decode extra args into map evm v1", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + encodedFields, err := evmExtraArgsV1Fields.Pack(gasLimit) require.NoError(t, err) + encoded := append(evmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp for big.Int comparison }) t.Run("decode extra args into map evm v2", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ - GasLimit: gasLimit, - AllowOutOfOrderExecution: true, - }) - encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + allowOoe := true + encodedFields, err := genericExtraArgsV2Fields.Pack(gasLimit, allowOoe) require.NoError(t, err) + encoded := append(genericExtraArgsV2Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 2) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp - ooe, exist := m["allowOutOfOrderExecution"] + ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, true, ooe) + require.Equal(t, allowOoe, ooeDecoded) // Check boolean directly }) t.Run("decode extra args into map svm", func(t *testing.T) { @@ -59,52 +56,99 @@ func Test_decodeExtraData(t *testing.T) { bitmap := uint64(4) ooe := false tokenReceiver := [32]byte(key.PublicKey().Bytes()) - accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} - encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ - ComputeUnits: cu, - AccountIsWritableBitmap: bitmap, - AllowOutOfOrderExecution: ooe, - TokenReceiver: tokenReceiver, - Accounts: accounts, - }) - encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} // Example with one account + + encodedFields, err := svmExtraArgsV1Fields.Pack( + cu, + bitmap, + ooe, + tokenReceiver, + accounts, + ) require.NoError(t, err) + encoded := append(svmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 5) cuDecoded, exist := m["computeUnits"] require.True(t, exist) - require.Equal(t, cuDecoded, cu) + require.Equal(t, cu, cuDecoded) bitmapDecoded, exist := m["accountIsWritableBitmap"] require.True(t, exist) - require.Equal(t, bitmapDecoded, bitmap) + require.Equal(t, bitmap, bitmapDecoded) ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, ooeDecoded, ooe) + require.Equal(t, ooe, ooeDecoded) tokenReceiverDecoded, exist := m["tokenReceiver"] require.True(t, exist) - require.Equal(t, tokenReceiverDecoded, tokenReceiver) + require.Equal(t, tokenReceiver, tokenReceiverDecoded.([32]byte)) accountsDecoded, exist := m["accounts"] require.True(t, exist) - require.Equal(t, accountsDecoded, accounts) + require.Equal(t, accounts, accountsDecoded.([][32]byte)) }) t.Run("decode dest exec data into map", func(t *testing.T) { destGasAmount := uint32(10000) - encoded, err := abiEncodeUint32(destGasAmount) + encoded, err := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) decoded, exist := m[aptosDestExecDataKey] require.True(t, exist) - require.Equal(t, destGasAmount, decoded) + require.Equal(t, destGasAmount, decoded.(uint32)) // Type assert and compare uint32 + }) + + t.Run("error on short extra args", func(t *testing.T) { + shortData := evmExtraArgsV1Tag[:2] // Less than 4 bytes + _, err := extraDataDecoder.DecodeExtraArgsToMap(shortData) + require.Error(t, err) + require.Contains(t, err.Error(), "extra args too short") + }) + + t.Run("error on unknown tag", func(t *testing.T) { + unknownTag := []byte{0xde, 0xad, 0xbe, 0xef} + dummyData, err := evmExtraArgsV1Fields.Pack(big.NewInt(1)) + require.NoError(t, err) + dataWithUnknownTag := append(unknownTag, dummyData...) + _, err = extraDataDecoder.DecodeExtraArgsToMap(dataWithUnknownTag) + require.Error(t, err) + require.Contains(t, err.Error(), "unknown extra args tag") + }) + + t.Run("error on malformed evm v1 data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint256 + encoded := append(evmExtraArgsV1Tag, malformedData...) + _, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.Error(t, err) + require.Contains(t, err.Error(), "abi decode extra args") + }) + + t.Run("error on malformed dest exec data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint32 (expects 32 bytes) + _, err := extraDataDecoder.DecodeDestExecDataToMap(malformedData) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "expected 32 bytes for uint32") + }) + + t.Run("error on dest exec data exceeding uint32 max", func(t *testing.T) { + tooLargeValue := new(big.Int).Lsh(big.NewInt(1), 32) + encodedTooLarge, err := abi.Arguments{{Type: uint256Type}}.Pack(tooLargeValue) // Pack as uint256 + require.NoError(t, err) + + _, err = extraDataDecoder.DecodeDestExecDataToMap(encodedTooLarge) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "exceeds uint32 max") }) } From 0579485f0bc6dc503b6647b924207876e413f729 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:19:21 +0400 Subject: [PATCH 010/136] core/capabilities/ccip/configs/aptos: add ccip CW/CR configs --- .../ccip/configs/aptos/chain_writer.go | 70 ++++++ .../ccip/configs/aptos/contract_reader.go | 231 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 core/capabilities/ccip/configs/aptos/chain_writer.go create mode 100644 core/capabilities/ccip/configs/aptos/contract_reader.go diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go new file mode 100644 index 00000000000..061672baac9 --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -0,0 +1,70 @@ +package aptosconfig + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-aptos/relayer/chainwriter" + "github.com/smartcontractkit/chainlink-aptos/relayer/utils" +) + +func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, error) { + fromAddress, err := utils.HexPublicKeyToAddress(publicKeyStr) + if err != nil { + return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) + } + + fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) + + return chainwriter.ChainWriterConfig{ + Modules: map[string]*chainwriter.ChainWriterModule{ + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainwriter.ChainWriterFunction{ + consts.MethodCommit: { + Name: "commit", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + { + Name: "Signatures", + Type: "vector>", + Required: true, + }, + }, + }, + consts.MethodExecute: { + Name: "execute", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + }, + }, + }, + }, + }, + FeeStrategy: chainwriter.DefaultFeeStrategy, + }, nil +} diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go new file mode 100644 index 00000000000..016d593239d --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -0,0 +1,231 @@ +package aptosconfig + +import ( + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" +) + +func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { + return chainreader.ChainReaderConfig{ + IsLoopPlugin: true, + Modules: map[string]*chainreader.ChainReaderModule{ + // TODO: more offramp config and other modules + consts.ContractNameRMNRemote: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetReportDigestHeader: { + Name: "get_report_digest_header", + }, + consts.MethodNameGetVersionedConfig: { + Name: "get_versioned_config", + // ref: https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L1440 + ResultTupleToStruct: []string{"version", "config"}, + }, + consts.MethodNameGetCursedSubjects: { + Name: "get_cursed_subjects", + }, + }, + }, + + consts.ContractNameRMNProxy: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetARM: { + Name: "get_arm", + }, + }, + }, + + consts.ContractNameFeeQuoter: { + Name: "fee_quoter", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameFeeQuoterGetTokenPrice: { + Name: "get_token_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "token", + Type: "address", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetTokenPrices: { + Name: "get_token_prices", + Params: []chainreader.AptosFunctionParam{ + { + Name: "tokens", + Type: "vector
", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetStaticConfig: { + Name: "get_static_config", + }, + }, + }, + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetExecutionState: { + Name: "get_execution_state", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + { + Name: "sequenceNumber", + Type: "u64", + Required: true, + }, + }, + }, + consts.MethodNameGetMerkleRoot: { + Name: "get_merkle_root", + Params: []chainreader.AptosFunctionParam{ + { + Name: "root", + Type: "vector", + Required: true, + }, + }, + }, + consts.MethodNameOffRampLatestConfigDetails: { + Name: "latest_config_details", + Params: []chainreader.AptosFunctionParam{ + { + Name: "ocrPluginType", + Type: "u8", + Required: true, + }, + }, + // wrap the returned OCR config + // https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L141 + ResultTupleToStruct: []string{"ocr_config"}, + }, + consts.MethodNameGetLatestPriceSequenceNumber: { + Name: "get_latest_price_sequence_number", + }, + consts.MethodNameOffRampGetStaticConfig: { + Name: "get_static_config", + // TODO: field renames + }, + consts.MethodNameOffRampGetDynamicConfig: { + Name: "get_dynamic_config", + // TODO: field renames + }, + consts.MethodNameGetSourceChainConfig: { + Name: "get_source_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameExecutionStateChanged: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "execution_state_changed_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageId", + }, + "message_hash": { + NewName: "MessageHash", + }, + "state": { + NewName: "State", + }, + }, + }, + consts.EventNameCommitReportAccepted: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "commit_report_accepted_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "blessed_merkle_roots": { + NewName: "BlessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "unblessed_merkle_roots": { + NewName: "UnblessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "price_updates": { + NewName: "PriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "token_price_updates": { + NewName: "TokenPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_token": { + NewName: "SourceToken", + }, + "usd_per_token": { + NewName: "UsdPerToken", + }, + }, + }, + "gas_price_updates": { + NewName: "GasPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "usd_per_unit_gas": { + NewName: "UsdPerUnitGas", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, nil +} From ee7a33b16449c6a9bc0e9b72f509b3362148f8c0 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:21:50 +0400 Subject: [PATCH 011/136] core/services/keystore/keys/ocr2key/aptos_keyring.go: implement Sign3 and Verify3 --- .../keystore/keys/ocr2key/aptos_keyring.go | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/services/keystore/keys/ocr2key/aptos_keyring.go b/core/services/keystore/keys/ocr2key/aptos_keyring.go index 154f6ea3d2a..393ddd4eb5a 100644 --- a/core/services/keystore/keys/ocr2key/aptos_keyring.go +++ b/core/services/keystore/keys/ocr2key/aptos_keyring.go @@ -56,8 +56,24 @@ func (akr *aptosKeyring) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes. return akr.SignBlob(sigData) } +func (ekr *aptosKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) ([]byte, error) { + rawReportContext := RawReportContext3(digest, seqNr) + h, err := blake2b.New256(nil) + if err != nil { + return nil, err + } + h.Write(r) + h.Write(rawReportContext[0][:]) + h.Write(rawReportContext[1][:]) + return h.Sum(nil), nil +} + func (akr *aptosKeyring) Sign3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) { - return nil, errors.New("not implemented") + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return nil, err + } + return akr.SignBlob(sigData) } func (akr *aptosKeyring) SignBlob(b []byte) ([]byte, error) { @@ -74,8 +90,12 @@ func (akr *aptosKeyring) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx o return akr.VerifyBlob(publicKey, hash, signature) } -func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { - return false +func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, digest ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return false + } + return akr.VerifyBlob(publicKey, sigData, signature) } func (akr *aptosKeyring) VerifyBlob(pubkey ocrtypes.OnchainPublicKey, b, sig []byte) bool { From ced4247c478c1cc5f61193868aff7fdbb619d0a4 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:30:05 +0400 Subject: [PATCH 012/136] core/capabilities/ccip/ocrimpls/config_tracker.go: dont use address codec for Aptos --- core/capabilities/ccip/ocrimpls/config_tracker.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/config_tracker.go b/core/capabilities/ccip/ocrimpls/config_tracker.go index 9619b0824cd..0500eb05a46 100644 --- a/core/capabilities/ccip/ocrimpls/config_tracker.go +++ b/core/capabilities/ccip/ocrimpls/config_tracker.go @@ -2,9 +2,11 @@ package ocrimpls import ( "context" + "encoding/hex" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -77,6 +79,13 @@ func toOnchainPublicKeys(signers [][]byte) []types.OnchainPublicKey { func toOCRAccounts(transmitters [][]byte, addressCodec ccipocr3.AddressCodec, chainSelector ccipocr3.ChainSelector) []types.Account { accounts := make([]types.Account, len(transmitters)) for i, transmitter := range transmitters { + family, _ := chainsel.GetSelectorFamily(uint64(chainSelector)) + // Aptos transmitter accounts do not go through the address codec, because they are ed25519 public keys. + if family == chainsel.FamilyAptos { + s := hex.EncodeToString(transmitter) + accounts[i] = types.Account(s) + continue + } address, _ := addressCodec.AddressBytesToString(transmitter, chainSelector) accounts[i] = types.Account(address) } From f6086601f94973bc10057396dbea0918ccf42305 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:43:57 +0400 Subject: [PATCH 013/136] core/capabilities/ccip/ocrimpls/contract_transmitter.go: support ed25519 signatures --- .../ccip/ocrimpls/contract_transmitter.go | 79 +++++++++++++------ 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 8dda409f3f3..24e9de74e38 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -31,15 +31,22 @@ type ToCalldataFunc func( codec ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) +type ToEd25519CalldataFunc func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + codec ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) + var _ ocr3types.ContractTransmitter[[]byte] = &ccipTransmitter{} type ccipTransmitter struct { - cw commontypes.ContractWriter - fromAccount ocrtypes.Account - offrampAddress string - toCalldataFn ToCalldataFunc - extraDataCodec ccipcommon.ExtraDataCodec - lggr logger.Logger + cw commontypes.ContractWriter + fromAccount ocrtypes.Account + offrampAddress string + toCalldataFn ToCalldataFunc + toEd25519CalldataFn ToEd25519CalldataFunc + extraDataCodec ccipcommon.ExtraDataCodec } func XXXNewContractTransmitterTestsOnly( @@ -81,35 +88,57 @@ func (c *ccipTransmitter) Transmit( reportWithInfo ocr3types.ReportWithInfo[[]byte], sigs []ocrtypes.AttributedOnchainSignature, ) error { - var rs [][32]byte - var ss [][32]byte - var vs [32]byte if len(sigs) > 32 { return errors.New("too many signatures, maximum is 32") } - for i, as := range sigs { - r, s, v, err := evmutil.SplitSignature(as.Signature) - if err != nil { - return fmt.Errorf("failed to split signature: %w", err) - } - rs = append(rs, r) - ss = append(ss, s) - vs[i] = v - } // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) - if c.toCalldataFn == nil { - return errors.New("toCalldataFn is nil") - } + var contract string + var method string + var args any + var err error + + if c.toCalldataFn != nil { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + for i, as := range sigs { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + return fmt.Errorf("failed to split signature: %w", err) + } + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } - // chain writer takes in the raw calldata and packs it on its own. - contract, method, args, err := c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) - if err != nil { - return fmt.Errorf("failed to generate call data: %w", err) + // chain writer takes in the raw calldata and packs it on its own. + contract, method, args, err = c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ecdsa call data: %w", err) + } + } else if c.toEd25519CalldataFn != nil { + var signatures [][96]byte + for _, as := range sigs { + sig := as.Signature + if len(sig) != 96 { + return fmt.Errorf("invalid ed25519 signature length, expected 96, got %d", len(sig)) + } + var sigBytes [96]byte + copy(sigBytes[:], sig) + signatures = append(signatures, sigBytes) + } + + contract, method, args, err = c.toEd25519CalldataFn(rawReportCtx, reportWithInfo, signatures, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ed25519 call data: %w", err) + } + } else { + return errors.New("no calldata function") } // TODO: no meta fields yet, what should we add? From d1102108781b63100ba5957dfc6154a4ae75ce2f Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:50:36 +0400 Subject: [PATCH 014/136] core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go: add --- .../aptos_contract_transmitter_factory.go | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go new file mode 100644 index 00000000000..f6c2e729263 --- /dev/null +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -0,0 +1,96 @@ +package ocrimpls + +import ( + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. +type AptosCommitCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` + Signatures [][96]byte `mapstructure:"Signatures"` +} + +// AptosExecCallArgs defines the calldata structure for an Aptos execute transaction. +type AptosExecCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` +} + +// AptosContractTransmitterFactory implements the transmitter factory for Aptos chains. +type AptosContractTransmitterFactory struct{} + +// NewAptosCommitCalldataFunc returns a ToCalldataFunc for Aptos commits that omits any Info object. +func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { + return func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, + ) (string, string, any, error) { + return consts.ContractNameOffRamp, + commitMethod, + AptosCommitCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + Signatures: signatures, + }, + nil + } +} + +// NewCommitTransmitter constructs an Aptos commit transmitter. +func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, + commitMethod, _ string, // priceOnlyMethod is ignored for Aptos +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: NewAptosCommitCalldataFunc(commitMethod), + } +} + +// AptosExecCallDataFunc builds the execute call data for Aptos +var AptosExecCallDataFunc = func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) { + return consts.ContractNameOffRamp, + consts.MethodExecute, + AptosExecCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + }, nil +} + +// NewExecTransmitter constructs an Aptos execute transmitter. +func (f *AptosContractTransmitterFactory) NewExecTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: AptosExecCallDataFunc, + extraDataCodec: ccipcommon.NewExtraDataCodec( + ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), + ), + } +} From 13452b9a49f8de46c7928e8122e4e59a9f3d2b37 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:53:01 +0400 Subject: [PATCH 015/136] core/capabilities/ccip/oraclecreator/plugin.go: support Aptos --- .../capabilities/ccip/oraclecreator/plugin.go | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 336b5f89541..f9b943977cd 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -26,9 +26,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + aptosconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/aptos" solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" + aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" @@ -88,6 +90,18 @@ var plugins = map[string]plugin{ PriceOnlyCommitFn: consts.MethodCommitPriceOnly, ContractTransmitterFactory: &ocrimpls.SVMContractTransmitterFactory{}, }, + chainsel.FamilyAptos: { + CommitPluginCodec: ccipaptos.NewCommitPluginCodecV1(), + ExecutePluginCodec: ccipaptos.NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: func(lggr logger.Logger) cciptypes.MessageHasher { + return ccipaptos.NewMessageHasherV1(lggr, extraDataCodec) + }, + TokenDataEncoder: ccipaptos.NewAptosTokenDataEncoder(), + GasEstimateProvider: ccipaptos.NewGasEstimateProvider(), + RMNCrypto: func(lggr logger.Logger) cciptypes.RMNCrypto { return nil }, + PriceOnlyCommitFn: consts.MethodCommitPriceOnly, + ContractTransmitterFactory: &ocrimpls.AptosContractTransmitterFactory{}, + }, } const ( @@ -466,6 +480,10 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } + if relayChainFamily == relay.NetworkAptos { + cr = aptosloop.NewLoopChainReader(i.lggr, cr) + } + if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ @@ -597,6 +615,18 @@ func getChainReaderConfig( } return marshaledConfig, nil + + case relay.NetworkAptos: + cfg, err := aptosconfig.GetChainReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain reader config: %w", err) + } + marshaledConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) + } + return marshaledConfig, nil + default: return nil, fmt.Errorf("unsupported chain family %s", chainFamily) } @@ -653,6 +683,14 @@ func createChainWriter( if chainWriterConfig, err = json.Marshal(evmConfig); err != nil { return nil, fmt.Errorf("failed to marshal EVM chain writer config: %w", err) } + case relay.NetworkAptos: + cfg, err := aptosconfig.GetChainWriterConfig(transmitter[0]) + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain writer config: %w", err) + } + if chainWriterConfig, err = json.Marshal(cfg); err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain writer config: %w", err) + } default: return nil, fmt.Errorf("unknown chain family %s", chainFamily) } From 7b6740761c69d9ece570d3438f895fc68bb4b4e8 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 03:02:22 +0400 Subject: [PATCH 016/136] core/capabilities/ccip/oraclecreator/plugin.go: refactor into createChainReader function --- .../capabilities/ccip/oraclecreator/plugin.go | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index f9b943977cd..21727297ebf 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -470,20 +470,11 @@ func (i *pluginOracleCreator) createReadersAndWriters( continue } - chainReaderConfig, err1 := getChainReaderConfig(i.lggr, chainID, destChainID, homeChainID, ofc, chainSelector, relayChainFamily) + cr, err1 := createChainReader(ctx, i.lggr, relayer, chainID, destChainID, homeChainID, ofc, chainSelector, relayChainFamily) if err1 != nil { return nil, nil, fmt.Errorf("failed to get chain reader config: %w", err1) } - cr, err1 := relayer.NewContractReader(ctx, chainReaderConfig) - if err1 != nil { - return nil, nil, err1 - } - - if relayChainFamily == relay.NetworkAptos { - cr = aptosloop.NewLoopChainReader(i.lggr, cr) - } - if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ @@ -554,15 +545,17 @@ func decodeAndValidateOffchainConfig( return ofc, nil } -func getChainReaderConfig( +func createChainReader( + ctx context.Context, lggr logger.Logger, + relayer loop.Relayer, chainID string, destChainID string, homeChainID string, ofc offChainConfig, chainSelector cciptypes.ChainSelector, chainFamily string, -) ([]byte, error) { +) (types.ContractReader, error) { // TODO: create a chain writer constructor interface and define family specific implementations in oraclecreator.plugin switch chainFamily { case relay.NetworkEVM: @@ -593,7 +586,12 @@ func getChainReaderConfig( return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) } - return marshaledConfig, nil + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + return cr, nil case relay.NetworkSolana: var err error var cfg config.ContractReader @@ -614,7 +612,12 @@ func getChainReaderConfig( return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) } - return marshaledConfig, nil + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + return cr, nil case relay.NetworkAptos: cfg, err := aptosconfig.GetChainReaderConfig() @@ -625,7 +628,16 @@ func getChainReaderConfig( if err != nil { return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) } - return marshaledConfig, nil + + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + // wrap the chain reader for LOOP specific behavior + cr = aptosloop.NewLoopChainReader(lggr, cr) + + return cr, nil default: return nil, fmt.Errorf("unsupported chain family %s", chainFamily) From 92f018061d9da693cb9240109313509653ed76ce Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:56:17 +0400 Subject: [PATCH 017/136] core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go: add aptos for extra data codec --- .../ccip/ocrimpls/svm_contract_transmitter_factory.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go index 53614f44f28..abb9e495957 100644 --- a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -179,7 +180,7 @@ func (f *SVMContractTransmitterFactory) NewExecTransmitter( offrampAddress: offrampAddress, toCalldataFn: SVMExecCalldataFunc, extraDataCodec: ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}), + ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), ), } } From c6b9f828c6ee78621f6cabdf90e482663d68a8a2 Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 22 Apr 2025 19:12:49 +0400 Subject: [PATCH 018/136] core/capabilities/ccip/ccipaptos: update chainlink-integrations refs --- core/capabilities/ccip/ccipaptos/commitcodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/executecodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/msghasher.go | 2 +- core/capabilities/ccip/ccipaptos/utils.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go index 3f05cb75d52..ccc24d18a22 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec_test.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -11,7 +11,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index 0bd3b19d4bf..5773e707a4c 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go index 995e7e0112e..73f18d4e6dc 100644 --- a/core/capabilities/ccip/ccipaptos/msghasher.go +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) var ( diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go index 5488f3903d2..f9610cb75c3 100644 --- a/core/capabilities/ccip/ccipaptos/utils.go +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) func abiEncodeUint32(data uint32) ([]byte, error) { From db0837a627c6bd4c6dc5b4b22bf64e2d23a965e2 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 19:46:07 +0400 Subject: [PATCH 019/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add CCIPMessageSent --- core/capabilities/ccip/configs/aptos/contract_reader.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 016d593239d..58fc435fd1c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -128,6 +128,11 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", From 24032323965a35499ee2bdea4f8015fb1ea57553 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 20:22:13 +0400 Subject: [PATCH 020/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add get_dest_chain_gas_price --- .../capabilities/ccip/configs/aptos/contract_reader.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 58fc435fd1c..e6a97e2171d 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -62,6 +62,16 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { consts.MethodNameFeeQuoterGetStaticConfig: { Name: "get_static_config", }, + consts.MethodNameGetFeePriceUpdate: { + Name: "get_dest_chain_gas_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, }, }, consts.ContractNameOffRamp: { From 942ff3140c5ae7b4da9053f4982fd55c24d303b7 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 20:30:15 +0400 Subject: [PATCH 021/136] add and update aptos-go-sdk and chainlink-aptos --- core/scripts/go.mod | 4 +-- core/scripts/go.sum | 8 +++--- deployment/go.mod | 4 +-- deployment/go.sum | 8 +++--- go.mod | 10 +++++--- go.sum | 48 +++++++++++++++++++++++++++++------ integration-tests/go.mod | 4 +-- integration-tests/go.sum | 8 +++--- integration-tests/load/go.mod | 4 +-- integration-tests/load/go.sum | 8 +++--- system-tests/lib/go.mod | 4 +-- system-tests/lib/go.sum | 8 +++--- system-tests/tests/go.mod | 4 +-- system-tests/tests/go.sum | 8 +++--- 14 files changed, 83 insertions(+), 47 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 060bd1f6566..c082a791272 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -82,7 +82,7 @@ require ( github.com/XSAM/otelsql v0.37.0 // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect github.com/aws/aws-sdk-go v1.55.6 // indirect @@ -354,7 +354,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index ae425edf912..c662b9cd2c9 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -118,8 +118,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1181,8 +1181,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/deployment/go.mod b/deployment/go.mod index 9a28f1f31ee..492343137a0 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -15,7 +15,7 @@ require ( dario.cat/mergo v1.0.1 github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.3.1 - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/aws/aws-sdk-go v1.54.19 github.com/deckarep/golang-set/v2 v2.6.0 github.com/ethereum/go-ethereum v1.15.7 @@ -33,7 +33,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250429205337-7ee5f91ed065 diff --git a/deployment/go.sum b/deployment/go.sum index e84f35c09b3..503b64524c6 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -127,8 +127,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1230,8 +1230,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/go.mod b/go.mod index d65ceb0971a..13e68ad72a1 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/NethermindEth/juno v0.12.5 github.com/NethermindEth/starknet.go v0.8.0 github.com/andybalholm/brotli v1.1.1 + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/avast/retry-go/v4 v4.6.1 github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/cosmos/cosmos-sdk v0.50.13 @@ -18,7 +19,7 @@ require ( github.com/dominikbraun/graph v0.23.0 github.com/doyensec/safeurl v0.2.1 github.com/esote/minmaxheap v1.0.0 - github.com/ethereum/go-ethereum v1.15.3 + github.com/ethereum/go-ethereum v1.15.7 github.com/fatih/color v1.18.0 github.com/fbsobreira/gotron-sdk v0.0.0-20250403083053-2943ce8c759b github.com/fxamacker/cbor/v2 v2.7.0 @@ -76,6 +77,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.52 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 @@ -177,6 +179,7 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.38.17 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/consensys/bavard v0.1.22 // indirect @@ -194,7 +197,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/dgraph-io/badger/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -251,6 +254,7 @@ require ( github.com/hashicorp/go-metrics v0.5.3 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hasura/go-graphql-client v0.13.1 // indirect github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.2 // indirect @@ -334,7 +338,7 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/urfave/cli/v2 v2.27.5 // indirect - github.com/valyala/fastjson v1.4.1 // indirect + github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/go.sum b/go.sum index 21b41b9d918..3119dfb8304 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -224,6 +226,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/cometbft/cometbft v0.38.17 h1:FkrQNbAjiFqXydeAO81FUzriL4Bz0abYxN/eOHrQGOk= github.com/cometbft/cometbft v0.38.17/go.mod h1:5l0SkgeLRXi6bBfQuevXjKqML1jjfJJlvI1Ulp02/o4= github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= @@ -272,6 +276,12 @@ github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHH github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= +github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= +github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= +github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -285,12 +295,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= @@ -324,8 +336,8 @@ github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8nta github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.15.3 h1:OeTWAq6r8iR89bfJDjmmOemE74ywArl9DUViFsVj3Y8= -github.com/ethereum/go-ethereum v1.15.3/go.mod h1:jMXlpZXfSar1mGs/5sB0aEpEnPsiE1Jn6/3anlueqz8= +github.com/ethereum/go-ethereum v1.15.7 h1:vm1XXruZVnqtODBgqFaTclzP0xAvCvQIDKyFNUA1JpY= +github.com/ethereum/go-ethereum v1.15.7/go.mod h1:+S9k+jFzlyVTNcYGvqFhzN/SFhI6vA+aOY4T5tLSPL0= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -334,6 +346,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -358,6 +372,8 @@ github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdF github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= @@ -607,6 +623,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -638,6 +656,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hasura/go-graphql-client v0.13.1 h1:kKbjhxhpwz58usVl+Xvgah/TDha5K2akNTRQdsEHN6U= +github.com/hasura/go-graphql-client v0.13.1/go.mod h1:k7FF7h53C+hSNFRG3++DdVZWIuHdCaTbI7siTJ//zGQ= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -662,6 +682,12 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -829,6 +855,8 @@ github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8D github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -920,6 +948,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -1048,6 +1078,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= @@ -1196,8 +1228,8 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= -github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 5c9927e418d..a1859214754 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -115,7 +115,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -453,7 +453,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 1e2ee6da094..3f3c87e8c1c 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -159,8 +159,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a h1:2/4CQPSQ5LAAJHR5ONx+TwtfPDyG5tv2M2mJ2aw/8Kk= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 130e9968661..d230d10c58c 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -87,7 +87,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -440,7 +440,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.8 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 2d2fc474614..acbda6b67fe 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -163,8 +163,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1447,8 +1447,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 5a9658fa707..d3305edb7e9 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -66,7 +66,7 @@ require ( github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect @@ -355,7 +355,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index c885be0e227..99483450ae1 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -121,8 +121,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1218,8 +1218,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 15ca7e37c94..cdbb2a609fd 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -81,7 +81,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -429,7 +429,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 7d99ec786ba..14d83d627cf 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -157,8 +157,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= From d763ba2cb5556962ff0c43080474f96cf9c5339e Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:46:10 +0200 Subject: [PATCH 022/136] Upading aptos plugin ref --- plugins/plugins.private.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 589b99b7679..000e79af8dd 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,9 +9,9 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer" - gitRef: "2.21.0-beta16-aptos" - installPath: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer/cmd/chainlink-aptos" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" gitRef: "cf8a3317f89784ff2bf51c04e65b4afcb6eb4363" From 03e079f7a631a172fc1eaa963065e048c4846511 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:58:17 +0200 Subject: [PATCH 023/136] Adjusting aptos plugin ref to point to the chainlink-aptos as a whole --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 000e79af8dd..cbb4f733a67 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,7 +9,7 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos" gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: From dfe1056f47f5ec15f963fd915265165a29ba3a0a Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 30 Apr 2025 19:50:32 +0200 Subject: [PATCH 024/136] Fixing merge conflict resolution (logger-related) --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 3 +++ core/capabilities/ccip/ocrimpls/contract_transmitter.go | 1 + 2 files changed, 4 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index f6c2e729263..1db95ffe7ab 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) // AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. @@ -50,6 +51,7 @@ func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { // NewCommitTransmitter constructs an Aptos commit transmitter. func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, @@ -80,6 +82,7 @@ var AptosExecCallDataFunc = func( // NewExecTransmitter constructs an Aptos execute transmitter. func (f *AptosContractTransmitterFactory) NewExecTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 24e9de74e38..09e79744290 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -47,6 +47,7 @@ type ccipTransmitter struct { toCalldataFn ToCalldataFunc toEd25519CalldataFn ToEd25519CalldataFunc extraDataCodec ccipcommon.ExtraDataCodec + lggr logger.Logger } func XXXNewContractTransmitterTestsOnly( From 0b392b0732d7945e2e52e6080aebbdaa0bb3a367 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 24 Mar 2025 19:30:47 -0300 Subject: [PATCH 025/136] feat: Move and refactor changesets --- deployment/ccip/changeset/aptos/aptos_test.go | 38 --- .../ccip/changeset/aptos/config/config.go | 114 +++++++ .../changeset/aptos/cs_deploy_aptos_chain.go | 158 ++++++++++ .../aptos/cs_deploy_aptos_chain_test.go | 234 +++++++++++++++ .../ccip/changeset/aptos/operation/ccip.go | 284 ++++++++++++++++++ .../ccip/changeset/aptos/operation/mcms.go | 98 ++++++ deployment/ccip/changeset/aptos/state_test.go | 106 +++++++ .../ccip/changeset/aptos/test_helpers.go | 80 +++++ deployment/ccip/changeset/aptos/utils/mcms.go | 144 +++++++++ .../ccip/changeset/aptos/utils/utils.go | 38 +++ deployment/ccip/changeset/aptos_state.go | 2 +- .../changeset/testhelpers/test_environment.go | 29 ++ .../common/proposalutils/mcms_test_helpers.go | 7 + deployment/environment/memory/node.go | 22 ++ deployment/go.mod | 1 + 15 files changed, 1316 insertions(+), 39 deletions(-) delete mode 100644 deployment/ccip/changeset/aptos/aptos_test.go create mode 100644 deployment/ccip/changeset/aptos/config/config.go create mode 100644 deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go create mode 100644 deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go create mode 100644 deployment/ccip/changeset/aptos/operation/ccip.go create mode 100644 deployment/ccip/changeset/aptos/operation/mcms.go create mode 100644 deployment/ccip/changeset/aptos/state_test.go create mode 100644 deployment/ccip/changeset/aptos/test_helpers.go create mode 100644 deployment/ccip/changeset/aptos/utils/mcms.go create mode 100644 deployment/ccip/changeset/aptos/utils/utils.go diff --git a/deployment/ccip/changeset/aptos/aptos_test.go b/deployment/ccip/changeset/aptos/aptos_test.go deleted file mode 100644 index 8b7973bdf28..00000000000 --- a/deployment/ccip/changeset/aptos/aptos_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package aptos - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// TODO: This is to test the implementation of Aptos chains in memory environment -// To be deleted after changesets tests are added -func TestAptosMemoryEnv(t *testing.T) { - lggr := logger.TestLogger(t) - env := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - AptosChains: 1, - }) - aptosChainSelectors := env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors, 1) - require.NotEqual(t, 0, env.AptosChains[0].Selector) -} - -// TODO: This is to test the implementation of Aptos chains in memory environment -// To be deleted after changesets tests are added -func TestAptosHelperMemoryEnv(t *testing.T) { - depEvn, testEnv := testhelpers.NewMemoryEnvironment( - t, - testhelpers.WithAptosChains(1), - testhelpers.WithNoJobsAndContracts(), // currently not supporting jobs and contracts - ) - aptosChainSelectors := depEvn.Env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors, 1) - aptosChainSelectors2 := testEnv.DeployedEnvironment().Env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors2, 1) -} diff --git a/deployment/ccip/changeset/aptos/config/config.go b/deployment/ccip/changeset/aptos/config/config.go new file mode 100644 index 00000000000..064062eefd6 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/config.go @@ -0,0 +1,114 @@ +package config + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink/deployment" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +// DeployAptosChainConfig is a configuration for deploying CCIP Package for Aptos chains +type DeployAptosChainConfig struct { + MCMSConfigPerChain map[uint64]mcmstypes.Config + ContractParamsPerChain map[uint64]ChainContractParams +} + +func (c DeployAptosChainConfig) Validate() error { + for cs, args := range c.ContractParamsPerChain { + if err := deployment.IsValidChainSelector(cs); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + } + if err := args.Validate(); err != nil { + return fmt.Errorf("invalid contract args for chain %d: %w", cs, err) + } + } + return nil +} + +// ChainContractParams stores configuration to call initialize in CCIP contracts +type ChainContractParams struct { + FeeQuoterParams FeeQuoterParams + OffRampParams OffRampParams + OnRampParams OnRampParams +} + +func (c ChainContractParams) Validate() error { + // Validate every field + if err := c.FeeQuoterParams.Validate(); err != nil { + return fmt.Errorf("invalid FeeQuoterParams: %w", err) + } + if err := c.OffRampParams.Validate(); err != nil { + return fmt.Errorf("invalid OffRampParams: %w", err) + } + if err := c.OnRampParams.Validate(); err != nil { + return fmt.Errorf("invalid OnRampParams: %w", err) + } + return nil +} + +type FeeQuoterParams struct { + MaxFeeJuelsPerMsg uint64 + LinkToken aptos.AccountAddress + TokenPriceStalenessThreshold uint64 + FeeTokens []aptos.AccountAddress +} + +func (f FeeQuoterParams) Validate() error { + if f.LinkToken == aptos.AccountZero { + return fmt.Errorf("LinkToken is required") + } + if f.TokenPriceStalenessThreshold == 0 { + return fmt.Errorf("TokenPriceStalenessThreshold can't be 0") + } + if len(f.FeeTokens) == 0 { + return fmt.Errorf("at least one FeeTokens is required") + } + return nil +} + +type OffRampParams struct { + ChainSelector uint64 + PermissionlessExecutionThreshold uint32 + IsRMNVerificationDisabled []bool + SourceChainSelectors []uint64 + SourceChainIsEnabled []bool + SourceChainsOnRamp [][]byte +} + +func (o OffRampParams) Validate() error { + if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) + } + if o.PermissionlessExecutionThreshold == 0 { + return fmt.Errorf("PermissionlessExecutionThreshold can't be 0") + } + if len(o.SourceChainSelectors) != len(o.SourceChainIsEnabled) { + return fmt.Errorf("SourceChainSelectors and SourceChainIsEnabled must have the same length") + } + return nil +} + +type OnRampParams struct { + ChainSelector uint64 + AllowlistAdmin aptos.AccountAddress + DestChainSelectors []uint64 + DestChainEnabled []bool + DestChainAllowlistEnabled []bool +} + +func (o OnRampParams) Validate() error { + if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) + } + if o.AllowlistAdmin == aptos.AccountZero { + return fmt.Errorf("AllowlistAdmin is required") + } + if len(o.DestChainSelectors) != len(o.DestChainEnabled) { + return fmt.Errorf("DestChainSelectors and DestChainEnabled must have the same length") + } + if len(o.DestChainSelectors) != len(o.DestChainAllowlistEnabled) { + return fmt.Errorf("DestChainSelectors and DestChainAllowlistEnabled must have the same length") + } + return nil +} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go new file mode 100644 index 00000000000..e12ab1086e9 --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -0,0 +1,158 @@ +package aptos + +import ( + "errors" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/mcms" +) + +var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} + +// DeployAptosChain deploys Aptos chain packages and modules +type DeployAptosChain struct{} + +func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, config config.DeployAptosChainConfig) error { + // Validate env and prerequisite contracts + state, err := changeset.LoadOnchainStateAptos(env) + if err != nil { + return fmt.Errorf("failed to load existing Aptos onchain state: %w", err) + } + var errs []error + for chainSel := range config.ContractParamsPerChain { + if err := config.Validate(); err != nil { + errs = append(errs, fmt.Errorf("invalid config for Aptos chain %d: %w", chainSel, err)) + continue + } + if _, ok := env.AptosChains[chainSel]; !ok { + errs = append(errs, fmt.Errorf("aptos chain %d not found in env", chainSel)) + } + chainState, ok := state[chainSel] + if !ok { + errs = append(errs, fmt.Errorf("aptos chain %d not found in state", chainSel)) + continue + } + if chainState.MCMSAddress == aptos.AccountZero { + mcmsConfig := config.MCMSConfigPerChain[chainSel] + if err := mcmsConfig.Validate(); err != nil { + errs = append(errs, fmt.Errorf("invalid mcms configs for Aptos chain %d: %w", chainSel, err)) + } + } + } + + return errors.Join(errs...) +} + +func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainStateAptos(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + } + + ab := deployment.NewMemoryAddressBook() + proposals := &[]mcms.Proposal{} + + // Deploy CCIP on each Aptos chain in config + for chainSel := range config.ContractParamsPerChain { + chainState := state[chainSel] + aptosChain := env.AptosChains[chainSel] + + // MCMS Deploy operations + opsMCMS := operation.MCMSDeploymentOperations{ + Env: env, + Ab: ab, + AptosChain: aptosChain, + OnChainState: chainState, + MCMSConfigs: config.MCMSConfigPerChain[chainSel], + Proposals: proposals, + MCMSOpCount: 0, + } + err := runMCMSDeployOperations(&opsMCMS) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy MCMS for Aptos chain %d: %w", chainSel, err) + } + + // CCIP Deploy operations + ccipOps := operation.CCIPDeploymentOperations{ + Env: env, + Ab: ab, + AptosChain: aptosChain, + OnChainState: opsMCMS.OnChainState, + CCIPConfig: config.ContractParamsPerChain[chainSel], + Proposals: proposals, + MCMSOpCount: opsMCMS.MCMSOpCount, + } + err = runCCIPDeployOperations(&ccipOps) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) + } + } + + return deployment.ChangesetOutput{ + AddressBook: ab, + MCMSProposals: *proposals, + }, nil +} + +func runMCMSDeployOperations(ops *operation.MCMSDeploymentOperations) error { + // Check if MCMS package is already deployed + if ops.OnChainState.MCMSAddress != aptos.AccountZero { + ops.Env.Logger.Infow("MCMS Package already deployed", "addr", ops.OnChainState.MCMSAddress.String()) + return nil + } + // Deploy MCMS + addressMCMS, contractMCMS, err := ops.DeployMCMS() + if err != nil { + return fmt.Errorf("failed to deploy MCMS contract: %w", err) + } + // Configure MCMS + err = ops.ConfigureMCMS(addressMCMS) + if err != nil { + return fmt.Errorf("failed to configure MCMS contract: %w", err) + } + // Transfer ownership to self + err = ops.TransferOwnershipToSelf(contractMCMS) + if err != nil { + return fmt.Errorf("failed to transfer ownership to self: %w", err) + } + // Generate proposal to transfer ownership to self + proposal, mcmsOpCount, err := ops.GenerateAcceptOwnershipProposal(addressMCMS, contractMCMS) + if err != nil { + return fmt.Errorf("failed to build AcceptOwnership proposal: %w", err) + } + *ops.Proposals = append(*ops.Proposals, *proposal) + ops.MCMSOpCount = mcmsOpCount + + return nil +} + +func runCCIPDeployOperations(ops *operation.CCIPDeploymentOperations) error { + // Cleanup MCMS staging area + err := ops.GenerateCleanupStagingProposal() + if err != nil { + return fmt.Errorf("failed to generate cleanup staging proposal: %w", err) + } + // Generate proposals - Deploy CCIP package + ccipObjectAddress, err := ops.GenerateDeployCCIPProposal() + if err != nil { + return fmt.Errorf("failed to generate CCIP deploy proposal: %w", err) + } + // Generate proposals - Deploy Router package + err = ops.GenerateDeployRouterProposal(ccipObjectAddress) + if err != nil { + return fmt.Errorf("failed to generate Router deploy proposal: %w", err) + } + // Generate proposals - Initialize CCIP package + err = ops.GenerateInitializeCCIPProposal(ccipObjectAddress) + if err != nil { + return fmt.Errorf("failed to generate CCIP initialize proposal: %w", err) + } + + return nil +} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go new file mode 100644 index 00000000000..60414c4fa3a --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -0,0 +1,234 @@ +package aptos + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + ccipbind "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" +) + +func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { + tests := []struct { + name string + env deployment.Environment + config config.DeployAptosChainConfig + wantErrRe string + wantErr bool + }{ + { + name: "success - valid configs", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + 4457093679053095497: {}, + }, + ExistingAddresses: deployment.NewMemoryAddressBook(), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), + 743186221051783445: getMockChainContractParams(t, 743186221051783445), + }, + MCMSConfigPerChain: map[uint64]mcmstypes.Config{ + 4457093679053095497: getMockMCMSConfig(t), + 743186221051783445: getMockMCMSConfig(t), + }, + }, + wantErr: false, + }, + { + name: "success - valid config w MCMS deployed", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + 743186221051783445: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), + 743186221051783445: getMockChainContractParams(t, 743186221051783445), + }, + }, + wantErr: false, + }, + { + name: "error - chain has no env", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + 743186221051783445: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), + 743186221051783445: getMockChainContractParams(t, 743186221051783445), + }, + }, + wantErrRe: `chain 743186221051783445 not found in env`, + wantErr: true, + }, + { + name: "error - invalid config - chainSelector", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + ExistingAddresses: deployment.NewMemoryAddressBook(), + AptosChains: map[uint64]deployment.AptosChain{}, + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 1: {}, + }, + }, + wantErrRe: "invalid chain selector:", + wantErr: true, + }, + { + name: "error - missing MCMS config for chain without MCMS deployed", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: {}, // No MCMS address in state + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), + }, + // MCMSConfigPerChain is missing needed configs + }, + wantErrRe: `invalid mcms configs for chain 4457093679053095497`, + wantErr: true, + }, + { + name: "error - invalid config for chain", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, // MCMS already deployed + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: { + FeeQuoterParams: config.FeeQuoterParams{ + TokenPriceStalenessThreshold: 0, // Invalid gas limit (assuming 0 is invalid) + }, + }, + }, + }, + wantErrRe: `invalid config for chain 4457093679053095497`, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cs := DeployAptosChain{} + err := cs.VerifyPreconditions(tt.env, tt.config) + if tt.wantErr { + assert.Error(t, err) + errStr := err.Error() + assert.Regexp(t, tt.wantErrRe, errStr) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestDeployAptosChain_Apply(t *testing.T) { + lggr := logger.TestLogger(t) + + // Setup memory environment with 1 Aptos chain + env := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + AptosChains: 1, + }) + + // Get chain selectors + aptosChainSelectors := env.AllChainSelectorsAptos() + require.Equal(t, 1, len(aptosChainSelectors), "Expected exactly 1 Aptos chain") + chainSelector := aptosChainSelectors[0] + t.Log("Deployer: ", env.AptosChains[chainSelector].DeployerSigner) + + // Deploy CCIP to Aptos chain + mockCCIPParams := getMockChainContractParams(t, chainSelector) + ccipConfig := config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + chainSelector: mockCCIPParams, + }, + MCMSConfigPerChain: map[uint64]mcmstypes.Config{ + chainSelector: proposalutils.SingleGroupMCMSV2(t), + }, + } + env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure(DeployAptosChain{}, ccipConfig), + }) + require.NoError(t, err) + + // Verify CCIP deployment state by binding ccip contract and checking if it's deployed + state, err := changeset.LoadOnchainStateAptos(env) + require.NoError(t, err) + require.NotNil(t, state[chainSelector], "No state found for chain") + + ccipAddr := state[chainSelector].CCIPAddress + require.NotEmpty(t, ccipAddr, "CCIP address should not be empty") + + // Bind CCIP contract + ccipContract := ccipbind.Bind(ccipAddr, env.AptosChains[chainSelector].Client) + offRampSourceConfig, err := ccipContract.Offramp().GetSourceChainConfig(nil, mockCCIPParams.OffRampParams.SourceChainSelectors[0]) + require.NoError(t, err) + require.Equal(t, true, offRampSourceConfig.IsEnabled, "contracts were not initialized correctly") +} diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go new file mode 100644 index 00000000000..673af5b0eb8 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -0,0 +1,284 @@ +package operation + +import ( + "encoding/json" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +type CCIPDeploymentOperations struct { + Env deployment.Environment + Ab *deployment.AddressBookMap + AptosChain deployment.AptosChain + OnChainState changeset.AptosCCIPChainState + CCIPConfig aptoscfg.ChainContractParams + Proposals *[]mcms.Proposal + MCMSOpCount uint64 +} + +// GenerateCleanupStagingProposal generates cleanup MCMS operations for the staging area if it's not clean +func (op *CCIPDeploymentOperations) GenerateCleanupStagingProposal() error { + // Check resources first to see if staging is clean + IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(op.AptosChain.Client, op.OnChainState.MCMSAddress) + if err != nil { + return fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) + } + if IsMCMSStagingAreaClean { + op.Env.Logger.Infow("MCMS Staging Area already clean", "addr", op.OnChainState.MCMSAddress.String()) + return nil + } + + // Bind MCMS contract + mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) + mcmsAddress := mcmsContract.Address() + + // Get cleanup staging operations + var operations []types.Operation + moduleInfo, function, _, args, err := mcmsContract.MCMSDeployer().Encoder().CleanupStagingArea() + if err != nil { + return fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return fmt.Errorf("failed to marshal additional fields: %w", err) + } + operations = append(operations, types.Operation{ + ChainSelector: types.ChainSelector(op.AptosChain.Selector), + Transaction: types.Transaction{ + To: mcmsAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }) + + // Generate cleanup proposal + proposal, nextOpCount, err := utils.GenerateProposal( + op.AptosChain.Client, + mcmsContract.Address(), + op.AptosChain.Selector, + operations, + "Cleanup Staging Area", + op.MCMSOpCount, + ) + op.MCMSOpCount = nextOpCount + if err != nil { + return fmt.Errorf("failed to create deploy proposal: %w", err) + } + *op.Proposals = append(*op.Proposals, *proposal) + + return nil +} + +// GenerateDeployCCIPProposal generates deployment MCMS operations for the CCIP package +func (op *CCIPDeploymentOperations) GenerateDeployCCIPProposal() (*aptos.AccountAddress, error) { + // Validate there's no package deployed + if op.OnChainState.CCIPAddress != aptos.AccountZero { + op.Env.Logger.Infow("CCIP Package already deployed", "addr", op.OnChainState.CCIPAddress.String()) + return &op.OnChainState.CCIPAddress, nil + } + + // Compile, chunk and get CCIP deploy operations + mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) + ccipObjectAddress, operations, err := op.getCCIPDeployOperations(mcmsContract, op.AptosChain.Selector) + if err != nil { + return nil, fmt.Errorf("failed to compile and create deploy operations: %w", err) + } + + // Save the address of the CCIP object + typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + op.Ab.Save(op.AptosChain.Selector, ccipObjectAddress.String(), typeAndVersion) + op.OnChainState.CCIPAddress = ccipObjectAddress + + // Generate deploy proposal + proposal, nextOpCount, err := utils.GenerateProposal(op.AptosChain.Client, mcmsContract.Address(), op.AptosChain.Selector, operations, "Deploy CCIP Package", op.MCMSOpCount) + op.MCMSOpCount = nextOpCount + if err != nil { + return nil, fmt.Errorf("failed to create deploy proposal: %w", err) + } + *op.Proposals = append(*op.Proposals, *proposal) + + return &ccipObjectAddress, nil +} + +// GenerateDeployRouterProposal generates deployment MCMS operations for the Router module +func (op *CCIPDeploymentOperations) GenerateDeployRouterProposal(ccipObjectAddress *aptos.AccountAddress) error { + // TODO: is there a way to check if module exists? + // Compile, chunk and get Router deploy operations + mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) + operations, err := op.getRouterDeployOperations(mcmsContract, ccipObjectAddress) + if err != nil { + return fmt.Errorf("failed to compile and create deploy operations: %w", err) + } + + // Generate deploy proposal + proposal, nextOpCount, err := utils.GenerateProposal(op.AptosChain.Client, mcmsContract.Address(), op.AptosChain.Selector, operations, "Deploy Router Package", op.MCMSOpCount) + op.MCMSOpCount = nextOpCount + if err != nil { + return fmt.Errorf("failed to create deploy proposal: %w", err) + } + *op.Proposals = append(*op.Proposals, *proposal) + + return nil +} + +func (op *CCIPDeploymentOperations) GenerateInitializeCCIPProposal(ccipObjectAddress *aptos.AccountAddress) error { + var operations []types.Operation + ccipBind := ccip.Bind(*ccipObjectAddress, op.AptosChain.Client) + + // Config OnRamp + moduleInfo, function, _, args, err := ccipBind.Onramp().Encoder().Initialize( + op.AptosChain.Selector, + op.CCIPConfig.OnRampParams.AllowlistAdmin, + op.CCIPConfig.OnRampParams.DestChainSelectors, + op.CCIPConfig.OnRampParams.DestChainEnabled, + op.CCIPConfig.OnRampParams.DestChainAllowlistEnabled, + ) + if err != nil { + return fmt.Errorf("failed to encode onramp initialize: %w", err) + } + mcmsOp, err := generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + if err != nil { + return fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) + } + operations = append(operations, mcmsOp) + + // Config OffRamp + moduleInfo, function, _, args, err = ccipBind.Offramp().Encoder().Initialize( + op.AptosChain.Selector, + op.CCIPConfig.OffRampParams.PermissionlessExecutionThreshold, + op.CCIPConfig.OffRampParams.SourceChainSelectors, + op.CCIPConfig.OffRampParams.SourceChainIsEnabled, + op.CCIPConfig.OffRampParams.IsRMNVerificationDisabled, + op.CCIPConfig.OffRampParams.SourceChainsOnRamp, + ) + if err != nil { + return fmt.Errorf("failed to encode offramp initialize: %w", err) + } + mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + if err != nil { + return fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + } + operations = append(operations, mcmsOp) + + // Config FeeQuoter + moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().Initialize( + op.AptosChain.Selector, + op.CCIPConfig.FeeQuoterParams.LinkToken, + op.CCIPConfig.FeeQuoterParams.TokenPriceStalenessThreshold, + op.CCIPConfig.FeeQuoterParams.FeeTokens, + ) + if err != nil { + return fmt.Errorf("failed to encode feequoter initialize: %w", err) + } + mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + if err != nil { + return fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) + } + operations = append(operations, mcmsOp) + + // Config RMNRemote + moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(op.AptosChain.Selector) + if err != nil { + return fmt.Errorf("failed to encode rmnremote initialize: %w", err) + } + mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + if err != nil { + return fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) + } + operations = append(operations, mcmsOp) + + // Generate config proposal + proposal, nextOpCount, err := utils.GenerateProposal( + op.AptosChain.Client, + op.OnChainState.MCMSAddress, + op.AptosChain.Selector, + operations, + "Initialize CCIP Package", + op.MCMSOpCount, + ) + op.MCMSOpCount = nextOpCount + if err != nil { + return fmt.Errorf("failed to create deploy proposal: %w", err) + } + *op.Proposals = append(*op.Proposals, *proposal) + + return nil +} + +func (op *CCIPDeploymentOperations) getCCIPDeployOperations(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.AccountAddress, []types.Operation, error) { + // Calculate addresses of the owner and the object + ccipObjectAddress, err := mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) + } + + // Compile Package + payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), true) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) + if err != nil { + return ccipObjectAddress, operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) + } + + return ccipObjectAddress, operations, nil +} + +func (op *CCIPDeploymentOperations) getRouterDeployOperations( + mcmsContract mcmsbind.MCMS, + ccipObjectAddress *aptos.AccountAddress, +) ([]types.Operation, error) { + // Compile Package + payload, err := router.Compile(*ccipObjectAddress, mcmsContract.Address()) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, op.AptosChain.Selector, "", ccipObjectAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", op.AptosChain.Selector, err) + } + + return operations, nil +} + +func generateMCMSOperation(chainSel uint64, toAddress *aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Operation, error) { + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + return types.Operation{ + ChainSelector: types.ChainSelector(chainSel), + Transaction: types.Transaction{ + To: toAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go new file mode 100644 index 00000000000..1ca8ad35cc8 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -0,0 +1,98 @@ +package operation + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +const AcceptOwnershipProposalDescription = "Accept ownership of the contract to self" + +type MCMSDeploymentOperations struct { + Env deployment.Environment + Ab *deployment.AddressBookMap + AptosChain deployment.AptosChain + OnChainState changeset.AptosCCIPChainState + MCMSConfigs mcmstypes.Config + Proposals *[]mcms.Proposal + MCMSOpCount uint64 +} + +func (op *MCMSDeploymentOperations) DeployMCMS() (aptos.AccountAddress, mcmsbind.MCMS, error) { + mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() + addressMCMS, mcmsDeployTx, contractMCMS, err := mcmsbind.DeployToResourceAccount(op.AptosChain.DeployerSigner, op.AptosChain.Client, mcmsSeed) + if err != nil { + return aptos.AccountZero, mcmsbind.MCMSContract{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) + } + if err := utils.ConfirmTx(op.AptosChain, mcmsDeployTx.Hash); err != nil { + return aptos.AccountZero, mcmsbind.MCMSContract{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) + } + + typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_0_0) + op.Ab.Save(op.AptosChain.Selector, addressMCMS.String(), typeAndVersion) + op.OnChainState.MCMSAddress = addressMCMS + return addressMCMS, contractMCMS, nil +} + +func (op *MCMSDeploymentOperations) ConfigureMCMS(addressMCMS aptos.AccountAddress) error { + configurer := aptosmcms.NewConfigurer(op.AptosChain.Client, op.AptosChain.DeployerSigner) + setCfgTx, err := configurer.SetConfig(context.Background(), addressMCMS.StringLong(), &op.MCMSConfigs, false) + if err != nil { + return fmt.Errorf("failed to setConfig in MCMS contract: %w", err) + } + if err := utils.ConfirmTx(op.AptosChain, setCfgTx.Hash); err != nil { + return fmt.Errorf("MCMS setConfig transaction failed: %w", err) + } + return nil +} + +func (op *MCMSDeploymentOperations) TransferOwnershipToSelf(contractMCMS mcmsbind.MCMS) error { + opts := &bind.TransactOpts{Signer: op.AptosChain.DeployerSigner} + tx, err := contractMCMS.MCMSAccount().TransferOwnershipToSelf(opts) + if err != nil { + return fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) + } + _, err = op.AptosChain.Client.WaitForTransaction(tx.Hash) + if err != nil { + return fmt.Errorf("MCMS TransferOwnershipToSelf transaction failed: %w", err) + } + return nil +} + +func (op *MCMSDeploymentOperations) GenerateAcceptOwnershipProposal(addressMCMS aptos.AccountAddress, contractMCMS mcmsbind.MCMS) (*mcms.Proposal, uint64, error) { + var operations []mcmstypes.Operation + moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() + if err != nil { + return nil, 0, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + callOneAdditionalFields, err := json.Marshal(additionalFields) + if err != nil { + return nil, 0, fmt.Errorf("failed to marshal additionalFields: %w", err) + } + operations = append(operations, mcmstypes.Operation{ + ChainSelector: mcmstypes.ChainSelector(op.AptosChain.Selector), + Transaction: mcmstypes.Transaction{ + To: addressMCMS.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: callOneAdditionalFields, + }, + }) + + return utils.GenerateProposal(op.AptosChain.Client, contractMCMS.Address(), op.AptosChain.Selector, operations, AcceptOwnershipProposalDescription, 0) +} diff --git a/deployment/ccip/changeset/aptos/state_test.go b/deployment/ccip/changeset/aptos/state_test.go new file mode 100644 index 00000000000..8004bb815ba --- /dev/null +++ b/deployment/ccip/changeset/aptos/state_test.go @@ -0,0 +1,106 @@ +package aptos + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/stretchr/testify/assert" +) + +func TestLoadOnchainStateAptos(t *testing.T) { + tests := []struct { + name string + env deployment.Environment + want map[uint64]changeset.AptosCCIPChainState + err error + wantErrStr string + }{ + { + name: "success - empty env.AptosChains", + env: deployment.Environment{}, + want: map[uint64]changeset.AptosCCIPChainState{}, + err: nil, + }, + { + name: "success - chain not found in ab returns empty state", + env: deployment.Environment{ + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + want: map[uint64]changeset.AptosCCIPChainState{ + 743186221051783445: {}, + }, + err: nil, + }, + { + name: "success - loads multiple aptos chains state", + env: deployment.Environment{ + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + 743186221051783445: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockCCIPAddress: {Type: changeset.AptosCCIPType}, + }, + }, + ), + }, + want: map[uint64]changeset.AptosCCIPChainState{ + 4457093679053095497: { + MCMSAddress: mustParseAddress(t, mockMCMSAddress), + }, + 743186221051783445: { + MCMSAddress: mustParseAddress(t, mockMCMSAddress), + CCIPAddress: mustParseAddress(t, mockCCIPAddress), + }, + }, + err: nil, + }, + { + name: "error - failed to parse address", + env: deployment.Environment{ + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 743186221051783445: { + mockBadAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + want: nil, + err: assert.AnError, + wantErrStr: "failed to parse address 0xinvalid for AptosManyChainMultisig:", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := changeset.LoadOnchainStateAptos(tt.env) + if tt.err != nil { + assert.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErrStr) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go new file mode 100644 index 00000000000..eec4a49888c --- /dev/null +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -0,0 +1,80 @@ +package aptos + +import ( + "testing" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/assert" +) + +const ( + mockMCMSAddress = "0x3f20aa841a0eb5c038775bdb868924770df1ce377cc0013b3ba4ac9fd69a4f90" + mockCCIPAddress = "0xdccda7ae3917747b973a9d08609c328a37f9f8b44e4e00291be2fb58ae932bac" + mockAddress = "0x13a9f1a109368730f2e355d831ba8fbf5942fb82321863d55de54cb4ebe5d18f" + mockLinkAddress = "0xa" + mockBadAddress = "0xinvalid" + + mockMCMSSigner = "0x2A9685F653192edBac9F2405D95087c752fF6cd3" + sepChainSelector = 11155111 + sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" +) + +func getTestAddressBook(addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { + ab := deployment.NewMemoryAddressBook() + for chain, addrTypeAndVersion := range addrByChain { + for addr, typeAndVersion := range addrTypeAndVersion { + ab.Save(chain, addr, typeAndVersion) + } + } + return ab +} + +func mustParseAddress(t *testing.T, addr string) aptos.AccountAddress { + t.Helper() + var address aptos.AccountAddress + err := address.ParseStringRelaxed(addr) + assert.NoError(t, err) + return address +} + +func getMockChainContractParams(t *testing.T, chainSelector uint64) config.ChainContractParams { + mockParsedAddress := mustParseAddress(t, mockAddress) + mockParsedLinkAddress := mustParseAddress(t, mockLinkAddress) + + return config.ChainContractParams{ + FeeQuoterParams: config.FeeQuoterParams{ + MaxFeeJuelsPerMsg: 1000000, + LinkToken: mockParsedLinkAddress, + TokenPriceStalenessThreshold: 1000000, + FeeTokens: []aptos.AccountAddress{mockParsedLinkAddress}, + }, + OffRampParams: config.OffRampParams{ + ChainSelector: chainSelector, + PermissionlessExecutionThreshold: uint32(60 * 60 * 8), + IsRMNVerificationDisabled: []bool{false}, + SourceChainSelectors: []uint64{sepChainSelector}, + SourceChainIsEnabled: []bool{true}, + SourceChainsOnRamp: [][]byte{common.HexToAddress(sepMockOnRampAddress).Bytes()}, + }, + OnRampParams: config.OnRampParams{ + ChainSelector: chainSelector, + AllowlistAdmin: mockParsedAddress, + DestChainSelectors: []uint64{}, + DestChainEnabled: []bool{}, + DestChainAllowlistEnabled: []bool{}, + }, + } +} + +func getMockMCMSConfig(t *testing.T) mcmstypes.Config { + parsedAddress := common.HexToAddress(mockMCMSSigner) + return mcmstypes.Config{ + Quorum: 1, + Signers: []common.Address{parsedAddress}, + GroupSigners: []mcmstypes.Config{}, + } +} diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go new file mode 100644 index 00000000000..3d3cb74c670 --- /dev/null +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -0,0 +1,144 @@ +package utils + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/compile" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +const ( + ValidUntilHours = 72 + MCMSProposalVersion = "v1" +) + +func GenerateProposal( + client aptos.AptosRpcClient, + mcmsAddress aptos.AccountAddress, + chainSel uint64, + operations []types.Operation, + description string, + opCount uint64, +) (*mcms.Proposal, uint64, error) { + if opCount == 0 { + // Create MCMS inspector + inspector := aptosmcms.NewInspector(client) + startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) + if err != nil { + return nil, 0, fmt.Errorf("failed to get starting op count: %w", err) + } + opCount = startingOpCount + } + + // Create proposal builder + validUntil := time.Now().Add(time.Hour * ValidUntilHours).Unix() + proposalBuilder := mcms.NewProposalBuilder(). + SetVersion(MCMSProposalVersion). + SetValidUntil(uint32(validUntil)). + SetDescription(description). + SetOverridePreviousRoot(true). + AddChainMetadata( + types.ChainSelector(chainSel), + types.ChainMetadata{ + StartingOpCount: opCount, + MCMAddress: mcmsAddress.StringLong(), + }, + ) + + // Add operations and build + for _, op := range operations { + proposalBuilder.AddOperation(op) + } + proposal, err := proposalBuilder.Build() + if err != nil { + return nil, opCount, fmt.Errorf("failed to build proposal: %w", err) + } + + return proposal, opCount + uint64(len(operations)), nil +} + +// CreateChunksAndStage creates chunks from the compiled packages and build MCMS operations to stages them within the MCMS contract +func CreateChunksAndStage( + payload compile.CompiledPackage, + mcmsContract mcmsbind.MCMS, + chainSel uint64, + seed string, + codeObjectAddress *aptos.AccountAddress, +) ([]types.Operation, error) { + mcmsAddress := mcmsContract.Address() + // Validate seed XOR codeObjectAddress, one and only one must be provided + if (seed != "") == (codeObjectAddress != nil) { + return nil, fmt.Errorf("either provide seed to publishToObject or objectAddress to upgradeObjectCode") + } + + var operations []types.Operation + + // Create chunks + chunks, err := bind.CreateChunks(payload, bind.ChunkSizeInBytes) + if err != nil { + return operations, fmt.Errorf("failed to create chunks: %w", err) + } + + // Stage chunks with mcms_deployer module and execute with the last one + for i, chunk := range chunks { + var ( + moduleInfo bind.ModuleInformation + function string + args [][]byte + err error + ) + + // First chunks get staged, the last one gets published or upgraded + if i != len(chunks)-1 { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunk( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + ) + } else if seed != "" { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndPublishToObject( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + []byte(seed), + ) + } else { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndUpgradeObjectCode( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + *codeObjectAddress, + ) + } + if err != nil { + return operations, fmt.Errorf("failed to encode chunk %d: %w", i, err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return operations, fmt.Errorf("failed to marshal additional fields: %w", err) + } + operations = append(operations, types.Operation{ + ChainSelector: types.ChainSelector(chainSel), + Transaction: types.Transaction{ + To: mcmsAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }) + } + + return operations, nil +} diff --git a/deployment/ccip/changeset/aptos/utils/utils.go b/deployment/ccip/changeset/aptos/utils/utils.go new file mode 100644 index 00000000000..64b08db2ef4 --- /dev/null +++ b/deployment/ccip/changeset/aptos/utils/utils.go @@ -0,0 +1,38 @@ +package utils + +import ( + "fmt" + "strings" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink/deployment" +) + +// ConfirmTx confirms aptos transactions +// +// Optional arguments: +// - PollPeriod: time.Duration, how often to poll for the transaction. Default 100ms. +// - PollTimeout: time.Duration, how long to wait for the transaction. Default 10s. +func ConfirmTx(chain deployment.AptosChain, txHash string, opts ...any) error { + userTx, err := chain.Client.WaitForTransaction(txHash, opts...) + if err != nil { + return err + } + if !userTx.Success { + return fmt.Errorf("transaction failed: %s", userTx.VmStatus) + } + return nil +} + +func IsMCMSStagingAreaClean(client aptos.AptosRpcClient, aptosMCMSObjAddr aptos.AccountAddress) (bool, error) { + resources, err := client.AccountResources(aptosMCMSObjAddr) + if err != nil { + return false, err + } + for _, resource := range resources { + if strings.Contains(resource.Type, "StagingArea") { + return false, nil + } + } + return true, nil +} diff --git a/deployment/ccip/changeset/aptos_state.go b/deployment/ccip/changeset/aptos_state.go index fa0bde4eb4a..1ffe7400035 100644 --- a/deployment/ccip/changeset/aptos_state.go +++ b/deployment/ccip/changeset/aptos_state.go @@ -51,7 +51,7 @@ func loadAptosChainStateFromAddresses(addresses map[string]deployment.TypeAndVer chainState := AptosCCIPChainState{} for addrStr, typeAndVersion := range addresses { // Parse address - address := &aptos.AccountAddress{} + address := &aptos.AccountZero err := address.ParseStringRelaxed(addrStr) if err != nil { return chainState, fmt.Errorf("failed to parse address %s for %s: %w", addrStr, typeAndVersion.Type, err) diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 4cb21af29b0..85bf2c46a50 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -25,6 +25,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" solBinary "github.com/gagliardetto/binary" + solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" @@ -673,6 +674,13 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn } } + aptosChains := []uint64{} + for _, chain := range allChains { + if _, ok := e.Env.AptosChains[chain]; ok { + aptosChains = append(aptosChains, chain) + } + } + for _, chain := range evmChains { evmContractParams[chain] = v1_6.ChainContractParams{ FeeQuoterParams: v1_6.DefaultFeeQuoterParams(), @@ -820,6 +828,27 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn } } + for _, chain := range aptosChains { + // TODO(aptos): update this for token transfers + tokenInfo := map[cciptypes.UnknownEncodedAddress]pluginconfig.TokenInfo{} + linkTokenAddress := state.AptosChains[chain].LinkTokenAddress + tokenInfo[cciptypes.UnknownEncodedAddress(linkTokenAddress.String())] = tokenConfig.TokenSymbolToInfo[changeset.LinkSymbol] + + ocrOverride := tc.OCRConfigOverride + commitOCRConfigs[chain] = v1_6.DeriveOCRParamsForCommit(v1_6.SimulationTest, e.FeedChainSel, tokenInfo, ocrOverride) + execOCRConfigs[chain] = v1_6.DeriveOCRParamsForExec(v1_6.SimulationTest, tokenDataProviders, ocrOverride) + chainConfigs[chain] = v1_6.ChainConfig{ + Readers: nodeInfo.NonBootstraps().PeerIDs(), + // #nosec G115 - Overflow is not a concern in this test scenario + FChain: uint8(len(nodeInfo.NonBootstraps().PeerIDs()) / 3), + EncodableChainConfig: chainconfig.ChainConfig{ + GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.GasPriceDeviationPPB)}, + DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.DAGasPriceDeviationPPB)}, + OptimisticConfirmations: globals.OptimisticConfirmations, + }, + } + } + // Apply second set of changesets to configure the CCIP contracts. var mcmsConfig *proposalutils.TimelockConfig if mcmsEnabled { diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index b80c72ce603..5889754aa22 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -179,6 +179,13 @@ func SignMCMSProposal(t *testing.T, env deployment.Environment, proposal *mcmsli inspectorsMap[chainSel] = mcmssolanasdk.NewInspector(chain.Client) } + for _, chain := range env.AptosChains { + _, exists := chainsel.AptosChainBySelector(chain.Selector) + require.True(t, exists) + chainSel := mcmstypes.ChainSelector(chain.Selector) + inspectorsMap[chainSel] = mcmsaptossdk.NewInspector(chain.Client) + } + proposal.UseSimulatedBackend(true) signable, err := mcmslib.NewSignable(proposal, inspectorsMap) diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index f2ee54637b9..1da62f6aeb9 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -564,6 +564,28 @@ func CreateKeys(t *testing.T, } } + if len(aptoschains) > 0 { + ctype := chaintype.Aptos + err = app.GetKeyStore().OCR2().EnsureKeys(ctx, ctype) + require.NoError(t, err) + keys, err := app.GetKeyStore().OCR2().GetAllOfType(ctype) + require.NoError(t, err) + require.Len(t, keys, 1) + keybundle := keys[0] + keybundles[ctype] = keybundle + + err = app.GetKeyStore().Aptos().EnsureKey(ctx) + require.NoError(t, err, "failed to create key for Aptos") + + aptoskeys, err := app.GetKeyStore().Aptos().GetAll() + require.NoError(t, err) + require.Len(t, aptoskeys, 1) + transmitter := aptoskeys[0] + for chainSelector := range aptoschains { + transmitters[chainSelector] = transmitter.ID() + } + } + return Keys{ PeerID: peerID, CSA: csaKey, diff --git a/deployment/go.mod b/deployment/go.mod index 9a28f1f31ee..799c0e89181 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -368,6 +368,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/smartcontractkit/chainlink-aptos/relayer v0.0.0-20250320162700-de7f1c0fd741 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect From 12da651e5ea31a94f2997a5e97c4a74fb6528afc Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 10 Apr 2025 02:24:40 -0300 Subject: [PATCH 026/136] feat: migrate to operations api | lane deployment cs --- .../ccip/changeset/aptos/config/chain.go | 93 +++++ .../config/{config.go => deploy_chain.go} | 0 .../ccip/changeset/aptos/config/lane.go | 163 +++++++++ .../ccip/changeset/aptos/config/lane_test.go | 177 ++++++++++ .../changeset/aptos/cs_deploy_aptos_chain.go | 100 ++---- .../aptos/cs_deploy_aptos_chain_test.go | 16 +- .../changeset/aptos/cs_update_aptos_lanes.go | 78 +++++ .../aptos/cs_update_aptos_lanes_test.go | 193 +++++++++++ .../ccip/changeset/aptos/operation/ccip.go | 324 +++++++++++------- .../changeset/aptos/operation/dependencies.go | 14 + .../changeset/aptos/operation/fee_quoter.go | 183 ++++++++++ .../ccip/changeset/aptos/operation/mcms.go | 126 ++++--- .../changeset/aptos/operation/off_ramp.go | 92 +++++ .../ccip/changeset/aptos/operation/on_ramp.go | 85 +++++ .../ccip/changeset/aptos/operation/version.go | 5 + .../changeset/aptos/sequence/deploy_ccip.go | 101 ++++++ .../changeset/aptos/sequence/deploy_mcms.go | 66 ++++ .../changeset/aptos/sequence/update_lane.go | 157 +++++++++ .../ccip/changeset/aptos/test_helpers.go | 2 +- .../ccip/changeset/aptos/utils/utils.go | 2 + .../changeset/internal/deploy_home_chain.go | 7 + deployment/ccip/changeset/state.go | 3 + .../testhelpers/aptos_test_helper.go | 26 ++ .../changeset/testhelpers/test_environment.go | 8 +- .../ccip/changeset/v1_6/cs_chain_contracts.go | 2 + .../v1_6/cs_update_bidirectional_lanes.go | 17 +- 26 files changed, 1783 insertions(+), 257 deletions(-) create mode 100644 deployment/ccip/changeset/aptos/config/chain.go rename deployment/ccip/changeset/aptos/config/{config.go => deploy_chain.go} (100%) create mode 100644 deployment/ccip/changeset/aptos/config/lane.go create mode 100644 deployment/ccip/changeset/aptos/config/lane_test.go create mode 100644 deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go create mode 100644 deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go create mode 100644 deployment/ccip/changeset/aptos/operation/dependencies.go create mode 100644 deployment/ccip/changeset/aptos/operation/fee_quoter.go create mode 100644 deployment/ccip/changeset/aptos/operation/off_ramp.go create mode 100644 deployment/ccip/changeset/aptos/operation/on_ramp.go create mode 100644 deployment/ccip/changeset/aptos/operation/version.go create mode 100644 deployment/ccip/changeset/aptos/sequence/deploy_ccip.go create mode 100644 deployment/ccip/changeset/aptos/sequence/deploy_mcms.go create mode 100644 deployment/ccip/changeset/aptos/sequence/update_lane.go create mode 100644 deployment/ccip/changeset/testhelpers/aptos_test_helper.go diff --git a/deployment/ccip/changeset/aptos/config/chain.go b/deployment/ccip/changeset/aptos/config/chain.go new file mode 100644 index 00000000000..6294143f018 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/chain.go @@ -0,0 +1,93 @@ +package config + +import ( + "math/big" + + chainsel "github.com/smartcontractkit/chain-selectors" + aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + evm_fee_quoter "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" +) + +type IChainDefinition interface { + GetChainFamily() string +} + +type EVMChainDefinition struct { + v1_6.ChainDefinition +} + +func (c EVMChainDefinition) GetChainFamily() string { + return chainsel.FamilyEVM +} + +func (c EVMChainDefinition) GetConvertedAptosFeeQuoterConfig() aptos_fee_quoter.DestChainConfig { + efqc := c.FeeQuoterDestChainConfig + // Handle the byte slice to fixed-size array conversion + return aptos_fee_quoter.DestChainConfig{ + IsEnabled: efqc.IsEnabled, + MaxNumberOfTokensPerMsg: efqc.MaxNumberOfTokensPerMsg, + MaxDataBytes: efqc.MaxDataBytes, + MaxPerMsgGasLimit: efqc.MaxPerMsgGasLimit, + DestGasOverhead: efqc.DestGasOverhead, + DestGasPerPayloadByteBase: efqc.DestGasPerPayloadByteBase, + DestGasPerPayloadByteHigh: efqc.DestGasPerPayloadByteHigh, + DestGasPerPayloadByteThreshold: efqc.DestGasPerPayloadByteThreshold, + DestDataAvailabilityOverheadGas: efqc.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: efqc.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: efqc.DestDataAvailabilityMultiplierBps, + ChainFamilySelector: efqc.ChainFamilySelector[:], + EnforceOutOfOrder: efqc.EnforceOutOfOrder, + DefaultTokenFeeUsdCents: efqc.DefaultTokenFeeUSDCents, + DefaultTokenDestGasOverhead: efqc.DefaultTokenDestGasOverhead, + DefaultTxGasLimit: efqc.DefaultTxGasLimit, + GasMultiplierWeiPerEth: efqc.GasMultiplierWeiPerEth, + GasPriceStalenessThreshold: efqc.GasPriceStalenessThreshold, + NetworkFeeUsdCents: efqc.NetworkFeeUSDCents, + } +} + +type AptosChainDefinition struct { + // ConnectionConfig holds configuration for connection. + v1_6.ConnectionConfig `json:"connectionConfig"` + // Selector is the chain selector of this chain. + Selector uint64 `json:"selector"` + // GasPrice defines the USD price (18 decimals) per unit gas for this chain as a destination. + GasPrice *big.Int `json:"gasPrice"` + // FeeQuoterDestChainConfig is the configuration on a fee quoter for this chain as a destination. + FeeQuoterDestChainConfig aptos_fee_quoter.DestChainConfig `json:"feeQuoterDestChainConfig"` +} + +func (c AptosChainDefinition) GetChainFamily() string { + return chainsel.FamilyAptos +} + +func (c AptosChainDefinition) GetConvertedEVMFeeQuoterConfig() evm_fee_quoter.FeeQuoterDestChainConfig { + afqc := c.FeeQuoterDestChainConfig + // Handle the byte slice to fixed-size array conversion + var chainFamilySelector [4]byte + // Copy up to 4 bytes, zero-padding if source is shorter + copy(chainFamilySelector[:], afqc.ChainFamilySelector) + + return evm_fee_quoter.FeeQuoterDestChainConfig{ + IsEnabled: afqc.IsEnabled, + MaxNumberOfTokensPerMsg: afqc.MaxNumberOfTokensPerMsg, + MaxDataBytes: afqc.MaxDataBytes, + MaxPerMsgGasLimit: afqc.MaxPerMsgGasLimit, + DestGasOverhead: afqc.DestGasOverhead, + DestGasPerPayloadByteBase: uint8(afqc.DestGasPerPayloadByteBase), + DestGasPerPayloadByteHigh: uint8(afqc.DestGasPerPayloadByteHigh), + DestGasPerPayloadByteThreshold: afqc.DestGasPerPayloadByteThreshold, + DestDataAvailabilityOverheadGas: afqc.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: afqc.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: afqc.DestDataAvailabilityMultiplierBps, + ChainFamilySelector: chainFamilySelector, + EnforceOutOfOrder: afqc.EnforceOutOfOrder, + DefaultTokenFeeUSDCents: afqc.DefaultTokenFeeUsdCents, + DefaultTokenDestGasOverhead: afqc.DefaultTokenDestGasOverhead, + DefaultTxGasLimit: afqc.DefaultTxGasLimit, + GasMultiplierWeiPerEth: afqc.GasMultiplierWeiPerEth, + GasPriceStalenessThreshold: afqc.GasPriceStalenessThreshold, + NetworkFeeUSDCents: afqc.NetworkFeeUsdCents, + } +} diff --git a/deployment/ccip/changeset/aptos/config/config.go b/deployment/ccip/changeset/aptos/config/deploy_chain.go similarity index 100% rename from deployment/ccip/changeset/aptos/config/config.go rename to deployment/ccip/changeset/aptos/config/deploy_chain.go diff --git a/deployment/ccip/changeset/aptos/config/lane.go b/deployment/ccip/changeset/aptos/config/lane.go new file mode 100644 index 00000000000..d0b8794f022 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/lane.go @@ -0,0 +1,163 @@ +package config + +import ( + "math/big" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" +) + +type LaneConfig struct { + Source IChainDefinition + Dest IChainDefinition + IsDisabled bool +} + +// UpdateAptosLanesConfig is a configuration struct for AddAptosLanesChangeset +// Lanes accept different chain families +type UpdateAptosLanesConfig struct { + // MCMSConfig defines the MCMS configuration for the changeset. + MCMSConfig *proposalutils.TimelockConfig + // Lanes describes the lanes that we want to create. + Lanes []LaneConfig + // TestRouter indicates if we want to enable these lanes on the test router. + TestRouter bool +} + +// ToEVMUpdateLanesConfig adapts the Aptos Add Lanes config to EVM Update Lanes Config +// It adapts all Aptos <> EVM lanes to v1_6.UpdateBidirectionalLanesChangesetConfigs type to be used in UpdateLanesLogic "sequence" +func ToEVMUpdateLanesConfig(aptosAddCfg UpdateAptosLanesConfig) v1_6.UpdateBidirectionalLanesChangesetConfigs { + onRampUpdatesByChain := make(map[uint64]map[uint64]v1_6.OnRampDestinationUpdate) + offRampUpdatesByChain := make(map[uint64]map[uint64]v1_6.OffRampSourceUpdate) + routerUpdatesByChain := make(map[uint64]v1_6.RouterUpdates) + feeQuoterDestUpdatesByChain := make(map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig) + feeQuoterPriceUpdatesByChain := make(map[uint64]v1_6.FeeQuoterPriceUpdatePerSource) + + for _, lane := range aptosAddCfg.Lanes { + if lane.Source.GetChainFamily() == chainsel.FamilyEVM { + setEVMSourceUpdates( + lane, + onRampUpdatesByChain, + routerUpdatesByChain, + feeQuoterDestUpdatesByChain, + feeQuoterPriceUpdatesByChain, + aptosAddCfg.TestRouter, + ) + } + if lane.Dest.GetChainFamily() == chainsel.FamilyEVM { + setEVMDestUpdates( + lane, + routerUpdatesByChain, + offRampUpdatesByChain, + aptosAddCfg.TestRouter, + ) + } + } + + routerMCMSConfig := aptosAddCfg.MCMSConfig + if aptosAddCfg.TestRouter { + routerMCMSConfig = nil // Test router is never owned by MCMS + } + + return v1_6.UpdateBidirectionalLanesChangesetConfigs{ + UpdateFeeQuoterDestsConfig: v1_6.UpdateFeeQuoterDestsConfig{ + MCMS: aptosAddCfg.MCMSConfig, + UpdatesByChain: feeQuoterDestUpdatesByChain, + }, + UpdateFeeQuoterPricesConfig: v1_6.UpdateFeeQuoterPricesConfig{ + MCMS: aptosAddCfg.MCMSConfig, + PricesByChain: feeQuoterPriceUpdatesByChain, + }, + UpdateOnRampDestsConfig: v1_6.UpdateOnRampDestsConfig{ + MCMS: aptosAddCfg.MCMSConfig, + UpdatesByChain: onRampUpdatesByChain, + }, + UpdateOffRampSourcesConfig: v1_6.UpdateOffRampSourcesConfig{ + MCMS: aptosAddCfg.MCMSConfig, + UpdatesByChain: offRampUpdatesByChain, + }, + UpdateRouterRampsConfig: v1_6.UpdateRouterRampsConfig{ + TestRouter: aptosAddCfg.TestRouter, + MCMS: routerMCMSConfig, + UpdatesByChain: routerUpdatesByChain, + }, + } +} + +// setEVMSourceUpdates requires Source: EVM -> Destination: Aptos +func setEVMSourceUpdates( + lane LaneConfig, + onRampUpdatesByChain map[uint64]map[uint64]v1_6.OnRampDestinationUpdate, + routerUpdatesByChain map[uint64]v1_6.RouterUpdates, + feeQuoterDestUpdatesByChain map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig, + feeQuoterPriceUpdatesByChain map[uint64]v1_6.FeeQuoterPriceUpdatePerSource, + isTestRouter bool, +) { + source := lane.Source.(EVMChainDefinition) + dest := lane.Dest.(AptosChainDefinition) + isEnabled := !lane.IsDisabled + + // Setting the destination on the on ramp + if onRampUpdatesByChain[source.Selector] == nil { + onRampUpdatesByChain[source.Selector] = make(map[uint64]v1_6.OnRampDestinationUpdate) + } + onRampUpdatesByChain[source.Selector][dest.Selector] = v1_6.OnRampDestinationUpdate{ + IsEnabled: isEnabled, + TestRouter: isTestRouter, + AllowListEnabled: dest.AllowListEnabled, + } + + // Setting the on ramp on the source router + routerUpdatesOnSource := routerUpdatesByChain[source.Selector] + if routerUpdatesByChain[source.Selector].OnRampUpdates == nil { + routerUpdatesOnSource.OnRampUpdates = make(map[uint64]bool) + } + routerUpdatesOnSource.OnRampUpdates[dest.Selector] = isEnabled + routerUpdatesByChain[source.Selector] = routerUpdatesOnSource + + // Setting the fee quoter destination on the source chain + if feeQuoterDestUpdatesByChain[source.Selector] == nil { + feeQuoterDestUpdatesByChain[source.Selector] = make(map[uint64]fee_quoter.FeeQuoterDestChainConfig) + } + feeQuoterDestUpdatesByChain[source.Selector][dest.Selector] = dest.GetConvertedEVMFeeQuoterConfig() + + // Setting the destination gas prices on the source chain + feeQuoterPriceUpdatesOnSource := feeQuoterPriceUpdatesByChain[source.Selector] + if feeQuoterPriceUpdatesOnSource.GasPrices == nil { + feeQuoterPriceUpdatesOnSource.GasPrices = make(map[uint64]*big.Int) + } + feeQuoterPriceUpdatesOnSource.GasPrices[dest.Selector] = dest.GasPrice + feeQuoterPriceUpdatesByChain[source.Selector] = feeQuoterPriceUpdatesOnSource +} + +// setEVMSourceUpdates requires Source: Aptos -> Destination: EVM +func setEVMDestUpdates( + lane LaneConfig, + routerUpdatesByChain map[uint64]v1_6.RouterUpdates, + offRampUpdatesByChain map[uint64]map[uint64]v1_6.OffRampSourceUpdate, + isTestRouter bool, +) { + source := lane.Source.(AptosChainDefinition) + dest := lane.Dest.(EVMChainDefinition) + isEnabled := !lane.IsDisabled + + // Setting the source on the off ramp + if offRampUpdatesByChain[dest.Selector] == nil { + offRampUpdatesByChain[dest.Selector] = make(map[uint64]v1_6.OffRampSourceUpdate) + } + offRampUpdatesByChain[dest.Selector][source.Selector] = v1_6.OffRampSourceUpdate{ + IsEnabled: isEnabled, + TestRouter: isTestRouter, + IsRMNVerificationDisabled: source.RMNVerificationDisabled, + } + + // Setting the off ramp on the dest router + routerUpdatesOnDest := routerUpdatesByChain[dest.Selector] + if routerUpdatesByChain[dest.Selector].OffRampUpdates == nil { + routerUpdatesOnDest.OffRampUpdates = make(map[uint64]bool) + } + routerUpdatesOnDest.OffRampUpdates[source.Selector] = isEnabled + routerUpdatesByChain[dest.Selector] = routerUpdatesOnDest +} diff --git a/deployment/ccip/changeset/aptos/config/lane_test.go b/deployment/ccip/changeset/aptos/config/lane_test.go new file mode 100644 index 00000000000..4b695a24596 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/lane_test.go @@ -0,0 +1,177 @@ +package config + +import ( + "encoding/hex" + "math/big" + "testing" + + aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/stretchr/testify/assert" + "github.com/test-go/testify/require" +) + +func TestToEVMUpdateLanesConfig(t *testing.T) { + tests := []struct { + name string + input UpdateAptosLanesConfig + expected v1_6.UpdateBidirectionalLanesChangesetConfigs + }{ + { + name: "EVM <> Aptos Biderectional Lane", + input: UpdateAptosLanesConfig{ + MCMSConfig: &proposalutils.TimelockConfig{}, + Lanes: []LaneConfig{ + { + Source: getEVMDef(), + Dest: getAptosDef(t), + IsDisabled: false, + }, + { + Source: getAptosDef(t), + Dest: getEVMDef(), + IsDisabled: false, + }, + }, + TestRouter: false, + }, + expected: v1_6.UpdateBidirectionalLanesChangesetConfigs{ + UpdateFeeQuoterDestsConfig: v1_6.UpdateFeeQuoterDestsConfig{ + MCMS: &proposalutils.TimelockConfig{}, + UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ + 1881: { + 4457093679053095497: fee_quoter.FeeQuoterDestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 11, + MaxDataBytes: 40_000, + MaxPerMsgGasLimit: 4_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DefaultTokenFeeUSDCents: 30, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 700, + DestGasPerDataAvailabilityByte: 17, + DestDataAvailabilityMultiplierBps: 2, + DefaultTokenDestGasOverhead: 100_000, + DefaultTxGasLimit: 100_000, + GasMultiplierWeiPerEth: 12e17, + NetworkFeeUSDCents: 20, + EnforceOutOfOrder: false, + GasPriceStalenessThreshold: 2, + ChainFamilySelector: [4]byte{0xac, 0x77, 0xff, 0xec}, // From AptosFamilySelector "ac77ffec" + }, + }, + }, + }, + UpdateFeeQuoterPricesConfig: v1_6.UpdateFeeQuoterPricesConfig{ + MCMS: &proposalutils.TimelockConfig{}, + PricesByChain: map[uint64]v1_6.FeeQuoterPriceUpdatePerSource{ + 1881: { + GasPrices: map[uint64]*big.Int{ + 4457093679053095497: big.NewInt(100), + }, + }, + }, + }, + UpdateOnRampDestsConfig: v1_6.UpdateOnRampDestsConfig{ + MCMS: &proposalutils.TimelockConfig{}, + UpdatesByChain: map[uint64]map[uint64]v1_6.OnRampDestinationUpdate{ + 1881: { + 4457093679053095497: v1_6.OnRampDestinationUpdate{ + IsEnabled: true, + TestRouter: false, + AllowListEnabled: true, + }, + }, + }, + }, + UpdateOffRampSourcesConfig: v1_6.UpdateOffRampSourcesConfig{ + MCMS: &proposalutils.TimelockConfig{}, + UpdatesByChain: map[uint64]map[uint64]v1_6.OffRampSourceUpdate{ + 1881: { + 4457093679053095497: v1_6.OffRampSourceUpdate{ + IsEnabled: true, + TestRouter: false, + IsRMNVerificationDisabled: false, + }, + }, + }, + }, + UpdateRouterRampsConfig: v1_6.UpdateRouterRampsConfig{ + TestRouter: false, + MCMS: &proposalutils.TimelockConfig{}, + UpdatesByChain: map[uint64]v1_6.RouterUpdates{ + 1881: { + OnRampUpdates: map[uint64]bool{ + 4457093679053095497: true, + }, + OffRampUpdates: map[uint64]bool{ + 4457093679053095497: true, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ToEVMUpdateLanesConfig(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} + +func getEVMDef() EVMChainDefinition { + return EVMChainDefinition{ + v1_6.ChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, + Selector: 1881, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + } +} + +func getAptosDef(t *testing.T) AptosChainDefinition { + return AptosChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{AllowListEnabled: true}, + Selector: 4457093679053095497, + GasPrice: big.NewInt(100), + FeeQuoterDestChainConfig: aptos_fee_quoter.DestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 11, + MaxDataBytes: 40_000, + MaxPerMsgGasLimit: 4_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DefaultTokenFeeUsdCents: 30, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 700, + DestGasPerDataAvailabilityByte: 17, + DestDataAvailabilityMultiplierBps: 2, + DefaultTokenDestGasOverhead: 100_000, + DefaultTxGasLimit: 100_000, + GasMultiplierWeiPerEth: 12e17, + NetworkFeeUsdCents: 20, + ChainFamilySelector: hexMustDecode(t, v1_6.AptosFamilySelector), + EnforceOutOfOrder: false, + GasPriceStalenessThreshold: 2, + }, + } +} + +func hexMustDecode(t *testing.T, s string) []byte { + b, err := hex.DecodeString(s) + require.NoError(t, err) + return b +} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index e12ab1086e9..c8e33bc7331 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -10,6 +10,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" ) @@ -56,103 +58,47 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo } ab := deployment.NewMemoryAddressBook() - proposals := &[]mcms.Proposal{} + proposals := []mcms.Proposal{} + seqReports := make([]operations.Report[any, any], 0) // Deploy CCIP on each Aptos chain in config for chainSel := range config.ContractParamsPerChain { chainState := state[chainSel] aptosChain := env.AptosChains[chainSel] - // MCMS Deploy operations - opsMCMS := operation.MCMSDeploymentOperations{ - Env: env, - Ab: ab, + deps := operation.AptosDeps{ + AB: ab, AptosChain: aptosChain, OnChainState: chainState, - MCMSConfigs: config.MCMSConfigPerChain[chainSel], - Proposals: proposals, - MCMSOpCount: 0, } - err := runMCMSDeployOperations(&opsMCMS) + + // MCMS Deploy operations + mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSConfigPerChain[chainSel]) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy MCMS for Aptos chain %d: %w", chainSel, err) + return deployment.ChangesetOutput{}, err } + seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) + proposals = append(proposals, *mcmsSeqReport.Output.MCMSProposal) // CCIP Deploy operations - ccipOps := operation.CCIPDeploymentOperations{ - Env: env, - Ab: ab, - AptosChain: aptosChain, - OnChainState: opsMCMS.OnChainState, - CCIPConfig: config.ContractParamsPerChain[chainSel], - Proposals: proposals, - MCMSOpCount: opsMCMS.MCMSOpCount, + ccipSeqInput := seq.DeployCCIPSeqInput{ + MCMSAddress: mcmsSeqReport.Output.MCMSAddress, + MCMSOpCount: mcmsSeqReport.Output.NextOpCount, + CCIPConfig: config.ContractParamsPerChain[chainSel], } - err = runCCIPDeployOperations(&ccipOps) + ccipSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployCCIPSequence, deps, ccipSeqInput) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) } + seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) + for _, proposal := range ccipSeqReport.Output.MCMSProposals { + proposals = append(proposals, *proposal) + } } return deployment.ChangesetOutput{ AddressBook: ab, - MCMSProposals: *proposals, + MCMSProposals: proposals, + Reports: seqReports, }, nil } - -func runMCMSDeployOperations(ops *operation.MCMSDeploymentOperations) error { - // Check if MCMS package is already deployed - if ops.OnChainState.MCMSAddress != aptos.AccountZero { - ops.Env.Logger.Infow("MCMS Package already deployed", "addr", ops.OnChainState.MCMSAddress.String()) - return nil - } - // Deploy MCMS - addressMCMS, contractMCMS, err := ops.DeployMCMS() - if err != nil { - return fmt.Errorf("failed to deploy MCMS contract: %w", err) - } - // Configure MCMS - err = ops.ConfigureMCMS(addressMCMS) - if err != nil { - return fmt.Errorf("failed to configure MCMS contract: %w", err) - } - // Transfer ownership to self - err = ops.TransferOwnershipToSelf(contractMCMS) - if err != nil { - return fmt.Errorf("failed to transfer ownership to self: %w", err) - } - // Generate proposal to transfer ownership to self - proposal, mcmsOpCount, err := ops.GenerateAcceptOwnershipProposal(addressMCMS, contractMCMS) - if err != nil { - return fmt.Errorf("failed to build AcceptOwnership proposal: %w", err) - } - *ops.Proposals = append(*ops.Proposals, *proposal) - ops.MCMSOpCount = mcmsOpCount - - return nil -} - -func runCCIPDeployOperations(ops *operation.CCIPDeploymentOperations) error { - // Cleanup MCMS staging area - err := ops.GenerateCleanupStagingProposal() - if err != nil { - return fmt.Errorf("failed to generate cleanup staging proposal: %w", err) - } - // Generate proposals - Deploy CCIP package - ccipObjectAddress, err := ops.GenerateDeployCCIPProposal() - if err != nil { - return fmt.Errorf("failed to generate CCIP deploy proposal: %w", err) - } - // Generate proposals - Deploy Router package - err = ops.GenerateDeployRouterProposal(ccipObjectAddress) - if err != nil { - return fmt.Errorf("failed to generate Router deploy proposal: %w", err) - } - // Generate proposals - Initialize CCIP package - err = ops.GenerateInitializeCCIPProposal(ccipObjectAddress) - if err != nil { - return fmt.Errorf("failed to generate CCIP initialize proposal: %w", err) - } - - return nil -} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 60414c4fa3a..48a5f080d52 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -39,8 +39,8 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ - 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), - 743186221051783445: getMockChainContractParams(t, 743186221051783445), + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), }, MCMSConfigPerChain: map[uint64]mcmstypes.Config{ 4457093679053095497: getMockMCMSConfig(t), @@ -71,8 +71,8 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ - 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), - 743186221051783445: getMockChainContractParams(t, 743186221051783445), + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), }, }, wantErr: false, @@ -98,8 +98,8 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ - 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), - 743186221051783445: getMockChainContractParams(t, 743186221051783445), + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), }, }, wantErrRe: `chain 743186221051783445 not found in env`, @@ -137,7 +137,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ - 4457093679053095497: getMockChainContractParams(t, 4457093679053095497), + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), }, // MCMSConfigPerChain is missing needed configs }, @@ -204,7 +204,7 @@ func TestDeployAptosChain_Apply(t *testing.T) { t.Log("Deployer: ", env.AptosChains[chainSelector].DeployerSigner) // Deploy CCIP to Aptos chain - mockCCIPParams := getMockChainContractParams(t, chainSelector) + mockCCIPParams := GetMockChainContractParams(t, chainSelector) ccipConfig := config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ chainSelector: mockCCIPParams, diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go new file mode 100644 index 00000000000..7876393f902 --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -0,0 +1,78 @@ +package aptos + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/mcms" +) + +var _ deployment.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} + +// AddAptosLane implements adding a new lane to an existing Aptos CCIP deployment +type AddAptosLanes struct{} + +func (cs AddAptosLanes) VerifyPreconditions(env deployment.Environment, cfg config.UpdateAptosLanesConfig) error { + // TODO: Implement verification logic - check chain selector validity, MCMS configuration, etc. + // Placeholder implementation to show expected structure + + // This EVM specific changeset will be called from within this Aptos changeset, hence, we're verifying it here + // TODO: this is an anti-pattern, change this once EVM changesets are refactored as Operations + evmUpdateCfg := config.ToEVMUpdateLanesConfig(cfg) + err := v1_6.UpdateLanesPrecondition(env, evmUpdateCfg) + if err != nil { + return err + } + return nil +} + +func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptosLanesConfig) (deployment.ChangesetOutput, error) { + timeLockProposals := []mcms.TimelockProposal{} + proposals := []mcms.Proposal{} + seqReports := make([]operations.Report[any, any], 0) + + // Add lane on EVM chains + // TODO: applying a changeset within another changeset is an anti-pattern. Using it here until EVM is refactored into Operations + evmUpdatesInput := config.ToEVMUpdateLanesConfig(cfg) + out, err := v1_6.UpdateLanesLogic(env, cfg.MCMSConfig, evmUpdatesInput) + if err != nil { + return deployment.ChangesetOutput{}, err + } + timeLockProposals = append(timeLockProposals, out.MCMSTimelockProposals...) + + // Add lane on Aptos chains + // Execute UpdateAptosLanesSequence for each aptos chain + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + } + + updateInputsByAptosChain := seq.ConvertToUpdateAptosLanesSeqInput(state.AptosChains, cfg) + for aptosChainSel, sequenceInput := range updateInputsByAptosChain { + deps := operation.AptosDeps{ + AptosChain: env.AptosChains[aptosChainSel], + OnChainState: state.AptosChains[aptosChainSel], + CCIPOnChainState: state, + } + // Execute the sequence + updateSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.UpdateAptosLanesSequence, deps, sequenceInput) + if err != nil { + return deployment.ChangesetOutput{}, err + } + seqReports = append(seqReports, updateSeqReport.ExecutionReports...) + proposals = append(proposals, updateSeqReport.Output...) + + } + + return deployment.ChangesetOutput{ + MCMSTimelockProposals: timeLockProposals, + MCMSProposals: proposals, + Reports: seqReports, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go new file mode 100644 index 00000000000..dc5f18e510e --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -0,0 +1,193 @@ +package aptos_test + +import ( + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + aptosfeequoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + + // "github.com/smartcontractkit/chainlink/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestInputSerializable(t *testing.T) { + input := seq.UpdateAptosLanesSeqInput{ + UpdateFeeQuoterDestsConfig: operation.UpdateFeeQuoterDestsInput{ + MCMSAddress: aptos.AccountAddress{}, + Updates: map[uint64]aptosfeequoter.DestChainConfig{}, + }, + UpdateFeeQuoterPricesConfig: operation.UpdateFeeQuoterPricesInput{ + MCMSAddress: aptos.AccountAddress{}, + Prices: operation.FeeQuoterPriceUpdatePerSource{}, + }, + UpdateOnRampDestsConfig: operation.UpdateOnRampDestsInput{ + MCMSAddress: aptos.AccountAddress{}, + Updates: map[uint64]v1_6.OnRampDestinationUpdate{}, + }, + UpdateOffRampSourcesConfig: operation.UpdateOffRampSourcesInput{ + MCMSAddress: aptos.AccountAddress{}, + Updates: map[uint64]v1_6.OffRampSourceUpdate{}, + }, + } + isSer := operations.IsSerializable(logger.TestLogger(t), input) + fmt.Println(isSer) +} + +func TestAddAptosLanes_Apply(t *testing.T) { + // Setup environment and config + deployedEnvironment, _ := testhelpers.NewMemoryEnvironment( + t, + testhelpers.WithAptosChains(1), + ) + env := deployedEnvironment.Env + + emvSelector := env.AllChainSelectors()[0] + emvSelector2 := env.AllChainSelectors()[1] + aptosSelector := uint64(4457093679053095497) + + // Get chain selectors + aptosChainSelectors := env.AllChainSelectorsAptos() + require.Equal(t, 1, len(aptosChainSelectors), "Expected exactly 1 Aptos chain ") + chainSelector := aptosChainSelectors[0] + t.Log("Deployer: ", env.AptosChains[chainSelector].DeployerSigner) + + // Deploy Lane + cfg := getMockUpdateConfig(t, emvSelector, emvSelector2, aptosSelector) + + // Apply the changeset + env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure(aptoscs.AddAptosLanes{}, cfg), + }) + require.NoError(t, err) + + state, err := changeset.LoadOnchainState(env) + require.NoError(t, err, "must load onchain state") + + // bind ccip aptos + aptosCCIPAddr := state.AptosChains[aptosSelector].CCIPAddress + aptosCCIP := ccip.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) + + is_enabled1, sequence_number1, allowlist_enabled1, err := aptosCCIP.Onramp().GetDestChainConfig(nil, emvSelector) + require.NoError(t, err) + require.True(t, is_enabled1) + require.True(t, sequence_number1 > 0) + require.True(t, allowlist_enabled1) + + is_enabled2, sequence_number2, allowlist_enabled2, err := aptosCCIP.Onramp().GetDestChainConfig(nil, emvSelector2) + require.NoError(t, err) + require.True(t, is_enabled2) + require.True(t, sequence_number2 > 0) + require.True(t, allowlist_enabled2) +} + +func getMockUpdateConfig( + t *testing.T, + emvSelector, + emvSelector2, + aptosSelector uint64, +) config.UpdateAptosLanesConfig { + return config.UpdateAptosLanesConfig{ + MCMSConfig: nil, + // Aptos1 <> EVM1 | Aptos1 -> EVM2 + Lanes: []config.LaneConfig{ + { + Source: config.AptosChainDefinition{ + Selector: aptosSelector, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: aptosTestDestFeeQuoterConfig(t), + }, + Dest: config.EVMChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ + Selector: emvSelector, + GasPrice: big.NewInt(1e17), + TokenPrices: map[common.Address]*big.Int{}, + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + }, + IsDisabled: false, + }, + { + Source: config.EVMChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ + Selector: emvSelector, + GasPrice: big.NewInt(1e17), + TokenPrices: map[common.Address]*big.Int{}, + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + }, + Dest: config.AptosChainDefinition{ + Selector: aptosSelector, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: aptosTestDestFeeQuoterConfig(t), + }, + IsDisabled: false, + }, + { + Source: config.AptosChainDefinition{ + Selector: aptosSelector, + GasPrice: big.NewInt(1e17), + FeeQuoterDestChainConfig: aptosTestDestFeeQuoterConfig(t), + }, + Dest: config.EVMChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ + Selector: emvSelector2, + GasPrice: big.NewInt(1e17), + TokenPrices: map[common.Address]*big.Int{}, + FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + }, + }, + IsDisabled: false, + }, + }, + TestRouter: true, + } +} + +// TODO: Deduplicate these test helpers +func aptosTestDestFeeQuoterConfig(t *testing.T) aptosfeequoter.DestChainConfig { + return aptosfeequoter.DestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 11, + MaxDataBytes: 40_000, + MaxPerMsgGasLimit: 4_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DefaultTokenFeeUsdCents: 30, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 700, + DestGasPerDataAvailabilityByte: 17, + DestDataAvailabilityMultiplierBps: 2, + DefaultTokenDestGasOverhead: 100_000, + DefaultTxGasLimit: 100_000, + GasMultiplierWeiPerEth: 12e17, + NetworkFeeUsdCents: 20, + ChainFamilySelector: hexMustDecode(t, v1_6.AptosFamilySelector), + EnforceOutOfOrder: false, + GasPriceStalenessThreshold: 2, + } +} + +func hexMustDecode(t *testing.T, s string) []byte { + b, err := hex.DecodeString(s) + require.NoError(t, err) + return b +} diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index 673af5b0eb8..fb168155286 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -13,42 +13,51 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) -type CCIPDeploymentOperations struct { - Env deployment.Environment - Ab *deployment.AddressBookMap - AptosChain deployment.AptosChain - OnChainState changeset.AptosCCIPChainState - CCIPConfig aptoscfg.ChainContractParams - Proposals *[]mcms.Proposal - MCMSOpCount uint64 +// Shared types +type MCMSProposalOutput struct { + MCMSProposal *mcms.Proposal + NextOpCount uint64 } -// GenerateCleanupStagingProposal generates cleanup MCMS operations for the staging area if it's not clean -func (op *CCIPDeploymentOperations) GenerateCleanupStagingProposal() error { +// CleanupStagingArea Operation +type CleanupStagingAreaInput struct { + MCMSAddress aptos.AccountAddress + MCMSOpCount uint64 +} + +var CleanupStagingAreaOp = operations.NewOperation( + "cleanup-staging-area-op", + Version1_0_0, + "Cleans up MCMS staging area if it's not already clean", + cleanupStagingArea, +) + +func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAreaInput) (MCMSProposalOutput, error) { // Check resources first to see if staging is clean - IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(op.AptosChain.Client, op.OnChainState.MCMSAddress) + IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(deps.AptosChain.Client, in.MCMSAddress) if err != nil { - return fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) } if IsMCMSStagingAreaClean { - op.Env.Logger.Infow("MCMS Staging Area already clean", "addr", op.OnChainState.MCMSAddress.String()) - return nil + b.Logger.Infow("MCMS Staging Area already clean", "addr", in.MCMSAddress.String()) + return MCMSProposalOutput{}, nil } // Bind MCMS contract - mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) mcmsAddress := mcmsContract.Address() // Get cleanup staging operations var operations []types.Operation moduleInfo, function, _, args, err := mcmsContract.MCMSDeployer().Encoder().CleanupStagingArea() if err != nil { - return fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -57,10 +66,10 @@ func (op *CCIPDeploymentOperations) GenerateCleanupStagingProposal() error { } afBytes, err := json.Marshal(additionalFields) if err != nil { - return fmt.Errorf("failed to marshal additional fields: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to marshal additional fields: %w", err) } operations = append(operations, types.Operation{ - ChainSelector: types.ChainSelector(op.AptosChain.Selector), + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), Transaction: types.Transaction{ To: mcmsAddress.StringLong(), Data: aptosmcms.ArgsToData(args), @@ -70,200 +79,259 @@ func (op *CCIPDeploymentOperations) GenerateCleanupStagingProposal() error { // Generate cleanup proposal proposal, nextOpCount, err := utils.GenerateProposal( - op.AptosChain.Client, + deps.AptosChain.Client, mcmsContract.Address(), - op.AptosChain.Selector, + deps.AptosChain.Selector, operations, "Cleanup Staging Area", - op.MCMSOpCount, + in.MCMSOpCount, ) - op.MCMSOpCount = nextOpCount if err != nil { - return fmt.Errorf("failed to create deploy proposal: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) } - *op.Proposals = append(*op.Proposals, *proposal) - return nil + return MCMSProposalOutput{proposal, nextOpCount}, nil +} + +// GenerateDeployCCIPProposal Operation generates deployment MCMS operations for the CCIP package +type DeployCCIPInput struct { + MCMSAddress aptos.AccountAddress + MCMSOpCount uint64 } -// GenerateDeployCCIPProposal generates deployment MCMS operations for the CCIP package -func (op *CCIPDeploymentOperations) GenerateDeployCCIPProposal() (*aptos.AccountAddress, error) { +type DeployCCIPOutput struct { + CCIPAddress aptos.AccountAddress + MCMSProposalOutput +} + +var GenerateDeployCCIPProposalOp = operations.NewOperation( + "deploy-ccip-op", + Version1_0_0, + "Deploys CCIP Package for Aptos Chain", + generateDeployCCIPProposal, +) + +func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { // Validate there's no package deployed - if op.OnChainState.CCIPAddress != aptos.AccountZero { - op.Env.Logger.Infow("CCIP Package already deployed", "addr", op.OnChainState.CCIPAddress.String()) - return &op.OnChainState.CCIPAddress, nil + if deps.OnChainState.CCIPAddress != aptos.AccountZero { + b.Logger.Infow("CCIP Package already deployed", "addr", deps.OnChainState.CCIPAddress.String()) + return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress, MCMSProposalOutput: MCMSProposalOutput{NextOpCount: in.MCMSOpCount}}, nil } // Compile, chunk and get CCIP deploy operations - mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) - ccipObjectAddress, operations, err := op.getCCIPDeployOperations(mcmsContract, op.AptosChain.Selector) + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + ccipObjectAddress, operations, err := getCCIPDeployMCMSOps(mcmsContract, deps.AptosChain.Selector) if err != nil { - return nil, fmt.Errorf("failed to compile and create deploy operations: %w", err) + return DeployCCIPOutput{}, fmt.Errorf("failed to compile and create deploy operations: %w", err) } // Save the address of the CCIP object typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) - op.Ab.Save(op.AptosChain.Selector, ccipObjectAddress.String(), typeAndVersion) - op.OnChainState.CCIPAddress = ccipObjectAddress + deps.AB.Save(deps.AptosChain.Selector, ccipObjectAddress.String(), typeAndVersion) + deps.OnChainState.CCIPAddress = ccipObjectAddress // Generate deploy proposal - proposal, nextOpCount, err := utils.GenerateProposal(op.AptosChain.Client, mcmsContract.Address(), op.AptosChain.Selector, operations, "Deploy CCIP Package", op.MCMSOpCount) - op.MCMSOpCount = nextOpCount + proposal, nextOpCount, err := utils.GenerateProposal(deps.AptosChain.Client, mcmsContract.Address(), deps.AptosChain.Selector, operations, "Deploy CCIP Package", in.MCMSOpCount) + if err != nil { + return DeployCCIPOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) + } + + return DeployCCIPOutput{ + CCIPAddress: ccipObjectAddress, + MCMSProposalOutput: MCMSProposalOutput{ + MCMSProposal: proposal, + NextOpCount: nextOpCount, + }, + }, nil +} + +func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.AccountAddress, []types.Operation, error) { + // Calculate addresses of the owner and the object + ccipObjectAddress, err := mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) + } + + // Compile Package + payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), true) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) if err != nil { - return nil, fmt.Errorf("failed to create deploy proposal: %w", err) + return ccipObjectAddress, operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) } - *op.Proposals = append(*op.Proposals, *proposal) - return &ccipObjectAddress, nil + return ccipObjectAddress, operations, nil } // GenerateDeployRouterProposal generates deployment MCMS operations for the Router module -func (op *CCIPDeploymentOperations) GenerateDeployRouterProposal(ccipObjectAddress *aptos.AccountAddress) error { +type DeployRouterInput struct { + MCMSAddress aptos.AccountAddress + CCIPAddress aptos.AccountAddress + MCMSOpCount uint64 +} + +var GenerateDeployRouterProposalOp = operations.NewOperation( + "deploy-router-op", + Version1_0_0, + "Deploys Router Package for CCIP", + generateDeployRouterProposal, +) + +func generateDeployRouterProposal(b operations.Bundle, deps AptosDeps, in DeployRouterInput) (MCMSProposalOutput, error) { // TODO: is there a way to check if module exists? // Compile, chunk and get Router deploy operations - mcmsContract := mcmsbind.Bind(op.OnChainState.MCMSAddress, op.AptosChain.Client) - operations, err := op.getRouterDeployOperations(mcmsContract, ccipObjectAddress) + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + operations, err := getRouterDeployMCMSOps(mcmsContract, in.CCIPAddress, deps.AptosChain.Selector) if err != nil { - return fmt.Errorf("failed to compile and create deploy operations: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to compile and create deploy operations: %w", err) } // Generate deploy proposal - proposal, nextOpCount, err := utils.GenerateProposal(op.AptosChain.Client, mcmsContract.Address(), op.AptosChain.Selector, operations, "Deploy Router Package", op.MCMSOpCount) - op.MCMSOpCount = nextOpCount + proposal, nextOpCount, err := utils.GenerateProposal( + deps.AptosChain.Client, + mcmsContract.Address(), + deps.AptosChain.Selector, + operations, + "Deploy Router Package", + in.MCMSOpCount, + ) if err != nil { - return fmt.Errorf("failed to create deploy proposal: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) } - *op.Proposals = append(*op.Proposals, *proposal) - return nil + return MCMSProposalOutput{ + MCMSProposal: proposal, + NextOpCount: nextOpCount, + }, nil } -func (op *CCIPDeploymentOperations) GenerateInitializeCCIPProposal(ccipObjectAddress *aptos.AccountAddress) error { +func getRouterDeployMCMSOps( + mcmsContract mcmsbind.MCMS, + ccipObjectAddress aptos.AccountAddress, + chainSel uint64, +) ([]types.Operation, error) { + // Compile Package + payload, err := router.Compile(ccipObjectAddress, mcmsContract.Address()) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, "", &ccipObjectAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) + } + + return operations, nil +} + +// InitializeCCIP Operation +type InitializeCCIPInput struct { + MCMSAddress aptos.AccountAddress + CCIPAddress aptos.AccountAddress + CCIPConfig aptoscfg.ChainContractParams + MCMSOpCount uint64 +} + +var InitializeCCIPOp = operations.NewOperation( + "initialize-ccip-op", + Version1_0_0, + "Initializes CCIP components with configuration parameters", + generateInitializeCCIPProposal, +) + +func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (MCMSProposalOutput, error) { var operations []types.Operation - ccipBind := ccip.Bind(*ccipObjectAddress, op.AptosChain.Client) + ccipBind := ccip.Bind(in.CCIPAddress, deps.AptosChain.Client) // Config OnRamp moduleInfo, function, _, args, err := ccipBind.Onramp().Encoder().Initialize( - op.AptosChain.Selector, - op.CCIPConfig.OnRampParams.AllowlistAdmin, - op.CCIPConfig.OnRampParams.DestChainSelectors, - op.CCIPConfig.OnRampParams.DestChainEnabled, - op.CCIPConfig.OnRampParams.DestChainAllowlistEnabled, + deps.AptosChain.Selector, + in.CCIPConfig.OnRampParams.AllowlistAdmin, + in.CCIPConfig.OnRampParams.DestChainSelectors, + in.CCIPConfig.OnRampParams.DestChainEnabled, + in.CCIPConfig.OnRampParams.DestChainAllowlistEnabled, ) if err != nil { - return fmt.Errorf("failed to encode onramp initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to encode onramp initialize: %w", err) } - mcmsOp, err := generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + mcmsOp, err := generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) } operations = append(operations, mcmsOp) // Config OffRamp moduleInfo, function, _, args, err = ccipBind.Offramp().Encoder().Initialize( - op.AptosChain.Selector, - op.CCIPConfig.OffRampParams.PermissionlessExecutionThreshold, - op.CCIPConfig.OffRampParams.SourceChainSelectors, - op.CCIPConfig.OffRampParams.SourceChainIsEnabled, - op.CCIPConfig.OffRampParams.IsRMNVerificationDisabled, - op.CCIPConfig.OffRampParams.SourceChainsOnRamp, + deps.AptosChain.Selector, + in.CCIPConfig.OffRampParams.PermissionlessExecutionThreshold, + in.CCIPConfig.OffRampParams.SourceChainSelectors, + in.CCIPConfig.OffRampParams.SourceChainIsEnabled, + in.CCIPConfig.OffRampParams.IsRMNVerificationDisabled, + in.CCIPConfig.OffRampParams.SourceChainsOnRamp, ) if err != nil { - return fmt.Errorf("failed to encode offramp initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to encode offramp initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) } operations = append(operations, mcmsOp) // Config FeeQuoter moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().Initialize( - op.AptosChain.Selector, - op.CCIPConfig.FeeQuoterParams.LinkToken, - op.CCIPConfig.FeeQuoterParams.TokenPriceStalenessThreshold, - op.CCIPConfig.FeeQuoterParams.FeeTokens, + deps.AptosChain.Selector, + in.CCIPConfig.FeeQuoterParams.LinkToken, + in.CCIPConfig.FeeQuoterParams.TokenPriceStalenessThreshold, + in.CCIPConfig.FeeQuoterParams.FeeTokens, ) if err != nil { - return fmt.Errorf("failed to encode feequoter initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to encode feequoter initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) } operations = append(operations, mcmsOp) // Config RMNRemote - moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(op.AptosChain.Selector) + moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(deps.AptosChain.Selector) if err != nil { - return fmt.Errorf("failed to encode rmnremote initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to encode rmnremote initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(op.AptosChain.Selector, ccipObjectAddress, moduleInfo, function, args) + mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) } operations = append(operations, mcmsOp) // Generate config proposal proposal, nextOpCount, err := utils.GenerateProposal( - op.AptosChain.Client, - op.OnChainState.MCMSAddress, - op.AptosChain.Selector, + deps.AptosChain.Client, + in.MCMSAddress, + deps.AptosChain.Selector, operations, "Initialize CCIP Package", - op.MCMSOpCount, + in.MCMSOpCount, ) - op.MCMSOpCount = nextOpCount if err != nil { - return fmt.Errorf("failed to create deploy proposal: %w", err) + return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) } - *op.Proposals = append(*op.Proposals, *proposal) - return nil -} - -func (op *CCIPDeploymentOperations) getCCIPDeployOperations(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.AccountAddress, []types.Operation, error) { - // Calculate addresses of the owner and the object - ccipObjectAddress, err := mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) - if err != nil { - return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) - } - - // Compile Package - payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), true) - if err != nil { - return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to compile: %w", err) - } - - // Create chunks and stage operations - operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) - if err != nil { - return ccipObjectAddress, operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) - } - - return ccipObjectAddress, operations, nil -} - -func (op *CCIPDeploymentOperations) getRouterDeployOperations( - mcmsContract mcmsbind.MCMS, - ccipObjectAddress *aptos.AccountAddress, -) ([]types.Operation, error) { - // Compile Package - payload, err := router.Compile(*ccipObjectAddress, mcmsContract.Address()) - if err != nil { - return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) - } - - // Create chunks and stage operations - operations, err := utils.CreateChunksAndStage(payload, mcmsContract, op.AptosChain.Selector, "", ccipObjectAddress) - if err != nil { - return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", op.AptosChain.Selector, err) - } + return MCMSProposalOutput{ + MCMSProposal: proposal, + NextOpCount: nextOpCount, + }, nil - return operations, nil } -func generateMCMSOperation(chainSel uint64, toAddress *aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Operation, error) { +// generateMCMSOperation is a helper function that generates a MCMS operation for the given parameters +func generateMCMSOperation(chainSel uint64, toAddress aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Operation, error) { additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, ModuleName: moduleInfo.ModuleName, diff --git a/deployment/ccip/changeset/aptos/operation/dependencies.go b/deployment/ccip/changeset/aptos/operation/dependencies.go new file mode 100644 index 00000000000..964abd34ed0 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/dependencies.go @@ -0,0 +1,14 @@ +package operation + +import ( + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" +) + +type AptosDeps struct { + AB *deployment.AddressBookMap + AptosChain deployment.AptosChain + // TODO: Refactor this? + OnChainState changeset.AptosCCIPChainState + CCIPOnChainState changeset.CCIPOnChainState +} diff --git a/deployment/ccip/changeset/aptos/operation/fee_quoter.go b/deployment/ccip/changeset/aptos/operation/fee_quoter.go new file mode 100644 index 00000000000..fe067549b4b --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/fee_quoter.go @@ -0,0 +1,183 @@ +package operation + +import ( + "encoding/json" + "fmt" + "math/big" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink/deployment/operations" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +// UpdateFeeQuoterDestsInput contains configuration for updating FeeQuoter destination configs +type UpdateFeeQuoterDestsInput struct { + MCMSAddress aptos.AccountAddress + Updates map[uint64]aptos_fee_quoter.DestChainConfig +} + +// UpdateFeeQuoterDestsOp operation to update FeeQuoter destination configurations +var UpdateFeeQuoterDestsOp = operations.NewOperation( + "update-fee-quoter-dests-op", + Version1_0_0, + "Updates FeeQuoter destination chain configurations", + updateFeeQuoterDests, +) + +func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterDestsInput) ([]types.Operation, error) { + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + + // Process each destination chain config update + var operations []types.Operation + + for destChainSelector, destConfig := range in.Updates { + // Encode the update operation + moduleInfo, function, _, args, err := ccipBind.FeeQuoter().Encoder().ApplyDestChainConfigUpdates( + destChainSelector, + destConfig.IsEnabled, + destConfig.MaxNumberOfTokensPerMsg, + destConfig.MaxDataBytes, + destConfig.MaxPerMsgGasLimit, + destConfig.DestGasOverhead, + destConfig.DestGasPerPayloadByteBase, + destConfig.DestGasPerPayloadByteHigh, + destConfig.DestGasPerPayloadByteThreshold, + destConfig.DestDataAvailabilityOverheadGas, + destConfig.DestGasPerDataAvailabilityByte, + destConfig.DestDataAvailabilityMultiplierBps, + destConfig.ChainFamilySelector, + destConfig.EnforceOutOfOrder, + destConfig.DefaultTokenFeeUsdCents, + destConfig.DefaultTokenDestGasOverhead, + destConfig.DefaultTxGasLimit, + destConfig.GasMultiplierWeiPerEth, + destConfig.GasPriceStalenessThreshold, + destConfig.NetworkFeeUsdCents, + ) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for chain %d: %w", destChainSelector, err) + } + + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + operations = append(operations, types.Operation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transaction: types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }) + + b.Logger.Infow("Adding FeeQuoter destination config update operation", + "destChainSelector", destChainSelector, + "isEnabled", destConfig.IsEnabled) + } + + return operations, nil +} + +// UpdateFeeQuoterPricesInput contains configuration for updating FeeQuoter price configs +type UpdateFeeQuoterPricesInput struct { + MCMSAddress aptos.AccountAddress + Prices FeeQuoterPriceUpdatePerSource +} + +type FeeQuoterPriceUpdatePerSource struct { + TokenPrices map[string]*big.Int // token address (string) -> price + GasPrices map[uint64]*big.Int // dest chain -> gas price +} + +// UpdateFeeQuoterPricesOp operation to update FeeQuoter prices +var UpdateFeeQuoterPricesOp = operations.NewOperation( + "update-fee-quoter-prices-op", + Version1_0_0, + "Updates FeeQuoter token and gas prices", + updateFeeQuoterPrices, +) + +func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterPricesInput) ([]types.Operation, error) { + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + + // Convert token prices and gas prices to format expected by Aptos contract + var sourceTokens []aptos.AccountAddress + var sourceUsdPerToken []*big.Int + var gasDestChainSelectors []uint64 + var gasUsdPerUnitGas []*big.Int + + // Process token prices if any + for tokenAddr, price := range in.Prices.TokenPrices { + address := aptos.AccountAddress{} + err := address.ParseStringRelaxed(tokenAddr) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to parse Aptos token address %s: %w", tokenAddr, err) + } + sourceTokens = append(sourceTokens, address) + sourceUsdPerToken = append(sourceUsdPerToken, price) + } + + // Process gas prices if any + for destChainSel, gasPrice := range in.Prices.GasPrices { + gasDestChainSelectors = append(gasDestChainSelectors, destChainSel) + gasUsdPerUnitGas = append(gasUsdPerUnitGas, gasPrice) + } + + // Generate MCMS operation to update prices + var operations []types.Operation + + if len(sourceTokens) == 0 && len(gasDestChainSelectors) == 0 { + b.Logger.Infow("No price updates to apply") + return operations, nil + } + // Encode the update operation + moduleInfo, function, _, args, err := ccipBind.FeeQuoter().Encoder().UpdatePrices( + sourceTokens, + sourceUsdPerToken, + gasDestChainSelectors, + gasUsdPerUnitGas, + ) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to encode UpdatePrices: %w", err) + } + + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + operations = append(operations, types.Operation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transaction: types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }) + + b.Logger.Infow("Adding FeeQuoter price update operation", + "tokenPriceCount", len(sourceTokens), + "gasPriceCount", len(gasDestChainSelectors), + ) + + return operations, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 1ca8ad35cc8..a60cad21b15 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -15,66 +15,104 @@ import ( "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/chainlink/deployment/operations" ) const AcceptOwnershipProposalDescription = "Accept ownership of the contract to self" -type MCMSDeploymentOperations struct { - Env deployment.Environment - Ab *deployment.AddressBookMap - AptosChain deployment.AptosChain - OnChainState changeset.AptosCCIPChainState - MCMSConfigs mcmstypes.Config - Proposals *[]mcms.Proposal - MCMSOpCount uint64 +var DeployMCMSOp = operations.NewOperation( + "deploy-mcms-op", + Version1_0_0, + "Deploys MCMS Contract Operation for Aptos Chain", + deployMCMS, +) + +type DeployMCMSOutput struct { + AddressMCMS aptos.AccountAddress + ContractMCMS *mcmsbind.MCMS // TODO: outputs should be serializable } -func (op *MCMSDeploymentOperations) DeployMCMS() (aptos.AccountAddress, mcmsbind.MCMS, error) { +func deployMCMS(b operations.Bundle, deps AptosDeps, input operations.EmptyInput) (DeployMCMSOutput, error) { mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() - addressMCMS, mcmsDeployTx, contractMCMS, err := mcmsbind.DeployToResourceAccount(op.AptosChain.DeployerSigner, op.AptosChain.Client, mcmsSeed) + addressMCMS, mcmsDeployTx, contractMCMS, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) if err != nil { - return aptos.AccountZero, mcmsbind.MCMSContract{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) + return DeployMCMSOutput{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) } - if err := utils.ConfirmTx(op.AptosChain, mcmsDeployTx.Hash); err != nil { - return aptos.AccountZero, mcmsbind.MCMSContract{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) + if err := utils.ConfirmTx(deps.AptosChain, mcmsDeployTx.Hash); err != nil { + return DeployMCMSOutput{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) } typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_0_0) - op.Ab.Save(op.AptosChain.Selector, addressMCMS.String(), typeAndVersion) - op.OnChainState.MCMSAddress = addressMCMS - return addressMCMS, contractMCMS, nil + deps.AB.Save(deps.AptosChain.Selector, addressMCMS.String(), typeAndVersion) + return DeployMCMSOutput{addressMCMS, &contractMCMS}, nil +} + +type ConfigureMCMSInput struct { + AddressMCMS aptos.AccountAddress + MCMSConfigs mcmstypes.Config } -func (op *MCMSDeploymentOperations) ConfigureMCMS(addressMCMS aptos.AccountAddress) error { - configurer := aptosmcms.NewConfigurer(op.AptosChain.Client, op.AptosChain.DeployerSigner) - setCfgTx, err := configurer.SetConfig(context.Background(), addressMCMS.StringLong(), &op.MCMSConfigs, false) +var ConfigureMCMSOp = operations.NewOperation( + "configure-mcms-op", + Version1_0_0, + "Configure MCMS Contract Operation for Aptos Chain", + configureMCMS, +) + +func configureMCMS(b operations.Bundle, deps AptosDeps, in ConfigureMCMSInput) (any, error) { + configurer := aptosmcms.NewConfigurer(deps.AptosChain.Client, deps.AptosChain.DeployerSigner) + setCfgTx, err := configurer.SetConfig(context.Background(), in.AddressMCMS.StringLong(), &in.MCMSConfigs, false) if err != nil { - return fmt.Errorf("failed to setConfig in MCMS contract: %w", err) + return nil, fmt.Errorf("failed to setConfig in MCMS contract: %w", err) } - if err := utils.ConfirmTx(op.AptosChain, setCfgTx.Hash); err != nil { - return fmt.Errorf("MCMS setConfig transaction failed: %w", err) + if err := utils.ConfirmTx(deps.AptosChain, setCfgTx.Hash); err != nil { + return nil, fmt.Errorf("MCMS setConfig transaction failed: %w", err) } - return nil + return nil, nil } -func (op *MCMSDeploymentOperations) TransferOwnershipToSelf(contractMCMS mcmsbind.MCMS) error { - opts := &bind.TransactOpts{Signer: op.AptosChain.DeployerSigner} - tx, err := contractMCMS.MCMSAccount().TransferOwnershipToSelf(opts) +var TransferOwnershipToSelfOp = operations.NewOperation( + "transfer-ownership-to-self-op", + Version1_0_0, + "Transfer ownership to self", + transferOwnershipToSelf, +) + +func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, contractMCMS *mcmsbind.MCMS) (any, error) { + opts := &bind.TransactOpts{Signer: deps.AptosChain.DeployerSigner} + tx, err := (*contractMCMS).MCMSAccount().TransferOwnershipToSelf(opts) if err != nil { - return fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) + return nil, fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) } - _, err = op.AptosChain.Client.WaitForTransaction(tx.Hash) + _, err = deps.AptosChain.Client.WaitForTransaction(tx.Hash) if err != nil { - return fmt.Errorf("MCMS TransferOwnershipToSelf transaction failed: %w", err) + return nil, fmt.Errorf("MCMS TransferOwnershipToSelf transaction failed: %w", err) } - return nil + return nil, nil +} + +type GenerateAcceptOwnershipProposalInput struct { + AddressMCMS aptos.AccountAddress + ContractMCMS *mcmsbind.MCMS // TODO: outputs should be serializable } -func (op *MCMSDeploymentOperations) GenerateAcceptOwnershipProposal(addressMCMS aptos.AccountAddress, contractMCMS mcmsbind.MCMS) (*mcms.Proposal, uint64, error) { - var operations []mcmstypes.Operation - moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() +type GenerateAcceptOwnershipProposalOutput struct { + MCMSProposal *mcms.Proposal + NextOpCount uint64 +} + +var GenerateAcceptOwnershipProposalOp = operations.NewOperation( + "generate-accept-ownership-proposal-op", + Version1_0_0, + "Generate Accept Ownership Proposal for MCMS Contract", + generateAcceptOwnershipProposal, +) + +func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) (GenerateAcceptOwnershipProposalOutput, error) { + moduleInfo, function, _, args, err := (*in.ContractMCMS).MCMSAccount().Encoder().AcceptOwnership() if err != nil { - return nil, 0, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + return GenerateAcceptOwnershipProposalOutput{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -83,16 +121,24 @@ func (op *MCMSDeploymentOperations) GenerateAcceptOwnershipProposal(addressMCMS } callOneAdditionalFields, err := json.Marshal(additionalFields) if err != nil { - return nil, 0, fmt.Errorf("failed to marshal additionalFields: %w", err) + return GenerateAcceptOwnershipProposalOutput{}, fmt.Errorf("failed to marshal additionalFields: %w", err) } - operations = append(operations, mcmstypes.Operation{ - ChainSelector: mcmstypes.ChainSelector(op.AptosChain.Selector), + mcmsOps := []mcmstypes.Operation{{ + ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), Transaction: mcmstypes.Transaction{ - To: addressMCMS.StringLong(), + To: in.AddressMCMS.StringLong(), Data: aptosmcms.ArgsToData(args), AdditionalFields: callOneAdditionalFields, }, - }) + }} + mcmsProposal, nextOpCount, err := utils.GenerateProposal( + deps.AptosChain.Client, + (*in.ContractMCMS).Address(), + deps.AptosChain.Selector, + mcmsOps, + AcceptOwnershipProposalDescription, + 0, + ) - return utils.GenerateProposal(op.AptosChain.Client, contractMCMS.Address(), op.AptosChain.Selector, operations, AcceptOwnershipProposalDescription, 0) + return GenerateAcceptOwnershipProposalOutput{mcmsProposal, nextOpCount}, err } diff --git a/deployment/ccip/changeset/aptos/operation/off_ramp.go b/deployment/ccip/changeset/aptos/operation/off_ramp.go new file mode 100644 index 00000000000..9c3aa1bb0fa --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/off_ramp.go @@ -0,0 +1,92 @@ +package operation + +import ( + "encoding/json" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/operations" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +// UpdateOffRampSourcesInput contains configuration for updating OffRamp sources +type UpdateOffRampSourcesInput struct { + MCMSAddress aptos.AccountAddress + Updates map[uint64]v1_6.OffRampSourceUpdate +} + +// UpdateOffRampSourcesOp operation to update OffRamp source configurations +var UpdateOffRampSourcesOp = operations.NewOperation( + "update-offramp-sources-op", + Version1_0_0, + "Updates OffRamp source chain configurations", + updateOffRampSources, +) + +func updateOffRampSources(b operations.Bundle, deps AptosDeps, in UpdateOffRampSourcesInput) ([]types.Operation, error) { + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + + // Transform the updates into the format expected by the Aptos contract + var sourceChainSelectors []uint64 + var sourceChainEnabled []bool + var sourceChainRMNVerificationDisabled []bool + var sourceChainOnRamp [][]byte + + for sourceChainSelector, update := range in.Updates { + sourceChainSelectors = append(sourceChainSelectors, sourceChainSelector) + sourceChainEnabled = append(sourceChainEnabled, update.IsEnabled) + sourceChainRMNVerificationDisabled = append(sourceChainRMNVerificationDisabled, update.IsRMNVerificationDisabled) + + onRampBytes, err := deps.CCIPOnChainState.GetOnRampAddressBytes(sourceChainSelector) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to get onRamp address for source chain %d: %w", sourceChainSelector, err) + } + sourceChainOnRamp = append(sourceChainOnRamp, onRampBytes) + } + + if len(sourceChainSelectors) == 0 { + b.Logger.Infow("No OffRamp source updates to apply") + return []types.Operation{}, nil + } + + // Encode the update operation + moduleInfo, function, _, args, err := ccipBind.Offramp().Encoder().ApplySourceChainConfigUpdates( + sourceChainSelectors, + sourceChainEnabled, + sourceChainRMNVerificationDisabled, + sourceChainOnRamp, + ) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to encode ApplySourceChainConfigUpdates for OffRamp: %w", err) + } + + // Create MCMS operation + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + operation := types.Operation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transaction: types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + } + + b.Logger.Infow("Adding OffRamp source config update operation", + "chainCount", len(sourceChainSelectors)) + + return []types.Operation{operation}, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/on_ramp.go b/deployment/ccip/changeset/aptos/operation/on_ramp.go new file mode 100644 index 00000000000..2abedbf280b --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/on_ramp.go @@ -0,0 +1,85 @@ +package operation + +import ( + "encoding/json" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/operations" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +// UpdateOnRampDestsInput contains configuration for updating OnRamp destinations +type UpdateOnRampDestsInput struct { + MCMSAddress aptos.AccountAddress + Updates map[uint64]v1_6.OnRampDestinationUpdate +} + +// UpdateOnRampDestsOp operation to update OnRamp destination configurations +var UpdateOnRampDestsOp = operations.NewOperation( + "update-onramp-dests-op", + Version1_0_0, + "Updates OnRamp destination chain configurations", + updateOnRampDests, +) + +func updateOnRampDests(b operations.Bundle, deps AptosDeps, in UpdateOnRampDestsInput) ([]types.Operation, error) { + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + + // Transform the updates into the format expected by the Aptos contract + var destChainSelectors []uint64 + var destChainEnabled []bool + var destChainAllowlistEnabled []bool + + // Process each destination chain config update + for destChainSelector, update := range in.Updates { + destChainSelectors = append(destChainSelectors, destChainSelector) + destChainEnabled = append(destChainEnabled, update.IsEnabled) + destChainAllowlistEnabled = append(destChainAllowlistEnabled, update.AllowListEnabled) + } + + if len(destChainSelectors) == 0 { + b.Logger.Infow("No OnRamp destination updates to apply") + return []types.Operation{}, nil + } + + // Encode the update operation + moduleInfo, function, _, args, err := ccipBind.Onramp().Encoder().ApplyDestChainConfigUpdates( + destChainSelectors, + destChainEnabled, + destChainAllowlistEnabled, + ) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for OnRamp: %w", err) + } + + // Create MCMS operation + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + operation := types.Operation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transaction: types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + } + + b.Logger.Infow("Adding OnRamp destination config update operation", + "chainCount", len(destChainSelectors)) + + return []types.Operation{operation}, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/version.go b/deployment/ccip/changeset/aptos/operation/version.go new file mode 100644 index 00000000000..a0970e40fb3 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/version.go @@ -0,0 +1,5 @@ +package operation + +import "github.com/Masterminds/semver/v3" + +var Version1_0_0 = semver.MustParse("1.0.0") diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go new file mode 100644 index 00000000000..2c867aed267 --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -0,0 +1,101 @@ +package sequence + +import ( + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/mcms" +) + +// Deploy CCIP Sequence +type DeployCCIPSeqInput struct { + MCMSAddress aptos.AccountAddress + MCMSOpCount uint64 + CCIPConfig config.ChainContractParams +} + +type DeployCCIPSeqOutput struct { + CCIPAddress aptos.AccountAddress + MCMSProposals []*mcms.Proposal + NextOpCount uint64 +} + +var DeployCCIPSequence = operations.NewSequence( + "deploy-aptos-ccip-sequence", + operation.Version1_0_0, + "Deploy Aptos CCIP contracts and initialize them", + deployCCIPSequence, +) + +func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in DeployCCIPSeqInput) (DeployCCIPSeqOutput, error) { + var proposals []*mcms.Proposal + mcmsOpCount := in.MCMSOpCount + + // Cleanup staging area + cleanupInput := operation.CleanupStagingAreaInput{ + MCMSAddress: in.MCMSAddress, + MCMSOpCount: mcmsOpCount, + } + cleanupReport, err := operations.ExecuteOperation(b, operation.CleanupStagingAreaOp, deps, cleanupInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + if cleanupReport.Output.MCMSProposal != nil { + proposals = append(proposals, cleanupReport.Output.MCMSProposal) + mcmsOpCount = cleanupReport.Output.NextOpCount + } + + // Generate proposal to deploy CCIP package + deployCCIPInput := operation.DeployCCIPInput{ + MCMSAddress: in.MCMSAddress, + MCMSOpCount: mcmsOpCount, + } + deployCCIPReport, err := operations.ExecuteOperation(b, operation.GenerateDeployCCIPProposalOp, deps, deployCCIPInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + ccipAddress := deployCCIPReport.Output.CCIPAddress + if deployCCIPReport.Output.MCMSProposal != nil { + proposals = append(proposals, deployCCIPReport.Output.MCMSProposal) + mcmsOpCount = deployCCIPReport.Output.NextOpCount + } + + // Generate proposal to deploy Router module + deployRouterInput := operation.DeployRouterInput{ + MCMSAddress: in.MCMSAddress, + CCIPAddress: ccipAddress, + MCMSOpCount: mcmsOpCount, + } + deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployRouterInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + if deployRouterReport.Output.MCMSProposal != nil { + proposals = append(proposals, deployRouterReport.Output.MCMSProposal) + mcmsOpCount = deployRouterReport.Output.NextOpCount + } + + // Generate proposal to initialize CCIP + initCCIPInput := operation.InitializeCCIPInput{ + MCMSAddress: in.MCMSAddress, + CCIPAddress: ccipAddress, + CCIPConfig: in.CCIPConfig, + MCMSOpCount: mcmsOpCount, + } + initCCIPReport, err := operations.ExecuteOperation(b, operation.InitializeCCIPOp, deps, initCCIPInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + if initCCIPReport.Output.MCMSProposal != nil { + proposals = append(proposals, initCCIPReport.Output.MCMSProposal) + mcmsOpCount = initCCIPReport.Output.NextOpCount + } + + return DeployCCIPSeqOutput{ + CCIPAddress: ccipAddress, + MCMSProposals: proposals, + NextOpCount: mcmsOpCount, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go new file mode 100644 index 00000000000..48a06262b5a --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -0,0 +1,66 @@ +package sequence + +import ( + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +// Deploy MCMS Sequence +type DeployMCMSSeqOutput struct { + MCMSAddress aptos.AccountAddress + MCMSProposal *mcms.Proposal + NextOpCount uint64 +} + +var DeployMCMSSequence = operations.NewSequence( + "deploy-aptos-mcms-sequence", + operation.Version1_0_0, + "Deploy Aptos MCMS contract and configure it", + deployMCMSSequence, +) + +func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCMS mcmstypes.Config) (DeployMCMSSeqOutput, error) { + // Check if MCMS package is already deployed + if deps.OnChainState.MCMSAddress != aptos.AccountZero { + b.Logger.Infow("MCMS Package already deployed", "addr", deps.OnChainState.MCMSAddress.String()) + return DeployMCMSSeqOutput{}, nil + } + // Deploy MCMS + deployMCMSReport, err := operations.ExecuteOperation(b, operation.DeployMCMSOp, deps, operations.EmptyInput{}) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // Configure MCMS + configureMCMSInput := operation.ConfigureMCMSInput{ + AddressMCMS: deployMCMSReport.Output.AddressMCMS, + MCMSConfigs: configMCMS, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSInput) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // Transfer ownership to self + _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output.ContractMCMS) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // Generate proposal to accept ownership + generateAcceptOwnershipProposalInput := operation.GenerateAcceptOwnershipProposalInput{ + AddressMCMS: deployMCMSReport.Output.AddressMCMS, + ContractMCMS: deployMCMSReport.Output.ContractMCMS, + } + gaopReport, err := operations.ExecuteOperation(b, operation.GenerateAcceptOwnershipProposalOp, deps, generateAcceptOwnershipProposalInput) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + + return DeployMCMSSeqOutput{ + MCMSAddress: deployMCMSReport.Output.AddressMCMS, + MCMSProposal: gaopReport.Output.MCMSProposal, + NextOpCount: gaopReport.Output.NextOpCount, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go new file mode 100644 index 00000000000..731d422836e --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -0,0 +1,157 @@ +package sequence + +import ( + "fmt" + "math/big" + + "github.com/aptos-labs/aptos-go-sdk" + chainsel "github.com/smartcontractkit/chain-selectors" + aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/types" +) + +type UpdateAptosLanesSeqInput struct { + UpdateFeeQuoterDestsConfig operation.UpdateFeeQuoterDestsInput + UpdateFeeQuoterPricesConfig operation.UpdateFeeQuoterPricesInput + UpdateOnRampDestsConfig operation.UpdateOnRampDestsInput + UpdateOffRampSourcesConfig operation.UpdateOffRampSourcesInput +} + +// UpdateAptosLanesSequence orchestrates operations to update Aptos lanes +var UpdateAptosLanesSequence = operations.NewSequence( + "update-aptos-lanes-sequence", + operation.Version1_0_0, + "Update Aptos CCIP lanes to enable or disable connections", + updateAptosLanesSequence, +) + +func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in UpdateAptosLanesSeqInput) ([]mcms.Proposal, error) { + var mcmsOperations []types.Operation + + // 1. Update FeeQuoters with destination configs + b.Logger.Info("Updating destination configs on FeeQuoters") + feeQuoterDestReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterDestsOp, deps, in.UpdateFeeQuoterDestsConfig) + if err != nil { + return []mcms.Proposal{}, fmt.Errorf("failed to update FeeQuoter destinations: %w", err) + } + mcmsOperations = append(mcmsOperations, feeQuoterDestReport.Output...) + + // 2. Update FeeQuoters with gas prices + b.Logger.Info("Updating gas prices on FeeQuoters") + feeQuoterPricesReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterPricesOp, deps, in.UpdateFeeQuoterPricesConfig) + if err != nil { + return []mcms.Proposal{}, fmt.Errorf("failed to update FeeQuoter prices: %w", err) + } + mcmsOperations = append(mcmsOperations, feeQuoterPricesReport.Output...) + + // 3. Configure destinations on OnRamps + b.Logger.Info("Updating destination configs on OnRamps") + onRampReport, err := operations.ExecuteOperation(b, operation.UpdateOnRampDestsOp, deps, in.UpdateOnRampDestsConfig) + if err != nil { + return []mcms.Proposal{}, fmt.Errorf("failed to update OnRamp destinations: %w", err) + } + mcmsOperations = append(mcmsOperations, onRampReport.Output...) + + // 4. Configure sources on OffRamps + b.Logger.Info("Updating source configs on OffRamps") + offRampReport, err := operations.ExecuteOperation(b, operation.UpdateOffRampSourcesOp, deps, in.UpdateOffRampSourcesConfig) + if err != nil { + return []mcms.Proposal{}, fmt.Errorf("failed to update OffRamp sources: %w", err) + } + mcmsOperations = append(mcmsOperations, offRampReport.Output...) + + var proposals []mcms.Proposal + // TODO: Build proposal + + return proposals, nil +} + +// Convert config.UpdateAptosLanesConfig into a map[uint64]UpdateAptosLanesSeqInput +func ConvertToUpdateAptosLanesSeqInput(aptosChains map[uint64]changeset.AptosCCIPChainState, cfg config.UpdateAptosLanesConfig) map[uint64]UpdateAptosLanesSeqInput { + updateInputsByAptosChain := make(map[uint64]UpdateAptosLanesSeqInput) + + // Group the operations by Aptos chain + for _, lane := range cfg.Lanes { + // Process lanes with Aptos as the source chain + if lane.Source.GetChainFamily() == chainsel.FamilyAptos { + source := lane.Source.(config.AptosChainDefinition) + if _, exists := updateInputsByAptosChain[source.Selector]; !exists { + updateInputsByAptosChain[source.Selector] = UpdateAptosLanesSeqInput{} + } + mcmsAddress := aptosChains[source.Selector].MCMSAddress + setAptosSourceUpdates(lane, updateInputsByAptosChain, cfg.TestRouter, mcmsAddress) + } + + // Process lanes with Aptos as the destination chain + if lane.Dest.GetChainFamily() == chainsel.FamilyAptos { + dest := lane.Dest.(config.AptosChainDefinition) + if _, exists := updateInputsByAptosChain[dest.Selector]; !exists { + updateInputsByAptosChain[dest.Selector] = UpdateAptosLanesSeqInput{} + } + mcmsAddress := aptosChains[dest.Selector].MCMSAddress + setAptosDestinationUpdates(lane, updateInputsByAptosChain, cfg.TestRouter, mcmsAddress) + } + } + + return updateInputsByAptosChain +} + +func setAptosSourceUpdates(lane config.LaneConfig, updateInputsByAptosChain map[uint64]UpdateAptosLanesSeqInput, isTestRouter bool, mcmsAddress aptos.AccountAddress) { + source := lane.Source.(config.AptosChainDefinition) + dest := lane.Dest.(config.EVMChainDefinition) + isEnabled := !lane.IsDisabled + + // Setting the destination on the on ramp + input := updateInputsByAptosChain[source.Selector] + input.UpdateOnRampDestsConfig.MCMSAddress = mcmsAddress + if input.UpdateOnRampDestsConfig.Updates == nil { + input.UpdateOnRampDestsConfig.Updates = make(map[uint64]v1_6.OnRampDestinationUpdate) + } + input.UpdateOnRampDestsConfig.Updates[dest.Selector] = v1_6.OnRampDestinationUpdate{ + IsEnabled: isEnabled, + TestRouter: isTestRouter, + AllowListEnabled: dest.AllowListEnabled, + } + + // Setting gas prices updates + input.UpdateFeeQuoterPricesConfig.MCMSAddress = mcmsAddress + if input.UpdateFeeQuoterPricesConfig.Prices.GasPrices == nil { + input.UpdateFeeQuoterPricesConfig.Prices.GasPrices = make(map[uint64]*big.Int) + } + input.UpdateFeeQuoterPricesConfig.Prices.GasPrices[dest.Selector] = dest.GasPrice + + // Setting the fee quoter destination on the source chain + input.UpdateFeeQuoterDestsConfig.MCMSAddress = mcmsAddress + if input.UpdateFeeQuoterDestsConfig.Updates == nil { + input.UpdateFeeQuoterDestsConfig.Updates = make(map[uint64]aptos_fee_quoter.DestChainConfig) + } + input.UpdateFeeQuoterDestsConfig.Updates[dest.Selector] = dest.GetConvertedAptosFeeQuoterConfig() + + updateInputsByAptosChain[source.Selector] = input +} + +func setAptosDestinationUpdates(lane config.LaneConfig, updateInputsByAptosChain map[uint64]UpdateAptosLanesSeqInput, isTestRouter bool, mcmsAddress aptos.AccountAddress) { + source := lane.Source.(config.EVMChainDefinition) + dest := lane.Dest.(config.AptosChainDefinition) + isEnabled := !lane.IsDisabled + + // Setting off ramp updates + input := updateInputsByAptosChain[dest.Selector] + input.UpdateOffRampSourcesConfig.MCMSAddress = mcmsAddress + if input.UpdateOffRampSourcesConfig.Updates == nil { + input.UpdateOffRampSourcesConfig.Updates = make(map[uint64]v1_6.OffRampSourceUpdate) + } + input.UpdateOffRampSourcesConfig.Updates[source.Selector] = v1_6.OffRampSourceUpdate{ + IsEnabled: isEnabled, + TestRouter: isTestRouter, + IsRMNVerificationDisabled: source.RMNVerificationDisabled, + } + + updateInputsByAptosChain[dest.Selector] = input +} diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go index eec4a49888c..eddd44066a8 100644 --- a/deployment/ccip/changeset/aptos/test_helpers.go +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -41,7 +41,7 @@ func mustParseAddress(t *testing.T, addr string) aptos.AccountAddress { return address } -func getMockChainContractParams(t *testing.T, chainSelector uint64) config.ChainContractParams { +func GetMockChainContractParams(t *testing.T, chainSelector uint64) config.ChainContractParams { mockParsedAddress := mustParseAddress(t, mockAddress) mockParsedLinkAddress := mustParseAddress(t, mockLinkAddress) diff --git a/deployment/ccip/changeset/aptos/utils/utils.go b/deployment/ccip/changeset/aptos/utils/utils.go index 64b08db2ef4..ae136fa75cb 100644 --- a/deployment/ccip/changeset/aptos/utils/utils.go +++ b/deployment/ccip/changeset/aptos/utils/utils.go @@ -3,6 +3,7 @@ package utils import ( "fmt" "strings" + "time" "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink/deployment" @@ -21,6 +22,7 @@ func ConfirmTx(chain deployment.AptosChain, txHash string, opts ...any) error { if !userTx.Success { return fmt.Errorf("transaction failed: %s", userTx.VmStatus) } + time.Sleep(time.Second * 1) return nil } diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index 86761d9e521..3b4f785686c 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -2,8 +2,10 @@ package internal import ( "context" + "encoding/hex" "errors" "fmt" + "strings" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -404,6 +406,11 @@ func BuildOCR3ConfigForCCIPHome( return nil, fmt.Errorf("failed to decode SVM address '%s': %w", transmitter, err) } parsed = pk.Bytes() + case chain_selectors.FamilyAptos: + parsed, err = hex.DecodeString(strings.TrimPrefix(string(transmitter), "0x")) + if err != nil { + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", transmitter, err) + } } transmittersBytes[i] = parsed } diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index c19899e3fb0..0691916e098 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -829,6 +829,9 @@ func (c CCIPOnChainState) SupportedChains() map[uint64]struct{} { for chain := range c.AptosChains { chains[chain] = struct{}{} } + for chain := range c.AptosChains { + chains[chain] = struct{}{} + } return chains } diff --git a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go new file mode 100644 index 00000000000..a8dc2f2aada --- /dev/null +++ b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go @@ -0,0 +1,26 @@ +package testhelpers + +import ( + "testing" + + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" + aptoshelper "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +func DeployChainContractsToAptosCS(t *testing.T, e DeployedEnv, chainSelector uint64) commonchangeset.ConfiguredChangeSet { + mockCCIPParams := aptoshelper.GetMockChainContractParams(t, chainSelector) + ccipConfig := config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + chainSelector: mockCCIPParams, + }, + MCMSConfigPerChain: map[uint64]mcmstypes.Config{ + chainSelector: proposalutils.SingleGroupMCMSV2(t), + }, + } + + return commonchangeset.Configure(aptoscs.DeployAptosChain{}, ccipConfig) +} diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 85bf2c46a50..510e0e7caa1 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -25,7 +25,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" solBinary "github.com/gagliardetto/binary" - solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" @@ -717,6 +716,13 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, apps) require.NoError(t, err) + if len(aptosChains) != 0 { + // TODO: currently only one aptos chain supported in test environment + aptosCs := DeployChainContractsToAptosCS(t, e, aptosChains[0]) + e.Env, err = commonchangeset.ApplyChangesetsV2(t, e.Env, []commonchangeset.ConfiguredChangeSet{aptosCs}) + require.NoError(t, err) + } + state, err := changeset.LoadOnchainState(e.Env) require.NoError(t, err) // Assert link present diff --git a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go index ea1b47e8f8f..40aab86f8f5 100644 --- a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go +++ b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go @@ -1041,6 +1041,8 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter DestChainConfig: dc, }) } + tnv, _ := fq.TypeAndVersion(nil) + fmt.Println(tnv) tx, err := fq.ApplyDestChainConfigUpdates(txOpts, args) if cfg.MCMS == nil { if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 1fc3cbc4266..52a6948fa40 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -156,6 +156,11 @@ func (c UpdateBidirectionalLanesConfig) BuildConfigs() UpdateBidirectionalLanesC func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidirectionalLanesConfig) error { configs := c.BuildConfigs() + + return UpdateLanesPrecondition(e, configs) +} + +func UpdateLanesPrecondition(e deployment.Environment, configs UpdateBidirectionalLanesChangesetConfigs) error { state, err := changeset.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) @@ -190,9 +195,17 @@ func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidi } func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirectionalLanesConfig) (deployment.ChangesetOutput, error) { - proposals := make([]mcms.TimelockProposal, 0) configs := c.BuildConfigs() + return UpdateLanesLogic(e, c.MCMSConfig, configs) +} + +// UpdateLanesLogic is the main logic for updating lanes. Configs provided can be unidirectional +// TODO: this should be refactored as a sequence once EVM changesets move to Operations API +// TODO: UpdateBidirectionalLanesChangesetConfigs name is misleading, it accepts any kind of lane updates +func UpdateLanesLogic(e deployment.Environment, mcmsConfig *proposalutils.TimelockConfig, configs UpdateBidirectionalLanesChangesetConfigs) (deployment.ChangesetOutput, error) { + proposals := make([]mcms.TimelockProposal, 0) + out, err := UpdateFeeQuoterDestsChangeset(e, configs.UpdateFeeQuoterDestsConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterDestsChangeset: %w", err) @@ -232,7 +245,7 @@ func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirection if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), proposals, nil, "Update multiple bidirectional lanes", c.MCMSConfig) + proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), proposals, nil, "Update multiple bidirectional lanes", mcmsConfig) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) } From dcb7f8f4cb1e217f6e899e7b03b1ce93ce0cdd62 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Sun, 13 Apr 2025 12:25:45 -0300 Subject: [PATCH 027/136] refactor: deploy chain with a single proposal --- .../changeset/aptos/cs_deploy_aptos_chain.go | 18 ++- .../ccip/changeset/aptos/operation/ccip.go | 114 ++++-------------- .../ccip/changeset/aptos/operation/mcms.go | 24 +--- .../changeset/aptos/sequence/deploy_ccip.go | 40 ++---- .../changeset/aptos/sequence/deploy_mcms.go | 11 +- deployment/ccip/changeset/aptos/utils/mcms.go | 21 ++-- 6 files changed, 66 insertions(+), 162 deletions(-) diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index c8e33bc7331..8b6e42d2001 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -11,8 +11,10 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" ) var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} @@ -58,11 +60,12 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo } ab := deployment.NewMemoryAddressBook() - proposals := []mcms.Proposal{} seqReports := make([]operations.Report[any, any], 0) + proposals := make([]mcms.Proposal, 0) // Deploy CCIP on each Aptos chain in config for chainSel := range config.ContractParamsPerChain { + mcmsOperations := []mcmstypes.Operation{} chainState := state[chainSel] aptosChain := env.AptosChains[chainSel] @@ -78,12 +81,11 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo return deployment.ChangesetOutput{}, err } seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) - proposals = append(proposals, *mcmsSeqReport.Output.MCMSProposal) + mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperations...) // CCIP Deploy operations ccipSeqInput := seq.DeployCCIPSeqInput{ MCMSAddress: mcmsSeqReport.Output.MCMSAddress, - MCMSOpCount: mcmsSeqReport.Output.NextOpCount, CCIPConfig: config.ContractParamsPerChain[chainSel], } ccipSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployCCIPSequence, deps, ccipSeqInput) @@ -91,11 +93,15 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) } seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) - for _, proposal := range ccipSeqReport.Output.MCMSProposals { - proposals = append(proposals, *proposal) + mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) + + // Generate MCMS proposals + proposal, err := utils.GenerateProposal(aptosChain.Client, mcmsSeqReport.Output.MCMSAddress, chainSel, mcmsOperations, "Deploy Aptos MCMS and CCIP") + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) } + proposals = append(proposals, *proposal) } - return deployment.ChangesetOutput{ AddressBook: ab, MCMSProposals: proposals, diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index fb168155286..297c0378df0 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -14,21 +14,14 @@ import ( aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/operations" - "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" + mcmstypes "github.com/smartcontractkit/mcms/types" ) -// Shared types -type MCMSProposalOutput struct { - MCMSProposal *mcms.Proposal - NextOpCount uint64 -} - // CleanupStagingArea Operation type CleanupStagingAreaInput struct { MCMSAddress aptos.AccountAddress - MCMSOpCount uint64 } var CleanupStagingAreaOp = operations.NewOperation( @@ -38,15 +31,15 @@ var CleanupStagingAreaOp = operations.NewOperation( cleanupStagingArea, ) -func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAreaInput) (MCMSProposalOutput, error) { +func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAreaInput) ([]mcmstypes.Operation, error) { // Check resources first to see if staging is clean IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(deps.AptosChain.Client, in.MCMSAddress) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) + return nil, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) } if IsMCMSStagingAreaClean { b.Logger.Infow("MCMS Staging Area already clean", "addr", in.MCMSAddress.String()) - return MCMSProposalOutput{}, nil + return nil, nil } // Bind MCMS contract @@ -57,7 +50,7 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr var operations []types.Operation moduleInfo, function, _, args, err := mcmsContract.MCMSDeployer().Encoder().CleanupStagingArea() if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) + return nil, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -66,7 +59,7 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr } afBytes, err := json.Marshal(additionalFields) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to marshal additional fields: %w", err) + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) } operations = append(operations, types.Operation{ ChainSelector: types.ChainSelector(deps.AptosChain.Selector), @@ -77,31 +70,17 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr }, }) - // Generate cleanup proposal - proposal, nextOpCount, err := utils.GenerateProposal( - deps.AptosChain.Client, - mcmsContract.Address(), - deps.AptosChain.Selector, - operations, - "Cleanup Staging Area", - in.MCMSOpCount, - ) - if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) - } - - return MCMSProposalOutput{proposal, nextOpCount}, nil + return operations, nil } // GenerateDeployCCIPProposal Operation generates deployment MCMS operations for the CCIP package type DeployCCIPInput struct { MCMSAddress aptos.AccountAddress - MCMSOpCount uint64 } type DeployCCIPOutput struct { - CCIPAddress aptos.AccountAddress - MCMSProposalOutput + CCIPAddress aptos.AccountAddress + MCMSOperations []mcmstypes.Operation } var GenerateDeployCCIPProposalOp = operations.NewOperation( @@ -115,7 +94,7 @@ func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCC // Validate there's no package deployed if deps.OnChainState.CCIPAddress != aptos.AccountZero { b.Logger.Infow("CCIP Package already deployed", "addr", deps.OnChainState.CCIPAddress.String()) - return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress, MCMSProposalOutput: MCMSProposalOutput{NextOpCount: in.MCMSOpCount}}, nil + return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress}, nil } // Compile, chunk and get CCIP deploy operations @@ -130,18 +109,9 @@ func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCC deps.AB.Save(deps.AptosChain.Selector, ccipObjectAddress.String(), typeAndVersion) deps.OnChainState.CCIPAddress = ccipObjectAddress - // Generate deploy proposal - proposal, nextOpCount, err := utils.GenerateProposal(deps.AptosChain.Client, mcmsContract.Address(), deps.AptosChain.Selector, operations, "Deploy CCIP Package", in.MCMSOpCount) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) - } - return DeployCCIPOutput{ - CCIPAddress: ccipObjectAddress, - MCMSProposalOutput: MCMSProposalOutput{ - MCMSProposal: proposal, - NextOpCount: nextOpCount, - }, + CCIPAddress: ccipObjectAddress, + MCMSOperations: operations, }, nil } @@ -171,7 +141,6 @@ func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.Ac type DeployRouterInput struct { MCMSAddress aptos.AccountAddress CCIPAddress aptos.AccountAddress - MCMSOpCount uint64 } var GenerateDeployRouterProposalOp = operations.NewOperation( @@ -181,32 +150,16 @@ var GenerateDeployRouterProposalOp = operations.NewOperation( generateDeployRouterProposal, ) -func generateDeployRouterProposal(b operations.Bundle, deps AptosDeps, in DeployRouterInput) (MCMSProposalOutput, error) { +func generateDeployRouterProposal(b operations.Bundle, deps AptosDeps, in DeployRouterInput) ([]mcmstypes.Operation, error) { // TODO: is there a way to check if module exists? // Compile, chunk and get Router deploy operations mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) operations, err := getRouterDeployMCMSOps(mcmsContract, in.CCIPAddress, deps.AptosChain.Selector) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to compile and create deploy operations: %w", err) + return nil, fmt.Errorf("failed to compile and create deploy operations: %w", err) } - // Generate deploy proposal - proposal, nextOpCount, err := utils.GenerateProposal( - deps.AptosChain.Client, - mcmsContract.Address(), - deps.AptosChain.Selector, - operations, - "Deploy Router Package", - in.MCMSOpCount, - ) - if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) - } - - return MCMSProposalOutput{ - MCMSProposal: proposal, - NextOpCount: nextOpCount, - }, nil + return operations, nil } func getRouterDeployMCMSOps( @@ -234,7 +187,6 @@ type InitializeCCIPInput struct { MCMSAddress aptos.AccountAddress CCIPAddress aptos.AccountAddress CCIPConfig aptoscfg.ChainContractParams - MCMSOpCount uint64 } var InitializeCCIPOp = operations.NewOperation( @@ -244,7 +196,7 @@ var InitializeCCIPOp = operations.NewOperation( generateInitializeCCIPProposal, ) -func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (MCMSProposalOutput, error) { +func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) ([]types.Operation, error) { var operations []types.Operation ccipBind := ccip.Bind(in.CCIPAddress, deps.AptosChain.Client) @@ -257,11 +209,11 @@ func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in Init in.CCIPConfig.OnRampParams.DestChainAllowlistEnabled, ) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to encode onramp initialize: %w", err) + return nil, fmt.Errorf("failed to encode onramp initialize: %w", err) } mcmsOp, err := generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) + return nil, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) } operations = append(operations, mcmsOp) @@ -275,11 +227,11 @@ func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in Init in.CCIPConfig.OffRampParams.SourceChainsOnRamp, ) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to encode offramp initialize: %w", err) + return nil, fmt.Errorf("failed to encode offramp initialize: %w", err) } mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + return nil, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) } operations = append(operations, mcmsOp) @@ -291,42 +243,26 @@ func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in Init in.CCIPConfig.FeeQuoterParams.FeeTokens, ) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to encode feequoter initialize: %w", err) + return nil, fmt.Errorf("failed to encode feequoter initialize: %w", err) } mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) + return nil, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) } operations = append(operations, mcmsOp) // Config RMNRemote moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(deps.AptosChain.Selector) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to encode rmnremote initialize: %w", err) + return nil, fmt.Errorf("failed to encode rmnremote initialize: %w", err) } mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) + return nil, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) } operations = append(operations, mcmsOp) - // Generate config proposal - proposal, nextOpCount, err := utils.GenerateProposal( - deps.AptosChain.Client, - in.MCMSAddress, - deps.AptosChain.Selector, - operations, - "Initialize CCIP Package", - in.MCMSOpCount, - ) - if err != nil { - return MCMSProposalOutput{}, fmt.Errorf("failed to create deploy proposal: %w", err) - } - - return MCMSProposalOutput{ - MCMSProposal: proposal, - NextOpCount: nextOpCount, - }, nil + return operations, nil } diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index a60cad21b15..0194d6c0784 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" @@ -97,11 +96,6 @@ type GenerateAcceptOwnershipProposalInput struct { ContractMCMS *mcmsbind.MCMS // TODO: outputs should be serializable } -type GenerateAcceptOwnershipProposalOutput struct { - MCMSProposal *mcms.Proposal - NextOpCount uint64 -} - var GenerateAcceptOwnershipProposalOp = operations.NewOperation( "generate-accept-ownership-proposal-op", Version1_0_0, @@ -109,10 +103,10 @@ var GenerateAcceptOwnershipProposalOp = operations.NewOperation( generateAcceptOwnershipProposal, ) -func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) (GenerateAcceptOwnershipProposalOutput, error) { +func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) ([]mcmstypes.Operation, error) { moduleInfo, function, _, args, err := (*in.ContractMCMS).MCMSAccount().Encoder().AcceptOwnership() if err != nil { - return GenerateAcceptOwnershipProposalOutput{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + return []mcmstypes.Operation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -121,7 +115,7 @@ func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in Gen } callOneAdditionalFields, err := json.Marshal(additionalFields) if err != nil { - return GenerateAcceptOwnershipProposalOutput{}, fmt.Errorf("failed to marshal additionalFields: %w", err) + return []mcmstypes.Operation{}, fmt.Errorf("failed to marshal additionalFields: %w", err) } mcmsOps := []mcmstypes.Operation{{ ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), @@ -131,14 +125,6 @@ func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in Gen AdditionalFields: callOneAdditionalFields, }, }} - mcmsProposal, nextOpCount, err := utils.GenerateProposal( - deps.AptosChain.Client, - (*in.ContractMCMS).Address(), - deps.AptosChain.Selector, - mcmsOps, - AcceptOwnershipProposalDescription, - 0, - ) - - return GenerateAcceptOwnershipProposalOutput{mcmsProposal, nextOpCount}, err + + return mcmsOps, err } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index 2c867aed267..8830e2f775b 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -6,20 +6,18 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/operations" - "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" ) // Deploy CCIP Sequence type DeployCCIPSeqInput struct { MCMSAddress aptos.AccountAddress - MCMSOpCount uint64 CCIPConfig config.ChainContractParams } type DeployCCIPSeqOutput struct { - CCIPAddress aptos.AccountAddress - MCMSProposals []*mcms.Proposal - NextOpCount uint64 + CCIPAddress aptos.AccountAddress + MCMSOperations []mcmstypes.Operation } var DeployCCIPSequence = operations.NewSequence( @@ -30,72 +28,56 @@ var DeployCCIPSequence = operations.NewSequence( ) func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in DeployCCIPSeqInput) (DeployCCIPSeqOutput, error) { - var proposals []*mcms.Proposal - mcmsOpCount := in.MCMSOpCount + var mcmsOperations []mcmstypes.Operation // Cleanup staging area cleanupInput := operation.CleanupStagingAreaInput{ MCMSAddress: in.MCMSAddress, - MCMSOpCount: mcmsOpCount, } cleanupReport, err := operations.ExecuteOperation(b, operation.CleanupStagingAreaOp, deps, cleanupInput) if err != nil { return DeployCCIPSeqOutput{}, err } - if cleanupReport.Output.MCMSProposal != nil { - proposals = append(proposals, cleanupReport.Output.MCMSProposal) - mcmsOpCount = cleanupReport.Output.NextOpCount + if cleanupReport.Output != nil { + mcmsOperations = append(mcmsOperations, cleanupReport.Output...) } // Generate proposal to deploy CCIP package deployCCIPInput := operation.DeployCCIPInput{ MCMSAddress: in.MCMSAddress, - MCMSOpCount: mcmsOpCount, } deployCCIPReport, err := operations.ExecuteOperation(b, operation.GenerateDeployCCIPProposalOp, deps, deployCCIPInput) if err != nil { return DeployCCIPSeqOutput{}, err } ccipAddress := deployCCIPReport.Output.CCIPAddress - if deployCCIPReport.Output.MCMSProposal != nil { - proposals = append(proposals, deployCCIPReport.Output.MCMSProposal) - mcmsOpCount = deployCCIPReport.Output.NextOpCount - } + mcmsOperations = append(mcmsOperations, deployCCIPReport.Output.MCMSOperations...) // Generate proposal to deploy Router module deployRouterInput := operation.DeployRouterInput{ MCMSAddress: in.MCMSAddress, CCIPAddress: ccipAddress, - MCMSOpCount: mcmsOpCount, } deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployRouterInput) if err != nil { return DeployCCIPSeqOutput{}, err } - if deployRouterReport.Output.MCMSProposal != nil { - proposals = append(proposals, deployRouterReport.Output.MCMSProposal) - mcmsOpCount = deployRouterReport.Output.NextOpCount - } + mcmsOperations = append(mcmsOperations, deployRouterReport.Output...) // Generate proposal to initialize CCIP initCCIPInput := operation.InitializeCCIPInput{ MCMSAddress: in.MCMSAddress, CCIPAddress: ccipAddress, CCIPConfig: in.CCIPConfig, - MCMSOpCount: mcmsOpCount, } initCCIPReport, err := operations.ExecuteOperation(b, operation.InitializeCCIPOp, deps, initCCIPInput) if err != nil { return DeployCCIPSeqOutput{}, err } - if initCCIPReport.Output.MCMSProposal != nil { - proposals = append(proposals, initCCIPReport.Output.MCMSProposal) - mcmsOpCount = initCCIPReport.Output.NextOpCount - } + mcmsOperations = append(mcmsOperations, initCCIPReport.Output...) return DeployCCIPSeqOutput{ - CCIPAddress: ccipAddress, - MCMSProposals: proposals, - NextOpCount: mcmsOpCount, + CCIPAddress: ccipAddress, + MCMSOperations: mcmsOperations, }, nil } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index 48a06262b5a..c29c7a7c3c7 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -5,15 +5,13 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/operations" - "github.com/smartcontractkit/mcms" mcmstypes "github.com/smartcontractkit/mcms/types" ) // Deploy MCMS Sequence type DeployMCMSSeqOutput struct { - MCMSAddress aptos.AccountAddress - MCMSProposal *mcms.Proposal - NextOpCount uint64 + MCMSAddress aptos.AccountAddress + MCMSOperations []mcmstypes.Operation } var DeployMCMSSequence = operations.NewSequence( @@ -59,8 +57,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM } return DeployMCMSSeqOutput{ - MCMSAddress: deployMCMSReport.Output.AddressMCMS, - MCMSProposal: gaopReport.Output.MCMSProposal, - NextOpCount: gaopReport.Output.NextOpCount, + MCMSAddress: deployMCMSReport.Output.AddressMCMS, + MCMSOperations: gaopReport.Output, }, nil } diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go index 3d3cb74c670..cee4e1e637a 100644 --- a/deployment/ccip/changeset/aptos/utils/mcms.go +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -26,17 +26,14 @@ func GenerateProposal( chainSel uint64, operations []types.Operation, description string, - opCount uint64, -) (*mcms.Proposal, uint64, error) { - if opCount == 0 { - // Create MCMS inspector - inspector := aptosmcms.NewInspector(client) - startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) - if err != nil { - return nil, 0, fmt.Errorf("failed to get starting op count: %w", err) - } - opCount = startingOpCount +) (*mcms.Proposal, error) { + // Create MCMS inspector + inspector := aptosmcms.NewInspector(client) + startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) + if err != nil { + return nil, fmt.Errorf("failed to get starting op count: %w", err) } + opCount := startingOpCount // Create proposal builder validUntil := time.Now().Add(time.Hour * ValidUntilHours).Unix() @@ -59,10 +56,10 @@ func GenerateProposal( } proposal, err := proposalBuilder.Build() if err != nil { - return nil, opCount, fmt.Errorf("failed to build proposal: %w", err) + return nil, fmt.Errorf("failed to build proposal: %w", err) } - return proposal, opCount + uint64(len(operations)), nil + return proposal, nil } // CreateChunksAndStage creates chunks from the compiled packages and build MCMS operations to stages them within the MCMS contract From 5a120ed7549caee1b7642b2237517d91ae226167 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Sun, 13 Apr 2025 15:33:11 -0300 Subject: [PATCH 028/136] feat: Deploy Aptos Lanes cs working --- .../changeset/aptos/config/deploy_chain.go | 22 +-- .../changeset/aptos/cs_deploy_aptos_chain.go | 30 ++- .../aptos/cs_deploy_aptos_chain_test.go | 20 +- .../changeset/aptos/cs_set_ocr3_offramp.go | 78 ++++++++ .../aptos/cs_set_ocr3_offramp_test.go | 48 +++++ .../changeset/aptos/cs_update_aptos_lanes.go | 21 ++- .../aptos/cs_update_aptos_lanes_test.go | 59 ++---- .../ccip/changeset/aptos/operation/ccip.go | 177 ++++++++++-------- .../changeset/aptos/operation/fee_quoter.go | 89 +++++---- .../ccip/changeset/aptos/operation/mcms.go | 20 +- .../changeset/aptos/operation/off_ramp.go | 31 ++- .../ccip/changeset/aptos/operation/on_ramp.go | 64 +++++-- .../changeset/aptos/sequence/deploy_ccip.go | 37 +++- .../changeset/aptos/sequence/deploy_mcms.go | 40 +++- .../aptos/sequence/set_ocr3_offramp.go | 130 +++++++++++++ .../changeset/aptos/sequence/update_lane.go | 44 ++--- .../ccip/changeset/aptos/test_helpers.go | 25 ++- deployment/ccip/changeset/aptos/utils/mcms.go | 54 +++++- .../ccip/changeset/aptos/utils/utils.go | 6 +- deployment/ccip/changeset/aptos_state.go | 2 +- .../changeset/internal/deploy_home_chain.go | 66 +++++++ .../testhelpers/aptos_test_helper.go | 12 +- .../common/proposalutils/mcms_test_helpers.go | 8 - 23 files changed, 767 insertions(+), 316 deletions(-) create mode 100644 deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go create mode 100644 deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go create mode 100644 deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go diff --git a/deployment/ccip/changeset/aptos/config/deploy_chain.go b/deployment/ccip/changeset/aptos/config/deploy_chain.go index 064062eefd6..b6bca7ce9e6 100644 --- a/deployment/ccip/changeset/aptos/config/deploy_chain.go +++ b/deployment/ccip/changeset/aptos/config/deploy_chain.go @@ -5,12 +5,12 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink/deployment" - mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment/common/types" ) // DeployAptosChainConfig is a configuration for deploying CCIP Package for Aptos chains type DeployAptosChainConfig struct { - MCMSConfigPerChain map[uint64]mcmstypes.Config + MCMSConfigPerChain map[uint64]types.MCMSWithTimelockConfigV2 ContractParamsPerChain map[uint64]ChainContractParams } @@ -55,7 +55,7 @@ type FeeQuoterParams struct { } func (f FeeQuoterParams) Validate() error { - if f.LinkToken == aptos.AccountZero { + if f.LinkToken == (aptos.AccountAddress{}) { return fmt.Errorf("LinkToken is required") } if f.TokenPriceStalenessThreshold == 0 { @@ -90,25 +90,17 @@ func (o OffRampParams) Validate() error { } type OnRampParams struct { - ChainSelector uint64 - AllowlistAdmin aptos.AccountAddress - DestChainSelectors []uint64 - DestChainEnabled []bool - DestChainAllowlistEnabled []bool + ChainSelector uint64 + AllowlistAdmin aptos.AccountAddress + FeeAggregator aptos.AccountAddress } func (o OnRampParams) Validate() error { if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } - if o.AllowlistAdmin == aptos.AccountZero { + if o.AllowlistAdmin == (aptos.AccountAddress{}) { return fmt.Errorf("AllowlistAdmin is required") } - if len(o.DestChainSelectors) != len(o.DestChainEnabled) { - return fmt.Errorf("DestChainSelectors and DestChainEnabled must have the same length") - } - if len(o.DestChainSelectors) != len(o.DestChainAllowlistEnabled) { - return fmt.Errorf("DestChainSelectors and DestChainAllowlistEnabled must have the same length") - } return nil } diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index 8b6e42d2001..ef91b44be4f 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" ) @@ -42,10 +43,12 @@ func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, confi errs = append(errs, fmt.Errorf("aptos chain %d not found in state", chainSel)) continue } - if chainState.MCMSAddress == aptos.AccountZero { + if chainState.MCMSAddress == (aptos.AccountAddress{}) { mcmsConfig := config.MCMSConfigPerChain[chainSel] - if err := mcmsConfig.Validate(); err != nil { - errs = append(errs, fmt.Errorf("invalid mcms configs for Aptos chain %d: %w", chainSel, err)) + for _, cfg := range []mcmstypes.Config{mcmsConfig.Bypasser, mcmsConfig.Canceller, mcmsConfig.Proposer} { + if err := cfg.Validate(); err != nil { + errs = append(errs, fmt.Errorf("invalid mcms configs for Aptos chain %d: %w", chainSel, err)) + } } } } @@ -61,11 +64,11 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo ab := deployment.NewMemoryAddressBook() seqReports := make([]operations.Report[any, any], 0) - proposals := make([]mcms.Proposal, 0) + proposals := make([]mcms.TimelockProposal, 0) // Deploy CCIP on each Aptos chain in config for chainSel := range config.ContractParamsPerChain { - mcmsOperations := []mcmstypes.Operation{} + mcmsOperations := []mcmstypes.BatchOperation{} chainState := state[chainSel] aptosChain := env.AptosChains[chainSel] @@ -81,7 +84,7 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo return deployment.ChangesetOutput{}, err } seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) - mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperations...) + mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) // CCIP Deploy operations ccipSeqInput := seq.DeployCCIPSeqInput{ @@ -96,15 +99,22 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) // Generate MCMS proposals - proposal, err := utils.GenerateProposal(aptosChain.Client, mcmsSeqReport.Output.MCMSAddress, chainSel, mcmsOperations, "Deploy Aptos MCMS and CCIP") + proposal, err := utils.GenerateProposal( + aptosChain.Client, + mcmsSeqReport.Output.MCMSAddress, + chainSel, + mcmsOperations, + "Deploy Aptos MCMS and CCIP", + aptosmcms.TimelockRoleProposer, + ) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) } proposals = append(proposals, *proposal) } return deployment.ChangesetOutput{ - AddressBook: ab, - MCMSProposals: proposals, - Reports: seqReports, + AddressBook: ab, + MCMSTimelockProposals: proposals, + Reports: seqReports, }, nil } diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 48a5f080d52..9406badd91b 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -1,6 +1,7 @@ package aptos import ( + "math/big" "testing" "github.com/smartcontractkit/chainlink/deployment" @@ -8,14 +9,14 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" - mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - ccipbind "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" ) func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { @@ -42,7 +43,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), 743186221051783445: GetMockChainContractParams(t, 743186221051783445), }, - MCMSConfigPerChain: map[uint64]mcmstypes.Config{ + MCMSConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ 4457093679053095497: getMockMCMSConfig(t), 743186221051783445: getMockMCMSConfig(t), }, @@ -209,8 +210,13 @@ func TestDeployAptosChain_Apply(t *testing.T) { ContractParamsPerChain: map[uint64]config.ChainContractParams{ chainSelector: mockCCIPParams, }, - MCMSConfigPerChain: map[uint64]mcmstypes.Config{ - chainSelector: proposalutils.SingleGroupMCMSV2(t), + MCMSConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ + chainSelector: { + Canceller: proposalutils.SingleGroupMCMSV2(t), + Proposer: proposalutils.SingleGroupMCMSV2(t), + Bypasser: proposalutils.SingleGroupMCMSV2(t), + TimelockMinDelay: big.NewInt(0), + }, }, } env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ @@ -227,8 +233,8 @@ func TestDeployAptosChain_Apply(t *testing.T) { require.NotEmpty(t, ccipAddr, "CCIP address should not be empty") // Bind CCIP contract - ccipContract := ccipbind.Bind(ccipAddr, env.AptosChains[chainSelector].Client) - offRampSourceConfig, err := ccipContract.Offramp().GetSourceChainConfig(nil, mockCCIPParams.OffRampParams.SourceChainSelectors[0]) + offrampBind := ccip_offramp.Bind(ccipAddr, env.AptosChains[chainSelector].Client) + offRampSourceConfig, err := offrampBind.Offramp().GetSourceChainConfig(nil, mockCCIPParams.OffRampParams.SourceChainSelectors[0]) require.NoError(t, err) require.Equal(t, true, offRampSourceConfig.IsEnabled, "contracts were not initialized correctly") } diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go new file mode 100644 index 00000000000..99aec529604 --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go @@ -0,0 +1,78 @@ +package aptos + +import ( + "fmt" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +var _ deployment.ChangeSetV2[v1_6.SetOCR3OffRampConfig] = SetOCR3Offramp{} + +// SetOCR3Offramp updates OCR3 Offramp configurations +type SetOCR3Offramp struct{} + +func (cs SetOCR3Offramp) VerifyPreconditions(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) error { + for _, remoteSel := range config.RemoteChainSels { + chainFamily, _ := chain_selectors.GetSelectorFamily(remoteSel) + if chainFamily != chain_selectors.FamilyAptos { + return fmt.Errorf("chain %d is not an Aptos chain", remoteSel) + } + } + return nil +} + +func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) { + seqReports := make([]operations.Report[any, any], 0) + timeLockProposals := []mcms.TimelockProposal{} + + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + } + + for _, remoteSelector := range config.RemoteChainSels { + deps := operation.AptosDeps{ + AptosChain: env.AptosChains[remoteSelector], + OnChainState: state.AptosChains[remoteSelector], + CCIPOnChainState: state, + } + in := seq.SetOCR3OfframpSeqInput{ + HomeChainSelector: config.HomeChainSel, + ChainSelector: remoteSelector, + } + setOCR3SeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.SetOCR3OfframpSequence, deps, in) + if err != nil { + return deployment.ChangesetOutput{}, err + } + seqReports = append(seqReports, setOCR3SeqReport.ExecutionReports...) + + // Generate MCMS proposals + proposal, err := utils.GenerateProposal( + deps.AptosChain.Client, + state.AptosChains[remoteSelector].MCMSAddress, + deps.AptosChain.Selector, + []types.BatchOperation{setOCR3SeqReport.Output}, + "Set OCR3 Configs", + aptosmcms.TimelockRoleProposer, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", remoteSelector, err) + } + timeLockProposals = append(timeLockProposals, *proposal) + } + + return deployment.ChangesetOutput{ + MCMSTimelockProposals: timeLockProposals, + Reports: seqReports, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go new file mode 100644 index 00000000000..0367bc14b68 --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go @@ -0,0 +1,48 @@ +package aptos_test + +import ( + "testing" + + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/stretchr/testify/require" +) + +func TestSetOCR3Offramp_Apply(t *testing.T) { + // Setup environment and config + deployedEnvironment, _ := testhelpers.NewMemoryEnvironment( + t, + testhelpers.WithAptosChains(1), + ) + env := deployedEnvironment.Env + + cfg := v1_6.SetOCR3OffRampConfig{ + HomeChainSel: env.AllChainSelectors()[0], + RemoteChainSels: env.AllChainSelectorsAptos(), + CCIPHomeConfigType: globals.ConfigTypeActive, + } + env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure(aptoscs.SetOCR3Offramp{}, cfg), + }) + require.NoError(t, err) + + // Load onchain state + state, err := changeset.LoadOnchainState(env) + require.NoError(t, err, "must load onchain state") + + // bind ccip aptos + aptosCCIPAddr := state.AptosChains[env.AllChainSelectorsAptos()[0]].CCIPAddress + aptosOffRamp := ccip_offramp.Bind(aptosCCIPAddr, env.AptosChains[env.AllChainSelectorsAptos()[0]].Client) + ocr3Commit, err := aptosOffRamp.Offramp().LatestConfigDetails(nil, uint8(types.PluginTypeCCIPCommit)) + require.NoError(t, err) + require.Len(t, ocr3Commit.Signers, 4) + ocr3Exec, err := aptosOffRamp.Offramp().LatestConfigDetails(nil, uint8(types.PluginTypeCCIPExec)) + require.NoError(t, err) + require.Len(t, ocr3Exec.Transmitters, 4) +} diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go index 7876393f902..70e80a790ab 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -8,9 +8,12 @@ import ( config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" ) var _ deployment.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} @@ -34,7 +37,7 @@ func (cs AddAptosLanes) VerifyPreconditions(env deployment.Environment, cfg conf func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptosLanesConfig) (deployment.ChangesetOutput, error) { timeLockProposals := []mcms.TimelockProposal{} - proposals := []mcms.Proposal{} + mcmsOperations := []types.BatchOperation{} seqReports := make([]operations.Report[any, any], 0) // Add lane on EVM chains @@ -66,13 +69,25 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos return deployment.ChangesetOutput{}, err } seqReports = append(seqReports, updateSeqReport.ExecutionReports...) - proposals = append(proposals, updateSeqReport.Output...) + mcmsOperations = append(mcmsOperations, updateSeqReport.Output) + // Generate MCMS proposals + proposal, err := utils.GenerateProposal( + deps.AptosChain.Client, + state.AptosChains[aptosChainSel].MCMSAddress, + deps.AptosChain.Selector, + mcmsOperations, + "Update lanes on Aptos chain", + aptosmcms.TimelockRoleProposer, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", aptosChainSel, err) + } + timeLockProposals = append(timeLockProposals, *proposal) } return deployment.ChangesetOutput{ MCMSTimelockProposals: timeLockProposals, - MCMSProposals: proposals, Reports: seqReports, }, nil } diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index dc5f18e510e..f587762fda1 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -2,7 +2,6 @@ package aptos_test import ( "encoding/hex" - "fmt" "math/big" "testing" @@ -10,47 +9,20 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" aptosfeequoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" - // "github.com/smartcontractkit/chainlink/deployment" - + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" - seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) -func TestInputSerializable(t *testing.T) { - input := seq.UpdateAptosLanesSeqInput{ - UpdateFeeQuoterDestsConfig: operation.UpdateFeeQuoterDestsInput{ - MCMSAddress: aptos.AccountAddress{}, - Updates: map[uint64]aptosfeequoter.DestChainConfig{}, - }, - UpdateFeeQuoterPricesConfig: operation.UpdateFeeQuoterPricesInput{ - MCMSAddress: aptos.AccountAddress{}, - Prices: operation.FeeQuoterPriceUpdatePerSource{}, - }, - UpdateOnRampDestsConfig: operation.UpdateOnRampDestsInput{ - MCMSAddress: aptos.AccountAddress{}, - Updates: map[uint64]v1_6.OnRampDestinationUpdate{}, - }, - UpdateOffRampSourcesConfig: operation.UpdateOffRampSourcesInput{ - MCMSAddress: aptos.AccountAddress{}, - Updates: map[uint64]v1_6.OffRampSourceUpdate{}, - }, - } - isSer := operations.IsSerializable(logger.TestLogger(t), input) - fmt.Println(isSer) -} - func TestAddAptosLanes_Apply(t *testing.T) { // Setup environment and config deployedEnvironment, _ := testhelpers.NewMemoryEnvironment( @@ -83,19 +55,24 @@ func TestAddAptosLanes_Apply(t *testing.T) { // bind ccip aptos aptosCCIPAddr := state.AptosChains[aptosSelector].CCIPAddress - aptosCCIP := ccip.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) + aptosOnRamp := ccip_onramp.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) + aptosOffRamp := ccip_offramp.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) + + dynCfg, err := aptosOffRamp.Offramp().GetDynamicConfig(&bind.CallOpts{}) + require.NoError(t, err) + require.True(t, dynCfg.PermissionlessExecutionThresholdSeconds > 0) + + isSupported, err := aptosOnRamp.Onramp().IsChainSupported(&bind.CallOpts{}, emvSelector) + require.NoError(t, err) + require.True(t, isSupported) - is_enabled1, sequence_number1, allowlist_enabled1, err := aptosCCIP.Onramp().GetDestChainConfig(nil, emvSelector) + _, _, router, err := aptosOnRamp.Onramp().GetDestChainConfig(&bind.CallOpts{}, emvSelector) require.NoError(t, err) - require.True(t, is_enabled1) - require.True(t, sequence_number1 > 0) - require.True(t, allowlist_enabled1) + require.NotEqual(t, router, aptos.AccountAddress{}) - is_enabled2, sequence_number2, allowlist_enabled2, err := aptosCCIP.Onramp().GetDestChainConfig(nil, emvSelector2) + _, _, router2, err := aptosOnRamp.Onramp().GetDestChainConfig(&bind.CallOpts{}, emvSelector2) require.NoError(t, err) - require.True(t, is_enabled2) - require.True(t, sequence_number2 > 0) - require.True(t, allowlist_enabled2) + require.NotEqual(t, router2, aptos.AccountAddress{}) } func getMockUpdateConfig( @@ -157,7 +134,7 @@ func getMockUpdateConfig( IsDisabled: false, }, }, - TestRouter: true, + TestRouter: false, } } diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index 297c0378df0..d0ad9926979 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -5,9 +5,10 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" - router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -16,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" - mcmstypes "github.com/smartcontractkit/mcms/types" ) // CleanupStagingArea Operation @@ -31,15 +31,15 @@ var CleanupStagingAreaOp = operations.NewOperation( cleanupStagingArea, ) -func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAreaInput) ([]mcmstypes.Operation, error) { +func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAreaInput) (types.BatchOperation, error) { // Check resources first to see if staging is clean IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(deps.AptosChain.Client, in.MCMSAddress) if err != nil { - return nil, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) } if IsMCMSStagingAreaClean { b.Logger.Infow("MCMS Staging Area already clean", "addr", in.MCMSAddress.String()) - return nil, nil + return types.BatchOperation{}, nil } // Bind MCMS contract @@ -47,10 +47,9 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr mcmsAddress := mcmsContract.Address() // Get cleanup staging operations - var operations []types.Operation moduleInfo, function, _, args, err := mcmsContract.MCMSDeployer().Encoder().CleanupStagingArea() if err != nil { - return nil, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -59,18 +58,17 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr } afBytes, err := json.Marshal(additionalFields) if err != nil { - return nil, fmt.Errorf("failed to marshal additional fields: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to marshal additional fields: %w", err) } - operations = append(operations, types.Operation{ + + return types.BatchOperation{ ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transaction: types.Transaction{ + Transactions: []types.Transaction{{ To: mcmsAddress.StringLong(), Data: aptosmcms.ArgsToData(args), AdditionalFields: afBytes, - }, - }) - - return operations, nil + }}, + }, nil } // GenerateDeployCCIPProposal Operation generates deployment MCMS operations for the CCIP package @@ -80,7 +78,7 @@ type DeployCCIPInput struct { type DeployCCIPOutput struct { CCIPAddress aptos.AccountAddress - MCMSOperations []mcmstypes.Operation + MCMSOperations []types.Operation } var GenerateDeployCCIPProposalOp = operations.NewOperation( @@ -92,7 +90,7 @@ var GenerateDeployCCIPProposalOp = operations.NewOperation( func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { // Validate there's no package deployed - if deps.OnChainState.CCIPAddress != aptos.AccountZero { + if deps.OnChainState.CCIPAddress != (aptos.AccountAddress{}) { b.Logger.Infow("CCIP Package already deployed", "addr", deps.OnChainState.CCIPAddress.String()) return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress}, nil } @@ -137,48 +135,77 @@ func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.Ac return ccipObjectAddress, operations, nil } -// GenerateDeployRouterProposal generates deployment MCMS operations for the Router module -type DeployRouterInput struct { +type DeployModulesInput struct { MCMSAddress aptos.AccountAddress CCIPAddress aptos.AccountAddress } +// GenerateDeployRouterProposal generates deployment MCMS operations for the Router module var GenerateDeployRouterProposalOp = operations.NewOperation( "deploy-router-op", Version1_0_0, - "Deploys Router Package for CCIP", - generateDeployRouterProposal, + "Generates MCMS proposals that deployes Router module on CCIP package", + getDeployRouterMCMSOperations, ) -func generateDeployRouterProposal(b operations.Bundle, deps AptosDeps, in DeployRouterInput) ([]mcmstypes.Operation, error) { +func getDeployRouterMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { // TODO: is there a way to check if module exists? - // Compile, chunk and get Router deploy operations mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) - operations, err := getRouterDeployMCMSOps(mcmsContract, in.CCIPAddress, deps.AptosChain.Selector) + // Compile Package + payload, err := ccip_router.Compile(in.CCIPAddress, mcmsContract.Address(), true) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) if err != nil { - return nil, fmt.Errorf("failed to compile and create deploy operations: %w", err) + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) } return operations, nil } -func getRouterDeployMCMSOps( - mcmsContract mcmsbind.MCMS, - ccipObjectAddress aptos.AccountAddress, - chainSel uint64, -) ([]types.Operation, error) { +var GenerateDeployOffRampProposalOp = operations.NewOperation( + "deploy-offramp-op", + Version1_0_0, + "Generates MCMS proposals that deployes OffRamp module on CCIP package", + getDeployOffRampMCMSOperations, +) + +func getDeployOffRampMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) // Compile Package - payload, err := router.Compile(ccipObjectAddress, mcmsContract.Address()) + payload, err := ccip_offramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) if err != nil { return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) } - // Create chunks and stage operations - operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, "", &ccipObjectAddress) + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) if err != nil { - return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) } + return operations, nil +} +var GenerateDeployOnRampProposalOp = operations.NewOperation( + "deploy-onramp-op", + Version1_0_0, + "Generates MCMS proposals that deployes OnRamp module on CCIP package", + getDeployOnRampMCMSOperations, +) + +func getDeployOnRampMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + // Compile Package + payload, err := ccip_onramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) + } return operations, nil } @@ -196,29 +223,31 @@ var InitializeCCIPOp = operations.NewOperation( generateInitializeCCIPProposal, ) -func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) ([]types.Operation, error) { - var operations []types.Operation - ccipBind := ccip.Bind(in.CCIPAddress, deps.AptosChain.Client) +func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (types.BatchOperation, error) { + var txs []types.Transaction - // Config OnRamp - moduleInfo, function, _, args, err := ccipBind.Onramp().Encoder().Initialize( + // Config OnRamp with empty lane configs. We're only able to get router address after deploying the router module + onrampBind := ccip_onramp.Bind(in.CCIPAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err := onrampBind.Onramp().Encoder().Initialize( deps.AptosChain.Selector, + in.CCIPConfig.OnRampParams.FeeAggregator, in.CCIPConfig.OnRampParams.AllowlistAdmin, - in.CCIPConfig.OnRampParams.DestChainSelectors, - in.CCIPConfig.OnRampParams.DestChainEnabled, - in.CCIPConfig.OnRampParams.DestChainAllowlistEnabled, + []uint64{}, + []aptos.AccountAddress{}, + []bool{}, ) if err != nil { - return nil, fmt.Errorf("failed to encode onramp initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to encode onramp initialize: %w", err) } - mcmsOp, err := generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) + mcmsTx, err := utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) if err != nil { - return nil, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) } - operations = append(operations, mcmsOp) + txs = append(txs, mcmsTx) // Config OffRamp - moduleInfo, function, _, args, err = ccipBind.Offramp().Encoder().Initialize( + offrampBind := ccip_offramp.Bind(in.CCIPAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err = offrampBind.Offramp().Encoder().Initialize( deps.AptosChain.Selector, in.CCIPConfig.OffRampParams.PermissionlessExecutionThreshold, in.CCIPConfig.OffRampParams.SourceChainSelectors, @@ -227,15 +256,17 @@ func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in Init in.CCIPConfig.OffRampParams.SourceChainsOnRamp, ) if err != nil { - return nil, fmt.Errorf("failed to encode offramp initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to encode offramp initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) if err != nil { - return nil, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) } - operations = append(operations, mcmsOp) + txs = append(txs, mcmsTx) + + // Config FeeQuoter and RMNRemote + ccipBind := ccip.Bind(in.CCIPAddress, deps.AptosChain.Client) - // Config FeeQuoter moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().Initialize( deps.AptosChain.Selector, in.CCIPConfig.FeeQuoterParams.LinkToken, @@ -243,46 +274,26 @@ func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in Init in.CCIPConfig.FeeQuoterParams.FeeTokens, ) if err != nil { - return nil, fmt.Errorf("failed to encode feequoter initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to encode feequoter initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) if err != nil { - return nil, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) } - operations = append(operations, mcmsOp) + txs = append(txs, mcmsTx) - // Config RMNRemote moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(deps.AptosChain.Selector) if err != nil { - return nil, fmt.Errorf("failed to encode rmnremote initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to encode rmnremote initialize: %w", err) } - mcmsOp, err = generateMCMSOperation(deps.AptosChain.Selector, in.CCIPAddress, moduleInfo, function, args) + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) if err != nil { - return nil, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) } - operations = append(operations, mcmsOp) - - return operations, nil - -} + txs = append(txs, mcmsTx) -// generateMCMSOperation is a helper function that generates a MCMS operation for the given parameters -func generateMCMSOperation(chainSel uint64, toAddress aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Operation, error) { - additionalFields := aptosmcms.AdditionalFields{ - PackageName: moduleInfo.PackageName, - ModuleName: moduleInfo.ModuleName, - Function: function, - } - afBytes, err := json.Marshal(additionalFields) - if err != nil { - return types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) - } - return types.Operation{ - ChainSelector: types.ChainSelector(chainSel), - Transaction: types.Transaction{ - To: toAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }, + return types.BatchOperation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transactions: txs, }, nil } diff --git a/deployment/ccip/changeset/aptos/operation/fee_quoter.go b/deployment/ccip/changeset/aptos/operation/fee_quoter.go index fe067549b4b..4f67acff89d 100644 --- a/deployment/ccip/changeset/aptos/operation/fee_quoter.go +++ b/deployment/ccip/changeset/aptos/operation/fee_quoter.go @@ -8,6 +8,7 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" @@ -27,13 +28,13 @@ var UpdateFeeQuoterDestsOp = operations.NewOperation( updateFeeQuoterDests, ) -func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterDestsInput) ([]types.Operation, error) { +func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterDestsInput) ([]types.Transaction, error) { // Bind CCIP Package ccipAddress := deps.OnChainState.CCIPAddress ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) // Process each destination chain config update - var operations []types.Operation + var txs []types.Transaction for destChainSelector, destConfig := range in.Updates { // Encode the update operation @@ -60,7 +61,7 @@ func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuote destConfig.NetworkFeeUsdCents, ) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for chain %d: %w", destChainSelector, err) + return []types.Transaction{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for chain %d: %w", destChainSelector, err) } additionalFields := aptosmcms.AdditionalFields{ @@ -70,16 +71,13 @@ func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuote } afBytes, err := json.Marshal(additionalFields) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + return []types.Transaction{}, fmt.Errorf("failed to marshal additional fields: %w", err) } - operations = append(operations, types.Operation{ - ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transaction: types.Transaction{ - To: ccipAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }, + txs = append(txs, types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, }) b.Logger.Infow("Adding FeeQuoter destination config update operation", @@ -87,7 +85,7 @@ func updateFeeQuoterDests(b operations.Bundle, deps AptosDeps, in UpdateFeeQuote "isEnabled", destConfig.IsEnabled) } - return operations, nil + return txs, nil } // UpdateFeeQuoterPricesInput contains configuration for updating FeeQuoter price configs @@ -109,11 +107,42 @@ var UpdateFeeQuoterPricesOp = operations.NewOperation( updateFeeQuoterPrices, ) -func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterPricesInput) ([]types.Operation, error) { +func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuoterPricesInput) ([]types.Transaction, error) { + var txs []types.Transaction + // Bind CCIP Package ccipAddress := deps.OnChainState.CCIPAddress ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + // Bind MCMS Package + mcmsAddress := deps.OnChainState.MCMSAddress + mcmsBind := mcms.Bind(mcmsAddress, deps.AptosChain.Client) + + // Add CCIP Owner address to update token prices allow list + ccipOwnerAddress, err := mcmsBind.MCMSRegistry().GetRegisteredOwnerAddress(nil, ccipAddress) + if err != nil { + return nil, fmt.Errorf("failed to get CCIP owner address: %w", err) + } + moduleInfo, function, _, args, err := ccipBind.Auth().Encoder().ApplyAllowedOfframpUpdates(nil, []aptos.AccountAddress{ccipOwnerAddress}) + if err != nil { + return nil, fmt.Errorf("failed to encode ApplyAllowedOfframpUpdates: %w", err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + txs = append(txs, types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }) + // Convert token prices and gas prices to format expected by Aptos contract var sourceTokens []aptos.AccountAddress var sourceUsdPerToken []*big.Int @@ -125,7 +154,7 @@ func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuot address := aptos.AccountAddress{} err := address.ParseStringRelaxed(tokenAddr) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to parse Aptos token address %s: %w", tokenAddr, err) + return nil, fmt.Errorf("failed to parse Aptos token address %s: %w", tokenAddr, err) } sourceTokens = append(sourceTokens, address) sourceUsdPerToken = append(sourceUsdPerToken, price) @@ -137,41 +166,37 @@ func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuot gasUsdPerUnitGas = append(gasUsdPerUnitGas, gasPrice) } - // Generate MCMS operation to update prices - var operations []types.Operation - + // Generate MCMS tx to update prices if len(sourceTokens) == 0 && len(gasDestChainSelectors) == 0 { b.Logger.Infow("No price updates to apply") - return operations, nil + return txs, nil } - // Encode the update operation - moduleInfo, function, _, args, err := ccipBind.FeeQuoter().Encoder().UpdatePrices( + + // Encode the update tx + moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().UpdatePrices( sourceTokens, sourceUsdPerToken, gasDestChainSelectors, gasUsdPerUnitGas, ) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to encode UpdatePrices: %w", err) + return nil, fmt.Errorf("failed to encode UpdatePrices: %w", err) } - additionalFields := aptosmcms.AdditionalFields{ + additionalFields = aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, ModuleName: moduleInfo.ModuleName, Function: function, } - afBytes, err := json.Marshal(additionalFields) + afBytes, err = json.Marshal(additionalFields) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) } - operations = append(operations, types.Operation{ - ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transaction: types.Transaction{ - To: ccipAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }, + txs = append(txs, types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, }) b.Logger.Infow("Adding FeeQuoter price update operation", @@ -179,5 +204,5 @@ func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuot "gasPriceCount", len(gasDestChainSelectors), ) - return operations, nil + return txs, nil } diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 0194d6c0784..70ed5ace56d 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -50,6 +50,7 @@ func deployMCMS(b operations.Bundle, deps AptosDeps, input operations.EmptyInput type ConfigureMCMSInput struct { AddressMCMS aptos.AccountAddress MCMSConfigs mcmstypes.Config + MCMSRole aptosmcms.TimelockRole } var ConfigureMCMSOp = operations.NewOperation( @@ -60,7 +61,7 @@ var ConfigureMCMSOp = operations.NewOperation( ) func configureMCMS(b operations.Bundle, deps AptosDeps, in ConfigureMCMSInput) (any, error) { - configurer := aptosmcms.NewConfigurer(deps.AptosChain.Client, deps.AptosChain.DeployerSigner) + configurer := aptosmcms.NewConfigurer(deps.AptosChain.Client, deps.AptosChain.DeployerSigner, in.MCMSRole) setCfgTx, err := configurer.SetConfig(context.Background(), in.AddressMCMS.StringLong(), &in.MCMSConfigs, false) if err != nil { return nil, fmt.Errorf("failed to setConfig in MCMS contract: %w", err) @@ -103,10 +104,10 @@ var GenerateAcceptOwnershipProposalOp = operations.NewOperation( generateAcceptOwnershipProposal, ) -func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) ([]mcmstypes.Operation, error) { +func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) (mcmstypes.BatchOperation, error) { moduleInfo, function, _, args, err := (*in.ContractMCMS).MCMSAccount().Encoder().AcceptOwnership() if err != nil { - return []mcmstypes.Operation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } additionalFields := aptosmcms.AdditionalFields{ PackageName: moduleInfo.PackageName, @@ -115,16 +116,15 @@ func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in Gen } callOneAdditionalFields, err := json.Marshal(additionalFields) if err != nil { - return []mcmstypes.Operation{}, fmt.Errorf("failed to marshal additionalFields: %w", err) + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to marshal additionalFields: %w", err) } - mcmsOps := []mcmstypes.Operation{{ + + return mcmstypes.BatchOperation{ ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), - Transaction: mcmstypes.Transaction{ + Transactions: []mcmstypes.Transaction{{ To: in.AddressMCMS.StringLong(), Data: aptosmcms.ArgsToData(args), AdditionalFields: callOneAdditionalFields, - }, - }} - - return mcmsOps, err + }}, + }, err } diff --git a/deployment/ccip/changeset/aptos/operation/off_ramp.go b/deployment/ccip/changeset/aptos/operation/off_ramp.go index 9c3aa1bb0fa..d21d2d7b145 100644 --- a/deployment/ccip/changeset/aptos/operation/off_ramp.go +++ b/deployment/ccip/changeset/aptos/operation/off_ramp.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" @@ -26,10 +26,10 @@ var UpdateOffRampSourcesOp = operations.NewOperation( updateOffRampSources, ) -func updateOffRampSources(b operations.Bundle, deps AptosDeps, in UpdateOffRampSourcesInput) ([]types.Operation, error) { +func updateOffRampSources(b operations.Bundle, deps AptosDeps, in UpdateOffRampSourcesInput) ([]types.Transaction, error) { // Bind CCIP Package ccipAddress := deps.OnChainState.CCIPAddress - ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + offrampBind := ccip_offramp.Bind(ccipAddress, deps.AptosChain.Client) // Transform the updates into the format expected by the Aptos contract var sourceChainSelectors []uint64 @@ -44,25 +44,25 @@ func updateOffRampSources(b operations.Bundle, deps AptosDeps, in UpdateOffRampS onRampBytes, err := deps.CCIPOnChainState.GetOnRampAddressBytes(sourceChainSelector) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to get onRamp address for source chain %d: %w", sourceChainSelector, err) + return nil, fmt.Errorf("failed to get onRamp address for source chain %d: %w", sourceChainSelector, err) } sourceChainOnRamp = append(sourceChainOnRamp, onRampBytes) } if len(sourceChainSelectors) == 0 { b.Logger.Infow("No OffRamp source updates to apply") - return []types.Operation{}, nil + return nil, nil } // Encode the update operation - moduleInfo, function, _, args, err := ccipBind.Offramp().Encoder().ApplySourceChainConfigUpdates( + moduleInfo, function, _, args, err := offrampBind.Offramp().Encoder().ApplySourceChainConfigUpdates( sourceChainSelectors, sourceChainEnabled, sourceChainRMNVerificationDisabled, sourceChainOnRamp, ) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to encode ApplySourceChainConfigUpdates for OffRamp: %w", err) + return nil, fmt.Errorf("failed to encode ApplySourceChainConfigUpdates for OffRamp: %w", err) } // Create MCMS operation @@ -73,20 +73,15 @@ func updateOffRampSources(b operations.Bundle, deps AptosDeps, in UpdateOffRampS } afBytes, err := json.Marshal(additionalFields) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) - } - - operation := types.Operation{ - ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transaction: types.Transaction{ - To: ccipAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }, + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) } b.Logger.Infow("Adding OffRamp source config update operation", "chainCount", len(sourceChainSelectors)) - return []types.Operation{operation}, nil + return []types.Transaction{{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }}, nil } diff --git a/deployment/ccip/changeset/aptos/operation/on_ramp.go b/deployment/ccip/changeset/aptos/operation/on_ramp.go index 2abedbf280b..a8f3546bd25 100644 --- a/deployment/ccip/changeset/aptos/operation/on_ramp.go +++ b/deployment/ccip/changeset/aptos/operation/on_ramp.go @@ -5,7 +5,8 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" @@ -26,36 +27,64 @@ var UpdateOnRampDestsOp = operations.NewOperation( updateOnRampDests, ) -func updateOnRampDests(b operations.Bundle, deps AptosDeps, in UpdateOnRampDestsInput) ([]types.Operation, error) { +func updateOnRampDests(b operations.Bundle, deps AptosDeps, in UpdateOnRampDestsInput) ([]types.Transaction, error) { // Bind CCIP Package ccipAddress := deps.OnChainState.CCIPAddress - ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + onrampBind := ccip_onramp.Bind(ccipAddress, deps.AptosChain.Client) // Transform the updates into the format expected by the Aptos contract var destChainSelectors []uint64 - var destChainEnabled []bool + var destChainRouters []aptos.AccountAddress var destChainAllowlistEnabled []bool + // Get routers state addresses + var testRouterStateAddress aptos.AccountAddress + var routerStateAddress aptos.AccountAddress + if deps.OnChainState.TestRouterAddress != (aptos.AccountAddress{}) { + testRouter := ccip_router.Bind(deps.OnChainState.TestRouterAddress, deps.AptosChain.Client) + stateAddress, err := testRouter.Router().GetStateAddress(nil) + if err != nil { + return nil, fmt.Errorf("failed to get test router state address: %w", err) + } + testRouterStateAddress = stateAddress + } + router := ccip_router.Bind(deps.OnChainState.CCIPAddress, deps.AptosChain.Client) + routerStateAddress, err := router.Router().GetStateAddress(nil) + if err != nil { + return nil, fmt.Errorf("failed to get router state address: %w", err) + } + // Process each destination chain config update for destChainSelector, update := range in.Updates { + // destChainRouters + if !update.IsEnabled { + destChainRouters = append(destChainRouters, aptos.AccountAddress{}) + continue + } + if update.TestRouter { + destChainRouters = append(destChainRouters, testRouterStateAddress) + } else { + destChainRouters = append(destChainRouters, routerStateAddress) + } + // destChainSelectors destChainSelectors = append(destChainSelectors, destChainSelector) - destChainEnabled = append(destChainEnabled, update.IsEnabled) + // destChainAllowlistEnabled destChainAllowlistEnabled = append(destChainAllowlistEnabled, update.AllowListEnabled) } if len(destChainSelectors) == 0 { b.Logger.Infow("No OnRamp destination updates to apply") - return []types.Operation{}, nil + return nil, nil } // Encode the update operation - moduleInfo, function, _, args, err := ccipBind.Onramp().Encoder().ApplyDestChainConfigUpdates( + moduleInfo, function, _, args, err := onrampBind.Onramp().Encoder().ApplyDestChainConfigUpdates( destChainSelectors, - destChainEnabled, + destChainRouters, destChainAllowlistEnabled, ) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for OnRamp: %w", err) + return nil, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for OnRamp: %w", err) } // Create MCMS operation @@ -66,20 +95,15 @@ func updateOnRampDests(b operations.Bundle, deps AptosDeps, in UpdateOnRampDests } afBytes, err := json.Marshal(additionalFields) if err != nil { - return []types.Operation{}, fmt.Errorf("failed to marshal additional fields: %w", err) - } - - operation := types.Operation{ - ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transaction: types.Transaction{ - To: ccipAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }, + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) } b.Logger.Infow("Adding OnRamp destination config update operation", "chainCount", len(destChainSelectors)) - return []types.Operation{operation}, nil + return []types.Transaction{{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }}, nil } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index 8830e2f775b..7dbebcc49d7 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -5,6 +5,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/operations" mcmstypes "github.com/smartcontractkit/mcms/types" ) @@ -17,7 +18,7 @@ type DeployCCIPSeqInput struct { type DeployCCIPSeqOutput struct { CCIPAddress aptos.AccountAddress - MCMSOperations []mcmstypes.Operation + MCMSOperations []mcmstypes.BatchOperation } var DeployCCIPSequence = operations.NewSequence( @@ -28,7 +29,7 @@ var DeployCCIPSequence = operations.NewSequence( ) func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in DeployCCIPSeqInput) (DeployCCIPSeqOutput, error) { - var mcmsOperations []mcmstypes.Operation + var mcmsOperations []mcmstypes.BatchOperation // Cleanup staging area cleanupInput := operation.CleanupStagingAreaInput{ @@ -38,8 +39,8 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy if err != nil { return DeployCCIPSeqOutput{}, err } - if cleanupReport.Output != nil { - mcmsOperations = append(mcmsOperations, cleanupReport.Output...) + if len(cleanupReport.Output.Transactions) > 0 { + mcmsOperations = append(mcmsOperations, cleanupReport.Output) } // Generate proposal to deploy CCIP package @@ -51,18 +52,34 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy return DeployCCIPSeqOutput{}, err } ccipAddress := deployCCIPReport.Output.CCIPAddress - mcmsOperations = append(mcmsOperations, deployCCIPReport.Output.MCMSOperations...) + // For CCIP deployment the txs cannot be batched - it'd exceed Aptos API limits + // so it's converted to batch operations with single transactions in each + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployCCIPReport.Output.MCMSOperations)...) - // Generate proposal to deploy Router module - deployRouterInput := operation.DeployRouterInput{ + deployModulesInput := operation.DeployModulesInput{ MCMSAddress: in.MCMSAddress, CCIPAddress: ccipAddress, } - deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployRouterInput) + // Generate proposal to deploy OnRamp module + deployOnRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOnRampProposalOp, deps, deployModulesInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOnRampReport.Output)...) + + // Generate proposal to deploy OffRamp module + deployOffRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOffRampProposalOp, deps, deployModulesInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOffRampReport.Output)...) + + // Generate proposal to deploy Router module + deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployModulesInput) if err != nil { return DeployCCIPSeqOutput{}, err } - mcmsOperations = append(mcmsOperations, deployRouterReport.Output...) + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployRouterReport.Output)...) // Generate proposal to initialize CCIP initCCIPInput := operation.InitializeCCIPInput{ @@ -74,7 +91,7 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy if err != nil { return DeployCCIPSeqOutput{}, err } - mcmsOperations = append(mcmsOperations, initCCIPReport.Output...) + mcmsOperations = append(mcmsOperations, initCCIPReport.Output) return DeployCCIPSeqOutput{ CCIPAddress: ccipAddress, diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index c29c7a7c3c7..124efde101c 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -4,14 +4,16 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/operations" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" ) // Deploy MCMS Sequence type DeployMCMSSeqOutput struct { - MCMSAddress aptos.AccountAddress - MCMSOperations []mcmstypes.Operation + MCMSAddress aptos.AccountAddress + MCMSOperation mcmstypes.BatchOperation } var DeployMCMSSequence = operations.NewSequence( @@ -21,9 +23,9 @@ var DeployMCMSSequence = operations.NewSequence( deployMCMSSequence, ) -func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCMS mcmstypes.Config) (DeployMCMSSeqOutput, error) { +func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCMS types.MCMSWithTimelockConfigV2) (DeployMCMSSeqOutput, error) { // Check if MCMS package is already deployed - if deps.OnChainState.MCMSAddress != aptos.AccountZero { + if deps.OnChainState.MCMSAddress != (aptos.AccountAddress{}) { b.Logger.Infow("MCMS Package already deployed", "addr", deps.OnChainState.MCMSAddress.String()) return DeployMCMSSeqOutput{}, nil } @@ -33,14 +35,34 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } // Configure MCMS - configureMCMSInput := operation.ConfigureMCMSInput{ + configureMCMSBypassers := operation.ConfigureMCMSInput{ AddressMCMS: deployMCMSReport.Output.AddressMCMS, - MCMSConfigs: configMCMS, + MCMSConfigs: configMCMS.Bypasser, + MCMSRole: aptosmcms.TimelockRoleBypasser, } - _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSInput) + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSBypassers) if err != nil { return DeployMCMSSeqOutput{}, err } + configureMCMSCancellers := operation.ConfigureMCMSInput{ + AddressMCMS: deployMCMSReport.Output.AddressMCMS, + MCMSConfigs: configMCMS.Canceller, + MCMSRole: aptosmcms.TimelockRoleCanceller, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSCancellers) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + configureMCMSProposers := operation.ConfigureMCMSInput{ + AddressMCMS: deployMCMSReport.Output.AddressMCMS, + MCMSConfigs: configMCMS.Proposer, + MCMSRole: aptosmcms.TimelockRoleProposer, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSProposers) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // TODO: Should set MinDelay to timelock // Transfer ownership to self _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output.ContractMCMS) if err != nil { @@ -57,7 +79,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM } return DeployMCMSSeqOutput{ - MCMSAddress: deployMCMSReport.Output.AddressMCMS, - MCMSOperations: gaopReport.Output, + MCMSAddress: deployMCMSReport.Output.AddressMCMS, + MCMSOperation: gaopReport.Output, }, nil } diff --git a/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go new file mode 100644 index 00000000000..7832762148c --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go @@ -0,0 +1,130 @@ +package sequence + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + aptosutils "github.com/smartcontractkit/chainlink-aptos/relayer/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +// Set OCR3 Offramp Sequence Input +type SetOCR3OfframpSeqInput struct { + HomeChainSelector uint64 + ChainSelector uint64 +} + +var SetOCR3OfframpSequence = operations.NewSequence( + "set-aptos-ocr3-offramp-sequence", + operation.Version1_0_0, + "Set OCR3 configuration for Aptos CCIP Offramp", + setOCR3OfframpSequence, +) + +func setOCR3OfframpSequence(b operations.Bundle, deps operation.AptosDeps, in SetOCR3OfframpSeqInput) (mcmstypes.BatchOperation, error) { + var txs []mcmstypes.Transaction + + offRampBind := ccip_offramp.Bind(deps.OnChainState.CCIPAddress, deps.AptosChain.Client) + + donID, err := internal.DonIDForChain( + deps.CCIPOnChainState.Chains[in.HomeChainSelector].CapabilityRegistry, + deps.CCIPOnChainState.Chains[in.HomeChainSelector].CCIPHome, + in.ChainSelector, + ) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to get DON ID: %w", err) + } + + ocr3Args, err := internal.BuildSetOCR3ConfigArgsAptos( + donID, + deps.CCIPOnChainState.Chains[in.HomeChainSelector].CCIPHome, + in.ChainSelector, + globals.ConfigTypeActive, + ) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to build OCR3 config args: %w", err) + } + + var commitArgs *internal.MultiOCR3BaseOCRConfigArgsAptos = nil + var execArgs *internal.MultiOCR3BaseOCRConfigArgsAptos = nil + for _, ocr3Arg := range ocr3Args { + if ocr3Arg.OcrPluginType == uint8(types.PluginTypeCCIPCommit) { + commitArgs = &ocr3Arg + } else if ocr3Arg.OcrPluginType == uint8(types.PluginTypeCCIPExec) { + execArgs = &ocr3Arg + } else { + return mcmstypes.BatchOperation{}, fmt.Errorf("unknown plugin type %d", ocr3Arg.OcrPluginType) + } + } + + commitSigners := [][]byte{} + for _, signer := range commitArgs.Signers { + commitSigners = append(commitSigners, signer) + } + commitTransmitters := []aptos.AccountAddress{} + for _, transmitter := range commitArgs.Transmitters { + address, err := aptosutils.PublicKeyBytesToAddress(transmitter) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to convert transmitter to address: %w", err) + } + commitTransmitters = append(commitTransmitters, address) + } + moduleInfo, function, _, args, err := offRampBind.Offramp().Encoder().SetOcr3Config( + commitArgs.ConfigDigest[:], + uint8(types.PluginTypeCCIPCommit), + commitArgs.F, + commitArgs.IsSignatureVerificationEnabled, + commitSigners, + commitTransmitters, + ) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode SetOcr3Config for commit: %w", err) + } + mcmsTx, err := utils.GenerateMCMSTx(deps.OnChainState.CCIPAddress, moduleInfo, function, args) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + execSigners := [][]byte{} + for _, signer := range execArgs.Signers { + execSigners = append(execSigners, signer) + } + execTransmitters := []aptos.AccountAddress{} + for _, transmitter := range execArgs.Transmitters { + address, err := aptosutils.PublicKeyBytesToAddress(transmitter) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to convert transmitter to address: %w", err) + } + execTransmitters = append(execTransmitters, address) + } + moduleInfo, function, _, args, err = offRampBind.Offramp().Encoder().SetOcr3Config( + execArgs.ConfigDigest[:], + uint8(types.PluginTypeCCIPExec), + execArgs.F, + execArgs.IsSignatureVerificationEnabled, + execSigners, + execTransmitters, + ) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode SetOcr3Config for exec: %w", err) + } + mcmsTx, err = utils.GenerateMCMSTx(deps.OnChainState.CCIPAddress, moduleInfo, function, args) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + return mcmstypes.BatchOperation{ + ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), + Transactions: txs, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 731d422836e..0c497acbfc7 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/chainlink/deployment/operations" - "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/types" ) @@ -31,45 +30,46 @@ var UpdateAptosLanesSequence = operations.NewSequence( updateAptosLanesSequence, ) -func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in UpdateAptosLanesSeqInput) ([]mcms.Proposal, error) { - var mcmsOperations []types.Operation +func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in UpdateAptosLanesSeqInput) (types.BatchOperation, error) { + var mcmsTxs []types.Transaction // 1. Update FeeQuoters with destination configs b.Logger.Info("Updating destination configs on FeeQuoters") feeQuoterDestReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterDestsOp, deps, in.UpdateFeeQuoterDestsConfig) if err != nil { - return []mcms.Proposal{}, fmt.Errorf("failed to update FeeQuoter destinations: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to update FeeQuoter destinations: %w", err) } - mcmsOperations = append(mcmsOperations, feeQuoterDestReport.Output...) + mcmsTxs = append(mcmsTxs, feeQuoterDestReport.Output...) - // 2. Update FeeQuoters with gas prices - b.Logger.Info("Updating gas prices on FeeQuoters") - feeQuoterPricesReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterPricesOp, deps, in.UpdateFeeQuoterPricesConfig) - if err != nil { - return []mcms.Proposal{}, fmt.Errorf("failed to update FeeQuoter prices: %w", err) - } - mcmsOperations = append(mcmsOperations, feeQuoterPricesReport.Output...) - - // 3. Configure destinations on OnRamps + // 2. Configure destinations on OnRamps b.Logger.Info("Updating destination configs on OnRamps") onRampReport, err := operations.ExecuteOperation(b, operation.UpdateOnRampDestsOp, deps, in.UpdateOnRampDestsConfig) if err != nil { - return []mcms.Proposal{}, fmt.Errorf("failed to update OnRamp destinations: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to update OnRamp destinations: %w", err) } - mcmsOperations = append(mcmsOperations, onRampReport.Output...) + mcmsTxs = append(mcmsTxs, onRampReport.Output...) - // 4. Configure sources on OffRamps + // 3. Configure sources on OffRamps b.Logger.Info("Updating source configs on OffRamps") offRampReport, err := operations.ExecuteOperation(b, operation.UpdateOffRampSourcesOp, deps, in.UpdateOffRampSourcesConfig) if err != nil { - return []mcms.Proposal{}, fmt.Errorf("failed to update OffRamp sources: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to update OffRamp sources: %w", err) } - mcmsOperations = append(mcmsOperations, offRampReport.Output...) + mcmsTxs = append(mcmsTxs, offRampReport.Output...) - var proposals []mcms.Proposal - // TODO: Build proposal + // TODO: This is not working + // 4. Update FeeQuoters with gas prices + b.Logger.Info("Updating gas prices on FeeQuoters") + feeQuoterPricesReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterPricesOp, deps, in.UpdateFeeQuoterPricesConfig) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to update FeeQuoter prices: %w", err) + } + mcmsTxs = append(mcmsTxs, feeQuoterPricesReport.Output...) - return proposals, nil + return types.BatchOperation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transactions: mcmsTxs, + }, nil } // Convert config.UpdateAptosLanesConfig into a map[uint64]UpdateAptosLanesSeqInput diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go index eddd44066a8..d2108de9103 100644 --- a/deployment/ccip/changeset/aptos/test_helpers.go +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -1,13 +1,15 @@ package aptos import ( + "math/big" "testing" "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" - mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/stretchr/testify/assert" ) @@ -18,7 +20,6 @@ const ( mockLinkAddress = "0xa" mockBadAddress = "0xinvalid" - mockMCMSSigner = "0x2A9685F653192edBac9F2405D95087c752fF6cd3" sepChainSelector = 11155111 sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" ) @@ -61,20 +62,18 @@ func GetMockChainContractParams(t *testing.T, chainSelector uint64) config.Chain SourceChainsOnRamp: [][]byte{common.HexToAddress(sepMockOnRampAddress).Bytes()}, }, OnRampParams: config.OnRampParams{ - ChainSelector: chainSelector, - AllowlistAdmin: mockParsedAddress, - DestChainSelectors: []uint64{}, - DestChainEnabled: []bool{}, - DestChainAllowlistEnabled: []bool{}, + ChainSelector: chainSelector, + AllowlistAdmin: mockParsedAddress, + FeeAggregator: mockParsedAddress, }, } } -func getMockMCMSConfig(t *testing.T) mcmstypes.Config { - parsedAddress := common.HexToAddress(mockMCMSSigner) - return mcmstypes.Config{ - Quorum: 1, - Signers: []common.Address{parsedAddress}, - GroupSigners: []mcmstypes.Config{}, +func getMockMCMSConfig(t *testing.T) types.MCMSWithTimelockConfigV2 { + return types.MCMSWithTimelockConfigV2{ + Canceller: proposalutils.SingleGroupMCMSV2(t), + Proposer: proposalutils.SingleGroupMCMSV2(t), + Bypasser: proposalutils.SingleGroupMCMSV2(t), + TimelockMinDelay: big.NewInt(0), } } diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go index cee4e1e637a..412170c1591 100644 --- a/deployment/ccip/changeset/aptos/utils/mcms.go +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -24,31 +24,42 @@ func GenerateProposal( client aptos.AptosRpcClient, mcmsAddress aptos.AccountAddress, chainSel uint64, - operations []types.Operation, + operations []types.BatchOperation, description string, -) (*mcms.Proposal, error) { + role aptosmcms.TimelockRole, +) (*mcms.TimelockProposal, error) { // Create MCMS inspector - inspector := aptosmcms.NewInspector(client) + inspector := aptosmcms.NewInspector(client, role) startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) if err != nil { return nil, fmt.Errorf("failed to get starting op count: %w", err) } opCount := startingOpCount + action := types.TimelockActionSchedule + if role == aptosmcms.TimelockRoleBypasser { + action = types.TimelockActionBypass + } + jsonRole, _ := json.Marshal(aptosmcms.AdditionalFieldsMetadata{Role: role}) + // Create proposal builder validUntil := time.Now().Add(time.Hour * ValidUntilHours).Unix() - proposalBuilder := mcms.NewProposalBuilder(). + proposalBuilder := mcms.NewTimelockProposalBuilder(). SetVersion(MCMSProposalVersion). SetValidUntil(uint32(validUntil)). SetDescription(description). + AddTimelockAddress(types.ChainSelector(chainSel), mcmsAddress.StringLong()). SetOverridePreviousRoot(true). AddChainMetadata( types.ChainSelector(chainSel), types.ChainMetadata{ - StartingOpCount: opCount, - MCMAddress: mcmsAddress.StringLong(), + StartingOpCount: opCount, + MCMAddress: mcmsAddress.StringLong(), + AdditionalFields: jsonRole, }, - ) + ). + SetAction(action). + SetDelay(types.NewDuration(time.Second)) // TODO: set propper delay // Add operations and build for _, op := range operations { @@ -62,6 +73,17 @@ func GenerateProposal( return proposal, nil } +func ToBatchOperations(ops []types.Operation) []types.BatchOperation { + batchOps := []types.BatchOperation{} + for _, op := range ops { + batchOps = append(batchOps, types.BatchOperation{ + ChainSelector: op.ChainSelector, + Transactions: []types.Transaction{op.Transaction}, + }) + } + return batchOps +} + // CreateChunksAndStage creates chunks from the compiled packages and build MCMS operations to stages them within the MCMS contract func CreateChunksAndStage( payload compile.CompiledPackage, @@ -139,3 +161,21 @@ func CreateChunksAndStage( return operations, nil } + +// GenerateMCMSTx is a helper function that generates a MCMS txs for the given parameters +func GenerateMCMSTx(toAddress aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Transaction, error) { + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return types.Transaction{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + return types.Transaction{ + To: toAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/utils/utils.go b/deployment/ccip/changeset/aptos/utils/utils.go index ae136fa75cb..a046de41dc2 100644 --- a/deployment/ccip/changeset/aptos/utils/utils.go +++ b/deployment/ccip/changeset/aptos/utils/utils.go @@ -3,7 +3,6 @@ package utils import ( "fmt" "strings" - "time" "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink/deployment" @@ -12,8 +11,8 @@ import ( // ConfirmTx confirms aptos transactions // // Optional arguments: -// - PollPeriod: time.Duration, how often to poll for the transaction. Default 100ms. -// - PollTimeout: time.Duration, how long to wait for the transaction. Default 10s. +// - aptos.PollPeriod: time.Duration, how often to poll for the transaction. Default 100ms. +// - aptos.PollTimeout: time.Duration, how long to wait for the transaction. Default 10s. func ConfirmTx(chain deployment.AptosChain, txHash string, opts ...any) error { userTx, err := chain.Client.WaitForTransaction(txHash, opts...) if err != nil { @@ -22,7 +21,6 @@ func ConfirmTx(chain deployment.AptosChain, txHash string, opts ...any) error { if !userTx.Success { return fmt.Errorf("transaction failed: %s", userTx.VmStatus) } - time.Sleep(time.Second * 1) return nil } diff --git a/deployment/ccip/changeset/aptos_state.go b/deployment/ccip/changeset/aptos_state.go index 1ffe7400035..fa0bde4eb4a 100644 --- a/deployment/ccip/changeset/aptos_state.go +++ b/deployment/ccip/changeset/aptos_state.go @@ -51,7 +51,7 @@ func loadAptosChainStateFromAddresses(addresses map[string]deployment.TypeAndVer chainState := AptosCCIPChainState{} for addrStr, typeAndVersion := range addresses { // Parse address - address := &aptos.AccountZero + address := &aptos.AccountAddress{} err := address.ParseStringRelaxed(addrStr) if err != nil { return chainState, fmt.Errorf("failed to parse address %s for %s: %w", addrStr, typeAndVersion.Type, err) diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index 3b4f785686c..6cd030798e3 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -296,6 +296,72 @@ func BuildSetOCR3ConfigArgsSolana( return ocr3Configs, nil } +// we can't use the EVM one because we need the 32 byte transmitter address +type MultiOCR3BaseOCRConfigArgsAptos struct { + ConfigDigest [32]byte + OcrPluginType uint8 + F uint8 + IsSignatureVerificationEnabled bool + Signers [][]byte + Transmitters [][]byte +} + +func BuildSetOCR3ConfigArgsAptos( + donID uint32, + ccipHome *ccip_home.CCIPHome, + destSelector uint64, + configType globals.ConfigType, +) ([]MultiOCR3BaseOCRConfigArgsAptos, error) { + chainCfg, err := ccipHome.GetChainConfig(nil, destSelector) + if err != nil { + return nil, fmt.Errorf("error getting chain config for chain selector %d it must be set before OCR3Config set up: %w", destSelector, err) + } + var offrampOCR3Configs []MultiOCR3BaseOCRConfigArgsAptos + for _, pluginType := range []types.PluginType{types.PluginTypeCCIPCommit, types.PluginTypeCCIPExec} { + ocrConfig, err2 := ccipHome.GetAllConfigs(&bind.CallOpts{ + Context: context.Background(), + }, donID, uint8(pluginType)) + if err2 != nil { + return nil, err2 + } + + configForOCR3 := ocrConfig.ActiveConfig + // we expect only an active config + if configType == globals.ConfigTypeActive { + if ocrConfig.ActiveConfig.ConfigDigest == [32]byte{} { + return nil, fmt.Errorf("invalid OCR3 config state, expected active config, donID: %d, activeConfig: %v, candidateConfig: %v", + donID, hexutil.Encode(ocrConfig.ActiveConfig.ConfigDigest[:]), hexutil.Encode(ocrConfig.CandidateConfig.ConfigDigest[:])) + } + } else if configType == globals.ConfigTypeCandidate { + if ocrConfig.CandidateConfig.ConfigDigest == [32]byte{} { + return nil, fmt.Errorf("invalid OCR3 config state, expected candidate config, donID: %d, activeConfig: %v, candidateConfig: %v", + donID, hexutil.Encode(ocrConfig.ActiveConfig.ConfigDigest[:]), hexutil.Encode(ocrConfig.CandidateConfig.ConfigDigest[:])) + } + configForOCR3 = ocrConfig.CandidateConfig + } + if err := validateOCR3Config(destSelector, configForOCR3.Config, &chainCfg); err != nil { + return nil, err + } + + var signerAddresses [][]byte + var transmitterAddresses [][]byte + for _, node := range configForOCR3.Config.Nodes { + signerAddresses = append(signerAddresses, node.SignerKey) + transmitterAddresses = append(transmitterAddresses, node.TransmitterKey) + } + + offrampOCR3Configs = append(offrampOCR3Configs, MultiOCR3BaseOCRConfigArgsAptos{ + ConfigDigest: configForOCR3.ConfigDigest, + OcrPluginType: uint8(pluginType), + F: configForOCR3.Config.FRoleDON, + IsSignatureVerificationEnabled: pluginType == types.PluginTypeCCIPCommit, + Signers: signerAddresses, + Transmitters: transmitterAddresses, + }) + } + return offrampOCR3Configs, nil +} + func BuildOCR3ConfigForCCIPHome( ccipHome *ccip_home.CCIPHome, ocrSecrets cldf.OCRSecrets, diff --git a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go index a8dc2f2aada..98d45816814 100644 --- a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go +++ b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go @@ -1,6 +1,7 @@ package testhelpers import ( + "math/big" "testing" aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" @@ -8,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - mcmstypes "github.com/smartcontractkit/mcms/types" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) func DeployChainContractsToAptosCS(t *testing.T, e DeployedEnv, chainSelector uint64) commonchangeset.ConfiguredChangeSet { @@ -17,8 +18,13 @@ func DeployChainContractsToAptosCS(t *testing.T, e DeployedEnv, chainSelector ui ContractParamsPerChain: map[uint64]config.ChainContractParams{ chainSelector: mockCCIPParams, }, - MCMSConfigPerChain: map[uint64]mcmstypes.Config{ - chainSelector: proposalutils.SingleGroupMCMSV2(t), + MCMSConfigPerChain: map[uint64]commontypes.MCMSWithTimelockConfigV2{ + chainSelector: { + Canceller: proposalutils.SingleGroupMCMSV2(t), + Proposer: proposalutils.SingleGroupMCMSV2(t), + Bypasser: proposalutils.SingleGroupMCMSV2(t), + TimelockMinDelay: big.NewInt(0), + }, }, } diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index 5889754aa22..702a2e366af 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -178,14 +178,6 @@ func SignMCMSProposal(t *testing.T, env deployment.Environment, proposal *mcmsli converters[chainSel] = &mcmssolanasdk.TimelockConverter{} inspectorsMap[chainSel] = mcmssolanasdk.NewInspector(chain.Client) } - - for _, chain := range env.AptosChains { - _, exists := chainsel.AptosChainBySelector(chain.Selector) - require.True(t, exists) - chainSel := mcmstypes.ChainSelector(chain.Selector) - inspectorsMap[chainSel] = mcmsaptossdk.NewInspector(chain.Client) - } - proposal.UseSimulatedBackend(true) signable, err := mcmslib.NewSignable(proposal, inspectorsMap) From 0f205412c708b71e9a6344e4183a5b14e96586e8 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 30 Apr 2025 22:23:58 -0300 Subject: [PATCH 029/136] rebase and solve conflicts --- deployment/ccip/changeset/aptos/config/lane.go | 12 ++++++------ deployment/ccip/changeset/aptos/config/lane_test.go | 2 +- .../ccip/changeset/aptos/cs_deploy_aptos_chain.go | 2 +- .../changeset/aptos/cs_deploy_aptos_chain_test.go | 2 +- .../ccip/changeset/aptos/cs_set_ocr3_offramp.go | 2 +- .../ccip/changeset/aptos/cs_set_ocr3_offramp_test.go | 4 ++-- .../ccip/changeset/aptos/cs_update_aptos_lanes.go | 4 ++-- .../changeset/aptos/cs_update_aptos_lanes_test.go | 4 ++-- deployment/ccip/changeset/aptos/operation/ccip.go | 2 +- .../ccip/changeset/aptos/operation/fee_quoter.go | 2 +- deployment/ccip/changeset/aptos/operation/mcms.go | 2 +- .../ccip/changeset/aptos/operation/off_ramp.go | 2 +- deployment/ccip/changeset/aptos/operation/on_ramp.go | 2 +- .../ccip/changeset/aptos/sequence/deploy_ccip.go | 2 +- .../ccip/changeset/aptos/sequence/deploy_mcms.go | 2 +- .../changeset/aptos/sequence/set_ocr3_offramp.go | 2 +- .../ccip/changeset/aptos/sequence/update_lane.go | 2 +- deployment/ccip/changeset/deployer_group.go | 4 ++++ .../ccip/changeset/testhelpers/test_environment.go | 2 +- deployment/go.mod | 9 ++++++--- deployment/go.sum | 4 ++-- 21 files changed, 38 insertions(+), 31 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/lane.go b/deployment/ccip/changeset/aptos/config/lane.go index d0b8794f022..16a994badcd 100644 --- a/deployment/ccip/changeset/aptos/config/lane.go +++ b/deployment/ccip/changeset/aptos/config/lane.go @@ -19,7 +19,7 @@ type LaneConfig struct { // Lanes accept different chain families type UpdateAptosLanesConfig struct { // MCMSConfig defines the MCMS configuration for the changeset. - MCMSConfig *proposalutils.TimelockConfig + EVMMCMSConfig *proposalutils.TimelockConfig // Lanes describes the lanes that we want to create. Lanes []LaneConfig // TestRouter indicates if we want to enable these lanes on the test router. @@ -56,26 +56,26 @@ func ToEVMUpdateLanesConfig(aptosAddCfg UpdateAptosLanesConfig) v1_6.UpdateBidir } } - routerMCMSConfig := aptosAddCfg.MCMSConfig + routerMCMSConfig := aptosAddCfg.EVMMCMSConfig if aptosAddCfg.TestRouter { routerMCMSConfig = nil // Test router is never owned by MCMS } return v1_6.UpdateBidirectionalLanesChangesetConfigs{ UpdateFeeQuoterDestsConfig: v1_6.UpdateFeeQuoterDestsConfig{ - MCMS: aptosAddCfg.MCMSConfig, + MCMS: aptosAddCfg.EVMMCMSConfig, UpdatesByChain: feeQuoterDestUpdatesByChain, }, UpdateFeeQuoterPricesConfig: v1_6.UpdateFeeQuoterPricesConfig{ - MCMS: aptosAddCfg.MCMSConfig, + MCMS: aptosAddCfg.EVMMCMSConfig, PricesByChain: feeQuoterPriceUpdatesByChain, }, UpdateOnRampDestsConfig: v1_6.UpdateOnRampDestsConfig{ - MCMS: aptosAddCfg.MCMSConfig, + MCMS: aptosAddCfg.EVMMCMSConfig, UpdatesByChain: onRampUpdatesByChain, }, UpdateOffRampSourcesConfig: v1_6.UpdateOffRampSourcesConfig{ - MCMS: aptosAddCfg.MCMSConfig, + MCMS: aptosAddCfg.EVMMCMSConfig, UpdatesByChain: offRampUpdatesByChain, }, UpdateRouterRampsConfig: v1_6.UpdateRouterRampsConfig{ diff --git a/deployment/ccip/changeset/aptos/config/lane_test.go b/deployment/ccip/changeset/aptos/config/lane_test.go index 4b695a24596..729b864254e 100644 --- a/deployment/ccip/changeset/aptos/config/lane_test.go +++ b/deployment/ccip/changeset/aptos/config/lane_test.go @@ -23,7 +23,7 @@ func TestToEVMUpdateLanesConfig(t *testing.T) { { name: "EVM <> Aptos Biderectional Lane", input: UpdateAptosLanesConfig{ - MCMSConfig: &proposalutils.TimelockConfig{}, + EVMMCMSConfig: &proposalutils.TimelockConfig{}, Lanes: []LaneConfig{ { Source: getEVMDef(), diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index ef91b44be4f..094dfca1a90 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -6,13 +6,13 @@ import ( "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 9406badd91b..53b39cacf54 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -219,7 +219,7 @@ func TestDeployAptosChain_Apply(t *testing.T) { }, }, } - env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ commonchangeset.Configure(DeployAptosChain{}, ccipConfig), }) require.NoError(t, err) diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go index 99aec529604..5798a25cb63 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go @@ -4,13 +4,13 @@ import ( "fmt" chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go index 0367bc14b68..940cc950c17 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go @@ -25,9 +25,9 @@ func TestSetOCR3Offramp_Apply(t *testing.T) { cfg := v1_6.SetOCR3OffRampConfig{ HomeChainSel: env.AllChainSelectors()[0], RemoteChainSels: env.AllChainSelectorsAptos(), - CCIPHomeConfigType: globals.ConfigTypeActive, + CCIPHomeConfigType: globals.ConfigTypeActive, // TODO: investigate why this is not being used, might be a bug } - env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ commonchangeset.Configure(aptoscs.SetOCR3Offramp{}, cfg), }) require.NoError(t, err) diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go index 70e80a790ab..7e1e9aa303c 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -3,6 +3,7 @@ package aptos import ( "fmt" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" @@ -10,7 +11,6 @@ import ( seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" @@ -43,7 +43,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos // Add lane on EVM chains // TODO: applying a changeset within another changeset is an anti-pattern. Using it here until EVM is refactored into Operations evmUpdatesInput := config.ToEVMUpdateLanesConfig(cfg) - out, err := v1_6.UpdateLanesLogic(env, cfg.MCMSConfig, evmUpdatesInput) + out, err := v1_6.UpdateLanesLogic(env, cfg.EVMMCMSConfig, evmUpdatesInput) if err != nil { return deployment.ChangesetOutput{}, err } diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index f587762fda1..61f9f234ce8 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -45,7 +45,7 @@ func TestAddAptosLanes_Apply(t *testing.T) { cfg := getMockUpdateConfig(t, emvSelector, emvSelector2, aptosSelector) // Apply the changeset - env, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ commonchangeset.Configure(aptoscs.AddAptosLanes{}, cfg), }) require.NoError(t, err) @@ -82,7 +82,7 @@ func getMockUpdateConfig( aptosSelector uint64, ) config.UpdateAptosLanesConfig { return config.UpdateAptosLanesConfig{ - MCMSConfig: nil, + EVMMCMSConfig: nil, // Aptos1 <> EVM1 | Aptos1 -> EVM2 Lanes: []config.LaneConfig{ { diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index d0ad9926979..b648fd9b940 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -10,11 +10,11 @@ import ( "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/operation/fee_quoter.go b/deployment/ccip/changeset/aptos/operation/fee_quoter.go index 4f67acff89d..d9cf28c821d 100644 --- a/deployment/ccip/changeset/aptos/operation/fee_quoter.go +++ b/deployment/ccip/changeset/aptos/operation/fee_quoter.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" - "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 70ed5ace56d..7a9483b4035 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -15,7 +15,7 @@ import ( aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment/operations" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" ) const AcceptOwnershipProposalDescription = "Accept ownership of the contract to self" diff --git a/deployment/ccip/changeset/aptos/operation/off_ramp.go b/deployment/ccip/changeset/aptos/operation/off_ramp.go index d21d2d7b145..36ab132a476 100644 --- a/deployment/ccip/changeset/aptos/operation/off_ramp.go +++ b/deployment/ccip/changeset/aptos/operation/off_ramp.go @@ -6,8 +6,8 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/operation/on_ramp.go b/deployment/ccip/changeset/aptos/operation/on_ramp.go index a8f3546bd25..f83cfab4961 100644 --- a/deployment/ccip/changeset/aptos/operation/on_ramp.go +++ b/deployment/ccip/changeset/aptos/operation/on_ramp.go @@ -7,8 +7,8 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index 7dbebcc49d7..ba8b32dbd73 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -3,10 +3,10 @@ package sequence import ( "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/chainlink/deployment/operations" mcmstypes "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index 124efde101c..47d938ae35d 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -3,9 +3,9 @@ package sequence import ( "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/operations" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go index 7832762148c..daae47c4c30 100644 --- a/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go +++ b/deployment/ccip/changeset/aptos/sequence/set_ocr3_offramp.go @@ -7,11 +7,11 @@ import ( "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" aptosutils "github.com/smartcontractkit/chainlink-aptos/relayer/utils" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" mcmstypes "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 0c497acbfc7..4ce82e18ac7 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -7,11 +7,11 @@ import ( "github.com/aptos-labs/aptos-go-sdk" chainsel "github.com/smartcontractkit/chain-selectors" aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/chainlink/deployment/operations" "github.com/smartcontractkit/mcms/types" ) diff --git a/deployment/ccip/changeset/deployer_group.go b/deployment/ccip/changeset/deployer_group.go index b062dec9bfa..0a461b2a98a 100644 --- a/deployment/ccip/changeset/deployer_group.go +++ b/deployment/ccip/changeset/deployer_group.go @@ -485,6 +485,10 @@ func BuildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map func BuildTimelockAddressPerChain(e deployment.Environment, onchainState CCIPOnChainState) map[uint64]string { addressPerChain := make(map[uint64]string) for _, chain := range e.Chains { + if onchainState.Chains[chain.Selector].Timelock == nil { + e.Logger.Warn("timelock is nil, skipping chain: %s", chain.Selector) + continue + } addressPerChain[chain.Selector] = onchainState.Chains[chain.Selector].Timelock.Address().Hex() } diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 510e0e7caa1..2ebe62d678e 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -719,7 +719,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn if len(aptosChains) != 0 { // TODO: currently only one aptos chain supported in test environment aptosCs := DeployChainContractsToAptosCS(t, e, aptosChains[0]) - e.Env, err = commonchangeset.ApplyChangesetsV2(t, e.Env, []commonchangeset.ConfiguredChangeSet{aptosCs}) + e.Env, _, err = commonchangeset.ApplyChangesetsV2(t, e.Env, []commonchangeset.ConfiguredChangeSet{aptosCs}) require.NoError(t, err) } diff --git a/deployment/go.mod b/deployment/go.mod index 799c0e89181..d0b9ad4ed2a 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -5,7 +5,10 @@ go 1.24.1 toolchain go1.24.2 // Make sure we're working with the latest chainlink libs -replace github.com/smartcontractkit/chainlink/v2 => ../ +replace ( + github.com/smartcontractkit/chainlink-aptos/relayer => github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 + github.com/smartcontractkit/chainlink/v2 => ../ +) // Using a separate inline `require` here to avoid surrounding line changes // creating potential merge conflicts. @@ -33,7 +36,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250429205337-7ee5f91ed065 @@ -49,6 +52,7 @@ require ( github.com/smartcontractkit/mcms v0.18.0 github.com/spf13/cast v1.7.1 github.com/stretchr/testify v1.10.0 + github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.36.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 @@ -368,7 +372,6 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-aptos/relayer v0.0.0-20250320162700-de7f1c0fd741 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/deployment/go.sum b/deployment/go.sum index e84f35c09b3..029673da83a 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1230,8 +1230,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= From 458c24104d8daef3a8a521b726e5bb71495625e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:30:51 +0200 Subject: [PATCH 030/136] Add OnRamp config --- .../ccip/configs/aptos/contract_reader.go | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index e6a97e2171d..4aa84dacf29 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -26,7 +26,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameRMNProxy: { Name: "rmn_remote", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -35,7 +34,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameFeeQuoter: { Name: "fee_quoter", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -138,11 +136,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ - consts.EventNameCCIPMessageSent: { - EventHandleStructName: "OnRampState", - EventHandleFieldName: "ccip_message_sent_events", - EventAccountAddress: "onramp::get_state_address", - }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", @@ -241,6 +234,45 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, + consts.ContractNameOnRamp: { + Name: "onramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameOnRampGetDynamicConfig: { + Name: "get_dynamic_config", + }, + consts.MethodNameOnRampGetStaticConfig: { + Name: "get_static_config", + }, + consts.MethodNameOnRampGetDestChainConfig: { + Name: "get_dest_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + ResultTupleToStruct: []string{"sequenceNumber", "allowListEnabled", "router"}, + }, + consts.MethodNameGetExpectedNextSequenceNumber: { + Name: "get_expected_next_sequence_number", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, + }, + }, }, }, nil } From 6e3c30af39b4df0fd0f5cac004a50c7a8f545630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:31:05 +0200 Subject: [PATCH 031/136] Fix NewExtraDataCodecParams --- deployment/ccip/manualexechelpers/exec.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/deployment/ccip/manualexechelpers/exec.go b/deployment/ccip/manualexechelpers/exec.go index 91f7a897c3d..bb221a4e896 100644 --- a/deployment/ccip/manualexechelpers/exec.go +++ b/deployment/ccip/manualexechelpers/exec.go @@ -12,17 +12,18 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm/manualexeclib" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) const ( @@ -503,7 +504,7 @@ func ManuallyExecuteAll( stepDuration time.Duration, reExecuteIfFailed bool, ) error { - extraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) + extraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) // for large backfills, these caches can speed things up because we don't need to query // the chain multiple times for the same root/messages. From be14b2c834838e349723af5e8599b1359ec7cdbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:43:54 +0200 Subject: [PATCH 032/136] Fix NewExtraDataCodecParams --- core/capabilities/ccip/ccipsolana/msghasher_test.go | 3 ++- core/capabilities/ccip/ocrimpls/contract_transmitter_test.go | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipsolana/msghasher_test.go b/core/capabilities/ccip/ccipsolana/msghasher_test.go index 0eb7ce44193..2d5087f7481 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher_test.go +++ b/core/capabilities/ccip/ccipsolana/msghasher_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" @@ -28,7 +29,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ExtraDataDecoder{})) +var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) func TestMessageHasher_EVM2SVM(t *testing.T) { any2AnyMsg, any2SolanaMsg, msgAccounts := createEVM2SolanaMessages(t) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 591ada5cb9d..5b63341b8f3 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -36,6 +36,7 @@ import ( evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" @@ -192,6 +193,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { ccipcommon.NewExtraDataCodecParams( ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, + ccipaptos.ExtraDataDecoder{}, ), ) t.Run("fails when multiple reports are included", func(t *testing.T) { From e047945aa8fb4ee60f3fb3e4cda2ab7b9bc3f380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 14:16:52 +0200 Subject: [PATCH 033/136] bump chainlink-aptos to latest --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 4 ++-- system-tests/tests/go.mod | 2 +- system-tests/tests/go.sum | 4 ++-- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 15c607cc79d..1cf184b09dc 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -354,7 +354,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 3031aced691..ca6a1be00d1 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1181,8 +1181,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/deployment/go.mod b/deployment/go.mod index a5e213780ce..7915396d1c4 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -33,7 +33,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250429205337-7ee5f91ed065 diff --git a/deployment/go.sum b/deployment/go.sum index 013f0394d82..70762b414a8 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1230,8 +1230,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/go.mod b/go.mod index e17ce25b76a..2424332c996 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 diff --git a/go.sum b/go.sum index 73eef086dcb..4c2aff8c059 100644 --- a/go.sum +++ b/go.sum @@ -1078,8 +1078,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 5d19c8f5d0d..f5a23bccf33 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -453,7 +453,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 3b7c187dbf6..5f9549d796a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index f7abc5134da..7776a54a880 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -440,7 +440,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.8 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 2994342a395..cf469e66db4 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1447,8 +1447,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index eba71f2bc5d..1f5085f4e78 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -355,7 +355,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index f1627929a4d..4262eb3b027 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1218,8 +1218,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 79e30db9af3..b207c2ca9dd 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -429,7 +429,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index f4a53686ed8..5384e3f57ee 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= From a85066f518f97fc27faf4e6c29d145b33f95bace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 15:16:55 +0200 Subject: [PATCH 034/136] Upgrade private plugin refs --- plugins/plugins.private.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index a307029794b..b94d4fa7d5f 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -14,19 +14,19 @@ plugins: installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" - gitRef: "a5c33ddc76128b14117579a075ec9d239d3b2209" + gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" installPath: "github.com/smartcontractkit/capabilities/cron" kvstore: - enabled: false moduleURI: "github.com/smartcontractkit/capabilities/kvstore" - gitRef: "a5c33ddc76128b14117579a075ec9d239d3b2209" + gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" installPath: "github.com/smartcontractkit/capabilities/kvstore" readcontract: - moduleURI: "github.com/smartcontractkit/capabilities/readcontract" - gitRef: "a5c33ddc76128b14117579a075ec9d239d3b2209" + gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" installPath: "github.com/smartcontractkit/capabilities/readcontract" workflowevent: - enabled: false moduleURI: "github.com/smartcontractkit/capabilities/workflowevent" - gitRef: "a5c33ddc76128b14117579a075ec9d239d3b2209" + gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" installPath: "github.com/smartcontractkit/capabilities/workflowevent" From 0ee2541b836902943b2e0285b9de02f7e0bec938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 15:17:03 +0200 Subject: [PATCH 035/136] Generate --- core/internal/mocks/flags.go | 2 +- core/internal/mocks/flux_aggregator.go | 2 +- .../ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go | 2 +- go.md | 4 ++++ 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/core/internal/mocks/flags.go b/core/internal/mocks/flags.go index 26c791eccfc..558c5d0c4b9 100644 --- a/core/internal/mocks/flags.go +++ b/core/internal/mocks/flags.go @@ -3,7 +3,7 @@ package mocks import ( - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/internal/mocks/flux_aggregator.go b/core/internal/mocks/flux_aggregator.go index d2c7ea3e216..5b61d7a34c6 100644 --- a/core/internal/mocks/flux_aggregator.go +++ b/core/internal/mocks/flux_aggregator.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go index 1c12e1eba81..daa676e23e3 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go @@ -5,7 +5,7 @@ package mock_contracts import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go index 2329746de1f..23fee609a78 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go index 7ff63e78229..1a80a1b8bc4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/go.md b/go.md index 302199ccd78..45e66fdbd5e 100644 --- a/go.md +++ b/go.md @@ -24,6 +24,8 @@ flowchart LR chain-selectors click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" + chainlink-aptos --> chainlink-common + click chainlink-aptos href "https://github.com/smartcontractkit/chainlink-aptos" chainlink-automation --> chainlink-common click chainlink-automation href "https://github.com/smartcontractkit/chainlink-automation" chainlink-ccip --> chain-selectors @@ -68,6 +70,7 @@ flowchart LR click chainlink-solana href "https://github.com/smartcontractkit/chainlink-solana" chainlink-tron/relayer --> chainlink-evm click chainlink-tron/relayer href "https://github.com/smartcontractkit/chainlink-tron" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds @@ -242,6 +245,7 @@ flowchart LR chainlink/system-tests/tests --> chainlink-testing-framework/wasp chainlink/system-tests/tests --> chainlink/system-tests/lib click chainlink/system-tests/tests href "https://github.com/smartcontractkit/chainlink" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds From a3a1fa5eabbd25fb13c5f1613528ea77728a0494 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 30 Apr 2025 22:27:13 -0300 Subject: [PATCH 036/136] feat: Implement contract update changesets --- .../ccip/changeset/aptos/config/update.go | 9 +++ .../changeset/aptos/cs_update_aptos_ccip.go | 70 +++++++++++++++++ .../ccip/changeset/aptos/operation/ccip.go | 42 ++++++++--- .../changeset/aptos/sequence/update_ccip.go | 75 +++++++++++++++++++ .../ccip/changeset/v1_6/cs_ccip_home.go | 2 +- 5 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 deployment/ccip/changeset/aptos/config/update.go create mode 100644 deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go create mode 100644 deployment/ccip/changeset/aptos/sequence/update_ccip.go diff --git a/deployment/ccip/changeset/aptos/config/update.go b/deployment/ccip/changeset/aptos/config/update.go new file mode 100644 index 00000000000..97f74195b36 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/update.go @@ -0,0 +1,9 @@ +package config + +type UpdateAptosChainConfig struct { + ChainSelector uint64 + UpdateCCIP bool + UpdateOffRamp bool + UpdateOnRamp bool + UpdateRouter bool +} diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go new file mode 100644 index 00000000000..bd528868d3d --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go @@ -0,0 +1,70 @@ +package aptos + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +var _ deployment.ChangeSetV2[config.UpdateAptosChainConfig] = UpdateAptosChain{} + +// DeployAptosChain deploys Aptos chain packages and modules +type UpdateAptosChain struct{} + +func (cs UpdateAptosChain) VerifyPreconditions(env deployment.Environment, config config.UpdateAptosChainConfig) error { + // TODO validate if required packages and modules are already deployed + return nil +} + +func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAptosChainConfig) (deployment.ChangesetOutput, error) { + timeLockProposals := []mcms.TimelockProposal{} + mcmsOperations := []types.BatchOperation{} + seqReports := make([]operations.Report[any, any], 0) + + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + } + + deps := operation.AptosDeps{ + AptosChain: env.AptosChains[cfg.ChainSelector], + OnChainState: state.AptosChains[cfg.ChainSelector], + CCIPOnChainState: state, + } + + // Execute the sequence + updateSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.UpdateCCIPSequence, deps, cfg) + if err != nil { + return deployment.ChangesetOutput{}, err + } + seqReports = append(seqReports, updateSeqReport.ExecutionReports...) + mcmsOperations = append(mcmsOperations, updateSeqReport.Output...) + + // Generate MCMS proposals + proposal, err := utils.GenerateProposal( + deps.AptosChain.Client, + state.AptosChains[cfg.ChainSelector].MCMSAddress, + deps.AptosChain.Selector, + mcmsOperations, + "Update chain contracts on Aptos chain", + aptosmcms.TimelockRoleProposer, + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", cfg.ChainSelector, err) + } + timeLockProposals = append(timeLockProposals, *proposal) + + return deployment.ChangesetOutput{ + MCMSTimelockProposals: []mcms.TimelockProposal{*proposal}, + Reports: seqReports, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index b648fd9b940..e35fd79887b 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -74,6 +74,7 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, in CleanupStagingAr // GenerateDeployCCIPProposal Operation generates deployment MCMS operations for the CCIP package type DeployCCIPInput struct { MCMSAddress aptos.AccountAddress + IsUpdate bool } type DeployCCIPOutput struct { @@ -90,17 +91,27 @@ var GenerateDeployCCIPProposalOp = operations.NewOperation( func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { // Validate there's no package deployed - if deps.OnChainState.CCIPAddress != (aptos.AccountAddress{}) { - b.Logger.Infow("CCIP Package already deployed", "addr", deps.OnChainState.CCIPAddress.String()) - return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress}, nil + if (deps.OnChainState.CCIPAddress == (aptos.AccountAddress{})) == (in.IsUpdate) { + if in.IsUpdate { + b.Logger.Infow("Trying to update a non-deployed package", "addr", deps.OnChainState.CCIPAddress.String()) + return DeployCCIPOutput{}, fmt.Errorf("CCIP package not deployed on Aptos chain %d", deps.AptosChain.Selector) + } else { + b.Logger.Infow("CCIP Package already deployed", "addr", deps.OnChainState.CCIPAddress.String()) + return DeployCCIPOutput{CCIPAddress: deps.OnChainState.CCIPAddress}, nil + } } // Compile, chunk and get CCIP deploy operations mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) - ccipObjectAddress, operations, err := getCCIPDeployMCMSOps(mcmsContract, deps.AptosChain.Selector) + ccipObjectAddress, operations, err := getCCIPDeployMCMSOps(mcmsContract, deps.AptosChain.Selector, deps.OnChainState.CCIPAddress) if err != nil { return DeployCCIPOutput{}, fmt.Errorf("failed to compile and create deploy operations: %w", err) } + if in.IsUpdate { + return DeployCCIPOutput{ + MCMSOperations: operations, + }, nil + } // Save the address of the CCIP object typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) @@ -113,21 +124,32 @@ func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCC }, nil } -func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64) (aptos.AccountAddress, []types.Operation, error) { +func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64, ccipAddress aptos.AccountAddress) (aptos.AccountAddress, []types.Operation, error) { // Calculate addresses of the owner and the object - ccipObjectAddress, err := mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) - if err != nil { - return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) + var ccipObjectAddress aptos.AccountAddress + var err error + if ccipAddress != (aptos.AccountAddress{}) { + ccipObjectAddress = ccipAddress + } else { + ccipObjectAddress, err = mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) + } } // Compile Package - payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), true) + payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), ccipAddress == aptos.AccountAddress{}) if err != nil { return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to compile: %w", err) } // Create chunks and stage operations - operations, err := utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) + var operations []types.Operation + if ccipAddress == (aptos.AccountAddress{}) { + operations, err = utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) + } else { + operations, err = utils.CreateChunksAndStage(payload, mcmsContract, chainSel, "", &ccipObjectAddress) + } if err != nil { return ccipObjectAddress, operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) } diff --git a/deployment/ccip/changeset/aptos/sequence/update_ccip.go b/deployment/ccip/changeset/aptos/sequence/update_ccip.go new file mode 100644 index 00000000000..becb8d5b03e --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/update_ccip.go @@ -0,0 +1,75 @@ +package sequence + +import ( + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +var UpdateCCIPSequence = operations.NewSequence( + "update-aptos-ccip-sequence", + operation.Version1_0_0, + "Update Aptos CCIP contracts", + updateCCIPSequence, +) + +func updateCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in config.UpdateAptosChainConfig) ([]mcmstypes.BatchOperation, error) { + var mcmsOperations []mcmstypes.BatchOperation + + // Cleanup staging area + cleanupInput := operation.CleanupStagingAreaInput{ + MCMSAddress: deps.OnChainState.MCMSAddress, + } + cleanupReport, err := operations.ExecuteOperation(b, operation.CleanupStagingAreaOp, deps, cleanupInput) + if err != nil { + return nil, err + } + if len(cleanupReport.Output.Transactions) > 0 { + mcmsOperations = append(mcmsOperations, cleanupReport.Output) + } + + if in.UpdateCCIP { + deployCCIPInput := operation.DeployCCIPInput{ + MCMSAddress: deps.OnChainState.MCMSAddress, + IsUpdate: in.UpdateCCIP, + } + deployCCIPReport, err := operations.ExecuteOperation(b, operation.GenerateDeployCCIPProposalOp, deps, deployCCIPInput) + if err != nil { + return nil, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployCCIPReport.Output.MCMSOperations)...) + } + + deployModulesInput := operation.DeployModulesInput{ + MCMSAddress: deps.OnChainState.MCMSAddress, + CCIPAddress: deps.OnChainState.CCIPAddress, + } + + if in.UpdateOnRamp { + deployOnRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOnRampProposalOp, deps, deployModulesInput) + if err != nil { + return nil, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOnRampReport.Output)...) + } + + if in.UpdateOffRamp { + deployOffRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOffRampProposalOp, deps, deployModulesInput) + if err != nil { + return nil, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOffRampReport.Output)...) + } + + if in.UpdateRouter { + deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployModulesInput) + if err != nil { + return nil, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployRouterReport.Output)...) + } + + return mcmsOperations, nil +} diff --git a/deployment/ccip/changeset/v1_6/cs_ccip_home.go b/deployment/ccip/changeset/v1_6/cs_ccip_home.go index 070886a77f3..047c8413e8f 100644 --- a/deployment/ccip/changeset/v1_6/cs_ccip_home.go +++ b/deployment/ccip/changeset/v1_6/cs_ccip_home.go @@ -553,7 +553,7 @@ func AddDonAndSetCandidateChangeset( return deployment.ChangesetOutput{}, err } - err = cfg.Validate(e, state) + // err = cfg.Validate(e, state) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) } From 7d688bd9ee231d0848f14e4d10b46b76ff317fbc Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 1 May 2025 15:14:36 -0300 Subject: [PATCH 037/136] ref: refactor MCMS deploy sequence --- .../ccip/changeset/aptos/config/chain.go | 4 +- .../ccip/changeset/aptos/config/lane.go | 4 +- .../ccip/changeset/aptos/config/update.go | 1 + .../ccip/changeset/aptos/operation/mcms.go | 41 +++++++------------ .../changeset/aptos/sequence/deploy_mcms.go | 22 +++++----- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/chain.go b/deployment/ccip/changeset/aptos/config/chain.go index 6294143f018..45471de96ae 100644 --- a/deployment/ccip/changeset/aptos/config/chain.go +++ b/deployment/ccip/changeset/aptos/config/chain.go @@ -9,7 +9,9 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" ) -type IChainDefinition interface { +// ChainDefinition is an interface that defines a chain config for lane deployment +// It is used to convert between Aptos and EVM fee quoter configs. +type ChainDefinition interface { GetChainFamily() string } diff --git a/deployment/ccip/changeset/aptos/config/lane.go b/deployment/ccip/changeset/aptos/config/lane.go index 16a994badcd..966802403b3 100644 --- a/deployment/ccip/changeset/aptos/config/lane.go +++ b/deployment/ccip/changeset/aptos/config/lane.go @@ -10,8 +10,8 @@ import ( ) type LaneConfig struct { - Source IChainDefinition - Dest IChainDefinition + Source ChainDefinition + Dest ChainDefinition IsDisabled bool } diff --git a/deployment/ccip/changeset/aptos/config/update.go b/deployment/ccip/changeset/aptos/config/update.go index 97f74195b36..d7315ab2904 100644 --- a/deployment/ccip/changeset/aptos/config/update.go +++ b/deployment/ccip/changeset/aptos/config/update.go @@ -1,5 +1,6 @@ package config +// UpdateAptosChainConfig holds configuration for updating Aptos chain changeset type UpdateAptosChainConfig struct { ChainSelector uint64 UpdateCCIP bool diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 7a9483b4035..1fa8e99055d 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -9,9 +9,6 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-aptos/bindings/bind" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" @@ -27,24 +24,17 @@ var DeployMCMSOp = operations.NewOperation( deployMCMS, ) -type DeployMCMSOutput struct { - AddressMCMS aptos.AccountAddress - ContractMCMS *mcmsbind.MCMS // TODO: outputs should be serializable -} - -func deployMCMS(b operations.Bundle, deps AptosDeps, input operations.EmptyInput) (DeployMCMSOutput, error) { +func deployMCMS(b operations.Bundle, deps AptosDeps, _ operations.EmptyInput) (aptos.AccountAddress, error) { mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() - addressMCMS, mcmsDeployTx, contractMCMS, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) + addressMCMS, mcmsDeployTx, _, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) if err != nil { - return DeployMCMSOutput{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) + return aptos.AccountAddress{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) } - if err := utils.ConfirmTx(deps.AptosChain, mcmsDeployTx.Hash); err != nil { - return DeployMCMSOutput{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) + if err := deps.AptosChain.Confirm(mcmsDeployTx.Hash); err != nil { + return aptos.AccountAddress{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) } - typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_0_0) - deps.AB.Save(deps.AptosChain.Selector, addressMCMS.String(), typeAndVersion) - return DeployMCMSOutput{addressMCMS, &contractMCMS}, nil + return addressMCMS, nil } type ConfigureMCMSInput struct { @@ -66,7 +56,7 @@ func configureMCMS(b operations.Bundle, deps AptosDeps, in ConfigureMCMSInput) ( if err != nil { return nil, fmt.Errorf("failed to setConfig in MCMS contract: %w", err) } - if err := utils.ConfirmTx(deps.AptosChain, setCfgTx.Hash); err != nil { + if err := deps.AptosChain.Confirm(setCfgTx.Hash); err != nil { return nil, fmt.Errorf("MCMS setConfig transaction failed: %w", err) } return nil, nil @@ -79,9 +69,10 @@ var TransferOwnershipToSelfOp = operations.NewOperation( transferOwnershipToSelf, ) -func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, contractMCMS *mcmsbind.MCMS) (any, error) { +func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (any, error) { opts := &bind.TransactOpts{Signer: deps.AptosChain.DeployerSigner} - tx, err := (*contractMCMS).MCMSAccount().TransferOwnershipToSelf(opts) + contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) + tx, err := contractMCMS.MCMSAccount().TransferOwnershipToSelf(opts) if err != nil { return nil, fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) } @@ -92,11 +83,6 @@ func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, contractMCMS * return nil, nil } -type GenerateAcceptOwnershipProposalInput struct { - AddressMCMS aptos.AccountAddress - ContractMCMS *mcmsbind.MCMS // TODO: outputs should be serializable -} - var GenerateAcceptOwnershipProposalOp = operations.NewOperation( "generate-accept-ownership-proposal-op", Version1_0_0, @@ -104,8 +90,9 @@ var GenerateAcceptOwnershipProposalOp = operations.NewOperation( generateAcceptOwnershipProposal, ) -func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in GenerateAcceptOwnershipProposalInput) (mcmstypes.BatchOperation, error) { - moduleInfo, function, _, args, err := (*in.ContractMCMS).MCMSAccount().Encoder().AcceptOwnership() +func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.BatchOperation, error) { + contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() if err != nil { return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } @@ -122,7 +109,7 @@ func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, in Gen return mcmstypes.BatchOperation{ ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), Transactions: []mcmstypes.Transaction{{ - To: in.AddressMCMS.StringLong(), + To: mcmsAddress.StringLong(), Data: aptosmcms.ArgsToData(args), AdditionalFields: callOneAdditionalFields, }}, diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index 47d938ae35d..e46a680cc7c 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -4,6 +4,8 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/common/types" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" @@ -34,9 +36,11 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM if err != nil { return DeployMCMSSeqOutput{}, err } + typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_0_0) + deps.AB.Save(deps.AptosChain.Selector, deployMCMSReport.Output.String(), typeAndVersion) // Configure MCMS configureMCMSBypassers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output.AddressMCMS, + AddressMCMS: deployMCMSReport.Output, MCMSConfigs: configMCMS.Bypasser, MCMSRole: aptosmcms.TimelockRoleBypasser, } @@ -45,7 +49,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } configureMCMSCancellers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output.AddressMCMS, + AddressMCMS: deployMCMSReport.Output, MCMSConfigs: configMCMS.Canceller, MCMSRole: aptosmcms.TimelockRoleCanceller, } @@ -54,32 +58,28 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } configureMCMSProposers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output.AddressMCMS, + AddressMCMS: deployMCMSReport.Output, MCMSConfigs: configMCMS.Proposer, MCMSRole: aptosmcms.TimelockRoleProposer, } + // TODO: Should set MinDelay to timelock _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSProposers) if err != nil { return DeployMCMSSeqOutput{}, err } - // TODO: Should set MinDelay to timelock // Transfer ownership to self - _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output.ContractMCMS) + _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output) if err != nil { return DeployMCMSSeqOutput{}, err } // Generate proposal to accept ownership - generateAcceptOwnershipProposalInput := operation.GenerateAcceptOwnershipProposalInput{ - AddressMCMS: deployMCMSReport.Output.AddressMCMS, - ContractMCMS: deployMCMSReport.Output.ContractMCMS, - } - gaopReport, err := operations.ExecuteOperation(b, operation.GenerateAcceptOwnershipProposalOp, deps, generateAcceptOwnershipProposalInput) + gaopReport, err := operations.ExecuteOperation(b, operation.GenerateAcceptOwnershipProposalOp, deps, deployMCMSReport.Output) if err != nil { return DeployMCMSSeqOutput{}, err } return DeployMCMSSeqOutput{ - MCMSAddress: deployMCMSReport.Output.AddressMCMS, + MCMSAddress: deployMCMSReport.Output, MCMSOperation: gaopReport.Output, }, nil } From 8a6b5023a027eab6f9150128d380ef7b18b280f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 21:01:46 +0200 Subject: [PATCH 038/136] Bump chainlink-aptos --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- deployment/go.mod | 2 +- deployment/go.sum | 1 + go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 4 ++-- system-tests/tests/go.mod | 2 +- system-tests/tests/go.sum | 4 ++-- 14 files changed, 20 insertions(+), 19 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index d97ce20f31a..afa36a271ea 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -353,7 +353,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 872be957fa3..d1d8d3affe9 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1179,8 +1179,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/deployment/go.mod b/deployment/go.mod index 083d96b4b74..25bfb69b728 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -32,7 +32,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250501134304-27c43a698294 diff --git a/deployment/go.sum b/deployment/go.sum index 4998d73c0c7..e4e1ebe1656 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1230,6 +1230,7 @@ github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/go.mod b/go.mod index 89d93071cda..c01c7daacf5 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 diff --git a/go.sum b/go.sum index ec72ea6da8b..c5218bdad0e 100644 --- a/go.sum +++ b/go.sum @@ -1076,8 +1076,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2d17ae5a7ce..3384b4778a0 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -452,7 +452,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250408161305-721208f43882 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index eb47f4efb17..3a404f1f5af 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 9337a9eef62..7432d977ce5 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -439,7 +439,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.8 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 93b052b7ec4..1466e641eb1 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1447,8 +1447,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 971bf710bbd..a9ca5479ef8 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -354,7 +354,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index de58978578a..e435b6f2fef 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1216,8 +1216,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 682fc98f9f6..9fe88f394d2 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -428,7 +428,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.52 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index f4f2475e94c..4a8f438c15f 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81 h1:eQAwO5jZAAS3WKXOb61giMPCO1nn8u0Zwqok259gK9I= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501112120-5ab3d000ab81/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507 h1:JvcS2i7myzPzJQ85LpD2ufXYyYRB5jhPBSkqcp+HKD0= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250501150122-023cbbe11507/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= From 4d6f882d053ce227e337702f24f605488a3aef1c Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Thu, 1 May 2025 21:14:32 +0200 Subject: [PATCH 039/136] Bumping up chainlink-aptos plugin gitRef --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index b94d4fa7d5f..540c3c55398 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From 56cf9a62d5158308711b1f7a83ae99bb0f472a9a Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 1 May 2025 19:05:42 -0300 Subject: [PATCH 040/136] ref: apply standards --- .../changeset/aptos/config/deploy_chain.go | 6 +- .../ccip/changeset/aptos/config/lane.go | 4 +- .../ccip/changeset/aptos/config/update.go | 13 +++-- .../changeset/aptos/cs_deploy_aptos_chain.go | 7 +-- .../aptos/cs_deploy_aptos_chain_test.go | 18 ++++-- .../changeset/aptos/cs_set_ocr3_offramp.go | 3 +- .../aptos/cs_set_ocr3_offramp_test.go | 12 +++- .../changeset/aptos/cs_update_aptos_ccip.go | 3 +- .../changeset/aptos/cs_update_aptos_lanes.go | 3 +- .../aptos/cs_update_aptos_lanes_test.go | 8 +++ .../ccip/changeset/aptos/operation/mcms.go | 8 +-- .../changeset/aptos/sequence/deploy_mcms.go | 6 +- deployment/ccip/changeset/aptos/utils/mcms.go | 55 +++++++++++++++---- .../ccip/changeset/aptos/utils/utils.go | 38 ------------- .../testhelpers/aptos_test_helper.go | 2 +- .../ccip/changeset/v1_6/cs_ccip_home.go | 2 +- .../ccip/changeset/v1_6/cs_chain_contracts.go | 2 - .../v1_6/cs_update_bidirectional_lanes.go | 2 +- .../common/proposalutils/mcms_test_helpers.go | 1 + deployment/environment/memory/node.go | 22 -------- 20 files changed, 107 insertions(+), 108 deletions(-) delete mode 100644 deployment/ccip/changeset/aptos/utils/utils.go diff --git a/deployment/ccip/changeset/aptos/config/deploy_chain.go b/deployment/ccip/changeset/aptos/config/deploy_chain.go index b6bca7ce9e6..c59470ad260 100644 --- a/deployment/ccip/changeset/aptos/config/deploy_chain.go +++ b/deployment/ccip/changeset/aptos/config/deploy_chain.go @@ -5,13 +5,15 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" ) // DeployAptosChainConfig is a configuration for deploying CCIP Package for Aptos chains type DeployAptosChainConfig struct { - MCMSConfigPerChain map[uint64]types.MCMSWithTimelockConfigV2 - ContractParamsPerChain map[uint64]ChainContractParams + MCMSDeployConfigPerChain map[uint64]types.MCMSWithTimelockConfigV2 + MCMSTimelockConfigPerChain map[uint64]proposalutils.TimelockConfig + ContractParamsPerChain map[uint64]ChainContractParams } func (c DeployAptosChainConfig) Validate() error { diff --git a/deployment/ccip/changeset/aptos/config/lane.go b/deployment/ccip/changeset/aptos/config/lane.go index 966802403b3..8adb6c73bf0 100644 --- a/deployment/ccip/changeset/aptos/config/lane.go +++ b/deployment/ccip/changeset/aptos/config/lane.go @@ -18,8 +18,10 @@ type LaneConfig struct { // UpdateAptosLanesConfig is a configuration struct for AddAptosLanesChangeset // Lanes accept different chain families type UpdateAptosLanesConfig struct { - // MCMSConfig defines the MCMS configuration for the changeset. + // EVMMCMSConfig defines the MCMS configuration for EVM chains. EVMMCMSConfig *proposalutils.TimelockConfig + // MCMSConfig defines the MCMS configuration for Aptos chains. + AptosMCMSConfig *proposalutils.TimelockConfig // Lanes describes the lanes that we want to create. Lanes []LaneConfig // TestRouter indicates if we want to enable these lanes on the test router. diff --git a/deployment/ccip/changeset/aptos/config/update.go b/deployment/ccip/changeset/aptos/config/update.go index d7315ab2904..2fe1722a657 100644 --- a/deployment/ccip/changeset/aptos/config/update.go +++ b/deployment/ccip/changeset/aptos/config/update.go @@ -1,10 +1,13 @@ package config +import "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + // UpdateAptosChainConfig holds configuration for updating Aptos chain changeset type UpdateAptosChainConfig struct { - ChainSelector uint64 - UpdateCCIP bool - UpdateOffRamp bool - UpdateOnRamp bool - UpdateRouter bool + ChainSelector uint64 + UpdateCCIP bool + UpdateOffRamp bool + UpdateOnRamp bool + UpdateRouter bool + MCMSTimelockConfig proposalutils.TimelockConfig } diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index 094dfca1a90..f72b1728951 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -14,7 +14,6 @@ import ( seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/mcms" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" mcmstypes "github.com/smartcontractkit/mcms/types" ) @@ -44,7 +43,7 @@ func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, confi continue } if chainState.MCMSAddress == (aptos.AccountAddress{}) { - mcmsConfig := config.MCMSConfigPerChain[chainSel] + mcmsConfig := config.MCMSDeployConfigPerChain[chainSel] for _, cfg := range []mcmstypes.Config{mcmsConfig.Bypasser, mcmsConfig.Canceller, mcmsConfig.Proposer} { if err := cfg.Validate(); err != nil { errs = append(errs, fmt.Errorf("invalid mcms configs for Aptos chain %d: %w", chainSel, err)) @@ -79,7 +78,7 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo } // MCMS Deploy operations - mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSConfigPerChain[chainSel]) + mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSDeployConfigPerChain[chainSel]) if err != nil { return deployment.ChangesetOutput{}, err } @@ -105,7 +104,7 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo chainSel, mcmsOperations, "Deploy Aptos MCMS and CCIP", - aptosmcms.TimelockRoleProposer, + config.MCMSTimelockConfigPerChain[chainSel], ) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 53b39cacf54..0f22da17add 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -3,7 +3,9 @@ package aptos import ( "math/big" "testing" + "time" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" @@ -12,11 +14,10 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" + mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" ) func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { @@ -43,7 +44,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), 743186221051783445: GetMockChainContractParams(t, 743186221051783445), }, - MCMSConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ + MCMSDeployConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ 4457093679053095497: getMockMCMSConfig(t), 743186221051783445: getMockMCMSConfig(t), }, @@ -140,7 +141,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { ContractParamsPerChain: map[uint64]config.ChainContractParams{ 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), }, - // MCMSConfigPerChain is missing needed configs + // MCMSDeployConfigPerChain is missing needed configs }, wantErrRe: `invalid mcms configs for chain 4457093679053095497`, wantErr: true, @@ -210,7 +211,7 @@ func TestDeployAptosChain_Apply(t *testing.T) { ContractParamsPerChain: map[uint64]config.ChainContractParams{ chainSelector: mockCCIPParams, }, - MCMSConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ + MCMSDeployConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ chainSelector: { Canceller: proposalutils.SingleGroupMCMSV2(t), Proposer: proposalutils.SingleGroupMCMSV2(t), @@ -218,6 +219,13 @@ func TestDeployAptosChain_Apply(t *testing.T) { TimelockMinDelay: big.NewInt(0), }, }, + MCMSTimelockConfigPerChain: map[uint64]proposalutils.TimelockConfig{ + chainSelector: { + MinDelay: time.Duration(1) * time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, + }, } env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ commonchangeset.Configure(DeployAptosChain{}, ccipConfig), diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go index 5798a25cb63..161138f4d2a 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/mcms" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) @@ -63,7 +62,7 @@ func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3Of deps.AptosChain.Selector, []types.BatchOperation{setOCR3SeqReport.Output}, "Set OCR3 Configs", - aptosmcms.TimelockRoleProposer, + *config.MCMS, ) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", remoteSelector, err) diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go index 940cc950c17..28f388fdaf2 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go @@ -2,6 +2,7 @@ package aptos_test import ( "testing" + "time" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -10,7 +11,9 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/stretchr/testify/require" ) @@ -23,8 +26,13 @@ func TestSetOCR3Offramp_Apply(t *testing.T) { env := deployedEnvironment.Env cfg := v1_6.SetOCR3OffRampConfig{ - HomeChainSel: env.AllChainSelectors()[0], - RemoteChainSels: env.AllChainSelectorsAptos(), + HomeChainSel: env.AllChainSelectors()[0], + RemoteChainSels: env.AllChainSelectorsAptos(), + MCMS: &proposalutils.TimelockConfig{ + MinDelay: time.Duration(1) * time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, CCIPHomeConfigType: globals.ConfigTypeActive, // TODO: investigate why this is not being used, might be a bug } env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go index bd528868d3d..2c9522b01c7 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go @@ -11,7 +11,6 @@ import ( seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/mcms" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) @@ -56,7 +55,7 @@ func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAp deps.AptosChain.Selector, mcmsOperations, "Update chain contracts on Aptos chain", - aptosmcms.TimelockRoleProposer, + cfg.MCMSTimelockConfig, ) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", cfg.ChainSelector, err) diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go index 7e1e9aa303c..085745f73d2 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/mcms" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) @@ -78,7 +77,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos deps.AptosChain.Selector, mcmsOperations, "Update lanes on Aptos chain", - aptosmcms.TimelockRoleProposer, + *cfg.AptosMCMSConfig, ) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", aptosChainSel, err) diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index 61f9f234ce8..cde20239171 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "math/big" "testing" + "time" "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" @@ -12,6 +13,7 @@ import ( aptosfeequoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" + mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -20,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" ) @@ -83,6 +86,11 @@ func getMockUpdateConfig( ) config.UpdateAptosLanesConfig { return config.UpdateAptosLanesConfig{ EVMMCMSConfig: nil, + AptosMCMSConfig: &proposalutils.TimelockConfig{ + MinDelay: time.Duration(1) * time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, // Aptos1 <> EVM1 | Aptos1 -> EVM2 Lanes: []config.LaneConfig{ { diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 1fa8e99055d..96c474d344a 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -26,7 +26,7 @@ var DeployMCMSOp = operations.NewOperation( func deployMCMS(b operations.Bundle, deps AptosDeps, _ operations.EmptyInput) (aptos.AccountAddress, error) { mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() - addressMCMS, mcmsDeployTx, _, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) + mcmsAddress, mcmsDeployTx, _, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) if err != nil { return aptos.AccountAddress{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) } @@ -34,11 +34,11 @@ func deployMCMS(b operations.Bundle, deps AptosDeps, _ operations.EmptyInput) (a return aptos.AccountAddress{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) } - return addressMCMS, nil + return mcmsAddress, nil } type ConfigureMCMSInput struct { - AddressMCMS aptos.AccountAddress + MCMSAddress aptos.AccountAddress MCMSConfigs mcmstypes.Config MCMSRole aptosmcms.TimelockRole } @@ -52,7 +52,7 @@ var ConfigureMCMSOp = operations.NewOperation( func configureMCMS(b operations.Bundle, deps AptosDeps, in ConfigureMCMSInput) (any, error) { configurer := aptosmcms.NewConfigurer(deps.AptosChain.Client, deps.AptosChain.DeployerSigner, in.MCMSRole) - setCfgTx, err := configurer.SetConfig(context.Background(), in.AddressMCMS.StringLong(), &in.MCMSConfigs, false) + setCfgTx, err := configurer.SetConfig(context.Background(), in.MCMSAddress.StringLong(), &in.MCMSConfigs, false) if err != nil { return nil, fmt.Errorf("failed to setConfig in MCMS contract: %w", err) } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index e46a680cc7c..31125427e47 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -40,7 +40,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM deps.AB.Save(deps.AptosChain.Selector, deployMCMSReport.Output.String(), typeAndVersion) // Configure MCMS configureMCMSBypassers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output, + MCMSAddress: deployMCMSReport.Output, MCMSConfigs: configMCMS.Bypasser, MCMSRole: aptosmcms.TimelockRoleBypasser, } @@ -49,7 +49,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } configureMCMSCancellers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output, + MCMSAddress: deployMCMSReport.Output, MCMSConfigs: configMCMS.Canceller, MCMSRole: aptosmcms.TimelockRoleCanceller, } @@ -58,7 +58,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } configureMCMSProposers := operation.ConfigureMCMSInput{ - AddressMCMS: deployMCMSReport.Output, + MCMSAddress: deployMCMSReport.Output, MCMSConfigs: configMCMS.Proposer, MCMSRole: aptosmcms.TimelockRoleProposer, } diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go index 412170c1591..eb6868ad503 100644 --- a/deployment/ccip/changeset/aptos/utils/mcms.go +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -4,19 +4,20 @@ import ( "context" "encoding/json" "fmt" + "strings" "time" "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink-aptos/bindings/compile" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/mcms" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" ) const ( - ValidUntilHours = 72 MCMSProposalVersion = "v1" ) @@ -26,8 +27,18 @@ func GenerateProposal( chainSel uint64, operations []types.BatchOperation, description string, - role aptosmcms.TimelockRole, + mcmsCfg proposalutils.TimelockConfig, ) (*mcms.TimelockProposal, error) { + // Get role from action + role, err := roleFromAction(mcmsCfg.MCMSAction) + if err != nil { + return nil, fmt.Errorf("failed to get role from action: %w", err) + } + jsonRole, _ := json.Marshal(aptosmcms.AdditionalFieldsMetadata{Role: role}) + var action = mcmsCfg.MCMSAction + if action == "" { + action = types.TimelockActionSchedule + } // Create MCMS inspector inspector := aptosmcms.NewInspector(client, role) startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) @@ -36,20 +47,14 @@ func GenerateProposal( } opCount := startingOpCount - action := types.TimelockActionSchedule - if role == aptosmcms.TimelockRoleBypasser { - action = types.TimelockActionBypass - } - jsonRole, _ := json.Marshal(aptosmcms.AdditionalFieldsMetadata{Role: role}) - // Create proposal builder - validUntil := time.Now().Add(time.Hour * ValidUntilHours).Unix() + validUntil := time.Now().Unix() + int64(proposalutils.DefaultValidUntil.Seconds()) proposalBuilder := mcms.NewTimelockProposalBuilder(). SetVersion(MCMSProposalVersion). SetValidUntil(uint32(validUntil)). SetDescription(description). AddTimelockAddress(types.ChainSelector(chainSel), mcmsAddress.StringLong()). - SetOverridePreviousRoot(true). + SetOverridePreviousRoot(mcmsCfg.OverrideRoot). AddChainMetadata( types.ChainSelector(chainSel), types.ChainMetadata{ @@ -59,7 +64,7 @@ func GenerateProposal( }, ). SetAction(action). - SetDelay(types.NewDuration(time.Second)) // TODO: set propper delay + SetDelay(types.NewDuration(mcmsCfg.MinDelay)) // Add operations and build for _, op := range operations { @@ -73,6 +78,21 @@ func GenerateProposal( return proposal, nil } +func roleFromAction(action types.TimelockAction) (aptosmcms.TimelockRole, error) { + switch action { + case types.TimelockActionSchedule: + return aptosmcms.TimelockRoleProposer, nil + case types.TimelockActionBypass: + return aptosmcms.TimelockRoleBypasser, nil + case types.TimelockActionCancel: + return aptosmcms.TimelockRoleCanceller, nil + case "": + return aptosmcms.TimelockRoleProposer, nil + default: + return aptosmcms.TimelockRoleProposer, fmt.Errorf("invalid action: %s", action) + } +} + func ToBatchOperations(ops []types.Operation) []types.BatchOperation { batchOps := []types.BatchOperation{} for _, op := range ops { @@ -179,3 +199,16 @@ func GenerateMCMSTx(toAddress aptos.AccountAddress, moduleInfo bind.ModuleInform AdditionalFields: afBytes, }, nil } + +func IsMCMSStagingAreaClean(client aptos.AptosRpcClient, aptosMCMSObjAddr aptos.AccountAddress) (bool, error) { + resources, err := client.AccountResources(aptosMCMSObjAddr) + if err != nil { + return false, err + } + for _, resource := range resources { + if strings.Contains(resource.Type, "StagingArea") { + return false, nil + } + } + return true, nil +} diff --git a/deployment/ccip/changeset/aptos/utils/utils.go b/deployment/ccip/changeset/aptos/utils/utils.go deleted file mode 100644 index a046de41dc2..00000000000 --- a/deployment/ccip/changeset/aptos/utils/utils.go +++ /dev/null @@ -1,38 +0,0 @@ -package utils - -import ( - "fmt" - "strings" - - "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink/deployment" -) - -// ConfirmTx confirms aptos transactions -// -// Optional arguments: -// - aptos.PollPeriod: time.Duration, how often to poll for the transaction. Default 100ms. -// - aptos.PollTimeout: time.Duration, how long to wait for the transaction. Default 10s. -func ConfirmTx(chain deployment.AptosChain, txHash string, opts ...any) error { - userTx, err := chain.Client.WaitForTransaction(txHash, opts...) - if err != nil { - return err - } - if !userTx.Success { - return fmt.Errorf("transaction failed: %s", userTx.VmStatus) - } - return nil -} - -func IsMCMSStagingAreaClean(client aptos.AptosRpcClient, aptosMCMSObjAddr aptos.AccountAddress) (bool, error) { - resources, err := client.AccountResources(aptosMCMSObjAddr) - if err != nil { - return false, err - } - for _, resource := range resources { - if strings.Contains(resource.Type, "StagingArea") { - return false, nil - } - } - return true, nil -} diff --git a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go index 98d45816814..5ead6fb7866 100644 --- a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go +++ b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go @@ -18,7 +18,7 @@ func DeployChainContractsToAptosCS(t *testing.T, e DeployedEnv, chainSelector ui ContractParamsPerChain: map[uint64]config.ChainContractParams{ chainSelector: mockCCIPParams, }, - MCMSConfigPerChain: map[uint64]commontypes.MCMSWithTimelockConfigV2{ + MCMSDeployConfigPerChain: map[uint64]commontypes.MCMSWithTimelockConfigV2{ chainSelector: { Canceller: proposalutils.SingleGroupMCMSV2(t), Proposer: proposalutils.SingleGroupMCMSV2(t), diff --git a/deployment/ccip/changeset/v1_6/cs_ccip_home.go b/deployment/ccip/changeset/v1_6/cs_ccip_home.go index 047c8413e8f..070886a77f3 100644 --- a/deployment/ccip/changeset/v1_6/cs_ccip_home.go +++ b/deployment/ccip/changeset/v1_6/cs_ccip_home.go @@ -553,7 +553,7 @@ func AddDonAndSetCandidateChangeset( return deployment.ChangesetOutput{}, err } - // err = cfg.Validate(e, state) + err = cfg.Validate(e, state) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) } diff --git a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go index 40aab86f8f5..ea1b47e8f8f 100644 --- a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go +++ b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go @@ -1041,8 +1041,6 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter DestChainConfig: dc, }) } - tnv, _ := fq.TypeAndVersion(nil) - fmt.Println(tnv) tx, err := fq.ApplyDestChainConfigUpdates(txOpts, args) if cfg.MCMS == nil { if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 52a6948fa40..194725dff8d 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -202,7 +202,7 @@ func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirection // UpdateLanesLogic is the main logic for updating lanes. Configs provided can be unidirectional // TODO: this should be refactored as a sequence once EVM changesets move to Operations API -// TODO: UpdateBidirectionalLanesChangesetConfigs name is misleading, it accepts any kind of lane updates +// TODO: UpdateBidirectionalLanesChangesetConfigs name is misleading, it also accepts unidirectional lane updates func UpdateLanesLogic(e deployment.Environment, mcmsConfig *proposalutils.TimelockConfig, configs UpdateBidirectionalLanesChangesetConfigs) (deployment.ChangesetOutput, error) { proposals := make([]mcms.TimelockProposal, 0) diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index 702a2e366af..b80c72ce603 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -178,6 +178,7 @@ func SignMCMSProposal(t *testing.T, env deployment.Environment, proposal *mcmsli converters[chainSel] = &mcmssolanasdk.TimelockConverter{} inspectorsMap[chainSel] = mcmssolanasdk.NewInspector(chain.Client) } + proposal.UseSimulatedBackend(true) signable, err := mcmslib.NewSignable(proposal, inspectorsMap) diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index 1da62f6aeb9..f2ee54637b9 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -564,28 +564,6 @@ func CreateKeys(t *testing.T, } } - if len(aptoschains) > 0 { - ctype := chaintype.Aptos - err = app.GetKeyStore().OCR2().EnsureKeys(ctx, ctype) - require.NoError(t, err) - keys, err := app.GetKeyStore().OCR2().GetAllOfType(ctype) - require.NoError(t, err) - require.Len(t, keys, 1) - keybundle := keys[0] - keybundles[ctype] = keybundle - - err = app.GetKeyStore().Aptos().EnsureKey(ctx) - require.NoError(t, err, "failed to create key for Aptos") - - aptoskeys, err := app.GetKeyStore().Aptos().GetAll() - require.NoError(t, err) - require.Len(t, aptoskeys, 1) - transmitter := aptoskeys[0] - for chainSelector := range aptoschains { - transmitters[chainSelector] = transmitter.ID() - } - } - return Keys{ PeerID: peerID, CSA: csaKey, From 47bf2f5eb16ee262faf2e6bcddeab00597f49c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 17:34:53 +0200 Subject: [PATCH 041/136] Fix logger --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index 1db95ffe7ab..855cc3a47f9 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -58,6 +58,7 @@ func (f *AptosContractTransmitterFactory) NewCommitTransmitter( commitMethod, _ string, // priceOnlyMethod is ignored for Aptos ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, @@ -88,6 +89,7 @@ func (f *AptosContractTransmitterFactory) NewExecTransmitter( offrampAddress string, ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, From dc5baa49273ba74f5943144971a228518f9b08ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 20:19:33 +0200 Subject: [PATCH 042/136] Add field renames to CCIPMessageSent event --- .../ccip/configs/aptos/chain_writer.go | 1 + .../ccip/configs/aptos/contract_reader.go | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go index 061672baac9..6594f0878a1 100644 --- a/core/capabilities/ccip/configs/aptos/chain_writer.go +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -16,6 +16,7 @@ func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, e return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) } + // TODO REMOVE fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) return chainwriter.ChainWriterConfig{ diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 4aa84dacf29..853b38aed3c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -270,6 +270,49 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { EventHandleStructName: "OnRampState", EventHandleFieldName: "ccip_message_sent_events", EventAccountAddress: "onramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + SubFieldRenames: nil, + }, + "sequence_number": { + NewName: "SequenceNumber", + SubFieldRenames: nil, + }, + "message": { + NewName: "Message", + SubFieldRenames: map[string]chainreader.RenamedField{ + "header": { + NewName: "Header", + }, + "sender": { + NewName: "Sender", + }, + "data": { + NewName: "Data", + }, + "receiver": { + NewName: "Receiver", + }, + "extra_args": { + NewName: "ExtraArgs", + }, + "fee_token": { + NewName: "FeeToken", + }, + "fee_token_amount": { + NewName: "FeeTokenAmount", + }, + "fee_value_juels": { + NewName: "FeeValueJuels", + }, + "token_amounts": { + NewName: "TokenAmounts", + SubFieldRenames: nil, // TODO + }, + }, + }, + }, }, }, }, From c09e1db73f330aa63f3c4c1fb120234322655bad Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:21:26 +0200 Subject: [PATCH 043/136] Temp chainlink-aptos version --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 540c3c55398..847dbbce46e 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" + gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From a34cca4a6ee1b763ffb9384eb6506b7514bc03eb Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:29:44 +0200 Subject: [PATCH 044/136] Fixing CCIPMessageSent event renamings --- .../ccip/configs/aptos/contract_reader.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 853b38aed3c..e4b89ca4ca2 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -284,6 +284,23 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { SubFieldRenames: map[string]chainreader.RenamedField{ "header": { NewName: "Header", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageID", + }, + "nonce": { + NewName: "Nonce", + }, + }, }, "sender": { NewName: "Sender", From d03fa922f360514a4200c141c44a499d9f7186af Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:43:05 +0200 Subject: [PATCH 045/136] Fixing plugin build --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 847dbbce46e..4af36c2d159 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" + gitRef: "808b080f471d054ff623164b3a316759a8f18758" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From 29eddf9768775ad6f986a28bcbdbe38807ea6693 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 5 May 2025 22:21:35 -0300 Subject: [PATCH 046/136] Move save to changeset level --- deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go | 8 ++++++++ deployment/ccip/changeset/aptos/operation/ccip.go | 7 ------- deployment/ccip/changeset/aptos/sequence/deploy_ccip.go | 1 + deployment/ccip/changeset/aptos/sequence/deploy_mcms.go | 4 ---- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index f72b1728951..9d89f21a31b 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -85,6 +85,10 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) + // Save MCMS address + typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) + deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) + // CCIP Deploy operations ccipSeqInput := seq.DeployCCIPSeqInput{ MCMSAddress: mcmsSeqReport.Output.MCMSAddress, @@ -97,6 +101,10 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) + // Save the address of the CCIP object + typeAndVersion = deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) + // Generate MCMS proposals proposal, err := utils.GenerateProposal( aptosChain.Client, diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index e35fd79887b..a1dc9fc21a4 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -11,8 +11,6 @@ import ( "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" @@ -113,11 +111,6 @@ func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCC }, nil } - // Save the address of the CCIP object - typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) - deps.AB.Save(deps.AptosChain.Selector, ccipObjectAddress.String(), typeAndVersion) - deps.OnChainState.CCIPAddress = ccipObjectAddress - return DeployCCIPOutput{ CCIPAddress: ccipObjectAddress, MCMSOperations: operations, diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index ba8b32dbd73..2fc1101c0af 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -52,6 +52,7 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy return DeployCCIPSeqOutput{}, err } ccipAddress := deployCCIPReport.Output.CCIPAddress + // For CCIP deployment the txs cannot be batched - it'd exceed Aptos API limits // so it's converted to batch operations with single transactions in each mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployCCIPReport.Output.MCMSOperations)...) diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index 31125427e47..a6c97ad3633 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -4,8 +4,6 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/common/types" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" @@ -36,8 +34,6 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM if err != nil { return DeployMCMSSeqOutput{}, err } - typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_0_0) - deps.AB.Save(deps.AptosChain.Selector, deployMCMSReport.Output.String(), typeAndVersion) // Configure MCMS configureMCMSBypassers := operation.ConfigureMCMSInput{ MCMSAddress: deployMCMSReport.Output, From d13dfa36c0c7e8f1d93976c2a05b197c74b47936 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 6 May 2025 14:54:28 -0300 Subject: [PATCH 047/136] ref: rename operations --- .../ccip/changeset/aptos/operation/ccip.go | 33 ++++++++++--------- .../ccip/changeset/aptos/operation/mcms.go | 6 ++-- .../changeset/aptos/sequence/deploy_ccip.go | 8 ++--- .../changeset/aptos/sequence/deploy_mcms.go | 2 +- .../changeset/aptos/sequence/update_ccip.go | 8 ++--- .../changeset/aptos/sequence/update_lane.go | 1 - 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index a1dc9fc21a4..a7fbe09bf8d 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -80,14 +80,15 @@ type DeployCCIPOutput struct { MCMSOperations []types.Operation } -var GenerateDeployCCIPProposalOp = operations.NewOperation( +// DeployCCIPOp deploys the CCIP package on Aptos chain +var DeployCCIPOp = operations.NewOperation( "deploy-ccip-op", Version1_0_0, "Deploys CCIP Package for Aptos Chain", - generateDeployCCIPProposal, + deployCCIP, ) -func generateDeployCCIPProposal(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { +func deployCCIP(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { // Validate there's no package deployed if (deps.OnChainState.CCIPAddress == (aptos.AccountAddress{})) == (in.IsUpdate) { if in.IsUpdate { @@ -155,15 +156,15 @@ type DeployModulesInput struct { CCIPAddress aptos.AccountAddress } -// GenerateDeployRouterProposal generates deployment MCMS operations for the Router module -var GenerateDeployRouterProposalOp = operations.NewOperation( +// DeployRouterOp generates deployment MCMS operations for the Router module +var DeployRouterOp = operations.NewOperation( "deploy-router-op", Version1_0_0, "Generates MCMS proposals that deployes Router module on CCIP package", - getDeployRouterMCMSOperations, + deployRouter, ) -func getDeployRouterMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { +func deployRouter(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { // TODO: is there a way to check if module exists? mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) // Compile Package @@ -180,14 +181,15 @@ func getDeployRouterMCMSOperations(b operations.Bundle, deps AptosDeps, in Deplo return operations, nil } -var GenerateDeployOffRampProposalOp = operations.NewOperation( +// DeployOffRampOp generates deployment MCMS operations for the OffRamp module +var DeployOffRampOp = operations.NewOperation( "deploy-offramp-op", Version1_0_0, "Generates MCMS proposals that deployes OffRamp module on CCIP package", - getDeployOffRampMCMSOperations, + deployOffRamp, ) -func getDeployOffRampMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { +func deployOffRamp(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) // Compile Package payload, err := ccip_offramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) @@ -202,14 +204,15 @@ func getDeployOffRampMCMSOperations(b operations.Bundle, deps AptosDeps, in Depl return operations, nil } -var GenerateDeployOnRampProposalOp = operations.NewOperation( +// DeployOnRampOp generates MCMS proposals for the OnRamp module deployment +var DeployOnRampOp = operations.NewOperation( "deploy-onramp-op", Version1_0_0, "Generates MCMS proposals that deployes OnRamp module on CCIP package", - getDeployOnRampMCMSOperations, + deployOnRamp, ) -func getDeployOnRampMCMSOperations(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { +func deployOnRamp(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) // Compile Package payload, err := ccip_onramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) @@ -235,10 +238,10 @@ var InitializeCCIPOp = operations.NewOperation( "initialize-ccip-op", Version1_0_0, "Initializes CCIP components with configuration parameters", - generateInitializeCCIPProposal, + initializeCCIP, ) -func generateInitializeCCIPProposal(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (types.BatchOperation, error) { +func initializeCCIP(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (types.BatchOperation, error) { var txs []types.Transaction // Config OnRamp with empty lane configs. We're only able to get router address after deploying the router module diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 96c474d344a..e5eec9aed92 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -83,14 +83,14 @@ func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, mcmsAddress ap return nil, nil } -var GenerateAcceptOwnershipProposalOp = operations.NewOperation( +var AcceptOwnershipOp = operations.NewOperation( "generate-accept-ownership-proposal-op", Version1_0_0, "Generate Accept Ownership Proposal for MCMS Contract", - generateAcceptOwnershipProposal, + acceptOwnership, ) -func generateAcceptOwnershipProposal(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.BatchOperation, error) { +func acceptOwnership(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.BatchOperation, error) { contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() if err != nil { diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index 2fc1101c0af..4fd1c0281d9 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -47,7 +47,7 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy deployCCIPInput := operation.DeployCCIPInput{ MCMSAddress: in.MCMSAddress, } - deployCCIPReport, err := operations.ExecuteOperation(b, operation.GenerateDeployCCIPProposalOp, deps, deployCCIPInput) + deployCCIPReport, err := operations.ExecuteOperation(b, operation.DeployCCIPOp, deps, deployCCIPInput) if err != nil { return DeployCCIPSeqOutput{}, err } @@ -62,21 +62,21 @@ func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in Deploy CCIPAddress: ccipAddress, } // Generate proposal to deploy OnRamp module - deployOnRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOnRampProposalOp, deps, deployModulesInput) + deployOnRampReport, err := operations.ExecuteOperation(b, operation.DeployOnRampOp, deps, deployModulesInput) if err != nil { return DeployCCIPSeqOutput{}, err } mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOnRampReport.Output)...) // Generate proposal to deploy OffRamp module - deployOffRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOffRampProposalOp, deps, deployModulesInput) + deployOffRampReport, err := operations.ExecuteOperation(b, operation.DeployOffRampOp, deps, deployModulesInput) if err != nil { return DeployCCIPSeqOutput{}, err } mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOffRampReport.Output)...) // Generate proposal to deploy Router module - deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployModulesInput) + deployRouterReport, err := operations.ExecuteOperation(b, operation.DeployRouterOp, deps, deployModulesInput) if err != nil { return DeployCCIPSeqOutput{}, err } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index a6c97ad3633..9b94c5f7295 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -69,7 +69,7 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM return DeployMCMSSeqOutput{}, err } // Generate proposal to accept ownership - gaopReport, err := operations.ExecuteOperation(b, operation.GenerateAcceptOwnershipProposalOp, deps, deployMCMSReport.Output) + gaopReport, err := operations.ExecuteOperation(b, operation.AcceptOwnershipOp, deps, deployMCMSReport.Output) if err != nil { return DeployMCMSSeqOutput{}, err } diff --git a/deployment/ccip/changeset/aptos/sequence/update_ccip.go b/deployment/ccip/changeset/aptos/sequence/update_ccip.go index becb8d5b03e..644251fdb0c 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/update_ccip.go @@ -35,7 +35,7 @@ func updateCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in config MCMSAddress: deps.OnChainState.MCMSAddress, IsUpdate: in.UpdateCCIP, } - deployCCIPReport, err := operations.ExecuteOperation(b, operation.GenerateDeployCCIPProposalOp, deps, deployCCIPInput) + deployCCIPReport, err := operations.ExecuteOperation(b, operation.DeployCCIPOp, deps, deployCCIPInput) if err != nil { return nil, err } @@ -48,7 +48,7 @@ func updateCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in config } if in.UpdateOnRamp { - deployOnRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOnRampProposalOp, deps, deployModulesInput) + deployOnRampReport, err := operations.ExecuteOperation(b, operation.DeployOnRampOp, deps, deployModulesInput) if err != nil { return nil, err } @@ -56,7 +56,7 @@ func updateCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in config } if in.UpdateOffRamp { - deployOffRampReport, err := operations.ExecuteOperation(b, operation.GenerateDeployOffRampProposalOp, deps, deployModulesInput) + deployOffRampReport, err := operations.ExecuteOperation(b, operation.DeployOffRampOp, deps, deployModulesInput) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func updateCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in config } if in.UpdateRouter { - deployRouterReport, err := operations.ExecuteOperation(b, operation.GenerateDeployRouterProposalOp, deps, deployModulesInput) + deployRouterReport, err := operations.ExecuteOperation(b, operation.DeployRouterOp, deps, deployModulesInput) if err != nil { return nil, err } diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 4ce82e18ac7..52f503ffd7a 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -57,7 +57,6 @@ func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in } mcmsTxs = append(mcmsTxs, offRampReport.Output...) - // TODO: This is not working // 4. Update FeeQuoters with gas prices b.Logger.Info("Updating gas prices on FeeQuoters") feeQuoterPricesReport, err := operations.ExecuteOperation(b, operation.UpdateFeeQuoterPricesOp, deps, in.UpdateFeeQuoterPricesConfig) From 7800b82a128f907af676a996162e8c2ff1d9fe3c Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 6 May 2025 15:54:47 -0300 Subject: [PATCH 048/136] feat: router configs on add lane --- .../ccip/changeset/aptos/config/chain.go | 1 + .../aptos/cs_update_aptos_lanes_test.go | 17 ++++- .../ccip/changeset/aptos/operation/router.go | 67 +++++++++++++++++++ .../changeset/aptos/sequence/update_lane.go | 24 +++++++ deployment/go.mod | 4 +- deployment/go.sum | 4 +- 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 deployment/ccip/changeset/aptos/operation/router.go diff --git a/deployment/ccip/changeset/aptos/config/chain.go b/deployment/ccip/changeset/aptos/config/chain.go index 45471de96ae..cba276b6d43 100644 --- a/deployment/ccip/changeset/aptos/config/chain.go +++ b/deployment/ccip/changeset/aptos/config/chain.go @@ -17,6 +17,7 @@ type ChainDefinition interface { type EVMChainDefinition struct { v1_6.ChainDefinition + OnRampVersion []byte } func (c EVMChainDefinition) GetChainFamily() string { diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index cde20239171..72650c5b364 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -13,6 +13,7 @@ import ( aptosfeequoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/smartcontractkit/chainlink-aptos/bindings/bind" @@ -60,6 +61,7 @@ func TestAddAptosLanes_Apply(t *testing.T) { aptosCCIPAddr := state.AptosChains[aptosSelector].CCIPAddress aptosOnRamp := ccip_onramp.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) aptosOffRamp := ccip_offramp.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) + aptosRouter := ccip_router.Bind(aptosCCIPAddr, env.AptosChains[aptosSelector].Client) dynCfg, err := aptosOffRamp.Offramp().GetDynamicConfig(&bind.CallOpts{}) require.NoError(t, err) @@ -76,6 +78,10 @@ func TestAddAptosLanes_Apply(t *testing.T) { _, _, router2, err := aptosOnRamp.Onramp().GetDestChainConfig(&bind.CallOpts{}, emvSelector2) require.NoError(t, err) require.NotEqual(t, router2, aptos.AccountAddress{}) + + versions, err := aptosRouter.Router().GetOnRampVersions(&bind.CallOpts{}, []uint64{emvSelector, emvSelector2}) + require.NoError(t, err) + require.ElementsMatch(t, versions, [][]byte{{1, 6, 1}, {1, 6, 0}}) } func getMockUpdateConfig( @@ -105,7 +111,12 @@ func getMockUpdateConfig( GasPrice: big.NewInt(1e17), TokenPrices: map[common.Address]*big.Int{}, FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, }, + OnRampVersion: []byte{1, 6, 1}, }, IsDisabled: false, }, @@ -116,6 +127,10 @@ func getMockUpdateConfig( GasPrice: big.NewInt(1e17), TokenPrices: map[common.Address]*big.Int{}, FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, }, }, Dest: config.AptosChainDefinition{ @@ -163,7 +178,7 @@ func aptosTestDestFeeQuoterConfig(t *testing.T) aptosfeequoter.DestChainConfig { DestDataAvailabilityMultiplierBps: 2, DefaultTokenDestGasOverhead: 100_000, DefaultTxGasLimit: 100_000, - GasMultiplierWeiPerEth: 12e17, + GasMultiplierWeiPerEth: 1e7, NetworkFeeUsdCents: 20, ChainFamilySelector: hexMustDecode(t, v1_6.AptosFamilySelector), EnforceOutOfOrder: false, diff --git a/deployment/ccip/changeset/aptos/operation/router.go b/deployment/ccip/changeset/aptos/operation/router.go new file mode 100644 index 00000000000..551a5482dc0 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/router.go @@ -0,0 +1,67 @@ +package operation + +import ( + "encoding/json" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + aptos_router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router/router" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +// UpdateRouterDestInput contains configuration for updating FeeQuoter destination configs +type UpdateRouterDestInput struct { + MCMSAddress aptos.AccountAddress + Updates []aptos_router.OnRampSet +} + +// UpdateRouterOp... +var UpdateRouterOp = operations.NewOperation( + "update-router-op", + Version1_0_0, + "Updates Router destination chain configurations", + updateRouter, +) + +func updateRouter(b operations.Bundle, deps AptosDeps, in UpdateRouterDestInput) ([]types.Transaction, error) { + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + routerBind := ccip_router.Bind(ccipAddress, deps.AptosChain.Client) + + // Process each destination chain config update + var txs []types.Transaction + + var destChainSelectors []uint64 + var onRampVersions [][]byte + for _, update := range in.Updates { + destChainSelectors = append(destChainSelectors, update.DestChainSelector) + onRampVersions = append(onRampVersions, update.OnRampVersion) + } + moduleInfo, function, _, args, err := routerBind.Router().Encoder().SetOnRampVersions(destChainSelectors, onRampVersions) + if err != nil { + return []types.Transaction{}, fmt.Errorf("failed to encode ApplyDestChainConfigUpdates for chains %d: %w", uint64(14767482510784806043), err) + } + + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return []types.Transaction{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + txs = append(txs, types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }) + + b.Logger.Infow("Adding Router destination config update operation") + + return txs, nil +} diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 52f503ffd7a..4865459b232 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -7,6 +7,7 @@ import ( "github.com/aptos-labs/aptos-go-sdk" chainsel "github.com/smartcontractkit/chain-selectors" aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + aptos_router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router/router" "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" @@ -20,6 +21,7 @@ type UpdateAptosLanesSeqInput struct { UpdateFeeQuoterPricesConfig operation.UpdateFeeQuoterPricesInput UpdateOnRampDestsConfig operation.UpdateOnRampDestsInput UpdateOffRampSourcesConfig operation.UpdateOffRampSourcesInput + UpdateRouterDestConfig operation.UpdateRouterDestInput } // UpdateAptosLanesSequence orchestrates operations to update Aptos lanes @@ -65,6 +67,14 @@ func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in } mcmsTxs = append(mcmsTxs, feeQuoterPricesReport.Output...) + // 5. Update Router with destination OnRamp versions + b.Logger.Info("Updating Router") + routerReport, err := operations.ExecuteOperation(b, operation.UpdateRouterOp, deps, in.UpdateRouterDestConfig) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to update Router: %w", err) + } + mcmsTxs = append(mcmsTxs, routerReport.Output...) + return types.BatchOperation{ ChainSelector: types.ChainSelector(deps.AptosChain.Selector), Transactions: mcmsTxs, @@ -132,6 +142,20 @@ func setAptosSourceUpdates(lane config.LaneConfig, updateInputsByAptosChain map[ } input.UpdateFeeQuoterDestsConfig.Updates[dest.Selector] = dest.GetConvertedAptosFeeQuoterConfig() + // Setting Router OnRamp version updates + input.UpdateRouterDestConfig.MCMSAddress = mcmsAddress + if input.UpdateRouterDestConfig.Updates == nil { + input.UpdateRouterDestConfig.Updates = []aptos_router.OnRampSet{} + } + onRampVersion := dest.OnRampVersion + if onRampVersion == nil { + onRampVersion = []byte{1, 6, 0} + } + input.UpdateRouterDestConfig.Updates = append(input.UpdateRouterDestConfig.Updates, aptos_router.OnRampSet{ + DestChainSelector: dest.Selector, + OnRampVersion: onRampVersion, + }) + updateInputsByAptosChain[source.Selector] = input } diff --git a/deployment/go.mod b/deployment/go.mod index d0b9ad4ed2a..659ce4a6dd0 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -6,7 +6,7 @@ toolchain go1.24.2 // Make sure we're working with the latest chainlink libs replace ( - github.com/smartcontractkit/chainlink-aptos/relayer => github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 + github.com/smartcontractkit/chainlink-aptos/relayer => github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf github.com/smartcontractkit/chainlink/v2 => ../ ) @@ -36,7 +36,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.52 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250429205337-7ee5f91ed065 diff --git a/deployment/go.sum b/deployment/go.sum index 029673da83a..acade2a1435 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1230,8 +1230,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.52 h1:TMy6hR0s8iZBbYpRFAXJo3HNF21egQ8xeKELQaQos8I= github.com/smartcontractkit/chain-selectors v1.0.52/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92 h1:VqDOwOgfNLIz9wdTpaneJ2XI4I1DGpma3HWtvmDxsnQ= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250429091131-bb7e84a7ec92/go.mod h1:ijGuVe7wWOrBpRc2GfVVoPb0utS+Ayfq/P5iX9FnEds= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250430132510-be8d09930aaa h1:DVD+mR+QNmPCUz4ORd8yV59BnOApWoKowPKglZ0e2wk= From 0b69104b48d5406c2e556b6e318cfb4bd1408204 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 6 May 2025 16:52:01 -0300 Subject: [PATCH 049/136] feat: feequoter token transfer fee configs operation --- .../ccip/changeset/aptos/config/chain.go | 4 + .../ccip/changeset/aptos/config/lane_test.go | 3 +- .../aptos/cs_update_aptos_lanes_test.go | 37 +++++- .../changeset/aptos/operation/fee_quoter.go | 108 ++++++++++++++++++ .../changeset/aptos/sequence/update_lane.go | 24 +++- 5 files changed, 169 insertions(+), 7 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/chain.go b/deployment/ccip/changeset/aptos/config/chain.go index cba276b6d43..e14a4120e35 100644 --- a/deployment/ccip/changeset/aptos/config/chain.go +++ b/deployment/ccip/changeset/aptos/config/chain.go @@ -59,6 +59,10 @@ type AptosChainDefinition struct { GasPrice *big.Int `json:"gasPrice"` // FeeQuoterDestChainConfig is the configuration on a fee quoter for this chain as a destination. FeeQuoterDestChainConfig aptos_fee_quoter.DestChainConfig `json:"feeQuoterDestChainConfig"` + // AddTokenTransferFeeConfigs is the configuration for token transfer fees to be added to fee quoter + AddTokenTransferFeeConfigs []aptos_fee_quoter.TokenTransferFeeConfigAdded + // RemoveTokenTransferFeeConfigs holds token transfer fees to be removed from fee quoter + RemoveTokenTransferFeeConfigs []aptos_fee_quoter.TokenTransferFeeConfigRemoved } func (c AptosChainDefinition) GetChainFamily() string { diff --git a/deployment/ccip/changeset/aptos/config/lane_test.go b/deployment/ccip/changeset/aptos/config/lane_test.go index 729b864254e..d8bf9a3828c 100644 --- a/deployment/ccip/changeset/aptos/config/lane_test.go +++ b/deployment/ccip/changeset/aptos/config/lane_test.go @@ -129,7 +129,7 @@ func TestToEVMUpdateLanesConfig(t *testing.T) { func getEVMDef() EVMChainDefinition { return EVMChainDefinition{ - v1_6.ChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ ConnectionConfig: v1_6.ConnectionConfig{ RMNVerificationDisabled: true, AllowListEnabled: false, @@ -138,6 +138,7 @@ func getEVMDef() EVMChainDefinition { GasPrice: big.NewInt(1e17), FeeQuoterDestChainConfig: v1_6.DefaultFeeQuoterDestChainConfig(true), }, + OnRampVersion: []byte{1, 6, 0}, } } diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index 72650c5b364..9fbc10db905 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -90,6 +90,11 @@ func getMockUpdateConfig( emvSelector2, aptosSelector uint64, ) config.UpdateAptosLanesConfig { + linkToken := aptos.AccountAddress{} + _ = linkToken.ParseStringRelaxed("0x3b17dad1bdd88f337712cc2f6187bb741d56da467320373fd9198262cc93de76") + otherToken := aptos.AccountAddress{} + _ = linkToken.ParseStringRelaxed("0xa") + return config.UpdateAptosLanesConfig{ EVMMCMSConfig: nil, AptosMCMSConfig: &proposalutils.TimelockConfig{ @@ -97,13 +102,43 @@ func getMockUpdateConfig( MCMSAction: mcmstypes.TimelockActionSchedule, OverrideRoot: false, }, - // Aptos1 <> EVM1 | Aptos1 -> EVM2 + // Aptos1 <> EVM1 + Aptos1 -> EVM2 Lanes: []config.LaneConfig{ { Source: config.AptosChainDefinition{ Selector: aptosSelector, GasPrice: big.NewInt(1e17), FeeQuoterDestChainConfig: aptosTestDestFeeQuoterConfig(t), + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + AllowListEnabled: false, + }, + AddTokenTransferFeeConfigs: []aptosfeequoter.TokenTransferFeeConfigAdded{ + { + DestChainSelector: emvSelector, + Token: linkToken, + TokenTransferFeeConfig: aptosfeequoter.TokenTransferFeeConfig{ + MinFeeUsdCents: 1, + MaxFeeUsdCents: 10000, + DeciBps: 0, + DestGasOverhead: 1000, + DestBytesOverhead: 1000, + IsEnabled: true, + }, + }, + { + DestChainSelector: emvSelector, + Token: otherToken, + TokenTransferFeeConfig: aptosfeequoter.TokenTransferFeeConfig{ + MinFeeUsdCents: 1, + MaxFeeUsdCents: 10000, + DeciBps: 0, + DestGasOverhead: 1000, + DestBytesOverhead: 1000, + IsEnabled: true, + }, + }, + }, }, Dest: config.EVMChainDefinition{ ChainDefinition: v1_6.ChainDefinition{ diff --git a/deployment/ccip/changeset/aptos/operation/fee_quoter.go b/deployment/ccip/changeset/aptos/operation/fee_quoter.go index d9cf28c821d..4e699935110 100644 --- a/deployment/ccip/changeset/aptos/operation/fee_quoter.go +++ b/deployment/ccip/changeset/aptos/operation/fee_quoter.go @@ -206,3 +206,111 @@ func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuot return txs, nil } + +// UpdateTokenTransferFeeConfigsInput ... +type UpdateTokenTransferFeeConfigsInput struct { + MCMSAddress aptos.AccountAddress + AddTokenConfigs []aptos_fee_quoter.TokenTransferFeeConfigAdded + RemoveTokenConfigs []aptos_fee_quoter.TokenTransferFeeConfigRemoved +} + +// UpdateTokenTransferCfgOp operation to update FeeQuoter prices +var UpdateTokenTransferCfgOp = operations.NewOperation( + "update-token-transfer-config-op", + Version1_0_0, + "Updates Token Transfer Fee Configs", + updateTokenTransferCfg, +) + +func updateTokenTransferCfg(b operations.Bundle, deps AptosDeps, in UpdateTokenTransferFeeConfigsInput) ([]types.Transaction, error) { + var txs []types.Transaction + + // Bind CCIP Package + ccipAddress := deps.OnChainState.CCIPAddress + ccipBind := ccip.Bind(ccipAddress, deps.AptosChain.Client) + + // Encode the update tx + argsByDestChain := toApplyTokenTransferFeeConfigUpdatesArgs(in.AddTokenConfigs, in.RemoveTokenConfigs) + for destChainSelector, args := range argsByDestChain { + moduleInfo, function, _, args, err := ccipBind.FeeQuoter().Encoder().ApplyTokenTransferFeeConfigUpdates( + destChainSelector, + args.addTokens, + args.addMinFeeUsdCents, + args.addMaxFeeUsdCents, + args.addDeciBps, + args.addDestGasOverhead, + args.addDestBytesOverhead, + args.addIsEnabled, + args.removeTokens, + ) + if err != nil { + return nil, fmt.Errorf("failed to encode UpdatePrices: %w", err) + } + + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return nil, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + txs = append(txs, types.Transaction{ + To: ccipAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }) + b.Logger.Infow("Adding TokenTransferFeeConfig update transaction", "destChainSelector", destChainSelector) + } + + return txs, nil +} + +type applyTokenTransferFeeConfigUpdatesArgs struct { + destChainSelector uint64 + addTokens []aptos.AccountAddress + addMinFeeUsdCents []uint32 + addMaxFeeUsdCents []uint32 + addDeciBps []uint16 + addDestGasOverhead []uint32 + addDestBytesOverhead []uint32 + addIsEnabled []bool + removeTokens []aptos.AccountAddress +} + +func toApplyTokenTransferFeeConfigUpdatesArgs( + AddTokenConfigs []aptos_fee_quoter.TokenTransferFeeConfigAdded, + RemovTokenConfigs []aptos_fee_quoter.TokenTransferFeeConfigRemoved, +) map[uint64]applyTokenTransferFeeConfigUpdatesArgs { + argsByDestChain := make(map[uint64]applyTokenTransferFeeConfigUpdatesArgs) + + // Process added token configs + for _, config := range AddTokenConfigs { + args := argsByDestChain[config.DestChainSelector] + + args.destChainSelector = config.DestChainSelector + args.addTokens = append(args.addTokens, config.Token) + args.addMinFeeUsdCents = append(args.addMinFeeUsdCents, config.TokenTransferFeeConfig.MinFeeUsdCents) + args.addMaxFeeUsdCents = append(args.addMaxFeeUsdCents, config.TokenTransferFeeConfig.MaxFeeUsdCents) + args.addDeciBps = append(args.addDeciBps, config.TokenTransferFeeConfig.DeciBps) + args.addDestGasOverhead = append(args.addDestGasOverhead, config.TokenTransferFeeConfig.DestGasOverhead) + args.addDestBytesOverhead = append(args.addDestBytesOverhead, config.TokenTransferFeeConfig.DestBytesOverhead) + args.addIsEnabled = append(args.addIsEnabled, config.TokenTransferFeeConfig.IsEnabled) + + argsByDestChain[config.DestChainSelector] = args + } + + // Process removed token configs + for _, config := range RemovTokenConfigs { + args := argsByDestChain[config.DestChainSelector] + + args.destChainSelector = config.DestChainSelector + args.removeTokens = append(args.removeTokens, config.Token) + + argsByDestChain[config.DestChainSelector] = args + } + + return argsByDestChain +} diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 4865459b232..30d59a8c9c6 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -17,11 +17,12 @@ import ( ) type UpdateAptosLanesSeqInput struct { - UpdateFeeQuoterDestsConfig operation.UpdateFeeQuoterDestsInput - UpdateFeeQuoterPricesConfig operation.UpdateFeeQuoterPricesInput - UpdateOnRampDestsConfig operation.UpdateOnRampDestsInput - UpdateOffRampSourcesConfig operation.UpdateOffRampSourcesInput - UpdateRouterDestConfig operation.UpdateRouterDestInput + UpdateFeeQuoterDestsConfig operation.UpdateFeeQuoterDestsInput + UpdateFeeQuoterPricesConfig operation.UpdateFeeQuoterPricesInput + UpdateOnRampDestsConfig operation.UpdateOnRampDestsInput + UpdateOffRampSourcesConfig operation.UpdateOffRampSourcesInput + UpdateRouterDestConfig operation.UpdateRouterDestInput + UpdateTokenTransferFeeConfig operation.UpdateTokenTransferFeeConfigsInput } // UpdateAptosLanesSequence orchestrates operations to update Aptos lanes @@ -75,6 +76,14 @@ func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in } mcmsTxs = append(mcmsTxs, routerReport.Output...) + // 6. Update FeeQuoter with TokenTransferFeeConfig + b.Logger.Info("Updating Router") + feeQuoterTTFReport, err := operations.ExecuteOperation(b, operation.UpdateTokenTransferCfgOp, deps, in.UpdateTokenTransferFeeConfig) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to update Router: %w", err) + } + mcmsTxs = append(mcmsTxs, feeQuoterTTFReport.Output...) + return types.BatchOperation{ ChainSelector: types.ChainSelector(deps.AptosChain.Selector), Transactions: mcmsTxs, @@ -156,6 +165,11 @@ func setAptosSourceUpdates(lane config.LaneConfig, updateInputsByAptosChain map[ OnRampVersion: onRampVersion, }) + // Setting token transfer fee updates + input.UpdateTokenTransferFeeConfig.MCMSAddress = mcmsAddress + input.UpdateTokenTransferFeeConfig.AddTokenConfigs = source.AddTokenTransferFeeConfigs + input.UpdateTokenTransferFeeConfig.RemoveTokenConfigs = source.RemoveTokenTransferFeeConfigs + updateInputsByAptosChain[source.Selector] = input } From 8fd8898f5334a68cdca9579a250b5f3e82c3a2b5 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 7 May 2025 15:58:59 -0300 Subject: [PATCH 050/136] feat(aptos): Add CCIP deployment changeset --- deployment/ccip/changeset/aptos/aptos_test.go | 38 --- .../aptos/config/deploy_aptos_chain.go | 108 +++++++ .../changeset/aptos/cs_deploy_aptos_chain.go | 126 +++++++++ .../aptos/cs_deploy_aptos_chain_test.go | 248 ++++++++++++++++ .../ccip/changeset/aptos/operation/ccip.go | 264 ++++++++++++++++++ .../changeset/aptos/operation/dependencies.go | 12 + .../ccip/changeset/aptos/operation/mcms.go | 168 +++++++++++ .../ccip/changeset/aptos/operation/version.go | 6 + .../changeset/aptos/sequence/deploy_ccip.go | 96 +++++++ .../changeset/aptos/sequence/deploy_mcms.go | 82 ++++++ .../ccip/changeset/aptos/test_helpers.go | 77 +++++ deployment/ccip/changeset/aptos/utils/mcms.go | 214 ++++++++++++++ deployment/go.mod | 2 +- deployment/go.sum | 4 +- 14 files changed, 1404 insertions(+), 41 deletions(-) delete mode 100644 deployment/ccip/changeset/aptos/aptos_test.go create mode 100644 deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go create mode 100644 deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go create mode 100644 deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go create mode 100644 deployment/ccip/changeset/aptos/operation/ccip.go create mode 100644 deployment/ccip/changeset/aptos/operation/dependencies.go create mode 100644 deployment/ccip/changeset/aptos/operation/mcms.go create mode 100644 deployment/ccip/changeset/aptos/operation/version.go create mode 100644 deployment/ccip/changeset/aptos/sequence/deploy_ccip.go create mode 100644 deployment/ccip/changeset/aptos/sequence/deploy_mcms.go create mode 100644 deployment/ccip/changeset/aptos/test_helpers.go create mode 100644 deployment/ccip/changeset/aptos/utils/mcms.go diff --git a/deployment/ccip/changeset/aptos/aptos_test.go b/deployment/ccip/changeset/aptos/aptos_test.go deleted file mode 100644 index 8b7973bdf28..00000000000 --- a/deployment/ccip/changeset/aptos/aptos_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package aptos - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// TODO: This is to test the implementation of Aptos chains in memory environment -// To be deleted after changesets tests are added -func TestAptosMemoryEnv(t *testing.T) { - lggr := logger.TestLogger(t) - env := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - AptosChains: 1, - }) - aptosChainSelectors := env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors, 1) - require.NotEqual(t, 0, env.AptosChains[0].Selector) -} - -// TODO: This is to test the implementation of Aptos chains in memory environment -// To be deleted after changesets tests are added -func TestAptosHelperMemoryEnv(t *testing.T) { - depEvn, testEnv := testhelpers.NewMemoryEnvironment( - t, - testhelpers.WithAptosChains(1), - testhelpers.WithNoJobsAndContracts(), // currently not supporting jobs and contracts - ) - aptosChainSelectors := depEvn.Env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors, 1) - aptosChainSelectors2 := testEnv.DeployedEnvironment().Env.AllChainSelectorsAptos() - require.Len(t, aptosChainSelectors2, 1) -} diff --git a/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go new file mode 100644 index 00000000000..c59470ad260 --- /dev/null +++ b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go @@ -0,0 +1,108 @@ +package config + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" +) + +// DeployAptosChainConfig is a configuration for deploying CCIP Package for Aptos chains +type DeployAptosChainConfig struct { + MCMSDeployConfigPerChain map[uint64]types.MCMSWithTimelockConfigV2 + MCMSTimelockConfigPerChain map[uint64]proposalutils.TimelockConfig + ContractParamsPerChain map[uint64]ChainContractParams +} + +func (c DeployAptosChainConfig) Validate() error { + for cs, args := range c.ContractParamsPerChain { + if err := deployment.IsValidChainSelector(cs); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + } + if err := args.Validate(); err != nil { + return fmt.Errorf("invalid contract args for chain %d: %w", cs, err) + } + } + return nil +} + +// ChainContractParams stores configuration to call initialize in CCIP contracts +type ChainContractParams struct { + FeeQuoterParams FeeQuoterParams + OffRampParams OffRampParams + OnRampParams OnRampParams +} + +func (c ChainContractParams) Validate() error { + // Validate every field + if err := c.FeeQuoterParams.Validate(); err != nil { + return fmt.Errorf("invalid FeeQuoterParams: %w", err) + } + if err := c.OffRampParams.Validate(); err != nil { + return fmt.Errorf("invalid OffRampParams: %w", err) + } + if err := c.OnRampParams.Validate(); err != nil { + return fmt.Errorf("invalid OnRampParams: %w", err) + } + return nil +} + +type FeeQuoterParams struct { + MaxFeeJuelsPerMsg uint64 + LinkToken aptos.AccountAddress + TokenPriceStalenessThreshold uint64 + FeeTokens []aptos.AccountAddress +} + +func (f FeeQuoterParams) Validate() error { + if f.LinkToken == (aptos.AccountAddress{}) { + return fmt.Errorf("LinkToken is required") + } + if f.TokenPriceStalenessThreshold == 0 { + return fmt.Errorf("TokenPriceStalenessThreshold can't be 0") + } + if len(f.FeeTokens) == 0 { + return fmt.Errorf("at least one FeeTokens is required") + } + return nil +} + +type OffRampParams struct { + ChainSelector uint64 + PermissionlessExecutionThreshold uint32 + IsRMNVerificationDisabled []bool + SourceChainSelectors []uint64 + SourceChainIsEnabled []bool + SourceChainsOnRamp [][]byte +} + +func (o OffRampParams) Validate() error { + if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) + } + if o.PermissionlessExecutionThreshold == 0 { + return fmt.Errorf("PermissionlessExecutionThreshold can't be 0") + } + if len(o.SourceChainSelectors) != len(o.SourceChainIsEnabled) { + return fmt.Errorf("SourceChainSelectors and SourceChainIsEnabled must have the same length") + } + return nil +} + +type OnRampParams struct { + ChainSelector uint64 + AllowlistAdmin aptos.AccountAddress + FeeAggregator aptos.AccountAddress +} + +func (o OnRampParams) Validate() error { + if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) + } + if o.AllowlistAdmin == (aptos.AccountAddress{}) { + return fmt.Errorf("AllowlistAdmin is required") + } + return nil +} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go new file mode 100644 index 00000000000..8176668501d --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -0,0 +1,126 @@ +package aptos + +import ( + "errors" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} + +// DeployAptosChain deploys Aptos chain packages and modules +type DeployAptosChain struct{} + +func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, config config.DeployAptosChainConfig) error { + // Validate env and prerequisite contracts + state, err := changeset.LoadOnchainStateAptos(env) + if err != nil { + return fmt.Errorf("failed to load existing Aptos onchain state: %w", err) + } + var errs []error + for chainSel := range config.ContractParamsPerChain { + if err := config.Validate(); err != nil { + errs = append(errs, fmt.Errorf("invalid config for Aptos chain %d: %w", chainSel, err)) + continue + } + if _, ok := env.AptosChains[chainSel]; !ok { + errs = append(errs, fmt.Errorf("aptos chain %d not found in env", chainSel)) + } + chainState, ok := state[chainSel] + if !ok { + errs = append(errs, fmt.Errorf("aptos chain %d not found in state", chainSel)) + continue + } + if chainState.MCMSAddress == (aptos.AccountAddress{}) { + mcmsConfig := config.MCMSDeployConfigPerChain[chainSel] + for _, cfg := range []mcmstypes.Config{mcmsConfig.Bypasser, mcmsConfig.Canceller, mcmsConfig.Proposer} { + if err := cfg.Validate(); err != nil { + errs = append(errs, fmt.Errorf("invalid mcms configs for Aptos chain %d: %w", chainSel, err)) + } + } + } + } + + return errors.Join(errs...) +} + +func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (deployment.ChangesetOutput, error) { + state, err := changeset.LoadOnchainState(env) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + } + + ab := deployment.NewMemoryAddressBook() + seqReports := make([]operations.Report[any, any], 0) + proposals := make([]mcms.TimelockProposal, 0) + + // Deploy CCIP on each Aptos chain in config + for chainSel := range config.ContractParamsPerChain { + mcmsOperations := []mcmstypes.BatchOperation{} + aptosChain := env.AptosChains[chainSel] + + deps := operation.AptosDeps{ + AB: ab, + AptosChain: aptosChain, + CCIPOnChainState: state, + } + + // MCMS Deploy operations + mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSDeployConfigPerChain[chainSel]) + if err != nil { + return deployment.ChangesetOutput{}, err + } + seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) + mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) + + // Save MCMS address + typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) + deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) + + // CCIP Deploy operations + ccipSeqInput := seq.DeployCCIPSeqInput{ + MCMSAddress: mcmsSeqReport.Output.MCMSAddress, + CCIPConfig: config.ContractParamsPerChain[chainSel], + } + ccipSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployCCIPSequence, deps, ccipSeqInput) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) + } + seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) + mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) + + // Save the address of the CCIP object + typeAndVersion = deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) + + // Generate MCMS proposals + proposal, err := utils.GenerateProposal( + aptosChain.Client, + mcmsSeqReport.Output.MCMSAddress, + chainSel, + mcmsOperations, + "Deploy Aptos MCMS and CCIP", + config.MCMSTimelockConfigPerChain[chainSel], + ) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) + } + proposals = append(proposals, *proposal) + } + return deployment.ChangesetOutput{ + AddressBook: ab, + MCMSTimelockProposals: proposals, + Reports: seqReports, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go new file mode 100644 index 00000000000..0f22da17add --- /dev/null +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -0,0 +1,248 @@ +package aptos + +import ( + "math/big" + "testing" + "time" + + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { + tests := []struct { + name string + env deployment.Environment + config config.DeployAptosChainConfig + wantErrRe string + wantErr bool + }{ + { + name: "success - valid configs", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + 4457093679053095497: {}, + }, + ExistingAddresses: deployment.NewMemoryAddressBook(), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), + }, + MCMSDeployConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ + 4457093679053095497: getMockMCMSConfig(t), + 743186221051783445: getMockMCMSConfig(t), + }, + }, + wantErr: false, + }, + { + name: "success - valid config w MCMS deployed", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 743186221051783445: {}, + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + 743186221051783445: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), + }, + }, + wantErr: false, + }, + { + name: "error - chain has no env", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + 743186221051783445: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + 743186221051783445: GetMockChainContractParams(t, 743186221051783445), + }, + }, + wantErrRe: `chain 743186221051783445 not found in env`, + wantErr: true, + }, + { + name: "error - invalid config - chainSelector", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + ExistingAddresses: deployment.NewMemoryAddressBook(), + AptosChains: map[uint64]deployment.AptosChain{}, + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 1: {}, + }, + }, + wantErrRe: "invalid chain selector:", + wantErr: true, + }, + { + name: "error - missing MCMS config for chain without MCMS deployed", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: {}, // No MCMS address in state + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: GetMockChainContractParams(t, 4457093679053095497), + }, + // MCMSDeployConfigPerChain is missing needed configs + }, + wantErrRe: `invalid mcms configs for chain 4457093679053095497`, + wantErr: true, + }, + { + name: "error - invalid config for chain", + env: deployment.Environment{ + Name: "test", + Logger: logger.TestLogger(t), + AptosChains: map[uint64]deployment.AptosChain{ + 4457093679053095497: {}, + }, + ExistingAddresses: getTestAddressBook( + map[uint64]map[string]deployment.TypeAndVersion{ + 4457093679053095497: { + mockMCMSAddress: {Type: changeset.AptosMCMSType}, // MCMS already deployed + }, + }, + ), + }, + config: config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + 4457093679053095497: { + FeeQuoterParams: config.FeeQuoterParams{ + TokenPriceStalenessThreshold: 0, // Invalid gas limit (assuming 0 is invalid) + }, + }, + }, + }, + wantErrRe: `invalid config for chain 4457093679053095497`, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cs := DeployAptosChain{} + err := cs.VerifyPreconditions(tt.env, tt.config) + if tt.wantErr { + assert.Error(t, err) + errStr := err.Error() + assert.Regexp(t, tt.wantErrRe, errStr) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestDeployAptosChain_Apply(t *testing.T) { + lggr := logger.TestLogger(t) + + // Setup memory environment with 1 Aptos chain + env := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + AptosChains: 1, + }) + + // Get chain selectors + aptosChainSelectors := env.AllChainSelectorsAptos() + require.Equal(t, 1, len(aptosChainSelectors), "Expected exactly 1 Aptos chain") + chainSelector := aptosChainSelectors[0] + t.Log("Deployer: ", env.AptosChains[chainSelector].DeployerSigner) + + // Deploy CCIP to Aptos chain + mockCCIPParams := GetMockChainContractParams(t, chainSelector) + ccipConfig := config.DeployAptosChainConfig{ + ContractParamsPerChain: map[uint64]config.ChainContractParams{ + chainSelector: mockCCIPParams, + }, + MCMSDeployConfigPerChain: map[uint64]types.MCMSWithTimelockConfigV2{ + chainSelector: { + Canceller: proposalutils.SingleGroupMCMSV2(t), + Proposer: proposalutils.SingleGroupMCMSV2(t), + Bypasser: proposalutils.SingleGroupMCMSV2(t), + TimelockMinDelay: big.NewInt(0), + }, + }, + MCMSTimelockConfigPerChain: map[uint64]proposalutils.TimelockConfig{ + chainSelector: { + MinDelay: time.Duration(1) * time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, + }, + } + env, _, err := commonchangeset.ApplyChangesetsV2(t, env, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure(DeployAptosChain{}, ccipConfig), + }) + require.NoError(t, err) + + // Verify CCIP deployment state by binding ccip contract and checking if it's deployed + state, err := changeset.LoadOnchainStateAptos(env) + require.NoError(t, err) + require.NotNil(t, state[chainSelector], "No state found for chain") + + ccipAddr := state[chainSelector].CCIPAddress + require.NotEmpty(t, ccipAddr, "CCIP address should not be empty") + + // Bind CCIP contract + offrampBind := ccip_offramp.Bind(ccipAddr, env.AptosChains[chainSelector].Client) + offRampSourceConfig, err := offrampBind.Offramp().GetSourceChainConfig(nil, mockCCIPParams.OffRampParams.SourceChainSelectors[0]) + require.NoError(t, err) + require.Equal(t, true, offRampSourceConfig.IsEnabled, "contracts were not initialized correctly") +} diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go new file mode 100644 index 00000000000..f54b985c2dd --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -0,0 +1,264 @@ +package operation + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/mcms/types" +) + +// OP: DeployCCIPOp deploys the CCIP package on Aptos chain +type DeployCCIPInput struct { + MCMSAddress aptos.AccountAddress + IsUpdate bool +} + +type DeployCCIPOutput struct { + CCIPAddress aptos.AccountAddress + MCMSOperations []types.Operation +} + +var DeployCCIPOp = operations.NewOperation( + "deploy-ccip-op", + Version1_0_0, + "Deploys CCIP Package for Aptos Chain", + deployCCIP, +) + +func deployCCIP(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (DeployCCIPOutput, error) { + onChainState := deps.CCIPOnChainState.AptosChains[deps.AptosChain.Selector] + // Validate there's no package deployed XOR is update + if (onChainState.CCIPAddress == (aptos.AccountAddress{})) == (in.IsUpdate) { + if in.IsUpdate { + b.Logger.Infow("Trying to update a non-deployed package", "addr", onChainState.CCIPAddress.String()) + return DeployCCIPOutput{}, fmt.Errorf("CCIP package not deployed on Aptos chain %d", deps.AptosChain.Selector) + } else { + b.Logger.Infow("CCIP Package already deployed", "addr", onChainState.CCIPAddress.String()) + return DeployCCIPOutput{CCIPAddress: onChainState.CCIPAddress}, nil + } + } + + // Compile, chunk and get CCIP deploy operations + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + ccipObjectAddress, operations, err := getCCIPDeployMCMSOps(mcmsContract, deps.AptosChain.Selector, onChainState.CCIPAddress) + if err != nil { + return DeployCCIPOutput{}, fmt.Errorf("failed to compile and create deploy operations: %w", err) + } + if in.IsUpdate { + return DeployCCIPOutput{ + MCMSOperations: operations, + }, nil + } + + return DeployCCIPOutput{ + CCIPAddress: ccipObjectAddress, + MCMSOperations: operations, + }, nil +} + +func getCCIPDeployMCMSOps(mcmsContract mcmsbind.MCMS, chainSel uint64, ccipAddress aptos.AccountAddress) (aptos.AccountAddress, []types.Operation, error) { + // Calculate addresses of the owner and the object + var ccipObjectAddress aptos.AccountAddress + var err error + if ccipAddress != (aptos.AccountAddress{}) { + ccipObjectAddress = ccipAddress + } else { + ccipObjectAddress, err = mcmsContract.MCMSRegistry().GetNewCodeObjectAddress(nil, []byte(ccip.DefaultSeed)) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to calculate object address: %w", err) + } + } + + // Compile Package + payload, err := ccip.Compile(ccipObjectAddress, mcmsContract.Address(), ccipAddress == aptos.AccountAddress{}) + if err != nil { + return ccipObjectAddress, []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + + // Create chunks and stage operations + var operations []types.Operation + if ccipAddress == (aptos.AccountAddress{}) { + operations, err = utils.CreateChunksAndStage(payload, mcmsContract, chainSel, ccip.DefaultSeed, nil) + } else { + operations, err = utils.CreateChunksAndStage(payload, mcmsContract, chainSel, "", &ccipObjectAddress) + } + if err != nil { + return ccipObjectAddress, operations, fmt.Errorf("failed to create chunks and stage for %d: %w", chainSel, err) + } + + return ccipObjectAddress, operations, nil +} + +// DeployModulesInput is the input for every module deployment operation +type DeployModulesInput struct { + MCMSAddress aptos.AccountAddress + CCIPAddress aptos.AccountAddress +} + +// OP: DeployRouterOp generates deployment MCMS operations for the Router module +var DeployRouterOp = operations.NewOperation( + "deploy-router-op", + Version1_0_0, + "Generates MCMS proposals that deployes Router module on CCIP package", + deployRouter, +) + +func deployRouter(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { + // TODO: is there a way to check if module exists? + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + // Compile Package + payload, err := ccip_router.Compile(in.CCIPAddress, mcmsContract.Address(), true) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) + } + + return operations, nil +} + +// OP: DeployOffRampOp generates deployment MCMS operations for the OffRamp module +var DeployOffRampOp = operations.NewOperation( + "deploy-offramp-op", + Version1_0_0, + "Generates MCMS proposals that deployes OffRamp module on CCIP package", + deployOffRamp, +) + +func deployOffRamp(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + // Compile Package + payload, err := ccip_offramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) + } + return operations, nil +} + +// OP: DeployOnRampOp generates MCMS proposals for the OnRamp module deployment +var DeployOnRampOp = operations.NewOperation( + "deploy-onramp-op", + Version1_0_0, + "Generates MCMS proposals that deployes OnRamp module on CCIP package", + deployOnRamp, +) + +func deployOnRamp(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([]types.Operation, error) { + mcmsContract := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + // Compile Package + payload, err := ccip_onramp.Compile(in.CCIPAddress, mcmsContract.Address(), true) + if err != nil { + return []types.Operation{}, fmt.Errorf("failed to compile: %w", err) + } + // Create chunks and stage operations + operations, err := utils.CreateChunksAndStage(payload, mcmsContract, deps.AptosChain.Selector, "", &in.CCIPAddress) + if err != nil { + return operations, fmt.Errorf("failed to create chunks and stage for %d: %w", deps.AptosChain.Selector, err) + } + return operations, nil +} + +// OP: InitializeCCIP Operation +type InitializeCCIPInput struct { + MCMSAddress aptos.AccountAddress + CCIPAddress aptos.AccountAddress + CCIPConfig aptoscfg.ChainContractParams +} + +var InitializeCCIPOp = operations.NewOperation( + "initialize-ccip-op", + Version1_0_0, + "Initializes CCIP components with configuration parameters", + initializeCCIP, +) + +func initializeCCIP(b operations.Bundle, deps AptosDeps, in InitializeCCIPInput) (types.BatchOperation, error) { + var txs []types.Transaction + + // Config OnRamp with empty lane configs. We're only able to get router address after deploying the router module + onrampBind := ccip_onramp.Bind(in.CCIPAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err := onrampBind.Onramp().Encoder().Initialize( + deps.AptosChain.Selector, + in.CCIPConfig.OnRampParams.FeeAggregator, + in.CCIPConfig.OnRampParams.AllowlistAdmin, + []uint64{}, + []aptos.AccountAddress{}, + []bool{}, + ) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to encode onramp initialize: %w", err) + } + mcmsTx, err := utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OnRamp Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + // Config OffRamp + offrampBind := ccip_offramp.Bind(in.CCIPAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err = offrampBind.Offramp().Encoder().Initialize( + deps.AptosChain.Selector, + in.CCIPConfig.OffRampParams.PermissionlessExecutionThreshold, + in.CCIPConfig.OffRampParams.SourceChainSelectors, + in.CCIPConfig.OffRampParams.SourceChainIsEnabled, + in.CCIPConfig.OffRampParams.IsRMNVerificationDisabled, + in.CCIPConfig.OffRampParams.SourceChainsOnRamp, + ) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to encode offramp initialize: %w", err) + } + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for OffRamp Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + // Config FeeQuoter and RMNRemote + ccipBind := ccip.Bind(in.CCIPAddress, deps.AptosChain.Client) + + moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().Initialize( + deps.AptosChain.Selector, + in.CCIPConfig.FeeQuoterParams.LinkToken, + in.CCIPConfig.FeeQuoterParams.TokenPriceStalenessThreshold, + in.CCIPConfig.FeeQuoterParams.FeeTokens, + ) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to encode feequoter initialize: %w", err) + } + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + moduleInfo, function, _, args, err = ccipBind.RMNRemote().Encoder().Initialize(deps.AptosChain.Selector) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to encode rmnremote initialize: %w", err) + } + mcmsTx, err = utils.GenerateMCMSTx(in.CCIPAddress, moduleInfo, function, args) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for RMNRemote Initialize: %w", err) + } + txs = append(txs, mcmsTx) + + return types.BatchOperation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transactions: txs, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/dependencies.go b/deployment/ccip/changeset/aptos/operation/dependencies.go new file mode 100644 index 00000000000..a405395661d --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/dependencies.go @@ -0,0 +1,12 @@ +package operation + +import ( + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" +) + +type AptosDeps struct { + AB *deployment.AddressBookMap + AptosChain deployment.AptosChain + CCIPOnChainState changeset.CCIPOnChainState +} diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go new file mode 100644 index 00000000000..5668eac6c4e --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -0,0 +1,168 @@ +package operation + +import ( + "context" + "encoding/json" + "fmt" + "time" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" + mcmstypes "github.com/smartcontractkit/mcms/types" + + "github.com/smartcontractkit/chainlink-deployments-framework/operations" +) + +// OP: Deploy MCMS Contract +var DeployMCMSOp = operations.NewOperation( + "deploy-mcms-op", + Version1_0_0, + "Deploys MCMS Contract Operation for Aptos Chain", + deployMCMS, +) + +func deployMCMS(b operations.Bundle, deps AptosDeps, _ operations.EmptyInput) (aptos.AccountAddress, error) { + mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() + mcmsAddress, mcmsDeployTx, _, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) + if err != nil { + return aptos.AccountAddress{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) + } + if err := deps.AptosChain.Confirm(mcmsDeployTx.Hash); err != nil { + return aptos.AccountAddress{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) + } + + return mcmsAddress, nil +} + +// OP: Configure MCMS Contract +type ConfigureMCMSInput struct { + MCMSAddress aptos.AccountAddress + MCMSConfigs mcmstypes.Config + MCMSRole aptosmcms.TimelockRole +} + +var ConfigureMCMSOp = operations.NewOperation( + "configure-mcms-op", + Version1_0_0, + "Configure MCMS Contract Operation for Aptos Chain", + configureMCMS, +) + +func configureMCMS(b operations.Bundle, deps AptosDeps, in ConfigureMCMSInput) (any, error) { + configurer := aptosmcms.NewConfigurer(deps.AptosChain.Client, deps.AptosChain.DeployerSigner, in.MCMSRole) + setCfgTx, err := configurer.SetConfig(context.Background(), in.MCMSAddress.StringLong(), &in.MCMSConfigs, false) + if err != nil { + return nil, fmt.Errorf("failed to setConfig in MCMS contract: %w", err) + } + if err := deps.AptosChain.Confirm(setCfgTx.Hash); err != nil { + return nil, fmt.Errorf("MCMS setConfig transaction failed: %w", err) + } + return nil, nil +} + +// OP: Transfer Ownership to Self +var TransferOwnershipToSelfOp = operations.NewOperation( + "transfer-ownership-to-self-op", + Version1_0_0, + "Transfer ownership to self", + transferOwnershipToSelf, +) + +func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (any, error) { + opts := &bind.TransactOpts{Signer: deps.AptosChain.DeployerSigner} + contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) + tx, err := contractMCMS.MCMSAccount().TransferOwnershipToSelf(opts) + if err != nil { + return nil, fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) + } + _, err = deps.AptosChain.Client.WaitForTransaction(tx.Hash) + if err != nil { + return nil, fmt.Errorf("MCMS TransferOwnershipToSelf transaction failed: %w", err) + } + return nil, nil +} + +// OP: Accept Ownership +var AcceptOwnershipOp = operations.NewOperation( + "accept-ownership-op", + Version1_0_0, + "Generate Accept Ownership BatchOperations for MCMS Contract", + acceptOwnership, +) + +func acceptOwnership(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.BatchOperation, error) { + contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + callOneAdditionalFields, err := json.Marshal(additionalFields) + if err != nil { + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to marshal additionalFields: %w", err) + } + + return mcmstypes.BatchOperation{ + ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), + Transactions: []mcmstypes.Transaction{{ + To: mcmsAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: callOneAdditionalFields, + }}, + }, err +} + +// OP: CleanupStagingAreaOp generates a batch operation to clean up the staging area +var CleanupStagingAreaOp = operations.NewOperation( + "cleanup-staging-area-op", + Version1_0_0, + "Cleans up MCMS staging area if it's not already clean", + cleanupStagingArea, +) + +func cleanupStagingArea(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (types.BatchOperation, error) { + // Check resources first to see if staging is clean + IsMCMSStagingAreaClean, err := utils.IsMCMSStagingAreaClean(deps.AptosChain.Client, mcmsAddress) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to check if MCMS staging area is clean: %w", err) + } + if IsMCMSStagingAreaClean { + b.Logger.Infow("MCMS Staging Area already clean", "addr", mcmsAddress.String()) + return types.BatchOperation{}, nil + } + + // Bind MCMS contract + mcmsContract := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) + + // Get cleanup staging operations + moduleInfo, function, _, args, err := mcmsContract.MCMSDeployer().Encoder().CleanupStagingArea() + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return types.BatchOperation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + + return types.BatchOperation{ + ChainSelector: types.ChainSelector(deps.AptosChain.Selector), + Transactions: []types.Transaction{{ + To: mcmsAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }}, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/operation/version.go b/deployment/ccip/changeset/aptos/operation/version.go new file mode 100644 index 00000000000..aa2f2248147 --- /dev/null +++ b/deployment/ccip/changeset/aptos/operation/version.go @@ -0,0 +1,6 @@ +package operation + +import "github.com/Masterminds/semver/v3" + +// Holds versions for Aptos changeset/operations +var Version1_0_0 = semver.MustParse("1.0.0") diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go new file mode 100644 index 00000000000..ae464fcf7c6 --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -0,0 +1,96 @@ +package sequence + +import ( + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +type DeployCCIPSeqInput struct { + MCMSAddress aptos.AccountAddress + CCIPConfig config.ChainContractParams +} + +type DeployCCIPSeqOutput struct { + CCIPAddress aptos.AccountAddress + MCMSOperations []mcmstypes.BatchOperation +} + +var DeployCCIPSequence = operations.NewSequence( + "deploy-aptos-ccip-sequence", + operation.Version1_0_0, + "Deploy Aptos CCIP contracts and initialize them", + deployCCIPSequence, +) + +func deployCCIPSequence(b operations.Bundle, deps operation.AptosDeps, in DeployCCIPSeqInput) (DeployCCIPSeqOutput, error) { + var mcmsOperations []mcmstypes.BatchOperation + + // Cleanup MCMS staging area if not clear + cleanupReport, err := operations.ExecuteOperation(b, operation.CleanupStagingAreaOp, deps, in.MCMSAddress) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + if len(cleanupReport.Output.Transactions) > 0 { + mcmsOperations = append(mcmsOperations, cleanupReport.Output) + } + + // Generate batch operations to deploy CCIP package + deployCCIPInput := operation.DeployCCIPInput{ + MCMSAddress: in.MCMSAddress, + IsUpdate: false, + } + deployCCIPReport, err := operations.ExecuteOperation(b, operation.DeployCCIPOp, deps, deployCCIPInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + ccipAddress := deployCCIPReport.Output.CCIPAddress + // For CCIP deployment the txs cannot be batched - it'd exceed Aptos API limits + // so they're converted to batch operations with single transactions in each batch + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployCCIPReport.Output.MCMSOperations)...) + + // Generate batch operations to deploy CCIP modules + deployModulesInput := operation.DeployModulesInput{ + MCMSAddress: in.MCMSAddress, + CCIPAddress: ccipAddress, + } + // OnRamp module + deployOnRampReport, err := operations.ExecuteOperation(b, operation.DeployOnRampOp, deps, deployModulesInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOnRampReport.Output)...) + // OffRamp module + deployOffRampReport, err := operations.ExecuteOperation(b, operation.DeployOffRampOp, deps, deployModulesInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployOffRampReport.Output)...) + // Router module + deployRouterReport, err := operations.ExecuteOperation(b, operation.DeployRouterOp, deps, deployModulesInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, utils.ToBatchOperations(deployRouterReport.Output)...) + + // Generate batch operations to initialize CCIP + initCCIPInput := operation.InitializeCCIPInput{ + MCMSAddress: in.MCMSAddress, + CCIPAddress: ccipAddress, + CCIPConfig: in.CCIPConfig, + } + initCCIPReport, err := operations.ExecuteOperation(b, operation.InitializeCCIPOp, deps, initCCIPInput) + if err != nil { + return DeployCCIPSeqOutput{}, err + } + mcmsOperations = append(mcmsOperations, initCCIPReport.Output) + + return DeployCCIPSeqOutput{ + CCIPAddress: ccipAddress, + MCMSOperations: mcmsOperations, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go new file mode 100644 index 00000000000..25d1617b6ce --- /dev/null +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -0,0 +1,82 @@ +package sequence + +import ( + "github.com/aptos-labs/aptos-go-sdk" + + "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" + "github.com/smartcontractkit/chainlink/deployment/common/types" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + mcmstypes "github.com/smartcontractkit/mcms/types" +) + +// Deploy MCMS Sequence +type DeployMCMSSeqOutput struct { + MCMSAddress aptos.AccountAddress + MCMSOperation mcmstypes.BatchOperation +} + +var DeployMCMSSequence = operations.NewSequence( + "deploy-aptos-mcms-sequence", + operation.Version1_0_0, + "Deploy Aptos MCMS contract and configure it", + deployMCMSSequence, +) + +func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCMS types.MCMSWithTimelockConfigV2) (DeployMCMSSeqOutput, error) { + // Check if MCMS package is already deployed + onChainState := deps.CCIPOnChainState.AptosChains[deps.AptosChain.Selector] + if onChainState.MCMSAddress != (aptos.AccountAddress{}) { + b.Logger.Infow("MCMS Package already deployed", "addr", onChainState.MCMSAddress.String()) + return DeployMCMSSeqOutput{}, nil + } + // Deploy MCMS + deployMCMSReport, err := operations.ExecuteOperation(b, operation.DeployMCMSOp, deps, operations.EmptyInput{}) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // Configure MCMS + configureMCMSBypassers := operation.ConfigureMCMSInput{ + MCMSAddress: deployMCMSReport.Output, + MCMSConfigs: configMCMS.Bypasser, + MCMSRole: aptosmcms.TimelockRoleBypasser, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSBypassers) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + configureMCMSCancellers := operation.ConfigureMCMSInput{ + MCMSAddress: deployMCMSReport.Output, + MCMSConfigs: configMCMS.Canceller, + MCMSRole: aptosmcms.TimelockRoleCanceller, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSCancellers) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + configureMCMSProposers := operation.ConfigureMCMSInput{ + MCMSAddress: deployMCMSReport.Output, + MCMSConfigs: configMCMS.Proposer, + MCMSRole: aptosmcms.TimelockRoleProposer, + } + _, err = operations.ExecuteOperation(b, operation.ConfigureMCMSOp, deps, configureMCMSProposers) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // TODO: Should set MinDelay to timelock + // Transfer ownership to self + _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + // Generate proposal to accept ownership + gaopReport, err := operations.ExecuteOperation(b, operation.AcceptOwnershipOp, deps, deployMCMSReport.Output) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + + return DeployMCMSSeqOutput{ + MCMSAddress: deployMCMSReport.Output, + MCMSOperation: gaopReport.Output, + }, nil +} diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go new file mode 100644 index 00000000000..091580aa091 --- /dev/null +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -0,0 +1,77 @@ +package aptos + +import ( + "math/big" + "testing" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/stretchr/testify/assert" +) + +const ( + mockMCMSAddress = "0x3f20aa841a0eb5c038775bdb868924770df1ce377cc0013b3ba4ac9fd69a4f90" + mockAddress = "0x13a9f1a109368730f2e355d831ba8fbf5942fb82321863d55de54cb4ebe5d18f" + mockLinkAddress = "0xa" + + sepChainSelector = 11155111 + sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" +) + +func getTestAddressBook(addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { + ab := deployment.NewMemoryAddressBook() + for chain, addrTypeAndVersion := range addrByChain { + for addr, typeAndVersion := range addrTypeAndVersion { + ab.Save(chain, addr, typeAndVersion) + } + } + return ab +} + +func mustParseAddress(t *testing.T, addr string) aptos.AccountAddress { + t.Helper() + var address aptos.AccountAddress + err := address.ParseStringRelaxed(addr) + assert.NoError(t, err) + return address +} + +func GetMockChainContractParams(t *testing.T, chainSelector uint64) config.ChainContractParams { + mockParsedAddress := mustParseAddress(t, mockAddress) + mockParsedLinkAddress := mustParseAddress(t, mockLinkAddress) + + return config.ChainContractParams{ + FeeQuoterParams: config.FeeQuoterParams{ + MaxFeeJuelsPerMsg: 1000000, + LinkToken: mockParsedLinkAddress, + TokenPriceStalenessThreshold: 1000000, + FeeTokens: []aptos.AccountAddress{mockParsedLinkAddress}, + }, + OffRampParams: config.OffRampParams{ + ChainSelector: chainSelector, + PermissionlessExecutionThreshold: uint32(60 * 60 * 8), + IsRMNVerificationDisabled: []bool{false}, + SourceChainSelectors: []uint64{sepChainSelector}, + SourceChainIsEnabled: []bool{true}, + SourceChainsOnRamp: [][]byte{common.HexToAddress(sepMockOnRampAddress).Bytes()}, + }, + OnRampParams: config.OnRampParams{ + ChainSelector: chainSelector, + AllowlistAdmin: mockParsedAddress, + FeeAggregator: mockParsedAddress, + }, + } +} + +func getMockMCMSConfig(t *testing.T) types.MCMSWithTimelockConfigV2 { + return types.MCMSWithTimelockConfigV2{ + Canceller: proposalutils.SingleGroupMCMSV2(t), + Proposer: proposalutils.SingleGroupMCMSV2(t), + Bypasser: proposalutils.SingleGroupMCMSV2(t), + TimelockMinDelay: big.NewInt(0), + } +} diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go new file mode 100644 index 00000000000..cc46a927bb8 --- /dev/null +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -0,0 +1,214 @@ +package utils + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/compile" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" +) + +const MCMSProposalVersion = "v1" + +func GenerateProposal( + client aptos.AptosRpcClient, + mcmsAddress aptos.AccountAddress, + chainSel uint64, + operations []types.BatchOperation, + description string, + mcmsCfg proposalutils.TimelockConfig, +) (*mcms.TimelockProposal, error) { + // Get role from action + role, err := roleFromAction(mcmsCfg.MCMSAction) + if err != nil { + return nil, fmt.Errorf("failed to get role from action: %w", err) + } + jsonRole, _ := json.Marshal(aptosmcms.AdditionalFieldsMetadata{Role: role}) + var action = mcmsCfg.MCMSAction + if action == "" { + action = types.TimelockActionSchedule + } + // Create MCMS inspector + inspector := aptosmcms.NewInspector(client, role) + startingOpCount, err := inspector.GetOpCount(context.Background(), mcmsAddress.StringLong()) + if err != nil { + return nil, fmt.Errorf("failed to get starting op count: %w", err) + } + opCount := startingOpCount + + // Create proposal builder + validUntil := time.Now().Unix() + int64(proposalutils.DefaultValidUntil.Seconds()) + proposalBuilder := mcms.NewTimelockProposalBuilder(). + SetVersion(MCMSProposalVersion). + SetValidUntil(uint32(validUntil)). + SetDescription(description). + AddTimelockAddress(types.ChainSelector(chainSel), mcmsAddress.StringLong()). + SetOverridePreviousRoot(mcmsCfg.OverrideRoot). + AddChainMetadata( + types.ChainSelector(chainSel), + types.ChainMetadata{ + StartingOpCount: opCount, + MCMAddress: mcmsAddress.StringLong(), + AdditionalFields: jsonRole, + }, + ). + SetAction(action). + SetDelay(types.NewDuration(mcmsCfg.MinDelay)) + + // Add operations and build + for _, op := range operations { + proposalBuilder.AddOperation(op) + } + proposal, err := proposalBuilder.Build() + if err != nil { + return nil, fmt.Errorf("failed to build proposal: %w", err) + } + + return proposal, nil +} + +func roleFromAction(action types.TimelockAction) (aptosmcms.TimelockRole, error) { + switch action { + case types.TimelockActionSchedule: + return aptosmcms.TimelockRoleProposer, nil + case types.TimelockActionBypass: + return aptosmcms.TimelockRoleBypasser, nil + case types.TimelockActionCancel: + return aptosmcms.TimelockRoleCanceller, nil + case "": + return aptosmcms.TimelockRoleProposer, nil + default: + return aptosmcms.TimelockRoleProposer, fmt.Errorf("invalid action: %s", action) + } +} + +// ToBatchOperations converts Operations into BatchOperations with a single transaction each +func ToBatchOperations(ops []types.Operation) []types.BatchOperation { + batchOps := []types.BatchOperation{} + for _, op := range ops { + batchOps = append(batchOps, types.BatchOperation{ + ChainSelector: op.ChainSelector, + Transactions: []types.Transaction{op.Transaction}, + }) + } + return batchOps +} + +// IsMCMSStagingAreaClean checks if the MCMS staging area is clean +func IsMCMSStagingAreaClean(client aptos.AptosRpcClient, aptosMCMSObjAddr aptos.AccountAddress) (bool, error) { + resources, err := client.AccountResources(aptosMCMSObjAddr) + if err != nil { + return false, err + } + for _, resource := range resources { + if strings.Contains(resource.Type, "StagingArea") { + return false, nil + } + } + return true, nil +} + +// CreateChunksAndStage creates chunks from the compiled packages and build MCMS operations to stages them within the MCMS contract +func CreateChunksAndStage( + payload compile.CompiledPackage, + mcmsContract mcmsbind.MCMS, + chainSel uint64, + seed string, + codeObjectAddress *aptos.AccountAddress, +) ([]types.Operation, error) { + mcmsAddress := mcmsContract.Address() + // Validate seed XOR codeObjectAddress, one and only one must be provided + if (seed != "") == (codeObjectAddress != nil) { + return nil, fmt.Errorf("either provide seed to publishToObject or objectAddress to upgradeObjectCode") + } + + var operations []types.Operation + + // Create chunks + chunks, err := bind.CreateChunks(payload, bind.ChunkSizeInBytes) + if err != nil { + return operations, fmt.Errorf("failed to create chunks: %w", err) + } + + // Stage chunks with mcms_deployer module and execute with the last one + for i, chunk := range chunks { + var ( + moduleInfo bind.ModuleInformation + function string + args [][]byte + err error + ) + + // First chunks get staged, the last one gets published or upgraded + if i != len(chunks)-1 { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunk( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + ) + } else if seed != "" { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndPublishToObject( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + []byte(seed), + ) + } else { + moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndUpgradeObjectCode( + chunk.Metadata, + chunk.CodeIndices, + chunk.Chunks, + *codeObjectAddress, + ) + } + if err != nil { + return operations, fmt.Errorf("failed to encode chunk %d: %w", i, err) + } + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return operations, fmt.Errorf("failed to marshal additional fields: %w", err) + } + operations = append(operations, types.Operation{ + ChainSelector: types.ChainSelector(chainSel), + Transaction: types.Transaction{ + To: mcmsAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, + }) + } + + return operations, nil +} + +// GenerateMCMSTx is a helper function that generates a MCMS txs for the given parameters +func GenerateMCMSTx(toAddress aptos.AccountAddress, moduleInfo bind.ModuleInformation, function string, args [][]byte) (types.Transaction, error) { + additionalFields := aptosmcms.AdditionalFields{ + PackageName: moduleInfo.PackageName, + ModuleName: moduleInfo.ModuleName, + Function: function, + } + afBytes, err := json.Marshal(additionalFields) + if err != nil { + return types.Transaction{}, fmt.Errorf("failed to marshal additional fields: %w", err) + } + return types.Transaction{ + To: toAddress.StringLong(), + Data: aptosmcms.ArgsToData(args), + AdditionalFields: afBytes, + }, nil +} diff --git a/deployment/go.mod b/deployment/go.mod index 279de2021ec..c462d3bb200 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -31,7 +31,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250506185033-ea88ef405511 diff --git a/deployment/go.sum b/deployment/go.sum index 17b667700d2..4d8210091da 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1232,8 +1232,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= From e1b4edac8328ae66a1e89b1bb5812fadaef4a1b2 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 7 May 2025 16:53:35 -0300 Subject: [PATCH 051/136] feat: set timelock delay --- .../ccip/changeset/aptos/operation/mcms.go | 57 +++++++++---------- .../changeset/aptos/sequence/deploy_mcms.go | 22 +++++-- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index 5668eac6c4e..f4193ab39e1 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -2,7 +2,6 @@ package operation import ( "context" - "encoding/json" "fmt" "time" @@ -94,30 +93,37 @@ var AcceptOwnershipOp = operations.NewOperation( acceptOwnership, ) -func acceptOwnership(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.BatchOperation, error) { +func acceptOwnership(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.AccountAddress) (mcmstypes.Transaction, error) { contractMCMS := mcmsbind.Bind(mcmsAddress, deps.AptosChain.Client) moduleInfo, function, _, args, err := contractMCMS.MCMSAccount().Encoder().AcceptOwnership() if err != nil { - return mcmstypes.BatchOperation{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) + return mcmstypes.Transaction{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } - additionalFields := aptosmcms.AdditionalFields{ - PackageName: moduleInfo.PackageName, - ModuleName: moduleInfo.ModuleName, - Function: function, - } - callOneAdditionalFields, err := json.Marshal(additionalFields) + + return utils.GenerateMCMSTx(mcmsAddress, moduleInfo, function, args) +} + +// OP: SetMinDelay +type TimelockMinDelayInput struct { + MCMSAddress aptos.AccountAddress + TimelockMinDelay uint64 +} + +var SetMinDelayOP = operations.NewOperation( + "set-timelock-min-delay-op", + Version1_0_0, + "Generate set timelock min delay MCMS BatchOperations", + setMinDelay, +) + +func setMinDelay(b operations.Bundle, deps AptosDeps, in TimelockMinDelayInput) (mcmstypes.Transaction, error) { + contractMCMS := mcmsbind.Bind(in.MCMSAddress, deps.AptosChain.Client) + moduleInfo, function, _, args, err := contractMCMS.MCMS().Encoder().TimelockUpdateMinDelay(in.TimelockMinDelay) if err != nil { - return mcmstypes.BatchOperation{}, fmt.Errorf("failed to marshal additionalFields: %w", err) + return mcmstypes.Transaction{}, fmt.Errorf("failed to encode AcceptOwnership: %w", err) } - return mcmstypes.BatchOperation{ - ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), - Transactions: []mcmstypes.Transaction{{ - To: mcmsAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: callOneAdditionalFields, - }}, - }, err + return utils.GenerateMCMSTx(in.MCMSAddress, moduleInfo, function, args) } // OP: CleanupStagingAreaOp generates a batch operation to clean up the staging area @@ -147,22 +153,13 @@ func cleanupStagingArea(b operations.Bundle, deps AptosDeps, mcmsAddress aptos.A if err != nil { return types.BatchOperation{}, fmt.Errorf("failed to EncodeCleanupStagingArea: %w", err) } - additionalFields := aptosmcms.AdditionalFields{ - PackageName: moduleInfo.PackageName, - ModuleName: moduleInfo.ModuleName, - Function: function, - } - afBytes, err := json.Marshal(additionalFields) + mcmsTx, err := utils.GenerateMCMSTx(mcmsAddress, moduleInfo, function, args) if err != nil { - return types.BatchOperation{}, fmt.Errorf("failed to marshal additional fields: %w", err) + return types.BatchOperation{}, fmt.Errorf("failed to generate MCMS operations for FeeQuoter Initialize: %w", err) } return types.BatchOperation{ ChainSelector: types.ChainSelector(deps.AptosChain.Selector), - Transactions: []types.Transaction{{ - To: mcmsAddress.StringLong(), - Data: aptosmcms.ArgsToData(args), - AdditionalFields: afBytes, - }}, + Transactions: []types.Transaction{mcmsTx}, }, nil } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index 25d1617b6ce..b1911ed0554 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -63,20 +63,34 @@ func deployMCMSSequence(b operations.Bundle, deps operation.AptosDeps, configMCM if err != nil { return DeployMCMSSeqOutput{}, err } - // TODO: Should set MinDelay to timelock // Transfer ownership to self _, err = operations.ExecuteOperation(b, operation.TransferOwnershipToSelfOp, deps, deployMCMSReport.Output) if err != nil { return DeployMCMSSeqOutput{}, err } - // Generate proposal to accept ownership - gaopReport, err := operations.ExecuteOperation(b, operation.AcceptOwnershipOp, deps, deployMCMSReport.Output) + // Accept ownership + aoReport, err := operations.ExecuteOperation(b, operation.AcceptOwnershipOp, deps, deployMCMSReport.Output) if err != nil { return DeployMCMSSeqOutput{}, err } + // Set MinDelay + timelockMinDelayInput := operation.TimelockMinDelayInput{ + MCMSAddress: deployMCMSReport.Output, + TimelockMinDelay: (*configMCMS.TimelockMinDelay).Uint64(), + } + mdReport, err := operations.ExecuteOperation(b, operation.SetMinDelayOP, deps, timelockMinDelayInput) + if err != nil { + return DeployMCMSSeqOutput{}, err + } + + // Generate MCMS Batch Operation + mcmsOps := mcmstypes.BatchOperation{ + ChainSelector: mcmstypes.ChainSelector(deps.AptosChain.Selector), + Transactions: []mcmstypes.Transaction{aoReport.Output, mdReport.Output}, + } return DeployMCMSSeqOutput{ MCMSAddress: deployMCMSReport.Output, - MCMSOperation: gaopReport.Output, + MCMSOperation: mcmsOps, }, nil } From 86e4e4cf46e79d30617525de31679c667ff1fbcf Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 8 May 2025 17:31:04 -0300 Subject: [PATCH 052/136] fix: review comments | fix lint --- .../aptos/config/deploy_aptos_chain.go | 15 ++++++------- .../changeset/aptos/cs_deploy_aptos_chain.go | 16 +++++++++----- .../aptos/cs_deploy_aptos_chain_test.go | 21 +++++++++++------- .../ccip/changeset/aptos/operation/ccip.go | 8 +++---- .../ccip/changeset/aptos/operation/mcms.go | 13 ++++++----- .../changeset/aptos/sequence/deploy_ccip.go | 3 ++- .../changeset/aptos/sequence/deploy_mcms.go | 5 +++-- .../ccip/changeset/aptos/test_helpers.go | 9 +++++--- deployment/ccip/changeset/aptos/utils/mcms.go | 22 +++++++++++++------ 9 files changed, 68 insertions(+), 44 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go index c59470ad260..a5a9b784208 100644 --- a/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go @@ -1,9 +1,11 @@ package config import ( + "errors" "fmt" "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -58,13 +60,13 @@ type FeeQuoterParams struct { func (f FeeQuoterParams) Validate() error { if f.LinkToken == (aptos.AccountAddress{}) { - return fmt.Errorf("LinkToken is required") + return errors.New("LinkToken is required") } if f.TokenPriceStalenessThreshold == 0 { - return fmt.Errorf("TokenPriceStalenessThreshold can't be 0") + return errors.New("TokenPriceStalenessThreshold can't be 0") } if len(f.FeeTokens) == 0 { - return fmt.Errorf("at least one FeeTokens is required") + return errors.New("at least one FeeTokens is required") } return nil } @@ -83,10 +85,10 @@ func (o OffRampParams) Validate() error { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } if o.PermissionlessExecutionThreshold == 0 { - return fmt.Errorf("PermissionlessExecutionThreshold can't be 0") + return errors.New("PermissionlessExecutionThreshold can't be 0") } if len(o.SourceChainSelectors) != len(o.SourceChainIsEnabled) { - return fmt.Errorf("SourceChainSelectors and SourceChainIsEnabled must have the same length") + return errors.New("SourceChainSelectors and SourceChainIsEnabled must have the same length") } return nil } @@ -101,8 +103,5 @@ func (o OnRampParams) Validate() error { if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } - if o.AllowlistAdmin == (aptos.AccountAddress{}) { - return fmt.Errorf("AllowlistAdmin is required") - } return nil } diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index 8176668501d..ca1bd5f540b 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -6,6 +6,9 @@ import ( "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -13,8 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/mcms" - mcmstypes "github.com/smartcontractkit/mcms/types" ) var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} @@ -86,8 +87,10 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo // Save MCMS address typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) - deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) - + err = deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to save MCMS address %s for Aptos chain %d: %w", mcmsSeqReport.Output.MCMSAddress.String(), chainSel, err) + } // CCIP Deploy operations ccipSeqInput := seq.DeployCCIPSeqInput{ MCMSAddress: mcmsSeqReport.Output.MCMSAddress, @@ -102,7 +105,10 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo // Save the address of the CCIP object typeAndVersion = deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) - deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) + err = deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("failed to save CCIP address %s for Aptos chain %d: %w", ccipSeqReport.Output.CCIPAddress.String(), chainSel, err) + } // Generate MCMS proposals proposal, err := utils.GenerateProposal( diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 0f22da17add..5d818be3689 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -5,6 +5,11 @@ import ( "testing" "time" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" @@ -14,10 +19,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" - mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" ) func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { @@ -61,6 +62,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]deployment.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, @@ -88,6 +90,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]deployment.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, @@ -132,6 +135,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]deployment.TypeAndVersion{ 4457093679053095497: {}, // No MCMS address in state }, @@ -155,6 +159,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]deployment.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, // MCMS already deployed @@ -181,11 +186,11 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { cs := DeployAptosChain{} err := cs.VerifyPreconditions(tt.env, tt.config) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) errStr := err.Error() assert.Regexp(t, tt.wantErrRe, errStr) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -201,7 +206,7 @@ func TestDeployAptosChain_Apply(t *testing.T) { // Get chain selectors aptosChainSelectors := env.AllChainSelectorsAptos() - require.Equal(t, 1, len(aptosChainSelectors), "Expected exactly 1 Aptos chain") + require.Len(t, aptosChainSelectors, 1, "Expected exactly 1 Aptos chain") chainSelector := aptosChainSelectors[0] t.Log("Deployer: ", env.AptosChains[chainSelector].DeployerSigner) @@ -244,5 +249,5 @@ func TestDeployAptosChain_Apply(t *testing.T) { offrampBind := ccip_offramp.Bind(ccipAddr, env.AptosChains[chainSelector].Client) offRampSourceConfig, err := offrampBind.Offramp().GetSourceChainConfig(nil, mockCCIPParams.OffRampParams.SourceChainSelectors[0]) require.NoError(t, err) - require.Equal(t, true, offRampSourceConfig.IsEnabled, "contracts were not initialized correctly") + require.True(t, offRampSourceConfig.IsEnabled, "contracts were not initialized correctly") } diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index f54b985c2dd..ce6026547e4 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -4,6 +4,8 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp" @@ -12,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/operations" aptoscfg "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/mcms/types" ) // OP: DeployCCIPOp deploys the CCIP package on Aptos chain @@ -40,10 +41,9 @@ func deployCCIP(b operations.Bundle, deps AptosDeps, in DeployCCIPInput) (Deploy if in.IsUpdate { b.Logger.Infow("Trying to update a non-deployed package", "addr", onChainState.CCIPAddress.String()) return DeployCCIPOutput{}, fmt.Errorf("CCIP package not deployed on Aptos chain %d", deps.AptosChain.Selector) - } else { - b.Logger.Infow("CCIP Package already deployed", "addr", onChainState.CCIPAddress.String()) - return DeployCCIPOutput{CCIPAddress: onChainState.CCIPAddress}, nil } + b.Logger.Infow("CCIP Package already deployed", "addr", onChainState.CCIPAddress.String()) + return DeployCCIPOutput{CCIPAddress: onChainState.CCIPAddress}, nil } // Compile, chunk and get CCIP deploy operations diff --git a/deployment/ccip/changeset/aptos/operation/mcms.go b/deployment/ccip/changeset/aptos/operation/mcms.go index f4193ab39e1..d3f8a096d7a 100644 --- a/deployment/ccip/changeset/aptos/operation/mcms.go +++ b/deployment/ccip/changeset/aptos/operation/mcms.go @@ -6,13 +6,14 @@ import ( "time" "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" "github.com/smartcontractkit/mcms/types" mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" ) @@ -28,10 +29,10 @@ func deployMCMS(b operations.Bundle, deps AptosDeps, _ operations.EmptyInput) (a mcmsSeed := mcmsbind.DefaultSeed + time.Now().String() mcmsAddress, mcmsDeployTx, _, err := mcmsbind.DeployToResourceAccount(deps.AptosChain.DeployerSigner, deps.AptosChain.Client, mcmsSeed) if err != nil { - return aptos.AccountAddress{}, fmt.Errorf("failed to deploy MCMS contract: %v", err) + return aptos.AccountAddress{}, fmt.Errorf("failed to deploy MCMS contract: %w", err) } if err := deps.AptosChain.Confirm(mcmsDeployTx.Hash); err != nil { - return aptos.AccountAddress{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %v", err) + return aptos.AccountAddress{}, fmt.Errorf("failed to confirm MCMS deployment transaction: %w", err) } return mcmsAddress, nil @@ -78,7 +79,7 @@ func transferOwnershipToSelf(b operations.Bundle, deps AptosDeps, mcmsAddress ap if err != nil { return nil, fmt.Errorf("failed to TransferOwnershipToSelf in MCMS contract: %w", err) } - _, err = deps.AptosChain.Client.WaitForTransaction(tx.Hash) + err = deps.AptosChain.Confirm(tx.Hash) if err != nil { return nil, fmt.Errorf("MCMS TransferOwnershipToSelf transaction failed: %w", err) } diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go index ae464fcf7c6..5d07fcf2a20 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_ccip.go @@ -3,11 +3,12 @@ package sequence import ( "github.com/aptos-labs/aptos-go-sdk" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - mcmstypes "github.com/smartcontractkit/mcms/types" ) type DeployCCIPSeqInput struct { diff --git a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go index b1911ed0554..b33a9c98087 100644 --- a/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go +++ b/deployment/ccip/changeset/aptos/sequence/deploy_mcms.go @@ -3,11 +3,12 @@ package sequence import ( "github.com/aptos-labs/aptos-go-sdk" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/common/types" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" - mcmstypes "github.com/smartcontractkit/mcms/types" ) // Deploy MCMS Sequence diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go index 091580aa091..5e04a61c34f 100644 --- a/deployment/ccip/changeset/aptos/test_helpers.go +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -6,11 +6,13 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/stretchr/testify/assert" ) const ( @@ -22,11 +24,12 @@ const ( sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" ) -func getTestAddressBook(addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { +func getTestAddressBook(t *testing.T, addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { ab := deployment.NewMemoryAddressBook() for chain, addrTypeAndVersion := range addrByChain { for addr, typeAndVersion := range addrTypeAndVersion { - ab.Save(chain, addr, typeAndVersion) + err := ab.Save(chain, addr, typeAndVersion) + require.NoError(t, err) } } return ab diff --git a/deployment/ccip/changeset/aptos/utils/mcms.go b/deployment/ccip/changeset/aptos/utils/mcms.go index cc46a927bb8..be76e8fb204 100644 --- a/deployment/ccip/changeset/aptos/utils/mcms.go +++ b/deployment/ccip/changeset/aptos/utils/mcms.go @@ -3,18 +3,21 @@ package utils import ( "context" "encoding/json" + "errors" "fmt" + "math" "strings" "time" "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/mcms" + aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" "github.com/smartcontractkit/chainlink-aptos/bindings/compile" mcmsbind "github.com/smartcontractkit/chainlink-aptos/bindings/mcms" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/mcms" - aptosmcms "github.com/smartcontractkit/mcms/sdk/aptos" - "github.com/smartcontractkit/mcms/types" ) const MCMSProposalVersion = "v1" @@ -47,6 +50,10 @@ func GenerateProposal( // Create proposal builder validUntil := time.Now().Unix() + int64(proposalutils.DefaultValidUntil.Seconds()) + if validUntil < 0 || validUntil > math.MaxUint32 { + return nil, fmt.Errorf("validUntil value out of range for uint32: %d", validUntil) + } + proposalBuilder := mcms.NewTimelockProposalBuilder(). SetVersion(MCMSProposalVersion). SetValidUntil(uint32(validUntil)). @@ -128,7 +135,7 @@ func CreateChunksAndStage( mcmsAddress := mcmsContract.Address() // Validate seed XOR codeObjectAddress, one and only one must be provided if (seed != "") == (codeObjectAddress != nil) { - return nil, fmt.Errorf("either provide seed to publishToObject or objectAddress to upgradeObjectCode") + return nil, errors.New("either provide seed to publishToObject or objectAddress to upgradeObjectCode") } var operations []types.Operation @@ -149,20 +156,21 @@ func CreateChunksAndStage( ) // First chunks get staged, the last one gets published or upgraded - if i != len(chunks)-1 { + switch { + case i != len(chunks)-1: moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunk( chunk.Metadata, chunk.CodeIndices, chunk.Chunks, ) - } else if seed != "" { + case seed != "": moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndPublishToObject( chunk.Metadata, chunk.CodeIndices, chunk.Chunks, []byte(seed), ) - } else { + default: moduleInfo, function, _, args, err = mcmsContract.MCMSDeployer().Encoder().StageCodeChunkAndUpgradeObjectCode( chunk.Metadata, chunk.CodeIndices, From 8a1f1c972094d274df997bbe958be0dedde69b0f Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 8 May 2025 17:35:38 -0300 Subject: [PATCH 053/136] fix: go mod tidy --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 4 ++-- system-tests/tests/go.mod | 2 +- system-tests/tests/go.sum | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index c82fb9892e6..bfc32649f5d 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -353,7 +353,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250502210357-2df484128afa // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 781261025ed..3323a9233ea 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1183,8 +1183,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f3f63406a76..c4ce4b3b6f5 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -450,7 +450,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250502210357-2df484128afa // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b3770bec9f1..62481765164 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 6050b2d99c5..692c0e4662b 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -437,7 +437,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.13 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 38e38d5f7e7..bd8ef7d0a9c 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1447,8 +1447,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 74fb4e422d8..a699c14fc70 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -354,7 +354,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 0a6fb66ab6c..49d89a8ab79 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1220,8 +1220,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index ac84b54ca52..0c268bdeca9 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -426,7 +426,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 2e3b2c73c4b..98268cb7f83 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= From a2a3f3a8b3114e82a2d0d2fa732b0274515c4e43 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:48:53 +0400 Subject: [PATCH 054/136] core/capabilities/ccip/ccipaptos: add initial ccipaptos implementation --- .../ccip/ccipaptos/addresscodec.go | 69 ++++ .../ccip/ccipaptos/addresscodec_test.go | 121 ++++++ .../ccip/ccipaptos/commitcodec.go | 168 ++++++++ .../ccip/ccipaptos/commitcodec_test.go | 163 ++++++++ .../ccip/ccipaptos/executecodec.go | 343 ++++++++++++++++ .../ccip/ccipaptos/executecodec_test.go | 179 +++++++++ .../ccip/ccipaptos/extradatadecoder.go | 150 +++++++ .../ccip/ccipaptos/extradatadecoder_test.go | 110 ++++++ .../ccip/ccipaptos/gas_helpers.go | 22 ++ core/capabilities/ccip/ccipaptos/msghasher.go | 367 ++++++++++++++++++ .../ccip/ccipaptos/msghasher_test.go | 93 +++++ core/capabilities/ccip/ccipaptos/rmncrypto.go | 20 + core/capabilities/ccip/ccipaptos/tokendata.go | 18 + core/capabilities/ccip/ccipaptos/utils.go | 23 ++ 14 files changed, 1846 insertions(+) create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec.go create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder_test.go create mode 100644 core/capabilities/ccip/ccipaptos/gas_helpers.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher_test.go create mode 100644 core/capabilities/ccip/ccipaptos/rmncrypto.go create mode 100644 core/capabilities/ccip/ccipaptos/tokendata.go create mode 100644 core/capabilities/ccip/ccipaptos/utils.go diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go new file mode 100644 index 00000000000..73ee4bb79c0 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -0,0 +1,69 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" +) + +type AddressCodec struct{} + +func (a AddressCodec) AddressBytesToString(addr []byte) (string, error) { + return addressBytesToString(addr) +} + +func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { + return addressStringToBytes(addr) +} + +func addressBytesToString(addr []byte) (string, error) { + if len(addr) != 32 { + return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + + accAddress := aptos.AccountAddress(addr) + return accAddress.String(), nil +} + +func addressStringToBytes(addr string) ([]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress[:], nil +} + +func addressStringToBytes32(addr string) ([32]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress, nil +} + +func addressBytesToBytes32(addr []byte) ([32]byte, error) { + if len(addr) > 32 { + return [32]byte{}, fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + var result [32]byte + // Left pad by copying to the end of the 32 byte array + copy(result[32-len(addr):], addr) + return result, nil +} + +// takes a valid Aptos address string and converts it into canonical format. +func addressStringToString(addr string) (string, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress.String(), nil +} + +func addressIsValid(addr string) bool { + _, err := addressStringToBytes(addr) + return err == nil +} diff --git a/core/capabilities/ccip/ccipaptos/addresscodec_test.go b/core/capabilities/ccip/ccipaptos/addresscodec_test.go new file mode 100644 index 00000000000..b40c52ce522 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec_test.go @@ -0,0 +1,121 @@ +package ccipaptos + +import ( + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func generateAddressBytes32() [32]byte { + var result [32]byte + _, err := rand.Read(result[:]) + if err != nil { + panic(fmt.Sprintf("failed to generate random address bytes: %v", err)) + } + return result +} + +func generateAddressBytes() []byte { + a := generateAddressBytes32() + return a[:] +} + +func generateAddressString() string { + addressBytes := generateAddressBytes() + addressString, err := addressBytesToString(addressBytes) + if err != nil { + panic(fmt.Sprintf("failed to generate random address string: %v", err)) + } + return addressString +} + +func TestAddressBytesToString(t *testing.T) { + tests := []struct { + name string + inHex string + isErr bool + expected string + }{ + { + "empty", + "", + true, + "", + }, + { + "equal to 32 bytes", + "0102030405060102030405060102030405060102030405060102030405060101", + false, + "0x0102030405060102030405060102030405060102030405060102030405060101", + }, + { + "longer than required", + "0102030405060102030405060102030405060102030405060102030405060101FFFFFFFFFF", + true, + "", + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + bytes, err := hex.DecodeString(test.inHex) + require.NoError(t, err) + + if test.isErr { + _, err := codec.AddressBytesToString(bytes) + require.Error(t, err, fmt.Sprintf("expected error for %s, input %s", test.name, test.inHex)) + } else { + actual, err := codec.AddressBytesToString(bytes) + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } + }) + } +} + +func TestAddressStringToBytes(t *testing.T) { + tests := []struct { + name string + in string + expected []byte + expectedErr error + }{ + { + "hand crafted", + "0x0102030405060102030405060102030405060102030405060102030405060101", + []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x01, + }, + nil, + }, + { + "hand crafted error", + "invalidAddress", + nil, + errors.New("failed to decode Aptos address 'invalidAddress': invalid address"), + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual, err := codec.AddressStringToBytes(test.in) + if test.expectedErr == nil { + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go new file mode 100644 index 00000000000..0fc28059a38 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -0,0 +1,168 @@ +package ccipaptos + +import ( + "context" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. +// Compatible with ccip::offramp version 1.6.0 +type CommitPluginCodecV1 struct{} + +func NewCommitPluginCodecV1() *CommitPluginCodecV1 { + return &CommitPluginCodecV1{} +} + +func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { + s := &bcs.Serializer{} + bcs.SerializeSequenceWithFunction(report.PriceUpdates.TokenPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.TokenPrice) { + sourceToken := aptos.AccountAddress{} + err := sourceToken.ParseStringRelaxed(string(item.TokenID)) + if err != nil { + s.SetError(fmt.Errorf("failed to parse source token address: %w", err)) + return + } + s.Struct(&sourceToken) + s.U256(*item.Price.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { + s.U64(uint64(item.ChainSel)) + s.U256(*item.GasPrice.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.BlessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize BlessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.UnblessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize UnblessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.RMNSignatures, s, func(s *bcs.Serializer, item cciptypes.RMNECDSASignature) { + s.FixedBytes(item.R[:]) + s.FixedBytes(item.S[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize RMNSignatures: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptypes.CommitPluginReport, error) { + des := bcs.NewDeserializer(data) + report := cciptypes.CommitPluginReport{} + + report.PriceUpdates.TokenPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.TokenPrice) { + var sourceToken aptos.AccountAddress + des.Struct(&sourceToken) + if des.Error() != nil { + return + } + item.TokenID = cciptypes.UnknownEncodedAddress(sourceToken.String()) + price := des.U256() + if des.Error() != nil { + return + } + item.Price = cciptypes.NewBigInt(&price) + }) + + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize TokenPriceUpdates: %w", des.Error()) + } + + report.PriceUpdates.GasPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.GasPriceChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + gasPrice := des.U256() + if des.Error() != nil { + return + } + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) + } + + deserializeMerkleRootChain := func(des *bcs.Deserializer, item *cciptypes.MerkleRootChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + onRampAddrBytes := des.ReadBytes() + if des.Error() != nil { + return + } + item.OnRampAddress = onRampAddrBytes + startSeqNum := des.U64() + if des.Error() != nil { + return + } + endSeqNum := des.U64() + if des.Error() != nil { + return + } + item.SeqNumsRange = cciptypes.NewSeqNumRange(cciptypes.SeqNum(startSeqNum), cciptypes.SeqNum(endSeqNum)) + des.ReadFixedBytesInto(item.MerkleRoot[:]) + if des.Error() != nil { + return + } + } + + report.BlessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize BlessedMerkleRoots: %w", des.Error()) + } + + report.UnblessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize UnblessedMerkleRoots: %w", des.Error()) + } + + report.RMNSignatures = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RMNECDSASignature) { + des.ReadFixedBytesInto(item.R[:]) + if des.Error() != nil { + return + } + des.ReadFixedBytesInto(item.S[:]) + if des.Error() != nil { + return + } + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize RMNSignatures: %w", des.Error()) + } + + if des.Remaining() > 0 { + return cciptypes.CommitPluginReport{}, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + return report, nil +} + +// Ensure CommitPluginCodec implements the CommitPluginCodec interface +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go new file mode 100644 index 00000000000..3f05cb75d52 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -0,0 +1,163 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomCommitReport = func() cciptypes.CommitPluginReport { + return cciptypes.CommitPluginReport{ + BlessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + UnblessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + PriceUpdates: cciptypes.PriceUpdates{ + TokenPriceUpdates: []cciptypes.TokenPrice{ + { + TokenID: cciptypes.UnknownEncodedAddress(generateAddressString()), + Price: cciptypes.NewBigInt(utils.RandUint256()), + }, + }, + GasPriceUpdates: []cciptypes.GasPriceChain{ + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + }, + }, + RMNSignatures: []cciptypes.RMNECDSASignature{ + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + }, + } +} + +func TestCommitPluginCodecV1(t *testing.T) { + testCases := []struct { + name string + report func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport + expErr bool + }{ + { + name: "base report", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + return report + }, + }, + { + name: "empty token address", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].TokenID = "" + return report + }, + expErr: true, + }, + { + name: "empty merkle root", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.BlessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + report.UnblessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + return report + }, + }, + { + name: "zero token price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].Price = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + { + name: "zero gas price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.GasPriceUpdates[0].GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + report := tc.report(randomCommitReport()) + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(t) + encodedReport, err := commitCodec.Encode(ctx, report) + if tc.expErr { + assert.Error(t, err) + return + } + require.NoError(t, err) + decodedReport, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(t, err) + require.Equal(t, report, decodedReport) + }) + } +} + +func BenchmarkCommitPluginCodecV1_Encode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + + rep := randomCommitReport() + for i := 0; i < b.N; i++ { + _, err := commitCodec.Encode(ctx, rep) + require.NoError(b, err) + } +} + +func BenchmarkCommitPluginCodecV1_Decode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + encodedReport, err := commitCodec.Encode(ctx, randomCommitReport()) + require.NoError(b, err) + + for i := 0; i < b.N; i++ { + _, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(b, err) + } +} diff --git a/core/capabilities/ccip/ccipaptos/executecodec.go b/core/capabilities/ccip/ccipaptos/executecodec.go new file mode 100644 index 00000000000..62c53e21fee --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec.go @@ -0,0 +1,343 @@ +package ccipaptos + +import ( + "context" + "fmt" + "math/big" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. +// Compatible with ccip_offramp::offramp version 1.6.0 +type ExecutePluginCodecV1 struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +func NewExecutePluginCodecV1(extraDataCodec ccipcommon.ExtraDataCodec) *ExecutePluginCodecV1 { + return &ExecutePluginCodecV1{ + extraDataCodec: extraDataCodec, + } +} + +func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.ExecutePluginReport) ([]byte, error) { + if len(report.ChainReports) == 0 { + return nil, nil + } + + if len(report.ChainReports) != 1 { + return nil, fmt.Errorf("ExecutePluginCodecV1 expects exactly one ChainReport, found %d", len(report.ChainReports)) + } + + chainReport := report.ChainReports[0] + + if len(chainReport.Messages) != 1 { + return nil, fmt.Errorf("only single report message expected, got %d", len(chainReport.Messages)) + } + + if len(chainReport.OffchainTokenData) != 1 { + return nil, fmt.Errorf("only single group of offchain token data expected, got %d", len(chainReport.OffchainTokenData)) + } + + message := chainReport.Messages[0] + offchainTokenData := chainReport.OffchainTokenData[0] + + s := &bcs.Serializer{} + + // 1. source_chain_selector: u64 + s.U64(uint64(chainReport.SourceChainSelector)) + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + if len(message.Header.MessageID) != 32 { + return nil, fmt.Errorf("invalid message ID length: expected 32, got %d", len(message.Header.MessageID)) + } + s.FixedBytes(message.Header.MessageID[:]) + + // 3. header_source_chain_selector: u64 + s.U64(uint64(message.Header.SourceChainSelector)) + + // 4. dest_chain_selector: u64 + s.U64(uint64(message.Header.DestChainSelector)) + + // 5. sequence_number: u64 + s.U64(uint64(message.Header.SequenceNumber)) + + // 6. nonce: u64 + s.U64(message.Header.Nonce) + // --- End Message Header --- + + // 7. sender: vector + s.WriteBytes(message.Sender) + + // 8. data: vector + s.WriteBytes(message.Data) + + // 9. receiver: address (Aptos address, 32 bytes) + var receiverAddr aptos.AccountAddress + if err := receiverAddr.ParseStringRelaxed(message.Receiver.String()); err != nil { + return nil, fmt.Errorf("failed to parse receiver address '%s': %w", message.Receiver.String(), err) + } + s.Struct(&receiverAddr) + + // 10. gas_limit: u256 + // Extract gas limit from ExtraArgs + decodedExtraArgsMap, err := e.extraDataCodec.DecodeExtraArgs(message.ExtraArgs, chainReport.SourceChainSelector) + if err != nil { + return nil, fmt.Errorf("failed to decode ExtraArgs: %w", err) + } + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) // Use a helper to extract the gas limit + if err != nil { + return nil, fmt.Errorf("failed to extract gas limit from decoded ExtraArgs map: %w", err) + } + s.U256(*gasLimit) + + // 11. token_amounts: vector + bcs.SerializeSequenceWithFunction(message.TokenAmounts, s, func(s *bcs.Serializer, item cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + s.WriteBytes(item.SourcePoolAddress) + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + if err := destTokenAddr.ParseStringRelaxed(item.DestTokenAddress.String()); err != nil { + s.SetError(fmt.Errorf("failed to parse dest_token_address '%s': %w", item.DestTokenAddress.String(), err)) + } + s.Struct(&destTokenAddr) + + // 11c. dest_gas_amount: u32 + // Extract dest gas amount from DestExecData + destExecDataDecodedMap, err := e.extraDataCodec.DecodeTokenAmountDestExecData(item.DestExecData, chainReport.SourceChainSelector) + if err != nil { + s.SetError(fmt.Errorf("failed to decode DestExecData for token %s: %w", destTokenAddr.String(), err)) + return + } + destGasAmount, err := extractDestGasAmountFromMap(destExecDataDecodedMap) // Use a helper + if err != nil { + s.SetError(fmt.Errorf("failed to extract dest gas amount from decoded DestExecData map for token %s: %w", destTokenAddr.String(), err)) + return + } + s.U32(destGasAmount) + + // 11d. extra_data: vector + s.WriteBytes(item.ExtraData) + + // 11e. amount: u256 + if item.Amount.Int == nil { + s.SetError(fmt.Errorf("token amount is nil for token %s", destTokenAddr.String())) + return + } + s.U256(*item.Amount.Int) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during token_amounts serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize token_amounts: %w", s.Error()) + } + + // 12. offchain_token_data: vector> + bcs.SerializeSequenceWithFunction(offchainTokenData, s, func(s *bcs.Serializer, item []byte) { + s.WriteBytes(item) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during offchain_token_data serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda (though unlikely here) + return nil, fmt.Errorf("failed to serialize offchain_token_data: %w", s.Error()) + } + + // 13. proofs: vector + bcs.SerializeSequenceWithFunction(chainReport.Proofs, s, func(s *bcs.Serializer, item cciptypes.Bytes32) { + if len(item) != 32 { + s.SetError(fmt.Errorf("invalid proof length: expected 32, got %d", len(item))) + return + } + s.FixedBytes(item[:]) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during proofs serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize proofs: %w", s.Error()) + } + + // Final check and return + if s.Error() != nil { + return nil, fmt.Errorf("BCS serialization failed: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) (cciptypes.ExecutePluginReport, error) { + des := bcs.NewDeserializer(encodedReport) + report := cciptypes.ExecutePluginReport{} + var chainReport cciptypes.ExecutePluginReportSingleChain + var message cciptypes.Message + + // 1. source_chain_selector: u64 + chainReport.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize source_chain_selector: %w", des.Error()) + } + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + messageIDBytes := des.ReadFixedBytes(32) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize message_id: %w", des.Error()) + } + copy(message.Header.MessageID[:], messageIDBytes) + + // 3. header_source_chain_selector: u64 + message.Header.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize header_source_chain_selector: %w", des.Error()) + } + + // 4. dest_chain_selector: u64 + message.Header.DestChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize dest_chain_selector: %w", des.Error()) + } + + // 5. sequence_number: u64 + message.Header.SequenceNumber = cciptypes.SeqNum(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sequence_number: %w", des.Error()) + } + + // 6. nonce: u64 + message.Header.Nonce = des.U64() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize nonce: %w", des.Error()) + } + + // --- End Message Header --- + + // 7. sender: vector + message.Sender = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sender: %w", des.Error()) + } + + // 8. data: vector + message.Data = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize data: %w", des.Error()) + } + + // 9. receiver: address + var receiverAddr aptos.AccountAddress + des.Struct(&receiverAddr) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize receiver: %w", des.Error()) + } + message.Receiver = receiverAddr[:] + + // 10. gas_limit: u256 + _ = des.U256() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize gas_limit: %w", des.Error()) + } + + // 11. token_amounts: vector + message.TokenAmounts = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + item.SourcePoolAddress = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + des.Struct(&destTokenAddr) + if des.Error() != nil { + return // Error handled by caller + } + item.DestTokenAddress = destTokenAddr[:] + + // 11c. dest_gas_amount: u32 + destGasAmount := des.U32() + if des.Error() != nil { + return // Error handled by caller + } + // Encode dest gas amount back into DestExecData + destData, err := abiEncodeUint32(destGasAmount) + if err != nil { + des.SetError(fmt.Errorf("abi encode dest gas amount: %w", err)) + return + } + item.DestExecData = destData + + // 11d. extra_data: vector + item.ExtraData = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11e. amount: u256 + amountU256 := des.U256() + if des.Error() != nil { + return // Error handled by caller + } + item.Amount = cciptypes.NewBigInt(&amountU256) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize token_amounts: %w", des.Error()) + } + + // 12. offchain_token_data: vector> + offchainTokenDataGroup := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadBytes() + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize offchain_token_data: %w", des.Error()) + } + // Wrap it in the expected [][][]byte structure + chainReport.OffchainTokenData = [][][]byte{offchainTokenDataGroup} + + // 13. proofs: vector + proofsBytes := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadFixedBytes(32) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize proofs: %w", des.Error()) + } + // Convert [][]byte to [][32]byte + chainReport.Proofs = make([]cciptypes.Bytes32, len(proofsBytes)) + for i, proofB := range proofsBytes { + if len(proofB) != 32 { + // This shouldn't happen if ReadFixedBytes worked correctly + return report, fmt.Errorf("internal error: deserialized proof %d has length %d, expected 32", i, len(proofB)) + } + copy(chainReport.Proofs[i][:], proofB) + } + + // Check if all bytes were consumed + if des.Remaining() > 0 { + return report, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + // Set empty fields + message.Header.MsgHash = cciptypes.Bytes32{} + message.Header.OnRamp = cciptypes.UnknownAddress{} + message.FeeToken = cciptypes.UnknownAddress{} + message.ExtraArgs = cciptypes.Bytes{} + message.FeeTokenAmount = cciptypes.BigInt{} + + // Assemble the final report + chainReport.Messages = []cciptypes.Message{message} + // ProofFlagBits is not part of the Aptos report, initialize it empty/zero. + chainReport.ProofFlagBits = cciptypes.NewBigInt(big.NewInt(0)) + report.ChainReports = []cciptypes.ExecutePluginReportSingleChain{chainReport} + + return report, nil +} + +// Ensure ExecutePluginCodec implements the ExecutePluginCodec interface +var _ cciptypes.ExecutePluginCodec = (*ExecutePluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go new file mode 100644 index 00000000000..f4500ef679a --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -0,0 +1,179 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big.Int, destGasAmount uint32) cciptypes.ExecutePluginReport { + const numChainReports = 1 + const msgsPerReport = 1 + const numTokensPerMsg = 3 + + chainReports := make([]cciptypes.ExecutePluginReportSingleChain, numChainReports) + for i := 0; i < numChainReports; i++ { + reportMessages := make([]cciptypes.Message, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + data, err := cciptypes.NewBytesFromString(utils.RandomAddress().String()) + require.NoError(t, err) + + tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) + for z := 0; z < numTokensPerMsg; z++ { + encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + require.NoError(t, err2) + + tokenAmounts[z] = cciptypes.RampTokenAmount{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: generateAddressBytes(), + ExtraData: data, + Amount: cciptypes.NewBigInt(utils.RandUint256()), + DestExecData: encodedDestExecData, + } + } + + extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + if err != nil { + t.Fatalf("failed to pack extra args: %v", err) + } + extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + + reportMessages[j] = cciptypes.Message{ + Header: cciptypes.RampMessageHeader{ + MessageID: utils.RandomBytes32(), + SourceChainSelector: cciptypes.ChainSelector(rand.Uint64()), + DestChainSelector: cciptypes.ChainSelector(rand.Uint64()), + SequenceNumber: cciptypes.SeqNum(rand.Uint64()), + Nonce: rand.Uint64(), + MsgHash: utils.RandomBytes32(), + OnRamp: utils.RandomAddress().Bytes(), + }, + Sender: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + Data: data, + Receiver: generateAddressBytes(), + ExtraArgs: extraArgs, + FeeToken: generateAddressBytes(), + FeeTokenAmount: cciptypes.NewBigInt(utils.RandUint256()), + TokenAmounts: tokenAmounts, + } + } + + tokenData := make([][][]byte, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + tokenData[j] = [][]byte{{0x1}, {0x2, 0x3}} + } + + chainReports[i] = cciptypes.ExecutePluginReportSingleChain{ + SourceChainSelector: cciptypes.ChainSelector(chainSelector), + Messages: reportMessages, + OffchainTokenData: tokenData, + Proofs: []cciptypes.Bytes32{utils.RandomBytes32(), utils.RandomBytes32()}, + ProofFlagBits: cciptypes.NewBigInt(big.NewInt(0)), + } + } + + return cciptypes.ExecutePluginReport{ChainReports: chainReports} +} + +func TestExecutePluginCodecV1(t *testing.T) { + ctx := testutils.Context(t) + mockExtraDataCodec := &mocks.ExtraDataCodec{} + destGasAmount := rand.Uint32() + gasLimit := utils.RandUint256() + mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + "destgasamount": destGasAmount, + }, nil) + mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + "gasLimit": utils.RandUint256(), + "accountIsWritableBitmap": gasLimit, + }, nil) + + testCases := []struct { + name string + report func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport + expErr bool + chainSelector uint64 + destGasAmount uint32 + gasLimit *big.Int + }{ + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 124615329519749607, // Solana mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty msgs", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].Messages = []cciptypes.Message{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty offchain token data", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].OffchainTokenData = [][][]byte{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + codec := NewExecutePluginCodecV1(mockExtraDataCodec) + report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) + bytes, err := codec.Encode(ctx, report) + if tc.expErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + // ignore unavailable fields in comparison + for i := range report.ChainReports { + for j := range report.ChainReports[i].Messages { + report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} + report.ChainReports[i].Messages[j].Header.OnRamp = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].FeeToken = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].ExtraArgs = cciptypes.Bytes{} + report.ChainReports[i].Messages[j].FeeTokenAmount = cciptypes.BigInt{} + } + } + + // decode using the codec + codecDecoded, err := codec.Decode(ctx, bytes) + require.NoError(t, err) + require.Equal(t, report, codecDecoded) + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go new file mode 100644 index 00000000000..5c600f266bd --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -0,0 +1,150 @@ +package ccipaptos + +import ( + "fmt" + "reflect" + + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +// ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder +// Compatible with ccip::fee_quoter version 1.6.0 +type ExtraDataDecoder struct{} + +const ( + aptosDestExecDataKey = "destGasAmount" +) + +var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) + +var ( + // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") + + // bytes4 public constant GENERIC_EXTRA_ARGS_V2_TAG = 0x181dcf10; + genericExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") + + // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba + svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") +) + +// DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data +func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { + destGasAmount, err := abiDecodeUint32(destExecData) + if err != nil { + return nil, fmt.Errorf("decode dest gas amount: %w", err) + } + + return map[string]any{ + aptosDestExecDataKey: destGasAmount, + }, nil +} + +// DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args +func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { + if len(extraArgs) < 4 { + return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) + } + + var method string + var argName string + switch string(extraArgs[:4]) { + case string(evmExtraArgsV1Tag): + method = "exposeEVMExtraArgsV1" + argName = "evmExtraArgsV1" + case string(genericExtraArgsV2Tag): + method = "exposeGenericExtraArgsV2" + argName = "evmExtraArgsV2" + case string(svmExtraArgsV1Tag): + method = "exposeSVMExtraArgsV1" + argName = "svmExtraArgsV1" + default: + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + } + + output := make(map[string]any) + args := make(map[string]any) + err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + if err != nil { + return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + } + + argValue, exists := args[argName] + if !exists { + return nil, fmt.Errorf("failed to get arg value for %s", argName) + } + + val := reflect.ValueOf(argValue) + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) + } + + switch argName { + case "evmExtraArgsV1": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + case "evmExtraArgsV2": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + case "svmExtraArgsV1": + computeUnitsField := val.FieldByName("ComputeUnits") + if computeUnitsField.IsValid() { + output["computeUnits"] = computeUnitsField.Interface() + } else { + output["computeUnits"] = nil + } + + bitmapField := val.FieldByName("AccountIsWritableBitmap") + if bitmapField.IsValid() { + output["accountIsWritableBitmap"] = bitmapField.Interface() + } else { + output["accountIsWritableBitmap"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + + tokenReceiverField := val.FieldByName("TokenReceiver") + if tokenReceiverField.IsValid() { + output["tokenReceiver"] = tokenReceiverField.Interface() + } else { + output["tokenReceiver"] = nil + } + + accountsField := val.FieldByName("Accounts") + if accountsField.IsValid() { + output["accounts"] = accountsField.Interface() + } else { + output["accounts"] = nil + } + } + return output, nil +} + +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go new file mode 100644 index 00000000000..234d2f29981 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -0,0 +1,110 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +func Test_decodeExtraData(t *testing.T) { + gasLimit := big.NewInt(rand.Int63()) + extraDataDecoder := &ExtraDataDecoder{} + + t.Run("decode extra args into map evm v1", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + }) + + t.Run("decode extra args into map evm v2", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ + GasLimit: gasLimit, + AllowOutOfOrderExecution: true, + }) + encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 2) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + + ooe, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, true, ooe) + }) + + t.Run("decode extra args into map svm", func(t *testing.T) { + key, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + cu := uint32(10000) + bitmap := uint64(4) + ooe := false + tokenReceiver := [32]byte(key.PublicKey().Bytes()) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} + encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ + ComputeUnits: cu, + AccountIsWritableBitmap: bitmap, + AllowOutOfOrderExecution: ooe, + TokenReceiver: tokenReceiver, + Accounts: accounts, + }) + encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 5) + + cuDecoded, exist := m["computeUnits"] + require.True(t, exist) + require.Equal(t, cuDecoded, cu) + + bitmapDecoded, exist := m["accountIsWritableBitmap"] + require.True(t, exist) + require.Equal(t, bitmapDecoded, bitmap) + + ooeDecoded, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, ooeDecoded, ooe) + + tokenReceiverDecoded, exist := m["tokenReceiver"] + require.True(t, exist) + require.Equal(t, tokenReceiverDecoded, tokenReceiver) + + accountsDecoded, exist := m["accounts"] + require.True(t, exist) + require.Equal(t, accountsDecoded, accounts) + }) + + t.Run("decode dest exec data into map", func(t *testing.T) { + destGasAmount := uint32(10000) + encoded, err := abiEncodeUint32(destGasAmount) + require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + decoded, exist := m[aptosDestExecDataKey] + require.True(t, exist) + require.Equal(t, destGasAmount, decoded) + }) +} diff --git a/core/capabilities/ccip/ccipaptos/gas_helpers.go b/core/capabilities/ccip/ccipaptos/gas_helpers.go new file mode 100644 index 00000000000..7f3922e5c6c --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/gas_helpers.go @@ -0,0 +1,22 @@ +package ccipaptos + +import ( + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +func NewGasEstimateProvider() EstimateProvider { + return EstimateProvider{} +} + +type EstimateProvider struct { +} + +// CalculateMerkleTreeGas is not implemented +func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { + return 0 +} + +// CalculateMessageMaxGas is not implemented. +func (gp EstimateProvider) CalculateMessageMaxGas(msg cciptypes.Message) uint64 { + return 0 +} diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go new file mode 100644 index 00000000000..995e7e0112e --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -0,0 +1,367 @@ +package ccipaptos + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink-ccip/pkg/logutil" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +var ( + // const LEAF_DOMAIN_SEPARATOR: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; + leafDomainSeparator = [32]byte{} + + // see aptos_hash::keccak256(b"Any2AptosMessageHashV1") in calculate_metadata_hash + any2AptosMessageHash = utils.Keccak256Fixed([]byte("Any2AptosMessageHashV1")) +) + +// MessageHasherV1 implements the MessageHasher interface. +// Compatible with ccip::offramp version 1.6.0 +type MessageHasherV1 struct { + lggr logger.Logger + extraDataCodec ccipcommon.ExtraDataCodec +} + +type any2AptosTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int +} + +func NewMessageHasherV1(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) *MessageHasherV1 { + return &MessageHasherV1{ + lggr: lggr, + extraDataCodec: extraDataCodec, + } +} + +// Hash implements the MessageHasher interface. +// It constructs all of the inputs to the final keccak256 hash in Internal._hash(Any2EVMRampMessage). +// The main structure of the hash is as follows: +// Fixed-size message fields are included in nested hash to reduce stack pressure. +// This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. +func (h *MessageHasherV1) Hash(ctx context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) { + lggr := logutil.WithContextValues(ctx, h.lggr) + lggr = logger.With( + lggr, + "msgID", msg.Header.MessageID.String(), + "ANY_2_APTOS_MESSAGE_HASH", hexutil.Encode(any2AptosMessageHash[:]), + "onrampAddress", msg.Header.OnRamp, + ) + lggr.Debugw("hashing message", "msg", msg) + + rampTokenAmounts := make([]any2AptosTokenTransfer, len(msg.TokenAmounts)) + for _, rta := range msg.TokenAmounts { + destGasAmount, err := abiDecodeUint32(rta.DestExecData) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest gas amount: %w", err) + } + + lggr.Debugw("decoded dest gas amount", + "destGasAmount", destGasAmount) + + destTokenAddress, err := addressBytesToBytes32(rta.DestTokenAddress) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest token address: %w", err) + } + + lggr.Debugw("abi decoded dest token address", + "destTokenAddress", destTokenAddress) + + rampTokenAmounts = append(rampTokenAmounts, any2AptosTokenTransfer{ + SourcePoolAddress: rta.SourcePoolAddress, + DestTokenAddress: destTokenAddress, + DestGasAmount: destGasAmount, + ExtraData: rta.ExtraData, + Amount: rta.Amount.Int, + }) + } + + // one difference from EVM is that we don't left pad the OnRamp to 32 bytes here, we use the source chain's canonical bytes encoding directly. + metaDataHashInput, err := computeMetadataHash(uint64(msg.Header.SourceChainSelector), uint64(msg.Header.DestChainSelector), msg.Header.OnRamp) + if err != nil { + return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) + } + + lggr.Debugw("metadata hash preimage", + "metaDataHashInput", hexutil.Encode(metaDataHashInput[:])) + + // Need to decode the extra args to get the gas limit. + // TODO: we assume that extra args is always abi-encoded for now, but we need + // to decode according to source chain selector family. We should add a family + // lookup API to the chain-selectors library. + + decodedExtraArgsMap, err := h.extraDataCodec.DecodeExtraArgs(msg.ExtraArgs, msg.Header.SourceChainSelector) + if err != nil { + return [32]byte{}, err + } + + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) + if err != nil { + return [32]byte{}, fmt.Errorf("decode extra args to get gas limit: %w", err) + } + + lggr.Debugw("decoded msg gas limit", "gasLimit", gasLimit) + + receiverAddress, err := addressBytesToBytes32(msg.Receiver) + if err != nil { + return [32]byte{}, err + } + + msgHash, err := computeMessageDataHash(metaDataHashInput, msg.Header.MessageID, receiverAddress, uint64(msg.Header.SequenceNumber), gasLimit, msg.Header.Nonce, msg.Sender, msg.Data, rampTokenAmounts) + if err != nil { + return [32]byte{}, err + } + + lggr.Debugw("final message hash result", + "msgHash", hexutil.Encode(msgHash[:]), + ) + + return msgHash, nil +} + +// This is the equivalent of offramp::calculate_message_hash. +// This is very similar to the EVM version, except for 32-byte addresses: +// +// bytes32 messageDataHash = keccak256( +// abi.encode( +// LEAF_DOMAIN_SEPARATOR, +// metadataHash, +// keccak256( +// abi.encode( +// original.header.originalId, +// original.receiver, +// original.header.sequenceNumber, +// original.gasLimit, +// original.header.nonce +// ) +// ), +// keccak256(original.sender), +// keccak256(original.data), +// keccak256(abi.encode(original.tokenAmounts)) +// ) +// ); +func computeMessageDataHash( + metadataHash [32]byte, + messageID [32]byte, + receiver [32]byte, + sequenceNumber uint64, + gasLimit *big.Int, + nonce uint64, + sender []byte, + data []byte, + tokenAmounts []any2AptosTokenTransfer, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + uint256Type, err := abi.NewType("uint256", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint256 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + headerArgs := abi.Arguments{ + {Type: bytes32Type}, // messageID + {Type: bytes32Type}, // receiver as bytes32 + {Type: uint64Type}, // sequenceNumber + {Type: uint256Type}, // gasLimit + {Type: uint64Type}, // nonce + } + headerEncoded, err := headerArgs.Pack( + messageID, + receiver, + sequenceNumber, + gasLimit, + nonce, + ) + if err != nil { + return [32]byte{}, err + } + headerHash := crypto.Keccak256Hash(headerEncoded) + + senderHash := crypto.Keccak256Hash(sender) + + dataHash := crypto.Keccak256Hash(data) + + type tokenTuple struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int + } + tokens := make([]tokenTuple, len(tokenAmounts)) + for i, token := range tokenAmounts { + tokens[i] = tokenTuple{ + SourcePoolAddress: token.SourcePoolAddress, + DestTokenAddress: token.DestTokenAddress, + DestGasAmount: token.DestGasAmount, + ExtraData: token.ExtraData, + Amount: token.Amount, + } + } + + // Manually encode tokens to match the Move implementation, because abi.Pack has different behavior + // for dynamic types. + var tokenHashData []byte + tokenHashData = append(tokenHashData, encodeUint256(big.NewInt(int64(len(tokens))))...) + for _, token := range tokens { + tokenHashData = append(tokenHashData, encodeBytes(token.SourcePoolAddress)...) + tokenHashData = append(tokenHashData, token.DestTokenAddress[:]...) + tokenHashData = append(tokenHashData, encodeUint32(token.DestGasAmount)...) + tokenHashData = append(tokenHashData, encodeBytes(token.ExtraData)...) + tokenHashData = append(tokenHashData, encodeUint256(token.Amount)...) + } + tokenAmountsHash := crypto.Keccak256Hash(tokenHashData) + + finalArgs := abi.Arguments{ + {Type: bytes32Type}, // LEAF_DOMAIN_SEPARATOR + {Type: bytes32Type}, // metadataHash + {Type: bytes32Type}, // headerHash + {Type: bytes32Type}, // senderHash + {Type: bytes32Type}, // dataHash + {Type: bytes32Type}, // tokenAmountsHash + } + + finalEncoded, err := finalArgs.Pack( + leafDomainSeparator, + metadataHash, + headerHash, + senderHash, + dataHash, + tokenAmountsHash, + ) + if err != nil { + return [32]byte{}, err + } + + return crypto.Keccak256Hash(finalEncoded), nil +} + +// ComputeMetadataHash calculates the metadataHash as per offramp::calculate_metadata_hash +// This is the same as the EVM version minus the separator: +// +// bytes32 metaDataHash = keccak256( +// abi.encode( +// Internal.ANY_2_APTOS_MESSAGE_HASH, +// sourceChainSelector, +// i_chainSelector, +// keccak256(_getEnabledSourceChainConfig(sourceChainSelector).onRamp) +// ) +// ); +func computeMetadataHash( + sourceChainSelector uint64, + destinationChainSelector uint64, + onRamp []byte, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + onRampHash := crypto.Keccak256Hash(onRamp) + + args := abi.Arguments{ + {Type: bytes32Type}, // ANY_2_APTOS_MESSAGE_HASH + {Type: uint64Type}, // sourceChainSelector + {Type: uint64Type}, // destinationChainSelector (i_chainSelector) + {Type: bytes32Type}, // onRamp + } + + encoded, err := args.Pack( + any2AptosMessageHash, + sourceChainSelector, + destinationChainSelector, + onRampHash, + ) + if err != nil { + return [32]byte{}, err + } + + metadataHash := crypto.Keccak256Hash(encoded) + return metadataHash, nil +} + +func encodeUint256(n *big.Int) []byte { + return common.LeftPadBytes(n.Bytes(), 32) +} + +func encodeUint32(n uint32) []byte { + return common.LeftPadBytes(new(big.Int).SetUint64(uint64(n)).Bytes(), 32) +} + +func encodeBytes(b []byte) []byte { + encodedLength := common.LeftPadBytes(big.NewInt(int64(len(b))).Bytes(), 32) + padLen := (32 - (len(b) % 32)) % 32 + result := make([]byte, 32+len(b)+padLen) + copy(result[:32], encodedLength) + copy(result[32:], b) + return result +} + +func parseExtraDataMap(input map[string]any) (*big.Int, error) { + var outputGas *big.Int + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "gaslimit": + // Expect [][32]byte + if val, ok := fieldValue.(*big.Int); ok { + outputGas = val + return outputGas, nil + } + return nil, fmt.Errorf("unexpected type for gas limit: %T", fieldValue) + default: + // no error here, as we only need the keys to gasLimit, other keys can be skipped without like AllowOutOfOrderExecution etc. + } + } + return outputGas, errors.New("gas limit not found in extra data map") +} + +func extractDestGasAmountFromMap(input map[string]any) (uint32, error) { + // Iterate through the expected fields in the struct + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "destgasamount": + // Expect uint32 + if val, ok := fieldValue.(uint32); ok { + return val, nil + } + return 0, errors.New("invalid type for destgasamount, expected uint32") + default: + } + } + + return 0, errors.New("invalid token message, dest gas amount not found in the DestExecDataDecoded map") +} + +// Interface compliance check +var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/msghasher_test.go b/core/capabilities/ccip/ccipaptos/msghasher_test.go new file mode 100644 index 00000000000..fa06a9fb2b7 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher_test.go @@ -0,0 +1,93 @@ +package ccipaptos + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_message_hash +func TestComputeMessageDataHash(t *testing.T) { + expectedHashStr := "0xc8d6cf666864a60dd6ecd89e5c294734c53b3218d3f83d2d19a3c3f9e200e00d" + + metadataHashBytes, err := hexutil.Decode("0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899") + require.NoError(t, err) + var metadataHash [32]byte + copy(metadataHash[:], metadataHashBytes) + + messageIDBytes, err := hexutil.Decode("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + require.NoError(t, err) + var messageID [32]byte + copy(messageID[:], messageIDBytes) + + receiverBytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000001234") + require.NoError(t, err) + var receiver [32]byte + copy(receiver[:], receiverBytes) + + sequenceNumber := uint64(42) + nonce := uint64(123) + gasLimit := big.NewInt(500000) + + sender, err := hexutil.Decode("0x8765432109fedcba8765432109fedcba87654321") + require.NoError(t, err) + + data := []byte("sample message data") + srcPool1, err := hexutil.Decode("0xabcdef1234567890abcdef1234567890abcdef12") + require.NoError(t, err) + destToken1Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000005678") + require.NoError(t, err) + var destToken1 [32]byte + copy(destToken1[:], destToken1Bytes) + extraData1, err := hexutil.Decode("0x00112233") + require.NoError(t, err) + token1 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool1, + DestTokenAddress: destToken1, + DestGasAmount: 10000, + ExtraData: extraData1, + Amount: big.NewInt(1000000), + } + srcPool2, err := hexutil.Decode("0x123456789abcdef123456789abcdef123456789a") + require.NoError(t, err) + destToken2Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000009abc") + require.NoError(t, err) + var destToken2 [32]byte + copy(destToken2[:], destToken2Bytes) + extraData2, err := hexutil.Decode("0xffeeddcc") + require.NoError(t, err) + token2 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool2, + DestTokenAddress: destToken2, + DestGasAmount: 20000, + ExtraData: extraData2, + Amount: big.NewInt(5000000), + } + + tokens := []any2AptosTokenTransfer{token1, token2} + + computedHash, err := computeMessageDataHash(metadataHash, messageID, receiver, sequenceNumber, gasLimit, nonce, sender, data, tokens) + require.NoError(t, err) + + require.Equal(t, expectedHashStr, hexutil.Encode(computedHash[:]), "Computed hash does not match expected hash") +} + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_metadata_hash +func TestComputeMetadataHash(t *testing.T) { + expectedHashStr := "0x812acb01df318f85be452cf6664891cf5481a69dac01e0df67102a295218dd17" + expectedHashAlternateStr := "0x6caf8756ae02ee4f12b83b38e0f21b5e43e90d203bd06729486fd4a0fc8bcc5e" + + sourceChainSelector := uint64(123456789) + destinationChainSelector := uint64(987654321) + onRamp := []byte("source-onramp-address") + + metadataHash, err := computeMetadataHash(sourceChainSelector, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashStr, hexutil.Encode(metadataHash[:]), "Computed hash does not match expected hash") + + metadataHashAlternate, err := computeMetadataHash(sourceChainSelector+1, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashAlternateStr, hexutil.Encode(metadataHashAlternate[:]), "Alternate computed hash does not match expected alternate hash") +} diff --git a/core/capabilities/ccip/ccipaptos/rmncrypto.go b/core/capabilities/ccip/ccipaptos/rmncrypto.go new file mode 100644 index 00000000000..986ebe90f36 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/rmncrypto.go @@ -0,0 +1,20 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// AptosRMNCrypto is the RMNCrypto implementation for Aptos chains. +type AptosRMNCrypto struct{} + +func (r *AptosRMNCrypto) VerifyReportSignatures( + _ context.Context, + _ []cciptypes.RMNECDSASignature, + _ cciptypes.RMNReport, + _ []cciptypes.UnknownAddress, +) error { + return errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/tokendata.go b/core/capabilities/ccip/ccipaptos/tokendata.go new file mode 100644 index 00000000000..4f18399c5f6 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/tokendata.go @@ -0,0 +1,18 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +type AptosTokenDataEncoder struct{} + +func NewAptosTokenDataEncoder() AptosTokenDataEncoder { + return AptosTokenDataEncoder{} +} + +func (e AptosTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) { + return nil, errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go new file mode 100644 index 00000000000..5488f3903d2 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -0,0 +1,23 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +func abiEncodeUint32(data uint32) ([]byte, error) { + return utils.ABIEncode(`[{ "type": "uint32" }]`, data) +} + +func abiDecodeUint32(data []byte) (uint32, error) { + raw, err := utils.ABIDecode(`[{ "type": "uint32" }]`, data) + if err != nil { + return 0, fmt.Errorf("abi decode uint32: %w", err) + } + + val := *abi.ConvertType(raw[0], new(uint32)).(*uint32) + return val, nil +} From eb2c48f20e3dce49113abf353c971ab91fe0a254 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:49:14 +0400 Subject: [PATCH 055/136] core/capabilities/ccip/common/addresscodec.go: add aptos address codec --- .../ccip/ccipaptos/addresscodec.go | 44 +++++++++---------- core/capabilities/ccip/common/addresscodec.go | 12 ++++- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go index 73ee4bb79c0..6297b220279 100644 --- a/core/capabilities/ccip/ccipaptos/addresscodec.go +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -1,9 +1,9 @@ package ccipaptos import ( + "encoding/hex" "fmt" - - "github.com/aptos-labs/aptos-go-sdk" + "strings" ) type AddressCodec struct{} @@ -17,30 +17,30 @@ func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { } func addressBytesToString(addr []byte) (string, error) { - if len(addr) != 32 { - return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + if len(addr) < 1 || len(addr) > 32 { + return "", fmt.Errorf("invalid Aptos address length (%d)", len(addr)) } - accAddress := aptos.AccountAddress(addr) - return accAddress.String(), nil + return fmt.Sprintf("0x%064x", addr), nil } func addressStringToBytes(addr string) ([]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) - if err != nil { - return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + a := strings.TrimPrefix(addr, "0x") + if len(a) == 0 { + return nil, fmt.Errorf("invalid Aptos address length, expected at least 1 character: %s", addr) + } + if len(a) > 64 { + return nil, fmt.Errorf("invalid Aptos address length, expected at most 64 characters: %s", addr) + } + for len(a) < 64 { + a = "0" + a } - return accAddress[:], nil -} -func addressStringToBytes32(addr string) ([32]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) + bytes, err := hex.DecodeString(a) if err != nil { - return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) } - return accAddress, nil + return bytes, nil } func addressBytesToBytes32(addr []byte) ([32]byte, error) { @@ -53,14 +53,12 @@ func addressBytesToBytes32(addr []byte) ([32]byte, error) { return result, nil } -// takes a valid Aptos address string and converts it into canonical format. -func addressStringToString(addr string) (string, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) +func addressStringToBytes32(addr string) ([32]byte, error) { + bytes, err := addressStringToBytes(addr) if err != nil { - return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return [32]byte{}, err } - return accAddress.String(), nil + return addressBytesToBytes32(bytes) } func addressIsValid(addr string) bool { diff --git a/core/capabilities/ccip/common/addresscodec.go b/core/capabilities/ccip/common/addresscodec.go index 3440ec4c391..b72666b906f 100644 --- a/core/capabilities/ccip/common/addresscodec.go +++ b/core/capabilities/ccip/common/addresscodec.go @@ -18,19 +18,22 @@ type ChainSpecificAddressCodec interface { type AddressCodec struct { EVMAddressCodec ChainSpecificAddressCodec SolanaAddressCodec ChainSpecificAddressCodec + AptosAddressCodec ChainSpecificAddressCodec } // AddressCodecParams is a struct that holds the parameters for creating a AddressCodec type AddressCodecParams struct { evmAddressCodec ChainSpecificAddressCodec solanaAddressCodec ChainSpecificAddressCodec + aptosAddressCodec ChainSpecificAddressCodec } // NewAddressCodecParams is a constructor for AddressCodecParams -func NewAddressCodecParams(evmAddressCodec ChainSpecificAddressCodec, solanaAddressCodec ChainSpecificAddressCodec) AddressCodecParams { +func NewAddressCodecParams(evmAddressCodec ChainSpecificAddressCodec, solanaAddressCodec ChainSpecificAddressCodec, aptosAddressCodec ChainSpecificAddressCodec) AddressCodecParams { return AddressCodecParams{ evmAddressCodec: evmAddressCodec, solanaAddressCodec: solanaAddressCodec, + aptosAddressCodec: aptosAddressCodec, } } @@ -39,6 +42,7 @@ func NewAddressCodec(params AddressCodecParams) AddressCodec { return AddressCodec{ EVMAddressCodec: params.evmAddressCodec, SolanaAddressCodec: params.solanaAddressCodec, + AptosAddressCodec: params.aptosAddressCodec, } } @@ -56,6 +60,9 @@ func (ac AddressCodec) AddressBytesToString(addr cciptypes.UnknownAddress, chain case chainsel.FamilySolana: return ac.SolanaAddressCodec.AddressBytesToString(addr) + case chainsel.FamilyAptos: + return ac.AptosAddressCodec.AddressBytesToString(addr) + default: return "", fmt.Errorf("unsupported family for address encode type %s", family) } @@ -75,6 +82,9 @@ func (ac AddressCodec) AddressStringToBytes(addr string, chainSelector cciptypes case chainsel.FamilySolana: return ac.SolanaAddressCodec.AddressStringToBytes(addr) + case chainsel.FamilyAptos: + return ac.AptosAddressCodec.AddressStringToBytes(addr) + default: return nil, fmt.Errorf("unsupported family for address decode type %s", family) } From 041426b37b2b749ea4faf778321e175bc7375b68 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:49:28 +0400 Subject: [PATCH 056/136] core/capabilities/ccip/delegate.go: initialize with aptos address codec --- core/capabilities/ccip/delegate.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 160fdd10961..7dc8a7b1e7f 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -9,6 +9,7 @@ import ( "golang.org/x/exp/maps" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" @@ -208,6 +209,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services common.NewAddressCodecParams( ccipevm.AddressCodec{}, ccipsolana.AddressCodec{}, + ccipaptos.AddressCodec{}, )) // if bootstrappers are provided we assume that the node is a plugin oracle. From b7a752c453e9e7bb5c44e48a142a4c921c7ddd61 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:20 +0400 Subject: [PATCH 057/136] core/capabilities/ccip/ccipevm/executecodec_test.go: initialize extra data codec with aptos decoder --- core/capabilities/ccip/ccipevm/executecodec_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go index db0619ca58f..1b57b750c83 100644 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ b/core/capabilities/ccip/ccipevm/executecodec_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" @@ -227,7 +228,7 @@ func TestExecutePluginCodecV1(t *testing.T) { } func Test_DecodeReport(t *testing.T) { - ExtraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) + ExtraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) offRampABI, err := offramp.OffRampMetaData.GetAbi() require.NoError(t, err) From 5f6fc4c53d7e4df159162db987d249c437e7b211 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:40 +0400 Subject: [PATCH 058/136] core/capabilities/ccip/common/extradatacodec.go: add Aptos --- core/capabilities/ccip/common/extradatacodec.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/common/extradatacodec.go b/core/capabilities/ccip/common/extradatacodec.go index 33f209f6e4c..3382d46415e 100644 --- a/core/capabilities/ccip/common/extradatacodec.go +++ b/core/capabilities/ccip/common/extradatacodec.go @@ -26,19 +26,22 @@ type ExtraDataDecoder interface { type RealExtraDataCodec struct { EVMExtraDataDecoder ExtraDataDecoder SolanaExtraDataDecoder ExtraDataDecoder + AptosExtraDataDecoder ExtraDataDecoder } // ExtraDataCodecParams is a struct that holds the parameters for creating a RealExtraDataCodec type ExtraDataCodecParams struct { evmExtraDataDecoder ExtraDataDecoder solanaExtraDataDecoder ExtraDataDecoder + aptosExtraDataDecoder ExtraDataDecoder } // NewExtraDataCodecParams is a constructor for ExtraDataCodecParams -func NewExtraDataCodecParams(evmDecoder ExtraDataDecoder, solanaDecoder ExtraDataDecoder) ExtraDataCodecParams { +func NewExtraDataCodecParams(evmDecoder ExtraDataDecoder, solanaDecoder ExtraDataDecoder, aptosDecoder ExtraDataDecoder) ExtraDataCodecParams { return ExtraDataCodecParams{ evmExtraDataDecoder: evmDecoder, solanaExtraDataDecoder: solanaDecoder, + aptosExtraDataDecoder: aptosDecoder, } } @@ -47,6 +50,7 @@ func NewExtraDataCodec(params ExtraDataCodecParams) RealExtraDataCodec { return RealExtraDataCodec{ EVMExtraDataDecoder: params.evmExtraDataDecoder, SolanaExtraDataDecoder: params.solanaExtraDataDecoder, + AptosExtraDataDecoder: params.aptosExtraDataDecoder, } } @@ -69,6 +73,9 @@ func (c RealExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceCha case chainsel.FamilySolana: return c.SolanaExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + case chainsel.FamilyAptos: + return c.AptosExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) } @@ -93,6 +100,9 @@ func (c RealExtraDataCodec) DecodeTokenAmountDestExecData(destExecData cciptypes case chainsel.FamilySolana: return c.SolanaExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + case chainsel.FamilyAptos: + return c.AptosExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) } From 8714c10fa038244f44c029329ca8365399e627a9 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:54 +0400 Subject: [PATCH 059/136] core/capabilities/ccip/oraclecreator/plugin.go: initialize extra data codec with Aptos decoder --- core/capabilities/ccip/oraclecreator/plugin.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index f510eb6cce0..336b5f89541 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" @@ -59,6 +60,7 @@ var extraDataCodec = ccipcommon.NewExtraDataCodec( ccipcommon.NewExtraDataCodecParams( ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, + ccipaptos.ExtraDataDecoder{}, ), ) From bfadb8b6d244789c48adb45cb49bbd73ad86381d Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:49:11 +0400 Subject: [PATCH 060/136] core/capabilities/ccip/ccipevm/msghasher_test.go: initialize extra data codec with Aptos decoder --- core/capabilities/ccip/ccipevm/msghasher_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go index 1dd329563dd..c5493a388a1 100644 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ b/core/capabilities/ccip/ccipevm/msghasher_test.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" @@ -39,7 +40,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) +var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) // NOTE: these test cases are only EVM <-> EVM. // Update these cases once we have non-EVM examples. From 0b92aa2d7d2f58e76c21c8cc856130518a5bbcd9 Mon Sep 17 00:00:00 2001 From: cfal Date: Thu, 27 Feb 2025 15:03:30 +0400 Subject: [PATCH 061/136] .changeset/warm-toys-give.md: add changeset --- .changeset/warm-toys-give.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/warm-toys-give.md diff --git a/.changeset/warm-toys-give.md b/.changeset/warm-toys-give.md new file mode 100644 index 00000000000..32417a44c80 --- /dev/null +++ b/.changeset/warm-toys-give.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +add support for Aptos CCIP #added + From 369558e27bbe97d55a23e24651e41b90f9eb1d7b Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 16 Apr 2025 01:24:00 +0400 Subject: [PATCH 062/136] core/capabilities/ccip/ccipaptos: update for contract changes, dont depend on generated bindings --- .../ccip/ccipaptos/commitcodec.go | 38 +++- .../ccip/ccipaptos/executecodec_test.go | 39 ++-- .../ccip/ccipaptos/extradatadecoder.go | 181 +++++++++++------- .../ccip/ccipaptos/extradatadecoder_test.go | 106 +++++++--- 4 files changed, 243 insertions(+), 121 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go index 0fc28059a38..8dbd9f4550e 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -3,6 +3,7 @@ package ccipaptos import ( "context" "fmt" + "math/big" "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" @@ -14,6 +15,8 @@ import ( // Compatible with ccip::offramp version 1.6.0 type CommitPluginCodecV1 struct{} +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) + func NewCommitPluginCodecV1() *CommitPluginCodecV1 { return &CommitPluginCodecV1{} } @@ -28,14 +31,22 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi return } s.Struct(&sourceToken) - s.U256(*item.Price.Int) + if item.Price.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.Price.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) } bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { s.U64(uint64(item.ChainSel)) - s.U256(*item.GasPrice.Int) + if item.GasPrice.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.GasPrice.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) @@ -86,7 +97,19 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.Price = cciptypes.NewBigInt(&price) + + // we need this clause because the zero token price test fails otherwise: + // - abs: (big.nat) + // + abs: (big.nat) { + // + } + // the reason is because big.NewInt(0) ends up not setting the `abs` field at all, while big.NewInt().SetBytes(..) will + // set the `abs` value to 0. + // ref: https://cs.opensource.google/go/go/+/master:src/math/big/int.go;drc=432fd9c60fac4485d0473173171206f1ef558829;l=85 + if price.Sign() == 0 { + item.Price = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.Price = cciptypes.NewBigInt(&price) + } }) if des.Error() != nil { @@ -102,7 +125,11 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.GasPrice = cciptypes.NewBigInt(&gasPrice) + if gasPrice.Sign() == 0 { + item.GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + } }) if des.Error() != nil { return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) @@ -163,6 +190,3 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype return report, nil } - -// Ensure CommitPluginCodec implements the CommitPluginCodec interface -var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index f4500ef679a..0bd3b19d4bf 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -12,7 +12,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-integrations/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -30,7 +29,8 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) for z := 0; z < numTokensPerMsg; z++ { - encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + // Use the predefined ABI arguments to pack destGasAmount + encodedDestExecData, err2 := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err2) tokenAmounts[z] = cciptypes.RampTokenAmount{ @@ -42,13 +42,12 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big } } - extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - if err != nil { - t.Fatalf("failed to pack extra args: %v", err) - } - extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + // Use the predefined ABI arguments to pack EVM V1 fields + encodedExtraArgsFields, err := evmExtraArgsV1Fields.Pack(gasLimit) + require.NoError(t, err, "failed to pack extra args fields") + + // Prepend the tag + extraArgs := append(evmExtraArgsV1Tag, encodedExtraArgsFields...) reportMessages[j] = cciptypes.Message{ Header: cciptypes.RampMessageHeader{ @@ -92,12 +91,15 @@ func TestExecutePluginCodecV1(t *testing.T) { mockExtraDataCodec := &mocks.ExtraDataCodec{} destGasAmount := rand.Uint32() gasLimit := utils.RandUint256() + + // Update mock return values to use the correct keys expected by the codec + // The codec uses the ExtraDataDecoder internally, which returns maps like these. mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ - "destgasamount": destGasAmount, + aptosDestExecDataKey: destGasAmount, // Use the constant defined in the decoder }, nil) mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ - "gasLimit": utils.RandUint256(), - "accountIsWritableBitmap": gasLimit, + "gasLimit": gasLimit, // Match the key used in the decoder for EVM V1/V2 gasLimit + // "allowOutOfOrderExecution": false, // Optionally mock other fields if needed by codec logic }, nil) testCases := []struct { @@ -109,7 +111,7 @@ func TestExecutePluginCodecV1(t *testing.T) { gasLimit *big.Int }{ { - name: "base report", + name: "base report EVM chain", report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 5009297550715157269, // ETH mainnet chain selector @@ -117,7 +119,7 @@ func TestExecutePluginCodecV1(t *testing.T) { destGasAmount: destGasAmount, }, { - name: "base report", + name: "base report non-EVM chain", // Name updated for clarity report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 124615329519749607, // Solana mainnet chain selector @@ -131,7 +133,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -142,7 +144,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -151,6 +153,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { codec := NewExecutePluginCodecV1(mockExtraDataCodec) + // randomExecuteReport now uses the new encoding internally report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) if tc.expErr { @@ -159,7 +162,7 @@ func TestExecutePluginCodecV1(t *testing.T) { } require.NoError(t, err) - // ignore unavailable fields in comparison + // ignore unavailable fields in comparison - This part remains the same for i := range report.ChainReports { for j := range report.ChainReports[i].Messages { report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} @@ -173,7 +176,7 @@ func TestExecutePluginCodecV1(t *testing.T) { // decode using the codec codecDecoded, err := codec.Decode(ctx, bytes) require.NoError(t, err) - require.Equal(t, report, codecDecoded) + require.Equal(t, report, codecDecoded) // Comparison should still work }) } } diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go index 5c600f266bd..2f59d9bed17 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -2,28 +2,25 @@ package ccipaptos import ( "fmt" - "reflect" + "math/big" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) // ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder // Compatible with ccip::fee_quoter version 1.6.0 type ExtraDataDecoder struct{} +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) + const ( aptosDestExecDataKey = "destGasAmount" ) -var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) - var ( // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") @@ -33,18 +30,71 @@ var ( // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") + + uint32Type = mustNewType("uint32") + uint64Type = mustNewType("uint64") + uint256Type = mustNewType("uint256") + boolType = mustNewType("bool") + bytes32Type = mustNewType("bytes32") + bytes32ArrType = mustNewType("bytes32[]") + + // Arguments for decoding destGasAmount + destGasAmountArguments = abi.Arguments{ + {Name: aptosDestExecDataKey, Type: uint32Type}, + } + + // Arguments matching the fields of EVMExtraArgsV1 struct + evmExtraArgsV1Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + } + + // Arguments matching the fields of GenericExtraArgsV2 struct + genericExtraArgsV2Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + } + + // Arguments matching the fields of SVMExtraArgsV1 struct + svmExtraArgsV1Fields = abi.Arguments{ + {Name: "computeUnits", Type: uint32Type}, + {Name: "accountIsWritableBitmap", Type: uint64Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + {Name: "tokenReceiver", Type: bytes32Type}, + {Name: "accounts", Type: bytes32ArrType}, + } ) +func mustNewType(typeStr string) abi.Type { + t, err := abi.NewType(typeStr, "", nil) + if err != nil { + panic(fmt.Sprintf("failed to create ABI type %s: %v", typeStr, err)) + } + return t +} + // DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { - destGasAmount, err := abiDecodeUint32(destExecData) + args := make(map[string]any) + err := destGasAmountArguments.UnpackIntoMap(args, destExecData) if err != nil { + if len(destExecData) != 32 { + return nil, fmt.Errorf("decode dest gas amount: expected 32 bytes for uint32, got %d: %w", len(destExecData), err) + } + + var val big.Int + val.SetBytes(destExecData) + if val.Cmp(big.NewInt(0xFFFFFFFF)) > 0 { + return nil, fmt.Errorf("decode dest gas amount: value %s exceeds uint32 max: %w", val.String(), err) + } + return nil, fmt.Errorf("decode dest gas amount: %w", err) } - return map[string]any{ - aptosDestExecDataKey: destGasAmount, - }, nil + if _, ok := args[aptosDestExecDataKey]; !ok { + return nil, fmt.Errorf("failed to unpack key '%s' for dest gas amount", aptosDestExecDataKey) + } + + return args, nil } // DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args @@ -53,98 +103,99 @@ func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[s return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) } - var method string - var argName string - switch string(extraArgs[:4]) { + var decoderArgs abi.Arguments + tag := string(extraArgs[:4]) + argsData := extraArgs[4:] + + switch tag { case string(evmExtraArgsV1Tag): - method = "exposeEVMExtraArgsV1" - argName = "evmExtraArgsV1" + decoderArgs = evmExtraArgsV1Fields case string(genericExtraArgsV2Tag): - method = "exposeGenericExtraArgsV2" - argName = "evmExtraArgsV2" + decoderArgs = genericExtraArgsV2Fields case string(svmExtraArgsV1Tag): - method = "exposeSVMExtraArgsV1" - argName = "svmExtraArgsV1" + decoderArgs = svmExtraArgsV1Fields default: - return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs[:4]) } - output := make(map[string]any) - args := make(map[string]any) - err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + unpackedArgs := make(map[string]any) + err := decoderArgs.UnpackIntoMap(unpackedArgs, argsData) if err != nil { - return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + return nil, fmt.Errorf("abi decode extra args (tag %x): %w", extraArgs[:4], err) } - argValue, exists := args[argName] - if !exists { - return nil, fmt.Errorf("failed to get arg value for %s", argName) - } - - val := reflect.ValueOf(argValue) - if val.Kind() != reflect.Struct { - return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) - } + output := make(map[string]any) - switch argName { - case "evmExtraArgsV1": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + switch tag { + case string(evmExtraArgsV1Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in EVMExtraArgsV1: %T", unpackedArgs["gasLimit"]) } else { - output["gasLimit"] = nil + output["gasLimit"] = nil // Field not present or nil } - case "evmExtraArgsV2": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + + case string(genericExtraArgsV2Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in GenericExtraArgsV2: %T", unpackedArgs["gasLimit"]) } else { output["gasLimit"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in GenericExtraArgsV2: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { + // Default to false if not present, consistent with original code. + // Note: ABI decoding of bool usually doesn't result in nil, but checking doesn't hurt. output["allowOutOfOrderExecution"] = false } - case "svmExtraArgsV1": - computeUnitsField := val.FieldByName("ComputeUnits") - if computeUnitsField.IsValid() { - output["computeUnits"] = computeUnitsField.Interface() + + case string(svmExtraArgsV1Tag): + if computeUnits, ok := unpackedArgs["computeUnits"].(uint32); ok { + output["computeUnits"] = computeUnits + } else if unpackedArgs["computeUnits"] != nil { + return nil, fmt.Errorf("unexpected type for computeUnits in SVMExtraArgsV1: %T", unpackedArgs["computeUnits"]) } else { output["computeUnits"] = nil } - bitmapField := val.FieldByName("AccountIsWritableBitmap") - if bitmapField.IsValid() { - output["accountIsWritableBitmap"] = bitmapField.Interface() + if bitmap, ok := unpackedArgs["accountIsWritableBitmap"].(uint64); ok { + output["accountIsWritableBitmap"] = bitmap + } else if unpackedArgs["accountIsWritableBitmap"] != nil { + return nil, fmt.Errorf("unexpected type for accountIsWritableBitmap in SVMExtraArgsV1: %T", unpackedArgs["accountIsWritableBitmap"]) } else { output["accountIsWritableBitmap"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in SVMExtraArgsV1: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { output["allowOutOfOrderExecution"] = false } - tokenReceiverField := val.FieldByName("TokenReceiver") - if tokenReceiverField.IsValid() { - output["tokenReceiver"] = tokenReceiverField.Interface() + if tokenReceiver, ok := unpackedArgs["tokenReceiver"].([32]byte); ok { + output["tokenReceiver"] = tokenReceiver + } else if unpackedArgs["tokenReceiver"] != nil { + return nil, fmt.Errorf("unexpected type for tokenReceiver in SVMExtraArgsV1: %T", unpackedArgs["tokenReceiver"]) } else { output["tokenReceiver"] = nil } - accountsField := val.FieldByName("Accounts") - if accountsField.IsValid() { - output["accounts"] = accountsField.Interface() + if accounts, ok := unpackedArgs["accounts"].([][32]byte); ok { + output["accounts"] = accounts + } else if unpackedArgs["accounts"] != nil { + return nil, fmt.Errorf("unexpected type for accounts in SVMExtraArgsV1: %T", unpackedArgs["accounts"]) } else { output["accounts"] = nil } } + return output, nil } - -var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go index 234d2f29981..d8188010362 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -5,10 +5,9 @@ import ( "math/rand" "testing" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) func Test_decodeExtraData(t *testing.T) { @@ -16,40 +15,38 @@ func Test_decodeExtraData(t *testing.T) { extraDataDecoder := &ExtraDataDecoder{} t.Run("decode extra args into map evm v1", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + encodedFields, err := evmExtraArgsV1Fields.Pack(gasLimit) require.NoError(t, err) + encoded := append(evmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp for big.Int comparison }) t.Run("decode extra args into map evm v2", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ - GasLimit: gasLimit, - AllowOutOfOrderExecution: true, - }) - encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + allowOoe := true + encodedFields, err := genericExtraArgsV2Fields.Pack(gasLimit, allowOoe) require.NoError(t, err) + encoded := append(genericExtraArgsV2Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 2) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp - ooe, exist := m["allowOutOfOrderExecution"] + ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, true, ooe) + require.Equal(t, allowOoe, ooeDecoded) // Check boolean directly }) t.Run("decode extra args into map svm", func(t *testing.T) { @@ -59,52 +56,99 @@ func Test_decodeExtraData(t *testing.T) { bitmap := uint64(4) ooe := false tokenReceiver := [32]byte(key.PublicKey().Bytes()) - accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} - encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ - ComputeUnits: cu, - AccountIsWritableBitmap: bitmap, - AllowOutOfOrderExecution: ooe, - TokenReceiver: tokenReceiver, - Accounts: accounts, - }) - encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} // Example with one account + + encodedFields, err := svmExtraArgsV1Fields.Pack( + cu, + bitmap, + ooe, + tokenReceiver, + accounts, + ) require.NoError(t, err) + encoded := append(svmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 5) cuDecoded, exist := m["computeUnits"] require.True(t, exist) - require.Equal(t, cuDecoded, cu) + require.Equal(t, cu, cuDecoded) bitmapDecoded, exist := m["accountIsWritableBitmap"] require.True(t, exist) - require.Equal(t, bitmapDecoded, bitmap) + require.Equal(t, bitmap, bitmapDecoded) ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, ooeDecoded, ooe) + require.Equal(t, ooe, ooeDecoded) tokenReceiverDecoded, exist := m["tokenReceiver"] require.True(t, exist) - require.Equal(t, tokenReceiverDecoded, tokenReceiver) + require.Equal(t, tokenReceiver, tokenReceiverDecoded.([32]byte)) accountsDecoded, exist := m["accounts"] require.True(t, exist) - require.Equal(t, accountsDecoded, accounts) + require.Equal(t, accounts, accountsDecoded.([][32]byte)) }) t.Run("decode dest exec data into map", func(t *testing.T) { destGasAmount := uint32(10000) - encoded, err := abiEncodeUint32(destGasAmount) + encoded, err := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) decoded, exist := m[aptosDestExecDataKey] require.True(t, exist) - require.Equal(t, destGasAmount, decoded) + require.Equal(t, destGasAmount, decoded.(uint32)) // Type assert and compare uint32 + }) + + t.Run("error on short extra args", func(t *testing.T) { + shortData := evmExtraArgsV1Tag[:2] // Less than 4 bytes + _, err := extraDataDecoder.DecodeExtraArgsToMap(shortData) + require.Error(t, err) + require.Contains(t, err.Error(), "extra args too short") + }) + + t.Run("error on unknown tag", func(t *testing.T) { + unknownTag := []byte{0xde, 0xad, 0xbe, 0xef} + dummyData, err := evmExtraArgsV1Fields.Pack(big.NewInt(1)) + require.NoError(t, err) + dataWithUnknownTag := append(unknownTag, dummyData...) + _, err = extraDataDecoder.DecodeExtraArgsToMap(dataWithUnknownTag) + require.Error(t, err) + require.Contains(t, err.Error(), "unknown extra args tag") + }) + + t.Run("error on malformed evm v1 data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint256 + encoded := append(evmExtraArgsV1Tag, malformedData...) + _, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.Error(t, err) + require.Contains(t, err.Error(), "abi decode extra args") + }) + + t.Run("error on malformed dest exec data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint32 (expects 32 bytes) + _, err := extraDataDecoder.DecodeDestExecDataToMap(malformedData) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "expected 32 bytes for uint32") + }) + + t.Run("error on dest exec data exceeding uint32 max", func(t *testing.T) { + tooLargeValue := new(big.Int).Lsh(big.NewInt(1), 32) + encodedTooLarge, err := abi.Arguments{{Type: uint256Type}}.Pack(tooLargeValue) // Pack as uint256 + require.NoError(t, err) + + _, err = extraDataDecoder.DecodeDestExecDataToMap(encodedTooLarge) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "exceeds uint32 max") }) } From 2189ddaba1cf028288dca4c171584a27a5495002 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:19:21 +0400 Subject: [PATCH 063/136] core/capabilities/ccip/configs/aptos: add ccip CW/CR configs --- .../ccip/configs/aptos/chain_writer.go | 70 ++++++ .../ccip/configs/aptos/contract_reader.go | 231 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 core/capabilities/ccip/configs/aptos/chain_writer.go create mode 100644 core/capabilities/ccip/configs/aptos/contract_reader.go diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go new file mode 100644 index 00000000000..061672baac9 --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -0,0 +1,70 @@ +package aptosconfig + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-aptos/relayer/chainwriter" + "github.com/smartcontractkit/chainlink-aptos/relayer/utils" +) + +func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, error) { + fromAddress, err := utils.HexPublicKeyToAddress(publicKeyStr) + if err != nil { + return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) + } + + fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) + + return chainwriter.ChainWriterConfig{ + Modules: map[string]*chainwriter.ChainWriterModule{ + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainwriter.ChainWriterFunction{ + consts.MethodCommit: { + Name: "commit", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + { + Name: "Signatures", + Type: "vector>", + Required: true, + }, + }, + }, + consts.MethodExecute: { + Name: "execute", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + }, + }, + }, + }, + }, + FeeStrategy: chainwriter.DefaultFeeStrategy, + }, nil +} diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go new file mode 100644 index 00000000000..016d593239d --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -0,0 +1,231 @@ +package aptosconfig + +import ( + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" +) + +func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { + return chainreader.ChainReaderConfig{ + IsLoopPlugin: true, + Modules: map[string]*chainreader.ChainReaderModule{ + // TODO: more offramp config and other modules + consts.ContractNameRMNRemote: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetReportDigestHeader: { + Name: "get_report_digest_header", + }, + consts.MethodNameGetVersionedConfig: { + Name: "get_versioned_config", + // ref: https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L1440 + ResultTupleToStruct: []string{"version", "config"}, + }, + consts.MethodNameGetCursedSubjects: { + Name: "get_cursed_subjects", + }, + }, + }, + + consts.ContractNameRMNProxy: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetARM: { + Name: "get_arm", + }, + }, + }, + + consts.ContractNameFeeQuoter: { + Name: "fee_quoter", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameFeeQuoterGetTokenPrice: { + Name: "get_token_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "token", + Type: "address", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetTokenPrices: { + Name: "get_token_prices", + Params: []chainreader.AptosFunctionParam{ + { + Name: "tokens", + Type: "vector
", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetStaticConfig: { + Name: "get_static_config", + }, + }, + }, + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetExecutionState: { + Name: "get_execution_state", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + { + Name: "sequenceNumber", + Type: "u64", + Required: true, + }, + }, + }, + consts.MethodNameGetMerkleRoot: { + Name: "get_merkle_root", + Params: []chainreader.AptosFunctionParam{ + { + Name: "root", + Type: "vector", + Required: true, + }, + }, + }, + consts.MethodNameOffRampLatestConfigDetails: { + Name: "latest_config_details", + Params: []chainreader.AptosFunctionParam{ + { + Name: "ocrPluginType", + Type: "u8", + Required: true, + }, + }, + // wrap the returned OCR config + // https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L141 + ResultTupleToStruct: []string{"ocr_config"}, + }, + consts.MethodNameGetLatestPriceSequenceNumber: { + Name: "get_latest_price_sequence_number", + }, + consts.MethodNameOffRampGetStaticConfig: { + Name: "get_static_config", + // TODO: field renames + }, + consts.MethodNameOffRampGetDynamicConfig: { + Name: "get_dynamic_config", + // TODO: field renames + }, + consts.MethodNameGetSourceChainConfig: { + Name: "get_source_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameExecutionStateChanged: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "execution_state_changed_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageId", + }, + "message_hash": { + NewName: "MessageHash", + }, + "state": { + NewName: "State", + }, + }, + }, + consts.EventNameCommitReportAccepted: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "commit_report_accepted_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "blessed_merkle_roots": { + NewName: "BlessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "unblessed_merkle_roots": { + NewName: "UnblessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "price_updates": { + NewName: "PriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "token_price_updates": { + NewName: "TokenPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_token": { + NewName: "SourceToken", + }, + "usd_per_token": { + NewName: "UsdPerToken", + }, + }, + }, + "gas_price_updates": { + NewName: "GasPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "usd_per_unit_gas": { + NewName: "UsdPerUnitGas", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, nil +} From a8ea6e676a305c1232afc2109e03c8dfc6b91561 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:21:50 +0400 Subject: [PATCH 064/136] core/services/keystore/keys/ocr2key/aptos_keyring.go: implement Sign3 and Verify3 --- .../keystore/keys/ocr2key/aptos_keyring.go | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/services/keystore/keys/ocr2key/aptos_keyring.go b/core/services/keystore/keys/ocr2key/aptos_keyring.go index 154f6ea3d2a..393ddd4eb5a 100644 --- a/core/services/keystore/keys/ocr2key/aptos_keyring.go +++ b/core/services/keystore/keys/ocr2key/aptos_keyring.go @@ -56,8 +56,24 @@ func (akr *aptosKeyring) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes. return akr.SignBlob(sigData) } +func (ekr *aptosKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) ([]byte, error) { + rawReportContext := RawReportContext3(digest, seqNr) + h, err := blake2b.New256(nil) + if err != nil { + return nil, err + } + h.Write(r) + h.Write(rawReportContext[0][:]) + h.Write(rawReportContext[1][:]) + return h.Sum(nil), nil +} + func (akr *aptosKeyring) Sign3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) { - return nil, errors.New("not implemented") + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return nil, err + } + return akr.SignBlob(sigData) } func (akr *aptosKeyring) SignBlob(b []byte) ([]byte, error) { @@ -74,8 +90,12 @@ func (akr *aptosKeyring) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx o return akr.VerifyBlob(publicKey, hash, signature) } -func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { - return false +func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, digest ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return false + } + return akr.VerifyBlob(publicKey, sigData, signature) } func (akr *aptosKeyring) VerifyBlob(pubkey ocrtypes.OnchainPublicKey, b, sig []byte) bool { From af6cf8769b09ce4df1405b20550b91e8c40295a0 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:30:05 +0400 Subject: [PATCH 065/136] core/capabilities/ccip/ocrimpls/config_tracker.go: dont use address codec for Aptos --- core/capabilities/ccip/ocrimpls/config_tracker.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/config_tracker.go b/core/capabilities/ccip/ocrimpls/config_tracker.go index 9619b0824cd..0500eb05a46 100644 --- a/core/capabilities/ccip/ocrimpls/config_tracker.go +++ b/core/capabilities/ccip/ocrimpls/config_tracker.go @@ -2,9 +2,11 @@ package ocrimpls import ( "context" + "encoding/hex" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -77,6 +79,13 @@ func toOnchainPublicKeys(signers [][]byte) []types.OnchainPublicKey { func toOCRAccounts(transmitters [][]byte, addressCodec ccipocr3.AddressCodec, chainSelector ccipocr3.ChainSelector) []types.Account { accounts := make([]types.Account, len(transmitters)) for i, transmitter := range transmitters { + family, _ := chainsel.GetSelectorFamily(uint64(chainSelector)) + // Aptos transmitter accounts do not go through the address codec, because they are ed25519 public keys. + if family == chainsel.FamilyAptos { + s := hex.EncodeToString(transmitter) + accounts[i] = types.Account(s) + continue + } address, _ := addressCodec.AddressBytesToString(transmitter, chainSelector) accounts[i] = types.Account(address) } From 46f8bc4cb3e8d9bcaf33a2cace5edf344269b813 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:43:57 +0400 Subject: [PATCH 066/136] core/capabilities/ccip/ocrimpls/contract_transmitter.go: support ed25519 signatures --- .../ccip/ocrimpls/contract_transmitter.go | 79 +++++++++++++------ 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 8dda409f3f3..24e9de74e38 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -31,15 +31,22 @@ type ToCalldataFunc func( codec ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) +type ToEd25519CalldataFunc func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + codec ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) + var _ ocr3types.ContractTransmitter[[]byte] = &ccipTransmitter{} type ccipTransmitter struct { - cw commontypes.ContractWriter - fromAccount ocrtypes.Account - offrampAddress string - toCalldataFn ToCalldataFunc - extraDataCodec ccipcommon.ExtraDataCodec - lggr logger.Logger + cw commontypes.ContractWriter + fromAccount ocrtypes.Account + offrampAddress string + toCalldataFn ToCalldataFunc + toEd25519CalldataFn ToEd25519CalldataFunc + extraDataCodec ccipcommon.ExtraDataCodec } func XXXNewContractTransmitterTestsOnly( @@ -81,35 +88,57 @@ func (c *ccipTransmitter) Transmit( reportWithInfo ocr3types.ReportWithInfo[[]byte], sigs []ocrtypes.AttributedOnchainSignature, ) error { - var rs [][32]byte - var ss [][32]byte - var vs [32]byte if len(sigs) > 32 { return errors.New("too many signatures, maximum is 32") } - for i, as := range sigs { - r, s, v, err := evmutil.SplitSignature(as.Signature) - if err != nil { - return fmt.Errorf("failed to split signature: %w", err) - } - rs = append(rs, r) - ss = append(ss, s) - vs[i] = v - } // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) - if c.toCalldataFn == nil { - return errors.New("toCalldataFn is nil") - } + var contract string + var method string + var args any + var err error + + if c.toCalldataFn != nil { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + for i, as := range sigs { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + return fmt.Errorf("failed to split signature: %w", err) + } + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } - // chain writer takes in the raw calldata and packs it on its own. - contract, method, args, err := c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) - if err != nil { - return fmt.Errorf("failed to generate call data: %w", err) + // chain writer takes in the raw calldata and packs it on its own. + contract, method, args, err = c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ecdsa call data: %w", err) + } + } else if c.toEd25519CalldataFn != nil { + var signatures [][96]byte + for _, as := range sigs { + sig := as.Signature + if len(sig) != 96 { + return fmt.Errorf("invalid ed25519 signature length, expected 96, got %d", len(sig)) + } + var sigBytes [96]byte + copy(sigBytes[:], sig) + signatures = append(signatures, sigBytes) + } + + contract, method, args, err = c.toEd25519CalldataFn(rawReportCtx, reportWithInfo, signatures, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ed25519 call data: %w", err) + } + } else { + return errors.New("no calldata function") } // TODO: no meta fields yet, what should we add? From abd7c9d6b633aeaec53ecaab822d27d6bf2172b2 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:50:36 +0400 Subject: [PATCH 067/136] core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go: add --- .../aptos_contract_transmitter_factory.go | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go new file mode 100644 index 00000000000..f6c2e729263 --- /dev/null +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -0,0 +1,96 @@ +package ocrimpls + +import ( + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. +type AptosCommitCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` + Signatures [][96]byte `mapstructure:"Signatures"` +} + +// AptosExecCallArgs defines the calldata structure for an Aptos execute transaction. +type AptosExecCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` +} + +// AptosContractTransmitterFactory implements the transmitter factory for Aptos chains. +type AptosContractTransmitterFactory struct{} + +// NewAptosCommitCalldataFunc returns a ToCalldataFunc for Aptos commits that omits any Info object. +func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { + return func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, + ) (string, string, any, error) { + return consts.ContractNameOffRamp, + commitMethod, + AptosCommitCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + Signatures: signatures, + }, + nil + } +} + +// NewCommitTransmitter constructs an Aptos commit transmitter. +func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, + commitMethod, _ string, // priceOnlyMethod is ignored for Aptos +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: NewAptosCommitCalldataFunc(commitMethod), + } +} + +// AptosExecCallDataFunc builds the execute call data for Aptos +var AptosExecCallDataFunc = func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) { + return consts.ContractNameOffRamp, + consts.MethodExecute, + AptosExecCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + }, nil +} + +// NewExecTransmitter constructs an Aptos execute transmitter. +func (f *AptosContractTransmitterFactory) NewExecTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: AptosExecCallDataFunc, + extraDataCodec: ccipcommon.NewExtraDataCodec( + ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), + ), + } +} From 41872b4aec0114a63b03e0ee7e5a10b5bcf267f6 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:53:01 +0400 Subject: [PATCH 068/136] core/capabilities/ccip/oraclecreator/plugin.go: support Aptos --- .../capabilities/ccip/oraclecreator/plugin.go | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 336b5f89541..f9b943977cd 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -26,9 +26,11 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + aptosconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/aptos" solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" + aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" @@ -88,6 +90,18 @@ var plugins = map[string]plugin{ PriceOnlyCommitFn: consts.MethodCommitPriceOnly, ContractTransmitterFactory: &ocrimpls.SVMContractTransmitterFactory{}, }, + chainsel.FamilyAptos: { + CommitPluginCodec: ccipaptos.NewCommitPluginCodecV1(), + ExecutePluginCodec: ccipaptos.NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: func(lggr logger.Logger) cciptypes.MessageHasher { + return ccipaptos.NewMessageHasherV1(lggr, extraDataCodec) + }, + TokenDataEncoder: ccipaptos.NewAptosTokenDataEncoder(), + GasEstimateProvider: ccipaptos.NewGasEstimateProvider(), + RMNCrypto: func(lggr logger.Logger) cciptypes.RMNCrypto { return nil }, + PriceOnlyCommitFn: consts.MethodCommitPriceOnly, + ContractTransmitterFactory: &ocrimpls.AptosContractTransmitterFactory{}, + }, } const ( @@ -466,6 +480,10 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } + if relayChainFamily == relay.NetworkAptos { + cr = aptosloop.NewLoopChainReader(i.lggr, cr) + } + if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ @@ -597,6 +615,18 @@ func getChainReaderConfig( } return marshaledConfig, nil + + case relay.NetworkAptos: + cfg, err := aptosconfig.GetChainReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain reader config: %w", err) + } + marshaledConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) + } + return marshaledConfig, nil + default: return nil, fmt.Errorf("unsupported chain family %s", chainFamily) } @@ -653,6 +683,14 @@ func createChainWriter( if chainWriterConfig, err = json.Marshal(evmConfig); err != nil { return nil, fmt.Errorf("failed to marshal EVM chain writer config: %w", err) } + case relay.NetworkAptos: + cfg, err := aptosconfig.GetChainWriterConfig(transmitter[0]) + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain writer config: %w", err) + } + if chainWriterConfig, err = json.Marshal(cfg); err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain writer config: %w", err) + } default: return nil, fmt.Errorf("unknown chain family %s", chainFamily) } From 6d0043b35862787906df60f3f00bfabf152de4fd Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 03:02:22 +0400 Subject: [PATCH 069/136] core/capabilities/ccip/oraclecreator/plugin.go: refactor into createChainReader function --- .../capabilities/ccip/oraclecreator/plugin.go | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index f9b943977cd..21727297ebf 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -470,20 +470,11 @@ func (i *pluginOracleCreator) createReadersAndWriters( continue } - chainReaderConfig, err1 := getChainReaderConfig(i.lggr, chainID, destChainID, homeChainID, ofc, chainSelector, relayChainFamily) + cr, err1 := createChainReader(ctx, i.lggr, relayer, chainID, destChainID, homeChainID, ofc, chainSelector, relayChainFamily) if err1 != nil { return nil, nil, fmt.Errorf("failed to get chain reader config: %w", err1) } - cr, err1 := relayer.NewContractReader(ctx, chainReaderConfig) - if err1 != nil { - return nil, nil, err1 - } - - if relayChainFamily == relay.NetworkAptos { - cr = aptosloop.NewLoopChainReader(i.lggr, cr) - } - if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ @@ -554,15 +545,17 @@ func decodeAndValidateOffchainConfig( return ofc, nil } -func getChainReaderConfig( +func createChainReader( + ctx context.Context, lggr logger.Logger, + relayer loop.Relayer, chainID string, destChainID string, homeChainID string, ofc offChainConfig, chainSelector cciptypes.ChainSelector, chainFamily string, -) ([]byte, error) { +) (types.ContractReader, error) { // TODO: create a chain writer constructor interface and define family specific implementations in oraclecreator.plugin switch chainFamily { case relay.NetworkEVM: @@ -593,7 +586,12 @@ func getChainReaderConfig( return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) } - return marshaledConfig, nil + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + return cr, nil case relay.NetworkSolana: var err error var cfg config.ContractReader @@ -614,7 +612,12 @@ func getChainReaderConfig( return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) } - return marshaledConfig, nil + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + return cr, nil case relay.NetworkAptos: cfg, err := aptosconfig.GetChainReaderConfig() @@ -625,7 +628,16 @@ func getChainReaderConfig( if err != nil { return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) } - return marshaledConfig, nil + + cr, err := relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain reader: %w", err) + } + + // wrap the chain reader for LOOP specific behavior + cr = aptosloop.NewLoopChainReader(lggr, cr) + + return cr, nil default: return nil, fmt.Errorf("unsupported chain family %s", chainFamily) From 40709a4da23d679fcc08de62b27e6e461ac25e4f Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:56:17 +0400 Subject: [PATCH 070/136] core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go: add aptos for extra data codec --- .../ccip/ocrimpls/svm_contract_transmitter_factory.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go index 53614f44f28..abb9e495957 100644 --- a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -179,7 +180,7 @@ func (f *SVMContractTransmitterFactory) NewExecTransmitter( offrampAddress: offrampAddress, toCalldataFn: SVMExecCalldataFunc, extraDataCodec: ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}), + ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), ), } } From 5bb5d439a8e0d95220c32b16c285f18783fa10fb Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 22 Apr 2025 19:12:49 +0400 Subject: [PATCH 071/136] core/capabilities/ccip/ccipaptos: update chainlink-integrations refs --- core/capabilities/ccip/ccipaptos/commitcodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/executecodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/msghasher.go | 2 +- core/capabilities/ccip/ccipaptos/utils.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go index 3f05cb75d52..ccc24d18a22 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec_test.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -11,7 +11,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index 0bd3b19d4bf..5773e707a4c 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go index 995e7e0112e..73f18d4e6dc 100644 --- a/core/capabilities/ccip/ccipaptos/msghasher.go +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) var ( diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go index 5488f3903d2..f9610cb75c3 100644 --- a/core/capabilities/ccip/ccipaptos/utils.go +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) func abiEncodeUint32(data uint32) ([]byte, error) { From 241f2a5dd21a594e62d7be68acda7139fe1fa2fe Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 19:46:07 +0400 Subject: [PATCH 072/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add CCIPMessageSent --- core/capabilities/ccip/configs/aptos/contract_reader.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 016d593239d..58fc435fd1c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -128,6 +128,11 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", From 5972342f8f691617e84d8d07297e0fc269a6144c Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 20:22:13 +0400 Subject: [PATCH 073/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add get_dest_chain_gas_price --- .../capabilities/ccip/configs/aptos/contract_reader.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 58fc435fd1c..e6a97e2171d 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -62,6 +62,16 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { consts.MethodNameFeeQuoterGetStaticConfig: { Name: "get_static_config", }, + consts.MethodNameGetFeePriceUpdate: { + Name: "get_dest_chain_gas_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, }, }, consts.ContractNameOffRamp: { From 5b37055a1d073337fcc99d74eca2a11cbdd3a037 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:46:10 +0200 Subject: [PATCH 074/136] Upading aptos plugin ref --- plugins/plugins.private.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 55f018827ce..be5dc524140 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,9 +9,9 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer" - gitRef: "2.21.0-beta16-aptos" - installPath: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer/cmd/chainlink-aptos" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" From daf6c209bb4db10ef4b19417b51c43e99b75a827 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:58:17 +0200 Subject: [PATCH 075/136] Adjusting aptos plugin ref to point to the chainlink-aptos as a whole --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index be5dc524140..b94d4fa7d5f 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,7 +9,7 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos" gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: From c872761114659da70c4ac9afdb11dfeb1abef21d Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 30 Apr 2025 19:50:32 +0200 Subject: [PATCH 076/136] Fixing merge conflict resolution (logger-related) --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 3 +++ core/capabilities/ccip/ocrimpls/contract_transmitter.go | 1 + 2 files changed, 4 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index f6c2e729263..1db95ffe7ab 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) // AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. @@ -50,6 +51,7 @@ func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { // NewCommitTransmitter constructs an Aptos commit transmitter. func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, @@ -80,6 +82,7 @@ var AptosExecCallDataFunc = func( // NewExecTransmitter constructs an Aptos execute transmitter. func (f *AptosContractTransmitterFactory) NewExecTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 24e9de74e38..09e79744290 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -47,6 +47,7 @@ type ccipTransmitter struct { toCalldataFn ToCalldataFunc toEd25519CalldataFn ToEd25519CalldataFunc extraDataCodec ccipcommon.ExtraDataCodec + lggr logger.Logger } func XXXNewContractTransmitterTestsOnly( From dcb5d7951e100b5221545a5e3bcca0a3dd474074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:30:51 +0200 Subject: [PATCH 077/136] Add OnRamp config --- .../ccip/configs/aptos/contract_reader.go | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index e6a97e2171d..4aa84dacf29 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -26,7 +26,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameRMNProxy: { Name: "rmn_remote", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -35,7 +34,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameFeeQuoter: { Name: "fee_quoter", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -138,11 +136,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ - consts.EventNameCCIPMessageSent: { - EventHandleStructName: "OnRampState", - EventHandleFieldName: "ccip_message_sent_events", - EventAccountAddress: "onramp::get_state_address", - }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", @@ -241,6 +234,45 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, + consts.ContractNameOnRamp: { + Name: "onramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameOnRampGetDynamicConfig: { + Name: "get_dynamic_config", + }, + consts.MethodNameOnRampGetStaticConfig: { + Name: "get_static_config", + }, + consts.MethodNameOnRampGetDestChainConfig: { + Name: "get_dest_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + ResultTupleToStruct: []string{"sequenceNumber", "allowListEnabled", "router"}, + }, + consts.MethodNameGetExpectedNextSequenceNumber: { + Name: "get_expected_next_sequence_number", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, + }, + }, }, }, nil } From e2e028bf0fd9e920acb195c7dc1b41ca5c710ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:31:05 +0200 Subject: [PATCH 078/136] Fix NewExtraDataCodecParams --- deployment/ccip/manualexechelpers/exec.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/deployment/ccip/manualexechelpers/exec.go b/deployment/ccip/manualexechelpers/exec.go index 173c0401321..f6bb76422db 100644 --- a/deployment/ccip/manualexechelpers/exec.go +++ b/deployment/ccip/manualexechelpers/exec.go @@ -12,17 +12,18 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm/manualexeclib" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) const ( @@ -551,7 +552,7 @@ func ManuallyExecuteAll( stepDuration time.Duration, reExecuteIfFailed bool, ) error { - extraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{})) + extraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) // for large backfills, these caches can speed things up because we don't need to query // the chain multiple times for the same root/messages. From 8eafaff73f22adf313a8bf760996db9356693ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:43:54 +0200 Subject: [PATCH 079/136] Fix NewExtraDataCodecParams --- core/capabilities/ccip/ccipsolana/msghasher_test.go | 3 ++- core/capabilities/ccip/ocrimpls/contract_transmitter_test.go | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/ccipsolana/msghasher_test.go b/core/capabilities/ccip/ccipsolana/msghasher_test.go index 0eb7ce44193..2d5087f7481 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher_test.go +++ b/core/capabilities/ccip/ccipsolana/msghasher_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" @@ -28,7 +29,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ExtraDataDecoder{})) +var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) func TestMessageHasher_EVM2SVM(t *testing.T) { any2AnyMsg, any2SolanaMsg, msgAccounts := createEVM2SolanaMessages(t) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 591ada5cb9d..5b63341b8f3 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -36,6 +36,7 @@ import ( evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" @@ -192,6 +193,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { ccipcommon.NewExtraDataCodecParams( ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, + ccipaptos.ExtraDataDecoder{}, ), ) t.Run("fails when multiple reports are included", func(t *testing.T) { From 7199d84fbb6be2d1945dd1d824e2a7769c26ced7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 15:17:03 +0200 Subject: [PATCH 080/136] Generate --- core/internal/mocks/flags.go | 2 +- core/internal/mocks/flux_aggregator.go | 2 +- .../ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go | 2 +- go.md | 4 ++++ 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/core/internal/mocks/flags.go b/core/internal/mocks/flags.go index 26c791eccfc..558c5d0c4b9 100644 --- a/core/internal/mocks/flags.go +++ b/core/internal/mocks/flags.go @@ -3,7 +3,7 @@ package mocks import ( - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/internal/mocks/flux_aggregator.go b/core/internal/mocks/flux_aggregator.go index d2c7ea3e216..5b61d7a34c6 100644 --- a/core/internal/mocks/flux_aggregator.go +++ b/core/internal/mocks/flux_aggregator.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go index 1c12e1eba81..daa676e23e3 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go @@ -5,7 +5,7 @@ package mock_contracts import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go index 2329746de1f..23fee609a78 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go index 7ff63e78229..1a80a1b8bc4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/go.md b/go.md index b8e62b5712f..77b34bfbdd6 100644 --- a/go.md +++ b/go.md @@ -24,6 +24,8 @@ flowchart LR chain-selectors click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" + chainlink-aptos --> chainlink-common + click chainlink-aptos href "https://github.com/smartcontractkit/chainlink-aptos" chainlink-automation --> chainlink-common click chainlink-automation href "https://github.com/smartcontractkit/chainlink-automation" chainlink-ccip --> chain-selectors @@ -70,6 +72,7 @@ flowchart LR click chainlink-solana href "https://github.com/smartcontractkit/chainlink-solana" chainlink-tron/relayer --> chainlink-evm click chainlink-tron/relayer href "https://github.com/smartcontractkit/chainlink-tron" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds @@ -249,6 +252,7 @@ flowchart LR chainlink/system-tests/tests --> chainlink-testing-framework/wasp chainlink/system-tests/tests --> chainlink/system-tests/lib click chainlink/system-tests/tests href "https://github.com/smartcontractkit/chainlink" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds From c3fecff58595dc308aa85850dbe8fe0e1768be93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 17:34:53 +0200 Subject: [PATCH 081/136] Fix logger --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index 1db95ffe7ab..855cc3a47f9 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -58,6 +58,7 @@ func (f *AptosContractTransmitterFactory) NewCommitTransmitter( commitMethod, _ string, // priceOnlyMethod is ignored for Aptos ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, @@ -88,6 +89,7 @@ func (f *AptosContractTransmitterFactory) NewExecTransmitter( offrampAddress string, ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, From bc7194158c299b519ce312272e779159f52fc091 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Thu, 1 May 2025 21:14:32 +0200 Subject: [PATCH 082/136] Bumping up chainlink-aptos plugin gitRef --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index b94d4fa7d5f..540c3c55398 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From 8deb72351761349fad8d4e782b5a18a21fda4b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 20:19:33 +0200 Subject: [PATCH 083/136] Add field renames to CCIPMessageSent event --- .../ccip/configs/aptos/chain_writer.go | 1 + .../ccip/configs/aptos/contract_reader.go | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go index 061672baac9..6594f0878a1 100644 --- a/core/capabilities/ccip/configs/aptos/chain_writer.go +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -16,6 +16,7 @@ func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, e return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) } + // TODO REMOVE fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) return chainwriter.ChainWriterConfig{ diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 4aa84dacf29..853b38aed3c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -270,6 +270,49 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { EventHandleStructName: "OnRampState", EventHandleFieldName: "ccip_message_sent_events", EventAccountAddress: "onramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + SubFieldRenames: nil, + }, + "sequence_number": { + NewName: "SequenceNumber", + SubFieldRenames: nil, + }, + "message": { + NewName: "Message", + SubFieldRenames: map[string]chainreader.RenamedField{ + "header": { + NewName: "Header", + }, + "sender": { + NewName: "Sender", + }, + "data": { + NewName: "Data", + }, + "receiver": { + NewName: "Receiver", + }, + "extra_args": { + NewName: "ExtraArgs", + }, + "fee_token": { + NewName: "FeeToken", + }, + "fee_token_amount": { + NewName: "FeeTokenAmount", + }, + "fee_value_juels": { + NewName: "FeeValueJuels", + }, + "token_amounts": { + NewName: "TokenAmounts", + SubFieldRenames: nil, // TODO + }, + }, + }, + }, }, }, }, From 6d5c55c7e5b76aa8b103de4802160c2c0ab73862 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:21:26 +0200 Subject: [PATCH 084/136] Temp chainlink-aptos version --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 540c3c55398..847dbbce46e 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" + gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From d7cfec92d32a915da7ad91e60b6d762fb1225f21 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:29:44 +0200 Subject: [PATCH 085/136] Fixing CCIPMessageSent event renamings --- .../ccip/configs/aptos/contract_reader.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 853b38aed3c..e4b89ca4ca2 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -284,6 +284,23 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { SubFieldRenames: map[string]chainreader.RenamedField{ "header": { NewName: "Header", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageID", + }, + "nonce": { + NewName: "Nonce", + }, + }, }, "sender": { NewName: "Sender", From 748a93ebf8a7f9f0a2c44224e78e1b3f504905bf Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:43:05 +0200 Subject: [PATCH 086/136] Fixing plugin build --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 847dbbce46e..4af36c2d159 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" + gitRef: "808b080f471d054ff623164b3a316759a8f18758" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From aa20978dff9008887a00c72c0e9c8826ea6fc6f5 Mon Sep 17 00:00:00 2001 From: cfal Date: Mon, 12 May 2025 20:03:19 +0400 Subject: [PATCH 087/136] add and update chainlink-aptos and aptos-go-sdk --- core/scripts/go.mod | 4 +-- core/scripts/go.sum | 8 +++--- deployment/go.mod | 4 +-- deployment/go.sum | 8 +++--- go.mod | 10 +++++--- go.sum | 48 +++++++++++++++++++++++++++++------ integration-tests/go.mod | 4 +-- integration-tests/go.sum | 8 +++--- integration-tests/load/go.mod | 4 +-- integration-tests/load/go.sum | 8 +++--- system-tests/lib/go.mod | 4 +-- system-tests/lib/go.sum | 8 +++--- system-tests/tests/go.mod | 4 +-- system-tests/tests/go.sum | 8 +++--- 14 files changed, 83 insertions(+), 47 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index fdfbb819cdb..fe6c7b1c595 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -83,7 +83,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect @@ -381,7 +381,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index c13306539d4..82c183c1eda 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -126,8 +126,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1256,8 +1256,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/deployment/go.mod b/deployment/go.mod index 48536e4a626..dd9be65b8a3 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -13,7 +13,7 @@ require ( dario.cat/mergo v1.0.1 github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.3.1 - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/aws/aws-sdk-go v1.55.6 github.com/deckarep/golang-set/v2 v2.6.0 github.com/ethereum/go-ethereum v1.15.7 @@ -31,7 +31,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 diff --git a/deployment/go.sum b/deployment/go.sum index beb68f10c0c..8275cea36bb 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -127,8 +127,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1232,8 +1232,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/go.mod b/go.mod index 94ece13a1a9..a7e218ac72f 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/NethermindEth/juno v0.12.5 github.com/NethermindEth/starknet.go v0.8.0 github.com/andybalholm/brotli v1.1.1 + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/avast/retry-go/v4 v4.6.1 github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/cosmos/cosmos-sdk v0.50.13 @@ -16,7 +17,7 @@ require ( github.com/dominikbraun/graph v0.23.0 github.com/doyensec/safeurl v0.2.1 github.com/esote/minmaxheap v1.0.0 - github.com/ethereum/go-ethereum v1.15.3 + github.com/ethereum/go-ethereum v1.15.7 github.com/fatih/color v1.18.0 github.com/fbsobreira/gotron-sdk v0.0.0-20250403083053-2943ce8c759b github.com/fxamacker/cbor/v2 v2.7.0 @@ -73,6 +74,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.55 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 @@ -177,6 +179,7 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.38.17 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/consensys/bavard v0.1.22 // indirect @@ -194,7 +197,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/dgraph-io/badger/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -252,6 +255,7 @@ require ( github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hasura/go-graphql-client v0.13.1 // indirect github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.2 // indirect @@ -334,7 +338,7 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/urfave/cli/v2 v2.27.5 // indirect - github.com/valyala/fastjson v1.4.1 // indirect + github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/go.sum b/go.sum index 20c779cfdc7..2a2d51719ac 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -224,6 +226,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/cometbft/cometbft v0.38.17 h1:FkrQNbAjiFqXydeAO81FUzriL4Bz0abYxN/eOHrQGOk= github.com/cometbft/cometbft v0.38.17/go.mod h1:5l0SkgeLRXi6bBfQuevXjKqML1jjfJJlvI1Ulp02/o4= github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= @@ -272,6 +276,12 @@ github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHH github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= +github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= +github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= +github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -285,12 +295,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= @@ -324,8 +336,8 @@ github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8nta github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.15.3 h1:OeTWAq6r8iR89bfJDjmmOemE74ywArl9DUViFsVj3Y8= -github.com/ethereum/go-ethereum v1.15.3/go.mod h1:jMXlpZXfSar1mGs/5sB0aEpEnPsiE1Jn6/3anlueqz8= +github.com/ethereum/go-ethereum v1.15.7 h1:vm1XXruZVnqtODBgqFaTclzP0xAvCvQIDKyFNUA1JpY= +github.com/ethereum/go-ethereum v1.15.7/go.mod h1:+S9k+jFzlyVTNcYGvqFhzN/SFhI6vA+aOY4T5tLSPL0= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -334,6 +346,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -358,6 +372,8 @@ github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdF github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= @@ -605,6 +621,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -636,6 +654,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hasura/go-graphql-client v0.13.1 h1:kKbjhxhpwz58usVl+Xvgah/TDha5K2akNTRQdsEHN6U= +github.com/hasura/go-graphql-client v0.13.1/go.mod h1:k7FF7h53C+hSNFRG3++DdVZWIuHdCaTbI7siTJ//zGQ= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -660,6 +680,12 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -827,6 +853,8 @@ github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8D github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -918,6 +946,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -1046,6 +1076,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= @@ -1198,8 +1230,8 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= -github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index a41c3ac3430..2b9232becc7 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -113,7 +113,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -450,7 +450,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 565039a36af..f5dbe2c9bd8 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -159,8 +159,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a h1:2/4CQPSQ5LAAJHR5ONx+TwtfPDyG5tv2M2mJ2aw/8Kk= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index dcd00051e71..0978ed63605 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -85,7 +85,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -437,7 +437,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 582f8481ccb..627a0b80d41 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -163,8 +163,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1447,8 +1447,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 9c8e66a7a93..4e3c6b7cbb3 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -64,7 +64,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect @@ -354,7 +354,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 747ca4011bd..041e8fe2da7 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -121,8 +121,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1220,8 +1220,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 1b82a7dd13c..c33efdf3212 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -80,7 +80,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -427,7 +427,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 9764c329c80..51a7564ebe0 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -157,8 +157,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= From 603ae24547f42c564d5e233b2bf16a8fe0d0d2b3 Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Wed, 14 May 2025 12:05:40 -0700 Subject: [PATCH 088/136] feat: install aptos CLI for ccip unit tests --- .github/workflows/ci-core.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 617666d0b6b..3b62fd2a3a7 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -197,6 +197,7 @@ jobs: is-self-hosted: ${{ needs.runner-config.outputs.deployment-tests-is-self-hosted }} should-run: ${{ needs.filter.outputs.should-run-deployment-tests }} setup-solana: "true" + setup-aptos: "true" use-flakeguard: ${{ github.event_name == 'merge_group' && 'true' || 'false' }} name: Core Tests (${{ matrix.type.cmd }}) @@ -267,6 +268,12 @@ jobs: if: ${{ matrix.type.should-run == 'true' && matrix.type.setup-solana == 'true' }} uses: ./.github/actions/setup-solana + - name: Setup Aptos + if: ${{ matrix.type.should-run == 'true' && matrix.type.setup-aptos == 'true' }} + uses: aptos-labs/actions/install-aptos-cli@63740b290d839b87ecfafbcf75ed03a36a54a29f # jan 15, 2025 + with: + CLI_VERSION: 7.2.0 + - name: Setup wasmd if: ${{ matrix.type.should-run == 'true' }} uses: ./.github/actions/setup-wasmd From 76c8c2db229aeeb0b32be31c9b27a4653b7ea21e Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 14 May 2025 16:23:40 -0300 Subject: [PATCH 089/136] fix: fix unit tests --- deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 5d818be3689..c408c825528 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -147,7 +147,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, // MCMSDeployConfigPerChain is missing needed configs }, - wantErrRe: `invalid mcms configs for chain 4457093679053095497`, + wantErrRe: `invalid mcms configs for Aptos chain 4457093679053095497`, wantErr: true, }, { @@ -176,7 +176,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, }, }, - wantErrRe: `invalid config for chain 4457093679053095497`, + wantErrRe: `invalid config for Aptos chain 4457093679053095497`, wantErr: true, }, } From 2f4cb728ff613b035d76ec20737c6e9fc505e952 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 14 May 2025 17:04:59 -0300 Subject: [PATCH 090/136] fix: breaking changes --- .../aptos/config/deploy_aptos_chain.go | 8 +-- .../changeset/aptos/cs_deploy_aptos_chain.go | 35 ++++++------ .../aptos/cs_deploy_aptos_chain_test.go | 55 ++++++++++--------- .../changeset/aptos/operation/dependencies.go | 10 ++-- .../ccip/changeset/aptos/test_helpers.go | 6 +- deployment/go.mod | 4 +- deployment/go.sum | 8 +-- 7 files changed, 65 insertions(+), 61 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go index a5a9b784208..8b856def8cd 100644 --- a/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/config/deploy_aptos_chain.go @@ -6,7 +6,7 @@ import ( "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -20,7 +20,7 @@ type DeployAptosChainConfig struct { func (c DeployAptosChainConfig) Validate() error { for cs, args := range c.ContractParamsPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } if err := args.Validate(); err != nil { @@ -81,7 +81,7 @@ type OffRampParams struct { } func (o OffRampParams) Validate() error { - if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } if o.PermissionlessExecutionThreshold == 0 { @@ -100,7 +100,7 @@ type OnRampParams struct { } func (o OnRampParams) Validate() error { - if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } return nil diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index ca1bd5f540b..1dc6f8684a9 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -9,23 +9,26 @@ import ( "github.com/smartcontractkit/mcms" mcmstypes "github.com/smartcontractkit/mcms/types" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) -var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} +var _ cldf.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} // DeployAptosChain deploys Aptos chain packages and modules type DeployAptosChain struct{} -func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, config config.DeployAptosChainConfig) error { +func (cs DeployAptosChain) VerifyPreconditions(env cldf.Environment, config config.DeployAptosChainConfig) error { // Validate env and prerequisite contracts - state, err := changeset.LoadOnchainStateAptos(env) + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return fmt.Errorf("failed to load existing Aptos onchain state: %w", err) } @@ -56,13 +59,13 @@ func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, confi return errors.Join(errs...) } -func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (deployment.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func (cs DeployAptosChain) Apply(env cldf.Environment, config config.DeployAptosChainConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } - ab := deployment.NewMemoryAddressBook() + ab := cldf.NewMemoryAddressBook() seqReports := make([]operations.Report[any, any], 0) proposals := make([]mcms.TimelockProposal, 0) @@ -80,16 +83,16 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo // MCMS Deploy operations mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSDeployConfigPerChain[chainSel]) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) // Save MCMS address - typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) + typeAndVersion := cldf.NewTypeAndVersion(shared.AptosMCMSType, deployment.Version1_6_0) err = deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to save MCMS address %s for Aptos chain %d: %w", mcmsSeqReport.Output.MCMSAddress.String(), chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to save MCMS address %s for Aptos chain %d: %w", mcmsSeqReport.Output.MCMSAddress.String(), chainSel, err) } // CCIP Deploy operations ccipSeqInput := seq.DeployCCIPSeqInput{ @@ -98,16 +101,16 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo } ccipSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployCCIPSequence, deps, ccipSeqInput) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) } seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) // Save the address of the CCIP object - typeAndVersion = deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + typeAndVersion = cldf.NewTypeAndVersion(shared.AptosCCIPType, deployment.Version1_6_0) err = deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to save CCIP address %s for Aptos chain %d: %w", ccipSeqReport.Output.CCIPAddress.String(), chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to save CCIP address %s for Aptos chain %d: %w", ccipSeqReport.Output.CCIPAddress.String(), chainSel, err) } // Generate MCMS proposals @@ -120,11 +123,11 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo config.MCMSTimelockConfigPerChain[chainSel], ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) } proposals = append(proposals, *proposal) } - return deployment.ChangesetOutput{ + return cldf.ChangesetOutput{ AddressBook: ab, MCMSTimelockProposals: proposals, Reports: seqReports, diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index c408c825528..e5f256a69f1 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -11,9 +11,10 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -24,21 +25,21 @@ import ( func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { tests := []struct { name string - env deployment.Environment + env cldf.Environment config config.DeployAptosChainConfig wantErrRe string wantErr bool }{ { name: "success - valid configs", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - AptosChains: map[uint64]deployment.AptosChain{ + AptosChains: map[uint64]cldf.AptosChain{ 743186221051783445: {}, 4457093679053095497: {}, }, - ExistingAddresses: deployment.NewMemoryAddressBook(), + ExistingAddresses: cldf.NewMemoryAddressBook(), }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ @@ -54,21 +55,21 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, { name: "success - valid config w MCMS deployed", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - AptosChains: map[uint64]deployment.AptosChain{ + AptosChains: map[uint64]cldf.AptosChain{ 743186221051783445: {}, 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( t, - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, 743186221051783445: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, }, ), @@ -83,20 +84,20 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, { name: "error - chain has no env", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - AptosChains: map[uint64]deployment.AptosChain{ + AptosChains: map[uint64]cldf.AptosChain{ 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( t, - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, 743186221051783445: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, }, ), @@ -112,11 +113,11 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, { name: "error - invalid config - chainSelector", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - ExistingAddresses: deployment.NewMemoryAddressBook(), - AptosChains: map[uint64]deployment.AptosChain{}, + ExistingAddresses: cldf.NewMemoryAddressBook(), + AptosChains: map[uint64]cldf.AptosChain{}, }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ @@ -128,15 +129,15 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, { name: "error - missing MCMS config for chain without MCMS deployed", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - AptosChains: map[uint64]deployment.AptosChain{ + AptosChains: map[uint64]cldf.AptosChain{ 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( t, - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: {}, // No MCMS address in state }, ), @@ -152,17 +153,17 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { }, { name: "error - invalid config for chain", - env: deployment.Environment{ + env: cldf.Environment{ Name: "test", Logger: logger.TestLogger(t), - AptosChains: map[uint64]deployment.AptosChain{ + AptosChains: map[uint64]cldf.AptosChain{ 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( t, - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, // MCMS already deployed + mockMCMSAddress: {Type: shared.AptosMCMSType}, // MCMS already deployed }, }, ), @@ -238,7 +239,7 @@ func TestDeployAptosChain_Apply(t *testing.T) { require.NoError(t, err) // Verify CCIP deployment state by binding ccip contract and checking if it's deployed - state, err := changeset.LoadOnchainStateAptos(env) + state, err := aptosstate.LoadOnchainStateAptos(env) require.NoError(t, err) require.NotNil(t, state[chainSelector], "No state found for chain") diff --git a/deployment/ccip/changeset/aptos/operation/dependencies.go b/deployment/ccip/changeset/aptos/operation/dependencies.go index a405395661d..d0b273ddbcf 100644 --- a/deployment/ccip/changeset/aptos/operation/dependencies.go +++ b/deployment/ccip/changeset/aptos/operation/dependencies.go @@ -1,12 +1,12 @@ package operation import ( - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) type AptosDeps struct { - AB *deployment.AddressBookMap - AptosChain deployment.AptosChain - CCIPOnChainState changeset.CCIPOnChainState + AB *cldf.AddressBookMap + AptosChain cldf.AptosChain + CCIPOnChainState stateview.CCIPOnChainState } diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go index 5e04a61c34f..7e3d3c09953 100644 --- a/deployment/ccip/changeset/aptos/test_helpers.go +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -24,8 +24,8 @@ const ( sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" ) -func getTestAddressBook(t *testing.T, addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { - ab := deployment.NewMemoryAddressBook() +func getTestAddressBook(t *testing.T, addrByChain map[uint64]map[string]cldf.TypeAndVersion) cldf.AddressBook { + ab := cldf.NewMemoryAddressBook() for chain, addrTypeAndVersion := range addrByChain { for addr, typeAndVersion := range addrTypeAndVersion { err := ab.Save(chain, addr, typeAndVersion) diff --git a/deployment/go.mod b/deployment/go.mod index 7b2d772197b..14e03cd3bd6 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -31,11 +31,11 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 - github.com/smartcontractkit/chainlink-deployments-framework v0.0.13 + github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250502210357-2df484128afa github.com/smartcontractkit/chainlink-protos/job-distributor v0.9.0 diff --git a/deployment/go.sum b/deployment/go.sum index 3d459af6b33..06459572169 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1232,8 +1232,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9 h1:lw8RZ8IR4UX1M7djAB3IuMtcAqFX4Z4bzQczClfb8bs= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250414155853-651b4e583ee9/go.mod h1:Sq/ddMOYch6ZuAnW2k5u9V4+TlGKFzuHQnTM8JXEU+g= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= @@ -1246,8 +1246,8 @@ github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-2025041523564 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= -github.com/smartcontractkit/chainlink-deployments-framework v0.0.13 h1:8JNmafFdAHJY4QIcgPOraZpEoxMDbIMRMxlNGivHu6g= -github.com/smartcontractkit/chainlink-deployments-framework v0.0.13/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= +github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= +github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 h1:8u9xUrC+yHrTDexOKDd+jrA6LCzFFHeX1G82oj2fsSI= From 517bda3c0347ff6ffa4ab5add2963a666e887384 Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Wed, 14 May 2025 15:22:03 -0700 Subject: [PATCH 091/136] fix: setup aptos for flakeguard --- .github/workflows/flakeguard.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml index 9c2d793c9c0..ed510ae1e00 100644 --- a/.github/workflows/flakeguard.yml +++ b/.github/workflows/flakeguard.yml @@ -288,6 +288,11 @@ jobs: - name: Setup Solana uses: ./.github/actions/setup-solana + - name: Setup Aptos + uses: aptos-labs/actions/install-aptos-cli@63740b290d839b87ecfafbcf75ed03a36a54a29f # jan 15, 2025 + with: + CLI_VERSION: 7.2.0 + - name: Setup wasmd uses: ./.github/actions/setup-wasmd From 37580b75f66012ee2749618ed03fda4d10ec1f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 15 May 2025 13:06:12 +0200 Subject: [PATCH 092/136] Add Aptos e2e messaging test --- .github/actions/setup-aptos/action.yml | 9 + .github/integration-in-memory-tests.yml | 11 + core/scripts/go.mod | 4 +- core/scripts/go.sum | 8 +- .../changeset/aptos/cs_deploy_aptos_chain.go | 27 +- .../aptos/cs_deploy_aptos_chain_test.go | 22 +- .../changeset/aptos/cs_set_ocr3_offramp.go | 18 +- .../changeset/aptos/cs_update_aptos_ccip.go | 18 +- .../changeset/aptos/cs_update_aptos_lanes.go | 22 +- .../ccip/changeset/aptos/operation/ccip.go | 2 +- .../changeset/aptos/operation/dependencies.go | 4 +- deployment/ccip/changeset/aptos/state_test.go | 10 +- .../ccip/changeset/aptos/test_helpers.go | 9 +- deployment/ccip/changeset/state.go | 6 +- .../testhelpers/aptos_test_helper.go | 30 ++- .../testhelpers/messagingtest/helpers.go | 10 +- .../changeset/testhelpers/test_assertions.go | 234 ++++++++++++++++++ .../changeset/testhelpers/test_environment.go | 16 ++ .../changeset/testhelpers/test_helpers.go | 186 ++++++++++++-- .../v1_6/cs_update_bidirectional_lanes.go | 17 +- .../common/proposalutils/mcms_test_helpers.go | 6 + deployment/environment/memory/aptos_chains.go | 31 ++- deployment/environment/memory/node.go | 12 +- .../environment/web/sdk/client/client.go | 2 +- deployment/go.mod | 4 +- deployment/go.sum | 8 +- deployment/helpers.go | 3 +- go.mod | 4 +- go.sum | 8 +- integration-tests/go.mod | 4 +- integration-tests/go.sum | 8 +- integration-tests/load/go.mod | 4 +- integration-tests/load/go.sum | 8 +- .../smoke/ccip/ccip_aptos_messaging_test.go | 92 +++++++ plugins/plugins.private.yaml | 4 - plugins/plugins.public.yaml | 5 + system-tests/lib/go.mod | 4 +- system-tests/lib/go.sum | 8 +- system-tests/tests/go.mod | 4 +- system-tests/tests/go.sum | 8 +- 40 files changed, 754 insertions(+), 136 deletions(-) create mode 100644 .github/actions/setup-aptos/action.yml create mode 100644 integration-tests/smoke/ccip/ccip_aptos_messaging_test.go diff --git a/.github/actions/setup-aptos/action.yml b/.github/actions/setup-aptos/action.yml new file mode 100644 index 00000000000..a0f22b2bc53 --- /dev/null +++ b/.github/actions/setup-aptos/action.yml @@ -0,0 +1,9 @@ +name: Setup Aptos CLI +description: Setup Aptos CLI +runs: + using: composite + steps: + - name: Install Aptos CLI + uses: aptos-labs/actions/install-aptos-cli@ce57287eb852b9819c1d74fecc3be187677559fd # v0.1 + with: + CLI_VERSION: 7.2.0 \ No newline at end of file diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index fcd6b8a4fd7..3a668aec196 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -297,4 +297,15 @@ runner-test-matrix: test_cmd: cd smoke/ccip/ && go test ccip_disable_lane_test.go -timeout 10m -test.parallel=1 -count=1 -json test_go_project_path: integration-tests + # Aptos tests + - id: smoke/ccip/ccip_aptos_messaging_test.go:* + path: integration-tests/smoke/ccip/ccip_aptos_messaging_test.go + test_env_type: in-memory + runs_on: ubuntu-latest + triggers: + - PR Integration CCIP Tests + - Nightly Integration CCIP Tests + test_cmd: cd smoke/ccip && go test ccip_aptos_messaging_test.go -timeout 15m -test.parallel=1 -count=1 -json + test_go_project_path: integration-tests + # END: CCIP tests diff --git a/core/scripts/go.mod b/core/scripts/go.mod index fe6c7b1c595..7389939b1db 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -32,7 +32,7 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd @@ -381,7 +381,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 82c183c1eda..fab299d8702 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1256,12 +1256,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index 9d89f21a31b..e14424d9559 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -5,19 +5,20 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" - + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/mcms" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/mcms" - mcmstypes "github.com/smartcontractkit/mcms/types" ) -var _ deployment.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} +var _ cldf.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} // DeployAptosChain deploys Aptos chain packages and modules type DeployAptosChain struct{} @@ -55,13 +56,13 @@ func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, confi return errors.Join(errs...) } -func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (deployment.ChangesetOutput, error) { +func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (cldf.ChangesetOutput, error) { state, err := changeset.LoadOnchainStateAptos(env) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } - ab := deployment.NewMemoryAddressBook() + ab := cldf.NewMemoryAddressBook() seqReports := make([]operations.Report[any, any], 0) proposals := make([]mcms.TimelockProposal, 0) @@ -80,13 +81,13 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo // MCMS Deploy operations mcmsSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployMCMSSequence, deps, config.MCMSDeployConfigPerChain[chainSel]) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } seqReports = append(seqReports, mcmsSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) // Save MCMS address - typeAndVersion := deployment.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) + typeAndVersion := cldf.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) // CCIP Deploy operations @@ -96,13 +97,13 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo } ccipSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.DeployCCIPSequence, deps, ccipSeqInput) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to deploy CCIP for Aptos chain %d: %w", chainSel, err) } seqReports = append(seqReports, ccipSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) // Save the address of the CCIP object - typeAndVersion = deployment.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + typeAndVersion = cldf.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) // Generate MCMS proposals @@ -115,11 +116,11 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo config.MCMSTimelockConfigPerChain[chainSel], ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", chainSel, err) } proposals = append(proposals, *proposal) } - return deployment.ChangesetOutput{ + return cldf.ChangesetOutput{ AddressBook: ab, MCMSTimelockProposals: proposals, Reports: seqReports, diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go index 0f22da17add..538460e7722 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain_test.go @@ -6,6 +6,12 @@ import ( "time" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" @@ -14,10 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" - mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" ) func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { @@ -37,7 +39,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 743186221051783445: {}, 4457093679053095497: {}, }, - ExistingAddresses: deployment.NewMemoryAddressBook(), + ExistingAddresses: cldf.NewMemoryAddressBook(), }, config: config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ @@ -61,7 +63,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, }, @@ -88,7 +90,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, }, @@ -112,7 +114,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { env: deployment.Environment{ Name: "test", Logger: logger.TestLogger(t), - ExistingAddresses: deployment.NewMemoryAddressBook(), + ExistingAddresses: cldf.NewMemoryAddressBook(), AptosChains: map[uint64]deployment.AptosChain{}, }, config: config.DeployAptosChainConfig{ @@ -132,7 +134,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: {}, // No MCMS address in state }, ), @@ -155,7 +157,7 @@ func TestDeployAptosChainImp_VerifyPreconditions(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, // MCMS already deployed }, diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go index 161138f4d2a..edf99076c3d 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go @@ -4,18 +4,20 @@ import ( "fmt" chain_selectors "github.com/smartcontractkit/chain-selectors" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/types" ) -var _ deployment.ChangeSetV2[v1_6.SetOCR3OffRampConfig] = SetOCR3Offramp{} +var _ cldf.ChangeSetV2[v1_6.SetOCR3OffRampConfig] = SetOCR3Offramp{} // SetOCR3Offramp updates OCR3 Offramp configurations type SetOCR3Offramp struct{} @@ -30,13 +32,13 @@ func (cs SetOCR3Offramp) VerifyPreconditions(env deployment.Environment, config return nil } -func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) { +func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { seqReports := make([]operations.Report[any, any], 0) timeLockProposals := []mcms.TimelockProposal{} state, err := changeset.LoadOnchainState(env) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } for _, remoteSelector := range config.RemoteChainSels { @@ -51,7 +53,7 @@ func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3Of } setOCR3SeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.SetOCR3OfframpSequence, deps, in) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } seqReports = append(seqReports, setOCR3SeqReport.ExecutionReports...) @@ -65,12 +67,12 @@ func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3Of *config.MCMS, ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", remoteSelector, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", remoteSelector, err) } timeLockProposals = append(timeLockProposals, *proposal) } - return deployment.ChangesetOutput{ + return cldf.ChangesetOutput{ MCMSTimelockProposals: timeLockProposals, Reports: seqReports, }, nil diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go index 2c9522b01c7..1287572f6fd 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go @@ -3,18 +3,20 @@ package aptos import ( "fmt" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/types" ) -var _ deployment.ChangeSetV2[config.UpdateAptosChainConfig] = UpdateAptosChain{} +var _ cldf.ChangeSetV2[config.UpdateAptosChainConfig] = UpdateAptosChain{} // DeployAptosChain deploys Aptos chain packages and modules type UpdateAptosChain struct{} @@ -24,14 +26,14 @@ func (cs UpdateAptosChain) VerifyPreconditions(env deployment.Environment, confi return nil } -func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAptosChainConfig) (deployment.ChangesetOutput, error) { +func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAptosChainConfig) (cldf.ChangesetOutput, error) { timeLockProposals := []mcms.TimelockProposal{} mcmsOperations := []types.BatchOperation{} seqReports := make([]operations.Report[any, any], 0) state, err := changeset.LoadOnchainState(env) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } deps := operation.AptosDeps{ @@ -43,7 +45,7 @@ func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAp // Execute the sequence updateSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.UpdateCCIPSequence, deps, cfg) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } seqReports = append(seqReports, updateSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, updateSeqReport.Output...) @@ -58,11 +60,11 @@ func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAp cfg.MCMSTimelockConfig, ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", cfg.ChainSelector, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", cfg.ChainSelector, err) } timeLockProposals = append(timeLockProposals, *proposal) - return deployment.ChangesetOutput{ + return cldf.ChangesetOutput{ MCMSTimelockProposals: []mcms.TimelockProposal{*proposal}, Reports: seqReports, }, nil diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go index 085745f73d2..a6997892c07 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -3,19 +3,21 @@ package aptos import ( "fmt" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" + "github.com/smartcontractkit/mcms" + "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" - "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/mcms/types" ) -var _ deployment.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} +var _ cldf.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} // AddAptosLane implements adding a new lane to an existing Aptos CCIP deployment type AddAptosLanes struct{} @@ -34,7 +36,7 @@ func (cs AddAptosLanes) VerifyPreconditions(env deployment.Environment, cfg conf return nil } -func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptosLanesConfig) (deployment.ChangesetOutput, error) { +func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptosLanesConfig) (cldf.ChangesetOutput, error) { timeLockProposals := []mcms.TimelockProposal{} mcmsOperations := []types.BatchOperation{} seqReports := make([]operations.Report[any, any], 0) @@ -44,7 +46,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos evmUpdatesInput := config.ToEVMUpdateLanesConfig(cfg) out, err := v1_6.UpdateLanesLogic(env, cfg.EVMMCMSConfig, evmUpdatesInput) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } timeLockProposals = append(timeLockProposals, out.MCMSTimelockProposals...) @@ -52,7 +54,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos // Execute UpdateAptosLanesSequence for each aptos chain state, err := changeset.LoadOnchainState(env) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } updateInputsByAptosChain := seq.ConvertToUpdateAptosLanesSeqInput(state.AptosChains, cfg) @@ -65,7 +67,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos // Execute the sequence updateSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.UpdateAptosLanesSequence, deps, sequenceInput) if err != nil { - return deployment.ChangesetOutput{}, err + return cldf.ChangesetOutput{}, err } seqReports = append(seqReports, updateSeqReport.ExecutionReports...) mcmsOperations = append(mcmsOperations, updateSeqReport.Output) @@ -80,12 +82,12 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos *cfg.AptosMCMSConfig, ) if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", aptosChainSel, err) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate MCMS proposal for Aptos chain %d: %w", aptosChainSel, err) } timeLockProposals = append(timeLockProposals, *proposal) } - return deployment.ChangesetOutput{ + return cldf.ChangesetOutput{ MCMSTimelockProposals: timeLockProposals, Reports: seqReports, }, nil diff --git a/deployment/ccip/changeset/aptos/operation/ccip.go b/deployment/ccip/changeset/aptos/operation/ccip.go index a7fbe09bf8d..25875a78784 100644 --- a/deployment/ccip/changeset/aptos/operation/ccip.go +++ b/deployment/ccip/changeset/aptos/operation/ccip.go @@ -185,7 +185,7 @@ func deployRouter(b operations.Bundle, deps AptosDeps, in DeployModulesInput) ([ var DeployOffRampOp = operations.NewOperation( "deploy-offramp-op", Version1_0_0, - "Generates MCMS proposals that deployes OffRamp module on CCIP package", + "Generates MCMS proposals that deploys OffRamp module on CCIP package", deployOffRamp, ) diff --git a/deployment/ccip/changeset/aptos/operation/dependencies.go b/deployment/ccip/changeset/aptos/operation/dependencies.go index 964abd34ed0..ca95dc64646 100644 --- a/deployment/ccip/changeset/aptos/operation/dependencies.go +++ b/deployment/ccip/changeset/aptos/operation/dependencies.go @@ -1,12 +1,14 @@ package operation import ( + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" ) type AptosDeps struct { - AB *deployment.AddressBookMap + AB *cldf.AddressBookMap AptosChain deployment.AptosChain // TODO: Refactor this? OnChainState changeset.AptosCCIPChainState diff --git a/deployment/ccip/changeset/aptos/state_test.go b/deployment/ccip/changeset/aptos/state_test.go index 8004bb815ba..178e7301f8c 100644 --- a/deployment/ccip/changeset/aptos/state_test.go +++ b/deployment/ccip/changeset/aptos/state_test.go @@ -3,9 +3,11 @@ package aptos import ( "testing" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/stretchr/testify/assert" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/stretchr/testify/assert" ) func TestLoadOnchainStateAptos(t *testing.T) { @@ -29,7 +31,7 @@ func TestLoadOnchainStateAptos(t *testing.T) { 743186221051783445: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, }, @@ -49,7 +51,7 @@ func TestLoadOnchainStateAptos(t *testing.T) { 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { mockMCMSAddress: {Type: changeset.AptosMCMSType}, }, @@ -78,7 +80,7 @@ func TestLoadOnchainStateAptos(t *testing.T) { 743186221051783445: {}, }, ExistingAddresses: getTestAddressBook( - map[uint64]map[string]deployment.TypeAndVersion{ + map[uint64]map[string]cldf.TypeAndVersion{ 743186221051783445: { mockBadAddress: {Type: changeset.AptosMCMSType}, }, diff --git a/deployment/ccip/changeset/aptos/test_helpers.go b/deployment/ccip/changeset/aptos/test_helpers.go index d2108de9103..8683a4159ce 100644 --- a/deployment/ccip/changeset/aptos/test_helpers.go +++ b/deployment/ccip/changeset/aptos/test_helpers.go @@ -6,11 +6,12 @@ import ( "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/stretchr/testify/assert" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/stretchr/testify/assert" ) const ( @@ -24,8 +25,8 @@ const ( sepMockOnRampAddress = "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59" ) -func getTestAddressBook(addrByChain map[uint64]map[string]deployment.TypeAndVersion) deployment.AddressBook { - ab := deployment.NewMemoryAddressBook() +func getTestAddressBook(addrByChain map[uint64]map[string]cldf.TypeAndVersion) cldf.AddressBook { + ab := cldf.NewMemoryAddressBook() for chain, addrTypeAndVersion := range addrByChain { for addr, typeAndVersion := range addrTypeAndVersion { ab.Save(chain, addr, typeAndVersion) diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go index 9c3591b581d..c85cf3595e8 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/changeset/state.go @@ -274,6 +274,9 @@ func (c CCIPChainState) validateCCIPHomeVersionedActiveConfig(e deployment.Envir if _, exists := e.SolChains[chainSel]; exists { return nil } + if _, exists := e.AptosChains[chainSel]; exists { + return nil + } offRamp, ok := offRampsByChain[chainSel] if !ok { return fmt.Errorf("offRamp for chain %d not found in the state", chainSel) @@ -1312,9 +1315,6 @@ func (c CCIPOnChainState) SupportedChains() map[uint64]struct{} { for chain := range c.AptosChains { chains[chain] = struct{}{} } - for chain := range c.AptosChains { - chains[chain] = struct{}{} - } return chains } diff --git a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go index 5ead6fb7866..a185bb90bf3 100644 --- a/deployment/ccip/changeset/testhelpers/aptos_test_helper.go +++ b/deployment/ccip/changeset/testhelpers/aptos_test_helper.go @@ -4,19 +4,43 @@ import ( "math/big" "testing" + "github.com/aptos-labs/aptos-go-sdk" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" - aptoshelper "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) func DeployChainContractsToAptosCS(t *testing.T, e DeployedEnv, chainSelector uint64) commonchangeset.ConfiguredChangeSet { - mockCCIPParams := aptoshelper.GetMockChainContractParams(t, chainSelector) + linkTokenAddress := aptos.AccountAddress{} + // TODO APT - replace with LINK once available + linkTokenAddress.ParseStringRelaxed("0xa") ccipConfig := config.DeployAptosChainConfig{ ContractParamsPerChain: map[uint64]config.ChainContractParams{ - chainSelector: mockCCIPParams, + chainSelector: { + FeeQuoterParams: config.FeeQuoterParams{ + MaxFeeJuelsPerMsg: 1000000000, + LinkToken: linkTokenAddress, + TokenPriceStalenessThreshold: 24 * 60 * 60, + FeeTokens: []aptos.AccountAddress{linkTokenAddress}, + }, + OffRampParams: config.OffRampParams{ + ChainSelector: chainSelector, + PermissionlessExecutionThreshold: uint32(globals.PermissionLessExecutionThreshold.Seconds()), + IsRMNVerificationDisabled: nil, + SourceChainSelectors: nil, + SourceChainIsEnabled: nil, + SourceChainsOnRamp: nil, + }, + OnRampParams: config.OnRampParams{ + ChainSelector: chainSelector, + AllowlistAdmin: e.Env.AptosChains[chainSelector].DeployerSigner.AccountAddress(), + FeeAggregator: e.Env.AptosChains[chainSelector].DeployerSigner.AccountAddress(), + }, + }, }, MCMSDeployConfigPerChain: map[uint64]commontypes.MCMSWithTimelockConfigV2{ chainSelector: { diff --git a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go index c87f3b2e4ba..c68df18117b 100644 --- a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" @@ -243,8 +244,15 @@ func Run(t *testing.T, tc TestCase) (out TestCaseOutput) { family, err := chain_selectors.GetSelectorFamily(tc.DestChain) require.NoError(tc.T, err) + unorderedExec := false + switch family { // Solana doesn't support catching CPI errors, so nonces can't be ordered - unorderedExec := family == chain_selectors.FamilySolana + case chain_selectors.FamilySolana: + fallthrough + // Aptos does only support out-of-order execution + case chain_selectors.FamilyAptos: + unorderedExec = true + } if !unorderedExec { latestNonce := getLatestNonce(tc) diff --git a/deployment/ccip/changeset/testhelpers/test_assertions.go b/deployment/ccip/changeset/testhelpers/test_assertions.go index fda5a198b5b..104a675d466 100644 --- a/deployment/ccip/changeset/testhelpers/test_assertions.go +++ b/deployment/ccip/changeset/testhelpers/test_assertions.go @@ -11,10 +11,14 @@ import ( "testing" "time" + "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" solrpc "github.com/gagliardetto/solana-go/rpc" + aptosOffRamp "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" + module_offramp "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp/offramp" + "github.com/smartcontractkit/chainlink-aptos/relayer/codec" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -36,6 +40,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" + "github.com/smartcontractkit/chainlink/deployment" ) @@ -232,6 +237,19 @@ func ConfirmCommitForAllWithExpectedSeqNums( }, true, )) + case chainsel.FamilyAptos: + return commonutils.JustError(ConfirmCommitWithExpectedSeqNumRangeAptos( + t, + srcChain, + e.AptosChains[dstChain], + state.AptosChains[dstChain].CCIPAddress, + startBlock, + ccipocr3.SeqNumRange{ + ccipocr3.SeqNum(expectedSeqNum), + ccipocr3.SeqNum(expectedSeqNum), + }, + true, + )) default: return fmt.Errorf("unsupported chain family; %v", family) } @@ -340,6 +358,17 @@ func ConfirmMultipleCommits( enforceSingleCommit, ) return err + case chainsel.FamilyAptos: + _, err := ConfirmCommitWithExpectedSeqNumRangeAptos( + t, + srcChain, + env.AptosChains[destChain], + state.AptosChains[destChain].CCIPAddress, + startBlocks[destChain], + seqRange, + enforceSingleCommit, + ) + return err default: return fmt.Errorf("unsupported chain family; %v", family) } @@ -588,6 +617,145 @@ func ConfirmCommitWithExpectedSeqNumRangeSol( } } +func AptosEventEmitter[T any]( + t *testing.T, + client aptos.AptosRpcClient, + address aptos.AccountAddress, + eventHandle, fieldname string, + startVersion *uint64, + done chan any, +) (<-chan struct { + Event T + Version uint64 +}, <-chan error) { + ch := make(chan struct { + Event T + Version uint64 + }, 200) + errChan := make(chan error) + limit := uint64(100) + seqNum := uint64(0) + go func() { + ticker := time.NewTicker(time.Second * 2) + defer ticker.Stop() + + for { + for { + // As this can take a few iterations if there are many events, check for done before each request + select { + case <-done: + return + default: + } + events, err := client.EventsByHandle(address, eventHandle, fieldname, &seqNum, &limit) + if err != nil { + errChan <- err + return + } + if len(events) == 0 { + // No new events found + break + } + for _, event := range events { + seqNum = event.SequenceNumber + 1 + if startVersion != nil && event.Version < *startVersion { + continue + } + var out T + if err := codec.DecodeAptosJsonValue(event.Data, &out); err != nil { + errChan <- err + continue + } + ch <- struct { + Event T + Version uint64 + }{ + Event: out, + Version: event.Version, + } + } + } + select { + case <-done: + return + case <-ticker.C: + continue + } + } + + }() + return ch, errChan +} + +func ConfirmCommitWithExpectedSeqNumRangeAptos( + t *testing.T, + srcSelector uint64, + dest deployment.AptosChain, + offRampAddress aptos.AccountAddress, + startVersion *uint64, + expectedSeqNumRange ccipocr3.SeqNumRange, + enforceSingleCommit bool, +) (*module_offramp.CommitReportAccepted, error) { + boundOffRamp := aptosOffRamp.Bind(offRampAddress, dest.Client) + offRampStateAddress, err := boundOffRamp.Offramp().GetStateAddress(nil) + require.NoError(t, err) + + done := make(chan any) + defer close(done) + sink, errChan := AptosEventEmitter[module_offramp.CommitReportAccepted](t, dest.Client, offRampStateAddress, fmt.Sprintf("%s::offramp::OffRampState", offRampAddress.StringLong()), "commit_report_accepted_events", startVersion, done) + + timeout := time.NewTimer(tests.WaitTimeout(t)) + defer timeout.Stop() + + seenMessages := NewCommitReportTracker(srcSelector, expectedSeqNumRange) + + verifyCommitReport := func(report module_offramp.CommitReportAccepted) bool { + processRoots := func(roots []module_offramp.MerkleRoot) bool { + for _, mr := range roots { + t.Logf("(Aptos) Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, srcSelector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates, + ) + seenMessages.visitCommitReport(srcSelector, mr.MinSeqNr, mr.MaxSeqNr) + + if mr.SourceChainSelector == srcSelector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { + t.Logf("(Aptos) All sequence numbers committed in a single report [%d, %d]", + expectedSeqNumRange.Start(), expectedSeqNumRange.End(), + ) + return true + } + + if !enforceSingleCommit && seenMessages.allCommited(srcSelector) { + t.Logf( + "(Aptos) All sequence numbers already committed from range [%d, %d]", + expectedSeqNumRange.Start(), expectedSeqNumRange.End(), + ) + return true + } + } + return false + } + + return processRoots(report.BlessedMerkleRoots) || processRoots(report.UnblessedMerkleRoots) + } + + for { + select { + case event := <-sink: + verified := verifyCommitReport(event.Event) + if verified { + return &event.Event, nil + } + case err := <-errChan: + require.NoError(t, err) + case <-timeout.C: + return nil, fmt.Errorf("(aptos) timed out after waiting for commit report on chain selector %d from source selector %d expected seq nr range %s", + dest.Selector, srcSelector, expectedSeqNumRange.String()) + } + } + + return nil, nil +} + // ConfirmExecWithSeqNrsForAll waits for all chains in the environment to execute the given expectedSeqNums. // If successful, it returns a map that maps the SourceDestPair to the expected sequence number // to its execution state. @@ -652,6 +820,18 @@ func ConfirmExecWithSeqNrsForAll( if err != nil { return err } + case chainsel.FamilyAptos: + innerExecutionStates, err = ConfirmExecWithExpectedSeqNrsAptos( + t, + srcChain, + e.AptosChains[dstChain], + state.AptosChains[dstChain].CCIPAddress, + startBlock, + seqRange, + ) + if err != nil { + return err + } default: return fmt.Errorf("unsupported chain family; %v", family) } @@ -798,6 +978,60 @@ func ConfirmExecWithSeqNrsSol( } } +func ConfirmExecWithExpectedSeqNrsAptos( + t *testing.T, + srcSelector uint64, + dest deployment.AptosChain, + offRampAddress aptos.AccountAddress, + startVersion *uint64, + expectedSeqNrs []uint64, +) (executionStates map[uint64]int, err error) { + if len(expectedSeqNrs) == 0 { + return nil, fmt.Errorf("no expected sequence numbers provided") + } + boundOffRamp := aptosOffRamp.Bind(offRampAddress, dest.Client) + offRampStateAddress, err := boundOffRamp.Offramp().GetStateAddress(nil) + require.NoError(t, err) + + done := make(chan any) + defer close(done) + sink, errChan := AptosEventEmitter[module_offramp.ExecutionStateChanged](t, dest.Client, offRampStateAddress, fmt.Sprintf("%s::offramp::OffRampState", offRampAddress.StringLong()), "execution_state_changed_events", startVersion, done) + + executionStates = make(map[uint64]int) + seqNrsToWatch := make(map[uint64]bool) + for _, seqNr := range expectedSeqNrs { + seqNrsToWatch[seqNr] = true + } + + timeout := time.NewTimer(tests.WaitTimeout(t)) + defer timeout.Stop() + + for { + select { + case event := <-sink: + if seqNrsToWatch[event.Event.SequenceNumber] && event.Event.SourceChainSelector == srcSelector { + t.Logf("(Aptos) received ExecutionStateChanged (state %s) on chain %d (offramp %s) with expected sequence number %d (tx %s)", + executionStateToString(event.Event.State), dest.Selector, offRampAddress.String(), event.Event.SequenceNumber, event.Version, + ) + if event.Event.State == EXECUTION_STATE_INPROGRESS { + continue + } + executionStates[event.Event.SequenceNumber] = int(event.Event.State) + delete(seqNrsToWatch, event.Event.SequenceNumber) + if len(seqNrsToWatch) == 0 { + return executionStates, nil + } + } + + case err := <-errChan: + require.NoError(t, err) + case <-timeout.C: + return nil, fmt.Errorf("(Aptos) timed out waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence numbers %+v", + dest.Selector, offRampAddress.String(), srcSelector, expectedSeqNrs) + } + } +} + func ConfirmNoExecConsistentlyWithSeqNr( t *testing.T, sourceSelector uint64, diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index ced93307605..724e147bf04 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" solanago "github.com/gagliardetto/solana-go" + mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -23,6 +24,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -961,6 +963,20 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn CCIPHomeConfigType: globals.ConfigTypeActive, }, ), + commonchangeset.Configure( + // Enable the OCR config on the remote chains. + aptoscs.SetOCR3Offramp{}, + v1_6.SetOCR3OffRampConfig{ + HomeChainSel: e.HomeChainSel, + RemoteChainSels: aptosChains, + CCIPHomeConfigType: globals.ConfigTypeActive, + MCMS: &proposalutils.TimelockConfig{ + MinDelay: time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, + }, + ), commonchangeset.Configure( // Enable the OCR config on the remote chains. cldf.CreateLegacyChangeSet(ccipChangeSetSolana.SetOCR3ConfigSolana), diff --git a/deployment/ccip/changeset/testhelpers/test_helpers.go b/deployment/ccip/changeset/testhelpers/test_helpers.go index 2fdd3dad4c7..b814e995dd7 100644 --- a/deployment/ccip/changeset/testhelpers/test_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_helpers.go @@ -14,6 +14,9 @@ import ( "testing" "time" + aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_dummy_receiver" + mcmstypes "github.com/smartcontractkit/mcms/types" "golang.org/x/sync/errgroup" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -27,6 +30,8 @@ import ( solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" ccipChangeSetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" @@ -143,7 +148,7 @@ func WithAssertOnError(assert bool) ReplayLogsOption { // By default, it will assert on errors. Use WithAssertOnError(false) to change this behavior. func ReplayLogs(t *testing.T, oc cldf.OffchainClient, replayBlocks map[uint64]uint64, opts ...ReplayLogsOption) { options := &replayLogsOptions{ - assertOnError: true, + assertOnError: false, } for _, opt := range opts { @@ -220,6 +225,12 @@ func LatestBlock(ctx context.Context, env deployment.Environment, chainSelector return block, nil case chainsel.FamilySolana: return env.SolChains[chainSelector].Client.GetSlot(ctx, solconfig.DefaultCommitment) + case chainsel.FamilyAptos: + chainInfo, err := env.AptosChains[chainSelector].Client.Info() + if err != nil { + return 0, errors.Wrapf(err, "failed to get chain info for chain %d", chainSelector) + } + return chainInfo.LedgerVersion(), nil default: return 0, errors.New("unsupported chain family") } @@ -231,6 +242,7 @@ func LatestBlocksByChain(ctx context.Context, env deployment.Environment) (map[u chains := []uint64{} chains = slices.AppendSeq(chains, maps.Keys(env.Chains)) chains = slices.AppendSeq(chains, maps.Keys(env.SolChains)) + chains = slices.AppendSeq(chains, maps.Keys(env.AptosChains)) for _, selector := range chains { block, err := LatestBlock(ctx, env, selector) if err != nil { @@ -478,6 +490,8 @@ func SendRequest( return SendRequestEVM(e, state, cfg) case chainsel.FamilySolana: return SendRequestSol(e, state, cfg) + case chainsel.FamilyAptos: + panic("Aptos - not implemented") default: return nil, fmt.Errorf("send request: unsupported chain family: %v", family) } @@ -845,22 +859,28 @@ func AddLane( fqCfg fee_quoter.FeeQuoterDestChainConfig, ) { var err error - fromFamily, _ := chainsel.GetSelectorFamily(from) - toFamily, _ := chainsel.GetSelectorFamily(to) + fromFamily, err := chainsel.GetSelectorFamily(from) + require.NoError(t, err) + toFamily, err := chainsel.GetSelectorFamily(to) + require.NoError(t, err) changesets := []commoncs.ConfiguredChangeSet{} - if fromFamily == chainsel.FamilyEVM { - evmSrcChangesets := addEVMSrcChangesets(from, to, isTestRouter, gasprice, tokenPrices, fqCfg) - changesets = append(changesets, evmSrcChangesets...) - } - if toFamily == chainsel.FamilyEVM { - evmDstChangesets := addEVMDestChangesets(e, to, from, isTestRouter) - changesets = append(changesets, evmDstChangesets...) - } - if fromFamily == chainsel.FamilySolana { + + switch fromFamily { + case chainsel.FamilyEVM: + changesets = append(changesets, addEVMSrcChangesets(from, to, isTestRouter, gasprice, tokenPrices, fqCfg)...) + case chainsel.FamilySolana: changesets = append(changesets, addLaneSolanaChangesets(t, e, from, to, toFamily)...) + case chainsel.FamilyAptos: + changesets = append(changesets, addLaneAptosChangesets(t, from, to)...) } - if toFamily == chainsel.FamilySolana { + + switch toFamily { + case chainsel.FamilyEVM: + changesets = append(changesets, addEVMDestChangesets(e, to, from, isTestRouter)...) + case chainsel.FamilySolana: changesets = append(changesets, addLaneSolanaChangesets(t, e, to, from, fromFamily)...) + case chainsel.FamilyAptos: + changesets = append(changesets, addLaneAptosChangesets(t, from, to)...) } e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), changesets) @@ -869,12 +889,18 @@ func AddLane( func addLaneSolanaChangesets(t *testing.T, e *DeployedEnv, solChainSelector, remoteChainSelector uint64, remoteFamily string) []commoncs.ConfiguredChangeSet { chainFamilySelector := [4]uint8{} - if remoteFamily == chainsel.FamilyEVM { + switch remoteFamily { + case chainsel.FamilyEVM: // bytes4(keccak256("CCIP ChainFamilySelector EVM")) chainFamilySelector = [4]uint8{40, 18, 213, 44} - } else if remoteFamily == chainsel.FamilySolana { + case chainsel.FamilySolana: // bytes4(keccak256("CCIP ChainFamilySelector SVM")); chainFamilySelector = [4]uint8{30, 16, 189, 196} + case chainsel.FamilyAptos: + // bytes4(keccak256("CCIP ChainFamilySelector APTOS")); + chainFamilySelector = [4]uint8{0xac, 0x77, 0xff, 0xec} + default: + panic("unsupported remote family") } solanaChangesets := []commoncs.ConfiguredChangeSet{ commoncs.Configure( @@ -1015,6 +1041,124 @@ func addEVMDestChangesets(e *DeployedEnv, to, from uint64, isTestRouter bool) [] return evmDstChangesets } +func addLaneAptosChangesets(t *testing.T, srcChainSelector, destChainSelector uint64) []commoncs.ConfiguredChangeSet { + srcFamily, err := chainsel.GetSelectorFamily(srcChainSelector) + require.NoError(t, err) + destFamily, err := chainsel.GetSelectorFamily(destChainSelector) + require.NoError(t, err) + + t.Logf("Adding lane %s=>%s", srcFamily, destFamily) + + var src, dest config.ChainDefinition + + switch srcFamily { + case chainsel.FamilyEVM: + src = config.EVMChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + }, + Selector: srcChainSelector, + }, + } + case chainsel.FamilyAptos: + src = config.AptosChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + RMNVerificationDisabled: true, + }, + Selector: srcChainSelector, + AddTokenTransferFeeConfigs: nil, + RemoveTokenTransferFeeConfigs: nil, + } + } + + switch destFamily { + case chainsel.FamilyEVM: + dest = config.EVMChainDefinition{ + ChainDefinition: v1_6.ChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + AllowListEnabled: false, + }, + Selector: destChainSelector, + GasPrice: big.NewInt(1e17), + TokenPrices: nil, + FeeQuoterDestChainConfig: fee_quoter.FeeQuoterDestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 10, + MaxDataBytes: 30_000, + MaxPerMsgGasLimit: 3_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 100, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 1, + ChainFamilySelector: [4]byte{0x28, 0x12, 0xd5, 0x2c}, + EnforceOutOfOrder: false, + DefaultTokenFeeUSDCents: 25, + DefaultTokenDestGasOverhead: 90_000, + DefaultTxGasLimit: 200_000, + GasMultiplierWeiPerEth: 11e8, // TODO what's the scale here? + GasPriceStalenessThreshold: 0, + NetworkFeeUSDCents: 10, + }, + }, + OnRampVersion: []byte{1, 6, 0}, + } + case chainsel.FamilyAptos: + dest = config.AptosChainDefinition{ + ConnectionConfig: v1_6.ConnectionConfig{ + AllowListEnabled: false, + }, + Selector: destChainSelector, + GasPrice: big.NewInt(1e7), + FeeQuoterDestChainConfig: aptos_fee_quoter.DestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 10, + MaxDataBytes: 30_000, + MaxPerMsgGasLimit: 3_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DestGasPerPayloadByteBase: ccipevm.CalldataGasPerByteBase, + DestGasPerPayloadByteHigh: ccipevm.CalldataGasPerByteHigh, + DestGasPerPayloadByteThreshold: ccipevm.CalldataGasPerByteThreshold, + DestDataAvailabilityOverheadGas: 100, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 1, + ChainFamilySelector: []byte{0xac, 0x77, 0xff, 0xec}, + EnforceOutOfOrder: true, + DefaultTokenFeeUsdCents: 25, + DefaultTokenDestGasOverhead: 90_000, + DefaultTxGasLimit: 200_000, + GasMultiplierWeiPerEth: 11e17, + GasPriceStalenessThreshold: 0, + NetworkFeeUsdCents: 10, + }, + } + } + + return []commoncs.ConfiguredChangeSet{ + commoncs.Configure( + aptoscs.AddAptosLanes{}, + config.UpdateAptosLanesConfig{ + AptosMCMSConfig: &proposalutils.TimelockConfig{ + MinDelay: time.Second, + MCMSAction: mcmstypes.TimelockActionSchedule, + OverrideRoot: false, + }, + Lanes: []config.LaneConfig{ + { + Source: src, + Dest: dest, + IsDisabled: false, + }, + }, + TestRouter: false, + }, + ), + } +} + // RemoveLane removes a lane between the source and destination chains in the deployed environment. func RemoveLane(t *testing.T, e *DeployedEnv, src, dest uint64, isTestRouter bool) { var err error @@ -2326,3 +2470,15 @@ func TransferToTimelock( require.NoError(t, err) AssertTimelockOwnership(t, tenv, chains, state) } + +func DeployAptosCCIPReceiver(t *testing.T, e deployment.Environment) { + state, err := changeset.LoadOnchainStateAptos(e) + require.NoError(t, err) + for selector, onchainState := range state { + addr, tx, _, err := ccip_dummy_receiver.DeployToObject(e.AptosChains[selector].DeployerSigner, e.AptosChains[selector].Client, onchainState.CCIPAddress, onchainState.MCMSAddress) + require.NoError(t, err) + t.Logf("(Aptos) CCIPDummyReceiver(ccip: %s, mcms: %s) deployed to %s in tx %s", onchainState.CCIPAddress.StringLong(), onchainState.MCMSAddress.StringLong(), addr.StringLong(), tx.Hash) + require.NoError(t, e.AptosChains[selector].Confirm(tx.Hash)) + e.ExistingAddresses.Save(selector, addr.StringLong(), cldf.NewTypeAndVersion(changeset.AptosReceiverType, deployment.Version1_0_0)) + } +} diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index 7a6d00d051a..b899017cb96 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -159,6 +159,11 @@ func (c UpdateBidirectionalLanesConfig) BuildConfigs() UpdateBidirectionalLanesC func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidirectionalLanesConfig) error { configs := c.BuildConfigs() + + return UpdateLanesPrecondition(e, configs) +} + +func UpdateLanesPrecondition(e deployment.Environment, configs UpdateBidirectionalLanesChangesetConfigs) error { state, err := changeset.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) @@ -193,9 +198,17 @@ func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidi } func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirectionalLanesConfig) (cldf.ChangesetOutput, error) { - proposals := make([]mcms.TimelockProposal, 0) configs := c.BuildConfigs() + return UpdateLanesLogic(e, c.MCMSConfig, configs) +} + +// UpdateLanesLogic is the main logic for updating lanes. Configs provided can be unidirectional +// TODO: this should be refactored as a sequence once EVM changesets move to Operations API +// TODO: UpdateBidirectionalLanesChangesetConfigs name is misleading, it also accepts unidirectional lane updates +func UpdateLanesLogic(e deployment.Environment, mcmsConfig *proposalutils.TimelockConfig, configs UpdateBidirectionalLanesChangesetConfigs) (cldf.ChangesetOutput, error) { + proposals := make([]mcms.TimelockProposal, 0) + out, err := UpdateFeeQuoterDestsChangeset(e, configs.UpdateFeeQuoterDestsConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to run UpdateFeeQuoterDestsChangeset: %w", err) @@ -235,7 +248,7 @@ func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirection if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), nil, proposals, nil, "Update multiple bidirectional lanes", c.MCMSConfig) + proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), nil, proposals, nil, "Update multiple bidirectional lanes", mcmsConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) } diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index b80c72ce603..2a1658e56ce 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -2,6 +2,7 @@ package proposalutils import ( "crypto/ecdsa" + "encoding/json" "fmt" "math/big" "slices" @@ -342,6 +343,11 @@ func ExecuteMCMSTimelockProposalV2(t *testing.T, env deployment.Environment, tim executorsMap[op.ChainSelector] = mcmsaptossdk.NewTimelockExecutor( env.AptosChains[uint64(op.ChainSelector)].Client, env.AptosChains[uint64(op.ChainSelector)].DeployerSigner) + for _, transaction := range op.Transactions { + af := mcmsaptossdk.AdditionalFields{} + _ = json.Unmarshal(transaction.AdditionalFields, &af) + fmt.Printf("Executing %s::%s::%s\n", af.PackageName, af.ModuleName, af.Function) + } default: require.FailNow(t, "unsupported chain family") diff --git a/deployment/environment/memory/aptos_chains.go b/deployment/environment/memory/aptos_chains.go index bde46f28dd9..85970ee2dc6 100644 --- a/deployment/environment/memory/aptos_chains.go +++ b/deployment/environment/memory/aptos_chains.go @@ -9,8 +9,8 @@ import ( "time" "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" "github.com/aptos-labs/aptos-go-sdk/crypto" - "github.com/smartcontractkit/freeport" "github.com/stretchr/testify/require" @@ -155,8 +155,8 @@ func createAptosChainConfig(chainID string, chain deployment.AptosChain) chainli chainConfig["Enabled"] = true chainConfig["ChainID"] = chainID - chainConfig["NetworkName"] = "aptos-local" - chainConfig["NetworkNameFull"] = "aptos-local" + chainConfig["NetworkName"] = "localnet" + chainConfig["NetworkNameFull"] = "aptos-localnet" chainConfig["Nodes"] = []any{ map[string]any{ "Name": "primary", @@ -166,3 +166,28 @@ func createAptosChainConfig(chainID string, chain deployment.AptosChain) chainli return chainConfig } + +func fundAptosAccount(t *testing.T, signer aptos.TransactionSigner, to aptos.AccountAddress, amount uint64, client aptos.AptosRpcClient) { + toBytes, err := bcs.Serialize(&to) + require.NoError(t, err) + amountBytes, err := bcs.SerializeU64(amount) + require.NoError(t, err) + payload := aptos.TransactionPayload{Payload: &aptos.EntryFunction{ + Module: aptos.ModuleId{ + Address: aptos.AccountOne, + Name: "aptos_account", + }, + Function: "transfer", + Args: [][]byte{ + toBytes, + amountBytes, + }, + }} + tx, err := client.BuildSignAndSubmitTransaction(signer, payload) + require.NoError(t, err) + res, err := client.WaitForTransaction(tx.Hash) + require.NoError(t, err) + require.True(t, res.Success, res.VmStatus) + sender := signer.AccountAddress() + t.Logf("Funded account %s from %s with %f", to.StringLong(), sender.StringLong(), float64(amount)/1e8) +} diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index 04aaed74364..e2f9389ab34 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/mock" @@ -91,6 +92,10 @@ func (n Node) ReplayLogs(ctx context.Context, chains map[uint64]uint64) error { for sel, block := range chains { family, _ := chainsel.GetSelectorFamily(sel) chainID, _ := chainsel.GetChainIDFromSelector(sel) + if family == "aptos" { + fmt.Printf("ReplayFromBlock: family: %q chainID: %q\n", family, chainID) + continue + } if err := n.App.ReplayFromBlock(ctx, family, chainID, block, false); err != nil { return err } @@ -511,7 +516,7 @@ func CreateKeys(t *testing.T, transmitter := keys[0] transmitters[chain.Selector] = transmitter.ID() - + t.Logf("Created Aptos Key: ID %v, Account %v", transmitter.ID(), transmitter.Account()) // TODO: funding case chainsel.FamilyStarknet: keystore := app.GetKeyStore().StarkNet() @@ -570,8 +575,11 @@ func CreateKeys(t *testing.T, require.NoError(t, err) require.Len(t, aptoskeys, 1) transmitter := aptoskeys[0] - for chainSelector := range aptoschains { + for chainSelector, aptosChain := range aptoschains { transmitters[chainSelector] = transmitter.ID() + transmitterAccountAddress := aptos.AccountAddress{} + transmitterAccountAddress.ParseStringRelaxed(transmitter.Account()) + fundAptosAccount(t, aptosChain.DeployerSigner, transmitterAccountAddress, 100*1e8, aptosChain.Client) } } diff --git a/deployment/environment/web/sdk/client/client.go b/deployment/environment/web/sdk/client/client.go index 6e390c7afff..4de2a338142 100644 --- a/deployment/environment/web/sdk/client/client.go +++ b/deployment/environment/web/sdk/client/client.go @@ -149,7 +149,7 @@ func (c *client) FetchKeys(ctx context.Context, chainType string) ([]string, err case generated.OCR2ChainTypeAptos: var accounts []string for _, key := range keys.AptosKeys.GetResults() { - accounts = append(accounts, key.Account) + accounts = append(accounts, key.Id) } return accounts, nil case generated.OCR2ChainTypeSolana: diff --git a/deployment/go.mod b/deployment/go.mod index 3ab922831e8..29a20dbe678 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -31,8 +31,8 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd diff --git a/deployment/go.sum b/deployment/go.sum index 8275cea36bb..20a5561968c 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1232,12 +1232,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/deployment/helpers.go b/deployment/helpers.go index 555921ed34b..18976f73a73 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -64,7 +64,8 @@ func ValidateSelectorsInEnvironment(e Environment, chains []uint64) error { for _, chain := range chains { _, evmOk := e.Chains[chain] _, solOk := e.SolChains[chain] - if !evmOk && !solOk { + _, aptosOk := e.AptosChains[chain] + if !evmOk && !solOk && !aptosOk { return fmt.Errorf("chain %d not found in environment", chain) } } diff --git a/go.mod b/go.mod index a7e218ac72f..3de9217e75d 100644 --- a/go.mod +++ b/go.mod @@ -74,9 +74,9 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 diff --git a/go.sum b/go.sum index 2a2d51719ac..0e627236312 100644 --- a/go.sum +++ b/go.sum @@ -1076,12 +1076,12 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 h1:j6Vo/NX2ABsPdGxETC5pfQLcz/h6iLJu/Yx+8AhPa34= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2b9232becc7..00d402ebcec 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -45,7 +45,7 @@ require ( github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd @@ -450,7 +450,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index f5dbe2c9bd8..f3304881712 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,12 +1466,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 0978ed63605..2ce3a4b6e69 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -27,7 +27,7 @@ require ( github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca @@ -437,7 +437,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 627a0b80d41..3bdbd7f58a0 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1447,12 +1447,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go new file mode 100644 index 00000000000..5a3903e29de --- /dev/null +++ b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go @@ -0,0 +1,92 @@ +package ccip + +import ( + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/messagingtest" + testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" +) + +func Test_CCIP_Messaging_EVM2Aptos(t *testing.T) { + e, _, _ := testsetups.NewIntegrationEnvironment( + t, + testhelpers.WithNumOfChains(2), + testhelpers.WithAptosChains(1), + ) + + evmChainSelectors := maps.Keys(e.Env.Chains) + aptosChainSelectors := maps.Keys(e.Env.AptosChains) + + fmt.Println("EVM: ", evmChainSelectors) + fmt.Println("Aptos: ", aptosChainSelectors) + + // Deploy dummy receiver + t.Log("Deploying CCIPDummyReceiver...") + testhelpers.DeployAptosCCIPReceiver(t, e.Env) + + state, err := changeset.LoadOnchainState(e.Env) + require.NoError(t, err) + + sourceChain := evmChainSelectors[0] + destChain := aptosChainSelectors[0] + + t.Log("Source chain (EVM): ", sourceChain, "Dest chain (Aptos): ", destChain) + + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain, destChain, false) + + var ( + replayed bool + nonce uint64 + sender = common.LeftPadBytes(e.Env.Chains[sourceChain].DeployerKey.From.Bytes(), 32) + out messagingtest.TestCaseOutput + setup = messagingtest.NewTestSetupWithDeployedEnv( + t, + e, + state, + sourceChain, + destChain, + sender, + false, // testRouter + ) + ) + + t.Run("Message to Aptos", func(t *testing.T) { + ccipChainState := state.AptosChains[destChain] + message := []byte("Hello Aptos, from EVM!") + out = messagingtest.Run(t, + messagingtest.TestCase{ + TestSetup: setup, + Replayed: replayed, + Nonce: &nonce, + ValidationType: messagingtest.ValidationTypeExec, + Receiver: ccipChainState.ReceiverAddress[:], + MsgData: message, + // true for out of order execution, which is necessary and enforced for Aptos + ExtraArgs: testhelpers.MakeEVMExtraArgsV2(100000, true), + ExpectedExecutionState: testhelpers.EXECUTION_STATE_SUCCESS, + ExtraAssertions: []func(t *testing.T){ + func(t *testing.T) { + // TODO: check dummy receiver events + // dummyReceiver := state.AptosChains[destChain].ReceiverAddress + // events, err := e.Env.AptosChains[destChain].Client.EventsByHandle(dummyReceiver, fmt.Sprintf("%s::dummy_receiver::ReceivedMessage", dummyReceiver), "received_message_events", nil, nil) + // require.NoError(t, err) + // require.Len(t, events, 1) + // var receivedMessage module_dummy_receiver.ReceivedMessage + // err = codec.DecodeAptosJsonValue(events[0].Data, &receivedMessage) + // require.NoError(t, err) + // require.Equal(t, message, receivedMessage.Data) + }, + }, + }, + ) + }) + + fmt.Printf("out: %v\n", out) +} diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 4af36c2d159..19efb0adb16 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -8,10 +8,6 @@ defaults: goflags: "-ldflags=-s" plugins: - aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "808b080f471d054ff623164b3a316759a8f18758" - installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" gitRef: "6bb81bba0e44efbca20a1ba7a3d2fb4a4be575d5" diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index 3b91c9dfd98..7b03d6a1bf6 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -28,6 +28,11 @@ plugins: gitRef: "v1.1.2-0.20250506153227-c817e421ec21" installPath: "github.com/smartcontractkit/chainlink-solana/pkg/solana/cmd/chainlink-solana" + aptos: + - moduleURI: "github.com/smartcontractkit/chainlink-aptos" + gitRef: "808b080f471d054ff623164b3a316759a8f18758" + installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" + starknet: - moduleURI: "github.com/smartcontractkit/chainlink-starknet/relayer" gitRef: "9a780650af4708e4bd9b75495feff2c5b4054e46" # 2025-02-04 diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 4e3c6b7cbb3..ea4e6cd5ed1 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -354,9 +354,9 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 041e8fe2da7..10e89b4e899 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1220,12 +1220,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index c33efdf3212..f11edfa0751 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -427,9 +427,9 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 51a7564ebe0..43d06e364e3 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,12 +1422,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa h1:IOWXNq3vIm8J7AgjRS1ozslripIX4T9rYsufpaJe4C8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512152539-826d731ba4fa/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6 h1:9EAwDMu3nvLsgzC4kv58qvFP3OjWivYOxA21/QBsUdE= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250506195202-6a3f20db41c6/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= From e08ee6f7d4f9fc0623836025d17ed470ccfaf287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 15 May 2025 14:20:56 +0200 Subject: [PATCH 093/136] Merge ccip-aptos-codec into aptos-ccip-e2e-tests --- .changeset/better-buckets-hang.md | 5 + .changeset/chatty-toes-compare.md | 6 + .changeset/chatty-toes-press.md | 7 + .changeset/tasty-pillows-drum.md | 5 + .../actions/build-chainlink-image/action.yml | 4 +- .github/e2e-tests.yml | 6 +- .github/workflows/build-publish.yml | 5 + .github/workflows/ci-core.yml | 7 +- .github/workflows/flakeguard.yml | 6 +- .github/workflows/run-nightly-e2e-tests.yml | 11 +- .gitignore | 4 + .mockery.yaml | 7 +- common/txmgr/mocks/utils.go | 17 + .../capabilities/ccip/ccipaptos/crcwconfig.go | 56 + .../ccip/ccipaptos/extradatadecoder.go | 2 +- .../ccip/ccipaptos/pluginconfig.go | 21 + core/capabilities/ccip/ccipevm/crcwconfig.go | 90 + .../capabilities/ccip/ccipevm/executecodec.go | 8 +- .../ccip/ccipevm/executecodec_test.go | 26 +- ...{extradatadecoder.go => extradatacodec.go} | 19 +- ...decoder_test.go => extradatacodec_test.go} | 4 +- .../ccip/ccipevm/gas_helpers_test.go | 4 +- core/capabilities/ccip/ccipevm/helpers.go | 7 - .../capabilities/ccip/ccipevm/helpers_test.go | 2 +- core/capabilities/ccip/ccipevm/msghasher.go | 7 +- .../ccip/ccipevm/msghasher_test.go | 33 +- .../capabilities/ccip/ccipevm/pluginconfig.go | 23 + .../ccip/ccipsolana/crcwconfig.go | 73 + .../ccip/ccipsolana/executecodec.go | 4 +- .../ccip/ccipsolana/executecodec_test.go | 21 +- ...{extradatadecoder.go => extradatacodec.go} | 12 +- ...decoder_test.go => extradatacodec_test.go} | 2 +- .../ccip/ccipsolana/gas_helpers_test.go | 6 +- .../capabilities/ccip/ccipsolana/msghasher.go | 7 +- .../ccip/ccipsolana/msghasher_test.go | 30 +- .../ccip/ccipsolana/pluginconfig.go | 23 + core/capabilities/ccip/common/addresscodec.go | 33 +- core/capabilities/ccip/common/common.go | 20 +- core/capabilities/ccip/common/crcwconfig.go | 71 + .../ccip/common/default/default.go | 22 + .../ccip/common/extradatacodec.go | 68 +- .../mocks/chain_specific_address_codec.go | 146 ++ .../ccip/common/mocks/extra_data_codec.go | 154 -- .../mocks/source_chain_extra_data_codec.go | 152 ++ .../ccip/common/msgfieldscodec.go | 20 + core/capabilities/ccip/common/pluginconfig.go | 54 + .../ccip/configs/aptos/contract_reader.go | 18 +- core/capabilities/ccip/delegate.go | 11 +- .../aptos_contract_transmitter_factory.go | 21 +- .../ccip/ocrimpls/contract_transmitter.go | 10 +- .../ocrimpls/contract_transmitter_test.go | 25 +- .../evm_contract_transmitter_factory.go | 17 +- .../svm_contract_transmitter_factory.go | 26 +- .../capabilities/ccip/oraclecreator/plugin.go | 400 +--- .../contract_transmitter_factory.go | 2 +- .../remote/executable/client_test.go | 1 + .../request/transmit_schedule_event.go | 2 +- core/chains/evm/log/integration_test.go | 21 +- .../evm/txmgr/broadcaster_benchmark_test.go | 6 +- core/chains/evm/txmgr/broadcaster_test.go | 46 +- .../evm/txmgr/confirmer_benchmark_test.go | 6 +- core/chains/evm/txmgr/confirmer_test.go | 124 +- .../evm/txmgr/evm_tx_store_benchmark_test.go | 3 +- core/chains/evm/txmgr/evm_tx_store_test.go | 254 +- .../evm/txmgr/finalizer_benchmark_test.go | 4 +- core/chains/evm/txmgr/finalizer_test.go | 161 +- core/chains/evm/txmgr/mocks/config.go | 260 -- core/chains/evm/txmgr/mocks/utils.go | 18 - core/chains/evm/txmgr/reaper_test.go | 22 +- core/chains/evm/txmgr/resender_test.go | 25 +- .../evm/txmgr/stuck_tx_detector_test.go | 63 +- core/chains/evm/txmgr/tracker_test.go | 8 +- core/chains/evm/txmgr/txmgr_test.go | 75 +- core/chains/evm/txmgr/txmgrtest/utils.go | 140 ++ core/cmd/evm_transaction_commands_test.go | 13 +- core/cmd/shell_local_test.go | 9 +- core/internal/cltest/cltest.go | 46 - core/internal/cltest/factories.go | 131 - core/scripts/go.mod | 16 +- core/scripts/go.sum | 32 +- core/services/blockhashstore/bhs_test.go | 2 +- .../fluxmonitorv2/flux_monitor_test.go | 44 +- core/services/fluxmonitorv2/orm_test.go | 2 +- .../headreporter/prometheus_reporter_test.go | 16 +- core/services/keeper/upkeep_executer_test.go | 3 +- core/services/keystore/eth_test.go | 5 +- core/services/ocr2/delegate_test.go | 3 +- .../ccip/transmitter/transmitter_test.go | 3 +- core/services/ocrcommon/peer_wrapper_test.go | 2 +- core/services/ocrcommon/transmitter_test.go | 2 +- core/services/pipeline/orm_test.go | 13 +- core/services/pipeline/task.eth_call_test.go | 2 +- core/services/pipeline/task.eth_tx_test.go | 2 +- core/services/relay/evm/chain_writer_test.go | 2 +- core/services/relay/evm/evm_service_test.go | 3 +- .../functions/contract_transmitter_test.go | 2 +- .../statuschecker/txm_status_checker_test.go | 3 +- core/services/relay/evm/write_target_test.go | 8 +- core/services/versioning/orm.go | 5 +- core/services/versioning/orm_test.go | 91 +- core/services/workflows/engine.go | 16 +- .../workflows/syncer/workflow_registry.go | 6 +- .../workflows/test/wasm/v2/cmd/main.go | 12 + core/services/workflows/v2/config.go | 11 +- core/services/workflows/v2/engine.go | 24 +- core/services/workflows/v2/engine_test.go | 157 +- core/web/evm_transactions_controller_test.go | 19 +- core/web/evm_tx_attempts_controller_test.go | 9 +- .../changeset/aptos/config/deploy_chain.go | 9 +- .../changeset/aptos/cs_deploy_aptos_chain.go | 15 +- .../changeset/aptos/cs_set_ocr3_offramp.go | 20 +- .../changeset/aptos/cs_update_aptos_ccip.go | 20 +- .../changeset/aptos/cs_update_aptos_lanes.go | 22 +- .../changeset/aptos/operation/dependencies.go | 10 +- .../changeset/aptos/sequence/update_lane.go | 8 +- .../v1_6/cs_add_evm_solana_lane.go | 45 +- .../v1_6/cs_add_evm_solana_lane_test.go | 18 +- deployment/ccip/changeset/cs_prerequisites.go | 90 +- .../ccip/changeset/cs_prerequisites_test.go | 3 +- deployment/ccip/changeset/globals/config.go | 23 +- .../changeset/internal/deploy_home_chain.go | 9 +- .../ccip/changeset/save_existing_test.go | 13 +- .../changeset/solana/cs_add_remote_chain.go | 88 +- .../ccip/changeset/solana/cs_billing.go | 125 +- .../ccip/changeset/solana/cs_build_solana.go | 43 +- .../changeset/solana/cs_chain_contracts.go | 155 +- .../solana/cs_chain_contracts_test.go | 36 +- .../ccip/changeset/solana/cs_deploy_chain.go | 125 +- .../changeset/solana/cs_deploy_chain_test.go | 45 +- .../solana/cs_disable_remote_chain.go | 38 +- deployment/ccip/changeset/solana/cs_e2e.go | 180 ++ deployment/ccip/changeset/solana/cs_idl.go | 40 +- deployment/ccip/changeset/solana/cs_ops.go | 119 +- .../ccip/changeset/solana/cs_set_ocr3.go | 20 +- .../ccip/changeset/solana/cs_solana_token.go | 115 +- .../changeset/solana/cs_solana_token_test.go | 21 +- .../solana/cs_token_admin_registry.go | 65 +- .../ccip/changeset/solana/cs_token_pool.go | 175 +- .../changeset/solana/cs_token_pool_test.go | 115 +- .../changeset/solana/cs_verify_contracts.go | 14 +- .../solana/ownership_transfer_helpers.go | 269 ++- .../changeset/solana/save_existing_test.go | 11 +- .../transfer_ccip_to_mcms_with_timelock.go | 79 +- ...ransfer_ccip_to_mcms_with_timelock_test.go | 109 +- deployment/ccip/changeset/solana/utils.go | 45 +- deployment/ccip/changeset/state.go | 2117 ----------------- .../changeset/testhelpers/feestest/helpers.go | 19 +- .../messagelimitationstest/helpers.go | 14 +- .../testhelpers/messagingtest/helpers.go | 15 +- .../changeset/testhelpers/test_assertions.go | 46 +- .../changeset/testhelpers/test_environment.go | 36 +- .../changeset/testhelpers/test_helpers.go | 193 +- .../testhelpers/test_token_helpers.go | 30 +- .../testhelpers/test_usdc_helpers.go | 29 +- .../testhelpers/v1_5/test_helpers.go | 26 +- deployment/ccip/changeset/v1_5/cs_jobspec.go | 15 +- .../ccip/changeset/v1_5/cs_lane_contracts.go | 48 +- .../ccip/changeset/v1_5/cs_ocr2_config.go | 24 +- deployment/ccip/changeset/v1_5/cs_rmn.go | 27 +- deployment/ccip/changeset/v1_5/e2e_test.go | 6 +- .../commonconfig.go} | 281 +-- .../changeset/v1_5_1/cs_accept_admin_role.go | 17 +- .../v1_5_1/cs_accept_admin_role_test.go | 62 +- .../ccip/changeset/v1_5_1/cs_add_token_e2e.go | 72 +- .../changeset/v1_5_1/cs_add_token_e2e_test.go | 17 +- .../v1_5_1/cs_configure_token_pools.go | 53 +- .../v1_5_1/cs_configure_token_pools_test.go | 93 +- .../v1_5_1/cs_deploy_token_pool_factory.go | 17 +- .../cs_deploy_token_pool_factory_test.go | 41 +- .../changeset/v1_5_1/cs_deploy_token_pools.go | 49 +- .../v1_5_1/cs_deploy_token_pools_test.go | 44 +- .../v1_5_1/cs_deploy_usdc_token_pools.go | 22 +- .../v1_5_1/cs_deploy_usdc_token_pools_test.go | 24 +- .../changeset/v1_5_1/cs_propose_admin_role.go | 17 +- .../v1_5_1/cs_propose_admin_role_test.go | 76 +- .../ccip/changeset/v1_5_1/cs_set_pool.go | 17 +- .../ccip/changeset/v1_5_1/cs_set_pool_test.go | 62 +- .../cs_sync_usdc_domains_with_chains.go | 14 +- .../cs_sync_usdc_domains_with_chains_test.go | 18 +- .../v1_5_1/cs_transfer_admin_role.go | 17 +- .../v1_5_1/cs_transfer_admin_role_test.go | 68 +- .../changeset/v1_6/accept_ownership_test.go | 7 +- deployment/ccip/changeset/v1_6/config.go | 2 +- .../v1_6/cs_active_candidate_test.go | 8 +- .../ccip/changeset/v1_6/cs_add_lane_test.go | 7 +- .../changeset/v1_6/cs_add_new_chain_e2e.go | 59 +- .../v1_6/cs_add_new_chain_e2e_test.go | 18 +- .../ccip/changeset/v1_6/cs_ccip_home.go | 182 +- .../ccip/changeset/v1_6/cs_ccip_home_test.go | 17 +- .../ccip/changeset/v1_6/cs_chain_contracts.go | 291 +-- .../changeset/v1_6/cs_chain_contracts_test.go | 72 +- .../ccip/changeset/v1_6/cs_deploy_chain.go | 62 +- .../changeset/v1_6/cs_deploy_chain_test.go | 10 +- .../ccip/changeset/v1_6/cs_home_chain.go | 114 +- .../ccip/changeset/v1_6/cs_home_chain_test.go | 25 +- deployment/ccip/changeset/v1_6/cs_jobspec.go | 17 +- .../changeset/v1_6/cs_rmn_curse_uncurse.go | 81 +- .../v1_6/cs_update_bidirectional_lanes.go | 17 +- .../cs_update_bidirectional_lanes_test.go | 10 +- .../changeset/v1_6/cs_update_rmn_config.go | 106 +- deployment/ccip/manualexechelpers/exec.go | 37 +- .../deployergroup}/deployer_group.go | 30 +- .../deployergroup}/deployer_group_test.go | 57 +- deployment/ccip/{ => shared}/helpers.go | 2 +- .../stateview/aptos/state.go} | 38 +- deployment/ccip/shared/stateview/evm/state.go | 1050 ++++++++ .../stateview/solana/state.go} | 517 ++-- deployment/ccip/shared/stateview/state.go | 1094 +++++++++ .../stateview}/state_test.go | 22 +- .../{changeset => shared/stateview}/view.go | 2 +- .../stateview}/view_test.go | 6 +- .../ccip/{changeset => shared}/token_info.go | 6 +- deployment/ccip/shared/token_pools.go | 91 + deployment/ccip/shared/types.go | 75 + deployment/ccip/view/solana/feequoter.go | 5 +- deployment/ccip/view/solana/offramp.go | 5 +- deployment/ccip/view/solana/rmnremote.go | 5 +- deployment/ccip/view/solana/router.go | 5 +- deployment/ccip/view/solana/token.go | 4 +- deployment/ccip/view/solana/tokenpool.go | 5 +- .../ccip/view/v1_2/price_registry_test.go | 6 +- deployment/ccip/view/v1_5/offramp_test.go | 8 +- deployment/ccip/view/v1_5/onramp_test.go | 6 +- deployment/ccip/view/v1_6/ccip_home.go | 4 +- deployment/ccip/view/v1_6/ccip_home_test.go | 8 +- deployment/ccip/view/v1_6/rmnremote_test.go | 10 +- deployment/{ => cldf}/migrated_environment.go | 2 +- .../common/changeset/deploy_link_token.go | 12 +- .../changeset/deploy_mcms_with_timelock.go | 6 +- .../deploy_mcms_with_timelock_test.go | 2 +- .../example/add_mint_burners_link.go | 8 +- .../common/changeset/example/link_transfer.go | 19 +- .../changeset/example/link_transfer_test.go | 20 +- .../common/changeset/example/mint_link.go | 6 +- .../operations/deploy_and_mint_example.go | 8 +- .../changeset/example/operations/operation.go | 6 +- .../operations/retry_config_example.go | 10 +- .../operations/terminal_error_example.go | 6 +- .../changeset/example/solana_transfer_mcm.go | 6 +- .../example/solana_transfer_mcm_test.go | 10 +- .../common/changeset/internal/evm/mcms.go | 20 +- deployment/common/changeset/jobspec.go | 11 +- deployment/common/changeset/mcms_firedrill.go | 5 +- .../common/changeset/mcms_firedrill_test.go | 4 +- .../changeset/run_changeset.go} | 2 +- deployment/common/changeset/save_existing.go | 6 +- .../common/changeset/save_existing_test.go | 12 +- .../common/changeset/set_config_mcms.go | 206 +- .../common/changeset/set_config_mcms_test.go | 276 +-- .../common/changeset/solana/fund_mcm_pdas.go | 6 +- .../changeset/solana/fund_mcm_pdas_test.go | 10 +- deployment/common/changeset/solana/helpers.go | 6 +- .../solana/mcms/access_controller.go | 14 +- .../common/changeset/solana/mcms/mcm.go | 10 +- .../common/changeset/solana/mcms/mcms.go | 5 +- .../common/changeset/solana/mcms/timelock.go | 6 +- .../changeset/solana/transfer_ownership.go | 9 +- .../solana/transfer_ownership_test.go | 13 +- .../changeset/solana/update_delay_timelock.go | 5 +- .../solana/update_delay_timelock_test.go | 12 +- deployment/common/changeset/state.go | 10 +- deployment/common/changeset/state/evm.go | 12 +- deployment/common/changeset/state/evm_test.go | 9 +- deployment/common/changeset/state/solana.go | 6 +- deployment/common/changeset/state_test.go | 4 +- deployment/common/changeset/test_helpers.go | 38 +- .../common/changeset/test_helpers_test.go | 30 +- .../transfer_to_mcms_with_timelock.go | 33 +- .../transfer_to_mcms_with_timelock_test.go | 7 +- .../common/proposalutils/mcms_helpers.go | 12 +- .../common/proposalutils/mcms_test_helpers.go | 18 +- deployment/common/proposalutils/propose.go | 40 +- .../data-feeds/changeset/accept_ownership.go | 8 +- .../changeset/confirm_aggregator.go | 10 +- deployment/data-feeds/changeset/deploy.go | 7 +- .../changeset/deploy_aggregator_proxy.go | 6 +- .../deploy_bundle_aggregator_proxy.go | 6 +- .../data-feeds/changeset/deploy_cache.go | 6 +- .../changeset/import_to_addressbook.go | 6 +- .../data-feeds/changeset/jd_delete_jobs.go | 6 +- .../changeset/jd_propose_bt_jobs.go | 6 +- .../changeset/jd_propose_wf_jobs.go | 10 +- .../data-feeds/changeset/jd_register_nodes.go | 6 +- .../data-feeds/changeset/jd_update_nodes.go | 6 +- .../data-feeds/changeset/migrate_feeds.go | 10 +- .../changeset/new_feed_with_proxy.go | 16 +- deployment/data-feeds/changeset/proposal.go | 5 +- .../changeset/propose_aggregator.go | 10 +- .../changeset/remove_dataid_proxy_mapping.go | 10 +- .../data-feeds/changeset/remove_feed.go | 12 +- .../changeset/remove_feed_config.go | 10 +- .../changeset/set_bundle_feed_config.go | 10 +- .../data-feeds/changeset/set_feed_admin.go | 10 +- .../data-feeds/changeset/set_feed_config.go | 10 +- deployment/data-feeds/changeset/state.go | 10 +- .../changeset/update_data_id_proxy.go | 10 +- deployment/data-feeds/changeset/utils.go | 21 - deployment/data-feeds/changeset/validation.go | 4 +- deployment/data-feeds/offchain/jd.go | 8 +- .../call_set_channel_definitions.go | 11 +- .../deploy_channel_config_store.go | 13 +- deployment/data-streams/changeset/common.go | 8 +- ...all_configurator_promote_staging_config.go | 11 +- ...call_configurator_set_production_config.go | 11 +- .../call_configurator_set_staging_config.go | 10 +- .../v0_5_0/deploy_configurator.go | 13 +- deployment/data-streams/changeset/deploy.go | 8 +- .../fee-manager/call_pay_link_deficit.go | 10 +- .../fee-manager/call_pay_link_deficit_test.go | 7 +- .../fee-manager/call_set_native_surcharge.go | 9 +- .../call_update_subscriber_discount.go | 10 +- .../call_update_subscriber_global_discount.go | 10 +- .../changeset/fee-manager/call_withdraw.go | 10 +- .../fee-manager/deploy_fee_manager.go | 15 +- .../changeset/fee-manager/state.go | 5 +- .../changeset/fee-manager/test_helpers.go | 5 +- .../data-streams/changeset/helpers_test.go | 161 ++ .../changeset/jd_distribute_llo_jobs.go | 21 +- .../changeset/jd_distribute_llo_jobs_test.go | 75 +- .../changeset/jd_distribute_stream_jobs.go | 15 +- .../jd_distribute_stream_jobs_test.go | 59 +- .../changeset/jd_register_nodes.go | 8 +- .../data-streams/changeset/jd_revoke_jobs.go | 97 + .../changeset/jd_revoke_jobs_test.go | 173 ++ .../mcms/deploy_and_transfer_mcms.go | 8 +- .../reward-manager/call_claim_rewards.go | 8 +- .../reward-manager/call_pay_recipients.go | 8 +- .../reward-manager/call_set_fee_manager.go | 6 +- .../call_set_reward_recipients.go | 8 +- .../call_update_reward_recipients.go | 8 +- .../reward-manager/deploy_reward_manager.go | 15 +- .../reward-manager/reward_manager.go | 5 +- .../changeset/reward-manager/test_helpers.go | 5 +- .../changeset/save_contract_views.go | 6 +- .../sequence/deploy_chain_contracts.go | 8 +- .../sequence/deploy_chain_contracts_evm.go | 31 +- .../data-streams/changeset/state/evm.go | 9 +- .../changeset/testutil/test_helpers.go | 23 +- .../verification/call_activate_config.go | 8 +- .../verification/call_deactivate_config.go | 8 +- .../verification/call_initialize_verifier.go | 11 +- .../call_set_access_controller.go | 12 +- .../changeset/verification/call_set_config.go | 8 +- .../verification/call_set_fee_manager.go | 11 +- .../verification/call_unset_verifier.go | 11 +- .../verification/call_update_config.go | 8 +- .../changeset/verification/deploy_verifier.go | 15 +- .../verification/deploy_verifier_proxy.go | 14 +- .../changeset/verification/state.go | 7 +- .../changeset/verification/test_helpers.go | 6 +- .../data-streams/utils/mcmsutil/mcmsutil.go | 13 +- .../data-streams/utils/txutil/get-tx.go | 6 +- .../data-streams/utils/txutil/transaction.go | 6 +- .../utils/txutil/transaction_test.go | 8 +- deployment/environment/crib/ccip_deployer.go | 48 +- deployment/environment/crib/helpers.go | 10 +- deployment/environment/crib/types.go | 6 +- deployment/environment/devenv/chain.go | 38 +- deployment/environment/devenv/environment.go | 6 +- deployment/environment/memory/aptos_chains.go | 11 +- deployment/environment/memory/environment.go | 44 +- deployment/environment/memory/node.go | 16 +- .../environment/test/job_service_client.go | 149 +- .../test/job_service_client_test.go | 386 +++ deployment/go.mod | 16 +- deployment/go.sum | 32 +- deployment/helpers.go | 4 +- .../keystone/changeset/accept_ownership.go | 6 +- .../keystone/changeset/add_capabilities.go | 8 +- deployment/keystone/changeset/add_dons.go | 5 +- deployment/keystone/changeset/add_nodes.go | 4 +- deployment/keystone/changeset/add_nops.go | 5 +- .../keystone/changeset/addrbook_utils.go | 16 +- .../changeset/append_node_capabilities.go | 5 +- .../keystone/changeset/configure_contracts.go | 3 +- deployment/keystone/changeset/contract_set.go | 4 +- deployment/keystone/changeset/contracts.go | 22 +- .../changeset/deploy_balance_reader.go | 5 +- .../keystone/changeset/deploy_consumer.go | 6 +- .../keystone/changeset/deploy_forwarder.go | 9 +- .../changeset/deploy_forwarder_test.go | 4 +- deployment/keystone/changeset/deploy_ocr3.go | 9 +- .../keystone/changeset/deploy_registry.go | 9 +- .../internal/append_node_capabilities.go | 6 +- .../internal/append_node_capabilities_test.go | 3 +- .../internal/capability_management.go | 14 +- .../internal/capability_registry_deployer.go | 4 +- .../changeset/internal/contract_set.go | 14 +- .../keystone/changeset/internal/deploy.go | 54 +- .../changeset/internal/deploy_test.go | 28 +- .../changeset/internal/forwarder_deployer.go | 4 +- .../keystone/changeset/internal/ocr3config.go | 9 +- .../changeset/internal/ocr3config_test.go | 7 +- .../changeset/internal/remove_dons.go | 10 +- .../changeset/internal/remove_dons_test.go | 13 +- .../keystone/changeset/internal/state.go | 6 +- .../keystone/changeset/internal/state_test.go | 4 +- .../keystone/changeset/internal/types.go | 4 +- .../keystone/changeset/internal/update_don.go | 10 +- .../changeset/internal/update_don_test.go | 5 +- .../internal/update_node_capabilities.go | 6 +- .../internal/update_node_capabilities_test.go | 3 +- .../changeset/internal/update_nodes.go | 17 +- .../changeset/internal/update_nodes_test.go | 18 +- deployment/keystone/changeset/remove_dons.go | 5 +- deployment/keystone/changeset/state.go | 4 +- .../keystone/changeset/test/env_setup.go | 26 +- .../keystone/changeset/test/registry.go | 28 +- deployment/keystone/changeset/update_don.go | 7 +- .../changeset/update_node_capabilities.go | 6 +- deployment/keystone/changeset/update_nodes.go | 5 +- deployment/keystone/changeset/view_test.go | 74 +- .../changeset/workflowregistry/deploy.go | 5 +- .../changeset/workflowregistry/setup_test.go | 7 +- .../changeset/workflowregistry/strategies.go | 7 +- .../workflowregistry/update_allowed_dons.go | 5 +- .../update_allowed_dons_test.go | 6 +- .../update_authorized_addresses.go | 7 +- .../update_authorized_addresses_test.go | 6 +- .../workflow_registry_deployer.go | 5 +- .../test/changeset/capability_registry.go | 13 +- go.mod | 14 +- go.sum | 28 +- integration-tests/go.mod | 16 +- integration-tests/go.sum | 32 +- .../load/ccip/ccip_staging_test.go | 5 +- integration-tests/load/ccip/ccip_test.go | 18 +- .../load/ccip/destination_gun.go | 24 +- integration-tests/load/ccip/helpers.go | 15 +- integration-tests/load/go.mod | 18 +- integration-tests/load/go.sum | 32 +- .../smoke/ccip/ccip_add_chain_test.go | 19 +- .../smoke/ccip/ccip_aptos_messaging_test.go | 4 +- .../smoke/ccip/ccip_batching_test.go | 20 +- .../ccip/ccip_cs_rmn_curse_uncurse_test.go | 14 +- .../ccip/ccip_cs_update_rmn_config_test.go | 19 +- .../smoke/ccip/ccip_disable_lane_test.go | 5 +- .../smoke/ccip/ccip_fees_test.go | 35 +- .../smoke/ccip/ccip_gas_price_updates_test.go | 6 +- .../ccip/ccip_message_limitations_test.go | 5 +- .../smoke/ccip/ccip_messaging_test.go | 11 +- .../ccip/ccip_migration_to_v_1_6_test.go | 26 +- .../smoke/ccip/ccip_ooo_execution_test.go | 10 +- .../smoke/ccip/ccip_reader_test.go | 12 +- .../smoke/ccip/ccip_reorg_test.go | 13 +- integration-tests/smoke/ccip/ccip_rmn_test.go | 16 +- .../ccip/ccip_token_price_updates_test.go | 8 +- .../smoke/ccip/ccip_token_transfer_test.go | 9 +- .../smoke/ccip/ccip_usdc_test.go | 12 +- integration-tests/testconfig/ccip/chaos.go | 4 +- integration-tests/testconfig/ccip/load.go | 5 +- .../testsetups/ccip/test_helpers.go | 4 +- plugins/chainlink.prebuilt.Dockerfile | 18 + plugins/plugins.public.yaml | 2 +- system-tests/lib/cre/contracts/contracts.go | 5 +- system-tests/lib/cre/devenv/devenv.go | 6 +- .../lib/cre/environment/environment.go | 5 +- system-tests/lib/cre/types/keystone.go | 14 +- system-tests/lib/cre/workflow/workflow.go | 17 +- system-tests/lib/crecli/commands.go | 42 +- system-tests/lib/crecli/settings.go | 133 +- system-tests/lib/go.mod | 16 +- system-tests/lib/go.sum | 32 +- system-tests/tests/.gitignore | 2 +- system-tests/tests/go.mod | 16 +- system-tests/tests/go.sum | 32 +- .../cre/workflow-don-load-test-streams.toml | 2 +- .../tests/smoke/cre/cmd/download/download.go | 56 +- .../smoke/cre/cmd/environment/environment.go | 5 +- .../cre/environment-capabilities-don-ci.toml | 2 +- .../environment-capabilities-don-crib.toml | 2 +- .../cre/environment-capabilities-don.toml | 2 +- .../smoke/cre/environment-gateway-don-ci.toml | 2 +- .../smoke/cre/environment-gateway-don.toml | 2 +- .../environment-one-don-multichain-ci.toml | 2 +- .../cre/environment-one-don-multichain.toml | 2 +- .../cre/environment-one-don-single-chain.toml | 2 +- system-tests/tests/smoke/cre/guidelines.md | 2 +- system-tests/tests/smoke/cre/por_test.go | 17 +- tools/bin/go_core_ccip_deployment_tests | 2 +- tools/bin/go_core_tests | 2 +- 481 files changed, 10175 insertions(+), 8418 deletions(-) create mode 100644 .changeset/better-buckets-hang.md create mode 100644 .changeset/chatty-toes-compare.md create mode 100644 .changeset/chatty-toes-press.md create mode 100644 .changeset/tasty-pillows-drum.md create mode 100644 common/txmgr/mocks/utils.go create mode 100644 core/capabilities/ccip/ccipaptos/crcwconfig.go create mode 100644 core/capabilities/ccip/ccipaptos/pluginconfig.go create mode 100644 core/capabilities/ccip/ccipevm/crcwconfig.go rename core/capabilities/ccip/ccipevm/{extradatadecoder.go => extradatacodec.go} (77%) rename core/capabilities/ccip/ccipevm/{extradatadecoder_test.go => extradatacodec_test.go} (98%) create mode 100644 core/capabilities/ccip/ccipevm/pluginconfig.go create mode 100644 core/capabilities/ccip/ccipsolana/crcwconfig.go rename core/capabilities/ccip/ccipsolana/{extradatadecoder.go => extradatacodec.go} (81%) rename core/capabilities/ccip/ccipsolana/{extradatadecoder_test.go => extradatacodec_test.go} (98%) create mode 100644 core/capabilities/ccip/ccipsolana/pluginconfig.go create mode 100644 core/capabilities/ccip/common/crcwconfig.go create mode 100644 core/capabilities/ccip/common/default/default.go create mode 100644 core/capabilities/ccip/common/mocks/chain_specific_address_codec.go delete mode 100644 core/capabilities/ccip/common/mocks/extra_data_codec.go create mode 100644 core/capabilities/ccip/common/mocks/source_chain_extra_data_codec.go create mode 100644 core/capabilities/ccip/common/msgfieldscodec.go create mode 100644 core/capabilities/ccip/common/pluginconfig.go rename core/capabilities/ccip/{oraclecreator => types}/contract_transmitter_factory.go (97%) delete mode 100644 core/chains/evm/txmgr/mocks/config.go delete mode 100644 core/chains/evm/txmgr/mocks/utils.go create mode 100644 core/chains/evm/txmgr/txmgrtest/utils.go create mode 100644 core/services/workflows/test/wasm/v2/cmd/main.go create mode 100644 deployment/ccip/changeset/solana/cs_e2e.go delete mode 100644 deployment/ccip/changeset/state.go rename deployment/ccip/changeset/{token_pools.go => v1_5_1/commonconfig.go} (63%) rename deployment/ccip/{changeset => shared/deployergroup}/deployer_group.go (93%) rename deployment/ccip/{changeset => shared/deployergroup}/deployer_group_test.go (83%) rename deployment/ccip/{ => shared}/helpers.go (98%) rename deployment/ccip/{changeset/aptos_state.go => shared/stateview/aptos/state.go} (64%) create mode 100644 deployment/ccip/shared/stateview/evm/state.go rename deployment/ccip/{changeset/solana_state.go => shared/stateview/solana/state.go} (58%) create mode 100644 deployment/ccip/shared/stateview/state.go rename deployment/ccip/{changeset => shared/stateview}/state_test.go (92%) rename deployment/ccip/{changeset => shared/stateview}/view.go (97%) rename deployment/ccip/{changeset => shared/stateview}/view_test.go (73%) rename deployment/ccip/{changeset => shared}/token_info.go (98%) create mode 100644 deployment/ccip/shared/token_pools.go create mode 100644 deployment/ccip/shared/types.go rename deployment/{ => cldf}/migrated_environment.go (98%) rename deployment/{migrated_changeset.go => common/changeset/run_changeset.go} (97%) create mode 100644 deployment/data-streams/changeset/helpers_test.go create mode 100644 deployment/data-streams/changeset/jd_revoke_jobs.go create mode 100644 deployment/data-streams/changeset/jd_revoke_jobs_test.go create mode 100644 plugins/chainlink.prebuilt.Dockerfile diff --git a/.changeset/better-buckets-hang.md b/.changeset/better-buckets-hang.md new file mode 100644 index 00000000000..1b22e5bb515 --- /dev/null +++ b/.changeset/better-buckets-hang.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal add env var CL_SKIP_APP_VERSION_CHECK to enable booting prior app versions diff --git a/.changeset/chatty-toes-compare.md b/.changeset/chatty-toes-compare.md new file mode 100644 index 00000000000..77bf6c50a4e --- /dev/null +++ b/.changeset/chatty-toes-compare.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +#updated Bump chainlink-solana +#updated Bump chainlink-ccip diff --git a/.changeset/chatty-toes-press.md b/.changeset/chatty-toes-press.md new file mode 100644 index 00000000000..d79c4704713 --- /dev/null +++ b/.changeset/chatty-toes-press.md @@ -0,0 +1,7 @@ +--- +"chainlink": patch +--- + +#updated Bump chainlink-solana +#updated Bump chainlink-ccip +#updated Bump mcms diff --git a/.changeset/tasty-pillows-drum.md b/.changeset/tasty-pillows-drum.md new file mode 100644 index 00000000000..908240c6605 --- /dev/null +++ b/.changeset/tasty-pillows-drum.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Cleanup and refactoring several functions to use the plugin map #added diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml index 0e457560bf0..c8c98055f2f 100644 --- a/.github/actions/build-chainlink-image/action.yml +++ b/.github/actions/build-chainlink-image/action.yml @@ -21,7 +21,7 @@ inputs: check_image_exists: description: "Check if the image exists in ECR before building" required: false - default: 'false' + default: "false" runs: using: composite @@ -37,7 +37,7 @@ runs: AWS_ROLE_TO_ASSUME: ${{ inputs.AWS_ROLE_TO_ASSUME }} - name: Build Image if: steps.check-image.outputs.exists != 'true' - uses: smartcontractkit/.github/actions/ctf-build-image@1a26fe378d7ebdc34ab1fe31ec4a6d1c376199f8 # ctf-build-image@0.0.0 + uses: smartcontractkit/.github/actions/ctf-build-image@ctf-build-image/0.2.0 with: cl_repo: smartcontractkit/chainlink cl_ref: ${{ inputs.git_commit_sha }} diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index b6d1b7766cd..7c26a396c53 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -214,7 +214,7 @@ runner-test-matrix: - Merge Queue CRE E2E Core Tests - Nightly E2E Tests - Push CRE E2E Core Tests - test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.1.5 --capability-name cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_SingleDon_MultipleWriters_MockedPrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop + test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.2.0 --capability-names cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_SingleDon_MultipleWriters_MockedPrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop pyroscope_env: ci-smoke-cre-evm-simulated test_env_vars: E2E_TEST_CHAINLINK_VERSION: "{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}" # This is the chainlink version that has the plugins @@ -235,7 +235,7 @@ runner-test-matrix: - Merge Queue CRE E2E Core Tests - Nightly E2E Tests - Push CRE E2E Core Tests - test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.1.5 --capability-name cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_GatewayDon_MockedPrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop + test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.2.0 --capability-names cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_GatewayDon_MockedPrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop pyroscope_env: ci-smoke-capabilities-evm-simulated test_env_vars: E2E_TEST_CHAINLINK_VERSION: "{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}" # This is the chainlink version that has the plugins @@ -256,7 +256,7 @@ runner-test-matrix: - Merge Queue CRE E2E Core Tests - Nightly E2E Tests - Push CRE E2E Core Tests - test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.1.5 --capability-name cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_CapabilitiesDons_LivePrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop + test_cmd: cd tests && pushd smoke/cre/cmd > /dev/null && go run main.go download all --output-dir ../ --gh-token-env-var-name GITHUB_API_TOKEN --cre-cli-version v0.2.0 --capability-names cron --capability-version v1.0.2-alpha 1>&2 && popd > /dev/null && { go test github.com/smartcontractkit/chainlink/system-tests/tests/smoke/cre -v -run "^(TestCRE_OCR3_PoR_Workflow_CapabilitiesDons_LivePrice)$" -timeout 30m -count=1 -test.parallel=1 -json; exit_code=$?; ../../tools/ci/wait-for-containers-to-stop.sh 30; exit $exit_code; } # Sleep to allow testcontainers to stop pyroscope_env: ci-smoke-capabilities-evm-simulated test_env_vars: E2E_TEST_CHAINLINK_VERSION: "{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}" # This is the chainlink version that has the plugins diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 9bc697b19d4..2d4811a18bf 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -58,6 +58,11 @@ jobs: with: tag: ${{ github.ref_name }} assert: true + - name: Fail if git tag is not from allowed branches + uses: smartcontractkit/.github/actions/guard-tag-from-branch@01d931b0455a754d12e7143cc54a5a3521a8f6f6 # guard-tag-from-branch@0.1.3 + with: + tag: ${{ github.ref_name }} + branch-regex: '^(develop|release\/.*)' build-sign-publish-chainlink: needs: [checks] diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 16bdbb15b91..5c71c1b6a79 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -316,9 +316,7 @@ jobs: USE_FLAKEGUARD: ${{ matrix.type.use-flakeguard == 'true' && 'true' || '' }} run: | # See: https://github.com/golang/go/issues/69179 - GODEBUG=goindex=0 - - ./tools/bin/${{ matrix.type.cmd }} ./... + GODEBUG=goindex=0 ./tools/bin/${{ matrix.type.cmd }} ./... - name: Generate Flakeguard Test Reports if: ${{ always() && steps.run-tests.outcome != 'skipped' && matrix.type.should-run == 'true' && matrix.type.use-flakeguard == 'true' }} @@ -640,6 +638,7 @@ jobs: runs-on: ubuntu-latest env: SH_TEST_RUNNER: runs-on=${{ github.run_id }}/cpu=32+64/ram=64+128/family=c6id+m6id+m6idn/spot=false/extras=s3-cache + SH_DEPLOYMENT_TEST_RUNNER: runs-on=${{ github.run_id }}/cpu=48/ram=96/family=c6id/spot=false/extras=s3-cache SH_FUZZ_RUNNER: runs-on=${{ github.run_id}}/cpu=8+16/ram=32+64/family=c6id+m6id+m6idn/spot=false/extras=s3-cache SH_RACE_TEST_RUNNER: runs-on=${{ github.run_id}}/cpu=64+128/ram=128+128/family=c7+m7/disk=large/spot=false/extras=s3-cache GH_TEST_RUNNER: ubuntu22.04-32cores-128GB @@ -716,7 +715,7 @@ jobs: echo "Opt-out is false for current run. Using self-hosted runner for deployment tests." echo "deployment-tests-is-self-hosted=true" | tee -a $GITHUB_OUTPUT - echo "deployment-tests-runner=${SH_TEST_RUNNER}" | tee -a $GITHUB_OUTPUT + echo "deployment-tests-runner=${SH_DEPLOYMENT_TEST_RUNNER}" | tee -a $GITHUB_OUTPUT - name: Select runners for core tests id: core-tests diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml index 965e151bb0d..9c2d793c9c0 100644 --- a/.github/workflows/flakeguard.yml +++ b/.github/workflows/flakeguard.yml @@ -322,9 +322,11 @@ jobs: id: gen_id run: echo "id=$(uuidgen)" >> "$GITHUB_OUTPUT" - - name: Install flakeguard + - name: Install flakeguard and gotestsum shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@bc66d27e3325a1fecedc0fc932d13d3e54ff6f25 # flakguard@0.1.0 + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@bc66d27e3325a1fecedc0fc932d13d3e54ff6f25 # flakguard@0.1.0 + go install gotest.tools/gotestsum@v1.12.2 # needed for flakeguard output formatting - name: Run tests with flakeguard shell: bash diff --git a/.github/workflows/run-nightly-e2e-tests.yml b/.github/workflows/run-nightly-e2e-tests.yml index 35c74671bd5..fd5b008bd67 100644 --- a/.github/workflows/run-nightly-e2e-tests.yml +++ b/.github/workflows/run-nightly-e2e-tests.yml @@ -1,9 +1,10 @@ name: Run Nightly E2E Tests on: - schedule: + # Disabled due to constant failures. Should be fixed in DX-809 + #schedule: # Run every night at midnight UTC (0:00 AM) - - cron: '0 0 * * *' + #- cron: '0 0 * * *' workflow_dispatch: # Useful when running the workflow manually inputs: @@ -23,7 +24,7 @@ on: image versions. Example: "5733cdcda9a9fc6da6343798b119b2ae136146cd,0b7d2c497a508efa5a827714780d908b7b8eda19"' required: false - type: string + type: string require_chainlink_plugin_versions_in_qa_ecr: description: 'Check Chainlink plugins versions to be present in QA ECR. If not, @@ -31,12 +32,12 @@ on: Chainlink image versions. Example: "5733cdcda9a9fc6da6343798b119b2ae136146cd,0b7d2c497a508efa5a827714780d908b7b8eda19"' required: false - type: string + type: string extraArgs: required: false type: string default: '{ "flakeguard_enable": "true", "flakeguard_run_count": "5" }' - description: 'JSON of extra arguments for the workflow.' + description: 'JSON of extra arguments for the workflow.' jobs: call-run-e2e-tests-workflow: diff --git a/.gitignore b/.gitignore index 042f806a305..f4a217b5360 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,7 @@ vendor/* contracts/lcov.info contracts/out/ /cache + +# Used by plugins/chianlink.prebuilt.Dockerfile +bin/ +lib/ diff --git a/.mockery.yaml b/.mockery.yaml index 82d4fa8428d..e5967c6502e 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -27,7 +27,8 @@ packages: OracleCreator: github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common: interfaces: - ExtraDataCodec: + SourceChainExtraDataCodec: + ChainSpecificAddressCodec: github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types: interfaces: Dispatcher: @@ -44,10 +45,6 @@ packages: LogPoller: github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr: interfaces: - ChainConfig: - config: - mockname: Config - filename: config.go EvmTxStore: github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm: interfaces: diff --git a/common/txmgr/mocks/utils.go b/common/txmgr/mocks/utils.go new file mode 100644 index 00000000000..2041a21fd36 --- /dev/null +++ b/common/txmgr/mocks/utils.go @@ -0,0 +1,17 @@ +package mocks + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-evm/pkg/gas" + "github.com/smartcontractkit/chainlink-evm/pkg/types" +) + +type MockEvmTxManager = TxManager[*big.Int, *types.Head, common.Address, common.Hash, common.Hash, types.Nonce, gas.EvmFee] + +func NewMockEvmTxManager(t *testing.T) *MockEvmTxManager { + return NewTxManager[*big.Int, *types.Head, common.Address, common.Hash, common.Hash, types.Nonce, gas.EvmFee](t) +} diff --git a/core/capabilities/ccip/ccipaptos/crcwconfig.go b/core/capabilities/ccip/ccipaptos/crcwconfig.go new file mode 100644 index 00000000000..0548e4add39 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/crcwconfig.go @@ -0,0 +1,56 @@ +package ccipaptos + +import ( + "context" + "encoding/json" + "fmt" + + aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + aptosconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/aptos" +) + +// ChainCWProvider is a struct that implements the ChainRWProvider interface for EVM chains. +type ChainCWProvider struct{} + +// GetChainReader returns a new ContractReader for EVM chains. +func (g ChainCWProvider) GetChainReader(ctx context.Context, params ccipcommon.ChainReaderProviderOpts) (types.ContractReader, error) { + cfg, err := aptosconfig.GetChainReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain reader config: %w", err) + } + marshaledConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) + } + + cr, err := params.Relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, err + } + + cr = aptosloop.NewLoopChainReader(params.Lggr, cr) + + return cr, nil +} + +// GetChainWriter returns a new ContractWriter for EVM chains. +func (g ChainCWProvider) GetChainWriter(ctx context.Context, params ccipcommon.ChainWriterProviderOpts) (types.ContractWriter, error) { + transmitter := params.Transmitters[types.NewRelayID(params.ChainFamily, params.ChainID)] + cfg, err := aptosconfig.GetChainWriterConfig(transmitter[0]) + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain writer config: %w", err) + } + chainWriterConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain writer config: %w", err) + } + + cw, err := params.Relayer.NewContractWriter(ctx, chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", params.ChainID, err) + } + + return cw, nil +} diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go index 2f59d9bed17..577583e3db0 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -15,7 +15,7 @@ import ( // Compatible with ccip::fee_quoter version 1.6.0 type ExtraDataDecoder struct{} -var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) +var _ ccipcommon.SourceChainExtraDataCodec = ExtraDataDecoder{} const ( aptosDestExecDataKey = "destGasAmount" diff --git a/core/capabilities/ccip/ccipaptos/pluginconfig.go b/core/capabilities/ccip/ccipaptos/pluginconfig.go new file mode 100644 index 00000000000..937fa3f3b3e --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/pluginconfig.go @@ -0,0 +1,21 @@ +package ccipaptos + +import ( + chainsel "github.com/smartcontractkit/chain-selectors" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// InitializePluginConfig returns a PluginConfig for EVM chains. +func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { + return ccipcommon.PluginConfig{ + CommitPluginCodec: NewCommitPluginCodecV1(), + ExecutePluginCodec: NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: NewMessageHasherV1(lggr.Named(chainsel.FamilyAptos).Named("MessageHasherV1"), extraDataCodec), + TokenDataEncoder: NewAptosTokenDataEncoder(), + GasEstimateProvider: NewGasEstimateProvider(), + RMNCrypto: nil, + ContractTransmitterFactory: ocrimpls.NewAptosContractTransmitterFactory(extraDataCodec), + } +} diff --git a/core/capabilities/ccip/ccipevm/crcwconfig.go b/core/capabilities/ccip/ccipevm/crcwconfig.go new file mode 100644 index 00000000000..4db478357f9 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/crcwconfig.go @@ -0,0 +1,90 @@ +package ccipevm + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/chainlink-common/pkg/types" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" + evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +// ChainCWProvider is a struct that implements the ChainRWProvider interface for EVM chains. +type ChainCWProvider struct{} + +// GetChainReader returns a new ContractReader for EVM chains. +func (g ChainCWProvider) GetChainReader(ctx context.Context, params ccipcommon.ChainReaderProviderOpts) (types.ContractReader, error) { + var chainReaderConfig evmrelaytypes.ChainReaderConfig + if params.ChainID == params.DestChainID { + chainReaderConfig = evmconfig.DestReaderConfig + } else { + chainReaderConfig = evmconfig.SourceReaderConfig + } + + if !params.Ofc.CommitEmpty() && params.Ofc.Commit.PriceFeedChainSelector == params.ChainSelector { + params.Lggr.Debugw("Adding feed reader config", "chainID", params.ChainID) + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.FeedReaderConfig) + } + + if isUSDCEnabled(params.Ofc) { + params.Lggr.Debugw("Adding USDC reader config", "chainID", params.ChainID) + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.USDCReaderConfig) + } + + if params.ChainID == params.HomeChainID { + params.Lggr.Debugw("Adding home chain reader config", "chainID", params.ChainID) + chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.HomeChainReaderConfigRaw) + } + + marshaledConfig, err := json.Marshal(chainReaderConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) + } + + cr, err := params.Relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, err + } + + return cr, nil +} + +// GetChainWriter returns a new ContractWriter for EVM chains. +func (g ChainCWProvider) GetChainWriter(ctx context.Context, params ccipcommon.ChainWriterProviderOpts) (types.ContractWriter, error) { + var fromAddress common.Address + transmitter, ok := params.Transmitters[types.NewRelayID(params.ChainFamily, params.ChainID)] + if ok { + fromAddress = common.HexToAddress(transmitter[0]) + } + + evmConfig, err := evmconfig.ChainWriterConfigRaw( + fromAddress, + defaultCommitGasLimit, + params.ExecBatchGasLimit) + if err != nil { + return nil, fmt.Errorf("failed to create EVM chain writer config: %w", err) + } + + chainWriterConfig, err := json.Marshal(evmConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal EVM chain writer config: %w", err) + } + + cw, err := params.Relayer.NewContractWriter(ctx, chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", params.ChainID, err) + } + + return cw, nil +} + +func isUSDCEnabled(ofc ccipcommon.OffChainConfig) bool { + if ofc.ExecEmpty() { + return false + } + + return ofc.Execute.IsUSDCEnabled() +} diff --git a/core/capabilities/ccip/ccipevm/executecodec.go b/core/capabilities/ccip/ccipevm/executecodec.go index ca3b771b3ff..f97a0820907 100644 --- a/core/capabilities/ccip/ccipevm/executecodec.go +++ b/core/capabilities/ccip/ccipevm/executecodec.go @@ -8,12 +8,9 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" chainsel "github.com/smartcontractkit/chain-selectors" - - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ) @@ -62,7 +59,6 @@ func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.Exec evmMessages := make([]offramp.InternalAny2EVMRampMessage, 0, len(chainReport.Messages)) for _, message := range chainReport.Messages { receiver := common.BytesToAddress(message.Receiver) - tokenAmounts := make([]offramp.InternalAny2EVMTokenTransfer, 0, len(message.TokenAmounts)) for _, tokenAmount := range message.TokenAmounts { if tokenAmount.Amount.IsEmpty() { diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go index 1b57b750c83..9eba720264a 100644 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ b/core/capabilities/ccip/ccipevm/executecodec_test.go @@ -11,15 +11,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/report_codec" @@ -27,7 +18,12 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/assets" evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) var randomExecuteReport = func(t *testing.T, d *testSetupData, chainSelector uint64, gasLimit *big.Int, destGasAmount uint32) cciptypes.ExecutePluginReport { @@ -101,13 +97,13 @@ var randomExecuteReport = func(t *testing.T, d *testSetupData, chainSelector uin func TestExecutePluginCodecV1(t *testing.T) { d := testSetup(t) ctx := testutils.Context(t) - mockExtraDataCodec := &mocks.ExtraDataCodec{} + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) destGasAmount := rand.Uint32() gasLimit := utils.RandUint256() - mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec.On("DecodeDestExecDataToMap", mock.Anything).Return(map[string]any{ "destgasamount": destGasAmount, }, nil) - mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec.On("DecodeExtraArgsToMap", mock.Anything).Return(map[string]any{ "gasLimit": utils.RandUint256(), "accountIsWritableBitmap": gasLimit, }, nil) @@ -186,7 +182,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - codec := NewExecutePluginCodecV1(mockExtraDataCodec) + codec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) report := tc.report(randomExecuteReport(t, d, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) if tc.expErr { @@ -228,7 +224,6 @@ func TestExecutePluginCodecV1(t *testing.T) { } func Test_DecodeReport(t *testing.T) { - ExtraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) offRampABI, err := offramp.OffRampMetaData.GetAbi() require.NoError(t, err) @@ -246,8 +241,7 @@ func Test_DecodeReport(t *testing.T) { t.Logf("reportCtx[0]: %x, reportCtx[1]: %x", reportCtx[0], reportCtx[1]) rawReport := *abi.ConvertType(executeInputs[1], new([]byte)).(*[]byte) - - codec := NewExecutePluginCodecV1(ExtraDataCodec) + codec := NewExecutePluginCodecV1(extraDataCodec) decoded, err := codec.Decode(t.Context(), rawReport) require.NoError(t, err) diff --git a/core/capabilities/ccip/ccipevm/extradatadecoder.go b/core/capabilities/ccip/ccipevm/extradatacodec.go similarity index 77% rename from core/capabilities/ccip/ccipevm/extradatadecoder.go rename to core/capabilities/ccip/ccipevm/extradatacodec.go index 5c30b564336..3b29ad52ebc 100644 --- a/core/capabilities/ccip/ccipevm/extradatadecoder.go +++ b/core/capabilities/ccip/ccipevm/extradatacodec.go @@ -4,13 +4,21 @@ import ( "fmt" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) -// ExtraDataDecoder is a concrete implementation of ExtraDataDecoder -type ExtraDataDecoder struct{} +const ( + svmV1DecodeStructName = "decodeSVMExtraArgsStruct" + evmV1DecodeName = "decodeEVMExtraArgsV1" + evmV2DecodeName = "decodeEVMExtraArgsV2" + evmDestExecDataKey = "destGasAmount" +) + +// ExtraDataCodec is a concrete implementation of SourceChainExtraDataCodec +type ExtraDataCodec struct{} // DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data -func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]interface{}, error) { +func (d ExtraDataCodec) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]interface{}, error) { destGasAmount, err := abiDecodeUint32(destExecData) if err != nil { return nil, fmt.Errorf("decode dest gas amount: %w", err) @@ -22,7 +30,7 @@ func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) } // DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args -func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { +func (d ExtraDataCodec) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { if len(extraArgs) < 4 { return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) } @@ -76,3 +84,6 @@ func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[s return output, nil } + +// Ensure ExtraDataCodec implements the SourceChainExtraDataCodec interface +var _ ccipcommon.SourceChainExtraDataCodec = &ExtraDataCodec{} diff --git a/core/capabilities/ccip/ccipevm/extradatadecoder_test.go b/core/capabilities/ccip/ccipevm/extradatacodec_test.go similarity index 98% rename from core/capabilities/ccip/ccipevm/extradatadecoder_test.go rename to core/capabilities/ccip/ccipevm/extradatacodec_test.go index 64b7a494475..cd7c9fec712 100644 --- a/core/capabilities/ccip/ccipevm/extradatadecoder_test.go +++ b/core/capabilities/ccip/ccipevm/extradatacodec_test.go @@ -15,7 +15,7 @@ import ( func Test_decodeExtraData(t *testing.T) { d := testSetup(t) gasLimit := big.NewInt(rand.Int63()) - extraDataDecoder := &ExtraDataDecoder{} + extraDataDecoder := &ExtraDataCodec{} t.Run("decode extra args into map evm v1", func(t *testing.T) { encoded, err := d.contract.EncodeEVMExtraArgsV1(nil, message_hasher.ClientEVMExtraArgsV1{ @@ -68,7 +68,7 @@ func Test_decodeExtraData(t *testing.T) { func TestExtraDataDecoder_DecodeExtraArgsToMap_SVMDestination(t *testing.T) { d := testSetup(t) - extraDataDecoder := &ExtraDataDecoder{} + extraDataDecoder := &ExtraDataCodec{} t.Run("decode extra args into map svm", func(t *testing.T) { key, err := solana.NewRandomPrivateKey() diff --git a/core/capabilities/ccip/ccipevm/gas_helpers_test.go b/core/capabilities/ccip/ccipevm/gas_helpers_test.go index 014054657b6..b840849d638 100644 --- a/core/capabilities/ccip/ccipevm/gas_helpers_test.go +++ b/core/capabilities/ccip/ccipevm/gas_helpers_test.go @@ -80,7 +80,7 @@ func Test_calculateMessageMaxGas(t *testing.T) { } // Set the source chain selector to be EVM for now msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector) - ep := EstimateProvider{extraDataCodec: ExtraDataCodec} + ep := EstimateProvider{extraDataCodec: extraDataCodec} got := ep.CalculateMessageMaxGas(msg) t.Log(got) assert.Equalf(t, tt.want, got, "calculateMessageMaxGas(%v, %v)", tt.args.dataLen, tt.args.numTokens) @@ -138,7 +138,7 @@ func TestCalculateMaxGas(t *testing.T) { } msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector) - ep := EstimateProvider{extraDataCodec: ExtraDataCodec} + ep := EstimateProvider{extraDataCodec: extraDataCodec} gotTree := ep.CalculateMerkleTreeGas(tt.numRequests) gotMsg := ep.CalculateMessageMaxGas(msg) t.Log("want", tt.want, "got", gotTree+gotMsg) diff --git a/core/capabilities/ccip/ccipevm/helpers.go b/core/capabilities/ccip/ccipevm/helpers.go index 8cbb41d0b29..6b869cb423e 100644 --- a/core/capabilities/ccip/ccipevm/helpers.go +++ b/core/capabilities/ccip/ccipevm/helpers.go @@ -13,13 +13,6 @@ import ( ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) -const ( - svmV1DecodeStructName = "decodeSVMExtraArgsStruct" - evmV1DecodeName = "decodeEVMExtraArgsV1" - evmV2DecodeName = "decodeEVMExtraArgsV2" - evmDestExecDataKey = "destGasAmount" -) - // abiEncodeMethodInputs encodes the inputs for a method call. // example abi: `[{ "name" : "method", "type": "function", "inputs": [{"name": "a", "type": "uint256"}]}]` func abiEncodeMethodInputs(abiDef abi.ABI, inputs ...interface{}) ([]byte, error) { diff --git a/core/capabilities/ccip/ccipevm/helpers_test.go b/core/capabilities/ccip/ccipevm/helpers_test.go index f42deb71310..946b122901d 100644 --- a/core/capabilities/ccip/ccipevm/helpers_test.go +++ b/core/capabilities/ccip/ccipevm/helpers_test.go @@ -13,7 +13,7 @@ import ( func Test_decodeExtraArgs(t *testing.T) { d := testSetup(t) gasLimit := big.NewInt(rand.Int63()) - extraDataDecoder := &ExtraDataDecoder{} + extraDataDecoder := &ExtraDataCodec{} t.Run("decode extra args into map evm v1", func(t *testing.T) { encoded, err := d.contract.EncodeEVMExtraArgsV1(nil, message_hasher.ClientEVMExtraArgsV1{ diff --git a/core/capabilities/ccip/ccipevm/msghasher.go b/core/capabilities/ccip/ccipevm/msghasher.go index f620619cf46..03e7427532a 100644 --- a/core/capabilities/ccip/ccipevm/msghasher.go +++ b/core/capabilities/ccip/ccipevm/msghasher.go @@ -12,16 +12,13 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ag_binary "github.com/gagliardetto/binary" chainsel "github.com/smartcontractkit/chain-selectors" - - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-ccip/pkg/logutil" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) var ( diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go index c5493a388a1..02caa44649f 100644 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ b/core/capabilities/ccip/ccipevm/msghasher_test.go @@ -21,26 +21,21 @@ import ( "github.com/ethereum/go-ethereum/core/types" agbinary "github.com/gagliardetto/binary" solanago "github.com/gagliardetto/solana-go" - "github.com/stretchr/testify/require" - + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-evm/pkg/assets" evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/stretchr/testify/require" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) +var extraDataCodec = ccipcommon.NewExtraDataCodec(ExtraDataCodec{}, ccipsolana.ExtraDataCodec{}, ccipaptos.ExtraDataDecoder{}) // NOTE: these test cases are only EVM <-> EVM. // Update these cases once we have non-EVM examples. @@ -94,7 +89,7 @@ func testHasherEVM2EVM(ctx context.Context, t *testing.T, d *testSetupData, evmE expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, ccipMsg.Header.OnRamp) require.NoError(t, err) - evmMsgHasher := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + evmMsgHasher := NewMessageHasherV1(logger.Test(t), extraDataCodec) actualHash, err := evmMsgHasher.Hash(ctx, ccipMsg) require.NoError(t, err) @@ -269,7 +264,7 @@ func TestMessagerHasher_againstRmnSharedVector(t *testing.T) { }, any2EVMMessage, common.LeftPadBytes(msg.Header.OnRamp, 32)) require.NoError(t, err) - h := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + h := NewMessageHasherV1(logger.Test(t), extraDataCodec) msgH, err := h.Hash(t.Context(), msg) require.NoError(t, err) require.Equal(t, expectedMsgHash, msgH.String()) @@ -341,7 +336,7 @@ func TestMessagerHasher_againstRmnSharedVector(t *testing.T) { rmnMsgHash = "0xb6ea678f918293745bfb8db05d79dcf08986c7da3e302ac5f6782618a6f11967" ) - h := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + h := NewMessageHasherV1(logger.Test(t), extraDataCodec) msgH, err := h.Hash(t.Context(), msg) require.NoError(t, err) @@ -435,7 +430,7 @@ func TestMessagerHasher_againstRmnSharedVector(t *testing.T) { // rmnMsgHash = "0xb6ea678f918293745bfb8db05d79dcf08986c7da3e302ac5f6782618a6f11967" //) - h := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + h := NewMessageHasherV1(logger.Test(t), extraDataCodec) msgH, err := h.Hash(t.Context(), msg) require.NoError(t, err) @@ -460,7 +455,7 @@ func TestMessagerHasher_againstRmnSharedVector(t *testing.T) { err = json.Unmarshal(data, &msgs) require.NoError(t, err) - msgHasher := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + msgHasher := NewMessageHasherV1(logger.Test(t), extraDataCodec) for _, msg := range msgs { any2EVMMessage := ccipMsgToAny2EVMMessage(t, msg, msg.Header.SourceChainSelector) @@ -482,7 +477,7 @@ func TestMessagerHasher_againstRmnSharedVector(t *testing.T) { func ccipMsgToAny2EVMMessage(t *testing.T, msg cciptypes.Message, sourceSelector cciptypes.ChainSelector) message_hasher.InternalAny2EVMRampMessage { var tokenAmounts []message_hasher.InternalAny2EVMTokenTransfer for _, rta := range msg.TokenAmounts { - decodedMap, err := ExtraDataCodec.DecodeTokenAmountDestExecData(rta.DestExecData, sourceSelector) + decodedMap, err := extraDataCodec.DecodeTokenAmountDestExecData(rta.DestExecData, sourceSelector) require.NoError(t, err) gasAmount, err := extractDestGasAmountFromMap(decodedMap) require.NoError(t, err) @@ -496,7 +491,7 @@ func ccipMsgToAny2EVMMessage(t *testing.T, msg cciptypes.Message, sourceSelector }) } - decodedMap, err := ExtraDataCodec.DecodeExtraArgs(msg.ExtraArgs, sourceSelector) + decodedMap, err := extraDataCodec.DecodeExtraArgs(msg.ExtraArgs, sourceSelector) require.NoError(t, err) gasLimit, err := parseExtraArgsMap(decodedMap) require.NoError(t, err) diff --git a/core/capabilities/ccip/ccipevm/pluginconfig.go b/core/capabilities/ccip/ccipevm/pluginconfig.go new file mode 100644 index 00000000000..ecfd1b152f0 --- /dev/null +++ b/core/capabilities/ccip/ccipevm/pluginconfig.go @@ -0,0 +1,23 @@ +package ccipevm + +import ( + chainsel "github.com/smartcontractkit/chain-selectors" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +const defaultCommitGasLimit = 500_000 + +// InitializePluginConfig returns a PluginConfig for EVM chains. +func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { + return ccipcommon.PluginConfig{ + CommitPluginCodec: NewCommitPluginCodecV1(), + ExecutePluginCodec: NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: NewMessageHasherV1(lggr.Named(chainsel.FamilyEVM).Named("MessageHasherV1"), extraDataCodec), + TokenDataEncoder: NewEVMTokenDataEncoder(), + GasEstimateProvider: NewGasEstimateProvider(extraDataCodec), + RMNCrypto: NewEVMRMNCrypto(lggr.Named(chainsel.FamilyEVM).Named("RMNCrypto")), + ContractTransmitterFactory: ocrimpls.NewEVMContractTransmitterFactory(extraDataCodec), + } +} diff --git a/core/capabilities/ccip/ccipsolana/crcwconfig.go b/core/capabilities/ccip/ccipsolana/crcwconfig.go new file mode 100644 index 00000000000..8b5aefc1aed --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/crcwconfig.go @@ -0,0 +1,73 @@ +package ccipsolana + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/gagliardetto/solana-go" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" +) + +// ChainRWProvider is a struct that implements the ChainRWProvider interface for Solana chains. +type ChainRWProvider struct{} + +// GetChainWriter ChainRWProvider returns a new ContractWriter for Solana chains. +func (g ChainRWProvider) GetChainWriter(ctx context.Context, pararms ccipcommon.ChainWriterProviderOpts) (types.ContractWriter, error) { + var offrampProgramAddress solana.PublicKey + // NOTE: this function can still be called with EVM inputs, and PublicKeyFromBytes will panic on addresses with len=20 + // technically we only need the writer to do fee estimation so this doesn't matter and we can use a zero address + if len(pararms.OfframpProgramAddress) == solana.PublicKeyLength { + offrampProgramAddress = solana.PublicKeyFromBytes(pararms.OfframpProgramAddress) + } + + transmitter := pararms.Transmitters[types.NewRelayID(pararms.ChainFamily, pararms.ChainID)] + solConfig, err := solanaconfig.GetSolanaChainWriterConfig(offrampProgramAddress.String(), transmitter[0]) + if err != nil { + return nil, fmt.Errorf("failed to get Solana chain writer config: %w", err) + } + chainWriterConfig, err := json.Marshal(solConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal Solana chain writer config: %w", err) + } + + cw, err := pararms.Relayer.NewContractWriter(ctx, chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", pararms.ChainID, err) + } + + return cw, nil +} + +// GetChainReader returns a new ContractReader for Solana chains. +func (g ChainRWProvider) GetChainReader(ctx context.Context, params ccipcommon.ChainReaderProviderOpts) (types.ContractReader, error) { + var err error + var cfg config.ContractReader + if params.ChainID == params.DestChainID { + cfg, err = solanaconfig.DestContractReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Solana dest contract reader config: %w", err) + } + } else { + cfg, err = solanaconfig.SourceContractReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Solana source contract reader config: %w", err) + } + } + + marshaledConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) + } + + cr, err := params.Relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, err + } + + return cr, nil +} diff --git a/core/capabilities/ccip/ccipsolana/executecodec.go b/core/capabilities/ccip/ccipsolana/executecodec.go index e50a15413aa..b5399d87ee7 100644 --- a/core/capabilities/ccip/ccipsolana/executecodec.go +++ b/core/capabilities/ccip/ccipsolana/executecodec.go @@ -11,11 +11,9 @@ import ( agbinary "github.com/gagliardetto/binary" "github.com/gagliardetto/solana-go" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) // ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. diff --git a/core/capabilities/ccip/ccipsolana/executecodec_test.go b/core/capabilities/ccip/ccipsolana/executecodec_test.go index 95d45c9d458..8fe8e69b003 100644 --- a/core/capabilities/ccip/ccipsolana/executecodec_test.go +++ b/core/capabilities/ccip/ccipsolana/executecodec_test.go @@ -11,6 +11,8 @@ import ( solanago "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/mock" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" @@ -168,19 +170,20 @@ func TestExecutePluginCodecV1(t *testing.T) { } ctx := testutils.Context(t) - mockExtraDataCodec := mocks.NewExtraDataCodec(t) - mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) + mockExtraDataCodec.On("DecodeDestExecDataToMap", mock.Anything).Return(map[string]any{ "destGasAmount": uint32(10), }, nil).Maybe() - mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec.On("DecodeExtraArgsToMap", mock.Anything).Return(map[string]any{ "ComputeUnits": uint32(1000), "accountIsWritableBitmap": uint64(2), "TokenReceiver": [32]byte(solanago.MustPublicKeyFromBase58("42Gia5bGsh8R2S44e37t9fsucap1qsgjr6GjBmWotgdF").Bytes()), }, nil).Maybe() + cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - cd := NewExecutePluginCodecV1(mockExtraDataCodec) + report := tc.report(randomExecuteReport(t, tc.chainSelector)) bytes, err := cd.Encode(ctx, report) if tc.expErr { @@ -208,11 +211,11 @@ func TestExecutePluginCodecV1(t *testing.T) { } func Test_DecodingExecuteReport(t *testing.T) { - mockExtraDataCodec := mocks.NewExtraDataCodec(t) - mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) + mockExtraDataCodec.On("DecodeDestExecDataToMap", mock.Anything, mock.Anything).Return(map[string]any{ "destGasAmount": uint32(10), }, nil) - mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec.On("DecodeExtraArgsToMap", mock.Anything, mock.Anything).Return(map[string]any{ "ComputeUnits": uint32(1000), "accountIsWritableBitmap": uint64(2), }, nil) @@ -254,7 +257,7 @@ func Test_DecodingExecuteReport(t *testing.T) { err = onChainReport.MarshalWithEncoder(encoder) require.NoError(t, err) - executeCodec := NewExecutePluginCodecV1(mockExtraDataCodec) + executeCodec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) decode, err := executeCodec.Decode(testutils.Context(t), buf.Bytes()) require.NoError(t, err) @@ -270,7 +273,7 @@ func Test_DecodingExecuteReport(t *testing.T) { t.Run("decode Borsh encoded execute report", func(t *testing.T) { ocrReport := randomExecuteReport(t, 124615329519749607) - cd := NewExecutePluginCodecV1(mockExtraDataCodec) + cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) encodedReport, err := cd.Encode(testutils.Context(t), ocrReport) require.NoError(t, err) diff --git a/core/capabilities/ccip/ccipsolana/extradatadecoder.go b/core/capabilities/ccip/ccipsolana/extradatacodec.go similarity index 81% rename from core/capabilities/ccip/ccipsolana/extradatadecoder.go rename to core/capabilities/ccip/ccipsolana/extradatacodec.go index 6a4387d8af9..59e1e266969 100644 --- a/core/capabilities/ccip/ccipsolana/extradatadecoder.go +++ b/core/capabilities/ccip/ccipsolana/extradatacodec.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" agbinary "github.com/gagliardetto/binary" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" @@ -28,11 +29,11 @@ var ( evmExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") ) -// ExtraDataDecoder is a helper struct for decoding extra data -type ExtraDataDecoder struct{} +// ExtraDataCodec is a helper struct for decoding extra data +type ExtraDataCodec struct{} // DecodeExtraArgsToMap is a helper function for converting Borsh encoded extra args bytes into map[string]any -func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { +func (d ExtraDataCodec) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { if len(extraArgs) < 4 { return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) } @@ -73,8 +74,11 @@ func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[s } // DecodeDestExecDataToMap is a helper function for converting dest exec data bytes into map[string]any -func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { +func (d ExtraDataCodec) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { return map[string]any{ svmDestExecDataKey: binary.BigEndian.Uint32(destExecData), }, nil } + +// Ensure ExtraDataCodec implements the SourceChainExtraDataCodec interface +var _ ccipcommon.SourceChainExtraDataCodec = &ExtraDataCodec{} diff --git a/core/capabilities/ccip/ccipsolana/extradatadecoder_test.go b/core/capabilities/ccip/ccipsolana/extradatacodec_test.go similarity index 98% rename from core/capabilities/ccip/ccipsolana/extradatadecoder_test.go rename to core/capabilities/ccip/ccipsolana/extradatacodec_test.go index d486fa65928..faf53e1035b 100644 --- a/core/capabilities/ccip/ccipsolana/extradatadecoder_test.go +++ b/core/capabilities/ccip/ccipsolana/extradatacodec_test.go @@ -15,7 +15,7 @@ import ( ) func Test_decodeExtraArgs(t *testing.T) { - extraDataDecoder := &ExtraDataDecoder{} + extraDataDecoder := &ExtraDataCodec{} t.Run("decode dest exec data into map svm", func(t *testing.T) { destGasAmount := uint32(10000) encoded := make([]byte, 4) diff --git a/core/capabilities/ccip/ccipsolana/gas_helpers_test.go b/core/capabilities/ccip/ccipsolana/gas_helpers_test.go index b702d11cd3b..dc9e8c81409 100644 --- a/core/capabilities/ccip/ccipsolana/gas_helpers_test.go +++ b/core/capabilities/ccip/ccipsolana/gas_helpers_test.go @@ -5,6 +5,8 @@ import ( "testing" chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/stretchr/testify/assert" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" @@ -54,7 +56,7 @@ func Test_calculateMessageMaxGas(t *testing.T) { } // Set the source chain selector to be EVM for now msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.SOLANA_TESTNET.Selector) - ep := EstimateProvider{extraDataCodec: ExtraDataCodec} + ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{})} got := ep.CalculateMessageMaxGas(msg) t.Log(got) assert.Equalf(t, tt.want, got, "calculateMessageMaxGas(%v, %v)", tt.args.dataLen, tt.args.numTokens) @@ -94,7 +96,7 @@ func TestCalculateMaxGas(t *testing.T) { } msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.SOLANA_TESTNET.Selector) - ep := EstimateProvider{extraDataCodec: ExtraDataCodec} + ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{})} gotTree := ep.CalculateMerkleTreeGas(tt.numRequests) gotMsg := ep.CalculateMessageMaxGas(msg) t.Log("want", tt.want, "got", gotTree+gotMsg) diff --git a/core/capabilities/ccip/ccipsolana/msghasher.go b/core/capabilities/ccip/ccipsolana/msghasher.go index 17cc101ba10..70ec32fb2a2 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher.go +++ b/core/capabilities/ccip/ccipsolana/msghasher.go @@ -8,15 +8,12 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gagliardetto/solana-go" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/ccip" "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) // MessageHasherV1 implements the MessageHasher interface. diff --git a/core/capabilities/ccip/ccipsolana/msghasher_test.go b/core/capabilities/ccip/ccipsolana/msghasher_test.go index 2d5087f7481..5f2beb269ab 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher_test.go +++ b/core/capabilities/ccip/ccipsolana/msghasher_test.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" @@ -29,11 +30,10 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -var ExtraDataCodec = ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) - func TestMessageHasher_EVM2SVM(t *testing.T) { + var extraDataCodec = ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{}, ccipaptos.ExtraDataDecoder{}) any2AnyMsg, any2SolanaMsg, msgAccounts := createEVM2SolanaMessages(t) - msgHasher := NewMessageHasherV1(logger.Test(t), ExtraDataCodec) + msgHasher := NewMessageHasherV1(logger.Test(t), extraDataCodec) actualHash, err := msgHasher.Hash(testutils.Context(t), any2AnyMsg) require.NoError(t, err) expectedHash, err := ccip.HashAnyToSVMMessage(any2SolanaMsg, any2AnyMsg.Header.OnRamp, msgAccounts) @@ -46,11 +46,11 @@ func TestMessageHasher_InvalidReceiver(t *testing.T) { // Set receiver to a []byte of 2 length any2AnyMsg.Receiver = []byte{0, 0} - mockExtraDataCodec := &mocks.ExtraDataCodec{} - mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) + mockExtraDataCodec.On("DecodeDestExecDataToMap", mock.Anything).Return(map[string]any{ "destGasAmount": uint32(10), - }, nil) - mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + }, nil).Maybe() + mockExtraDataCodec.On("DecodeExtraArgsToMap", mock.Anything).Return(map[string]any{ "ComputeUnits": uint32(1000), "AccountIsWritableBitmap": uint64(10), "Accounts": [][32]byte{ @@ -58,8 +58,8 @@ func TestMessageHasher_InvalidReceiver(t *testing.T) { [32]byte(config.ReceiverTargetAccountPDA.Bytes()), [32]byte(solana.SystemProgramID.Bytes()), }, - }, nil) - msgHasher := NewMessageHasherV1(logger.Test(t), mockExtraDataCodec) + }, nil).Maybe() + msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) _, err := msgHasher.Hash(testutils.Context(t), any2AnyMsg) require.Error(t, err) } @@ -69,11 +69,11 @@ func TestMessageHasher_InvalidDestinationTokenAddress(t *testing.T) { // Set DestTokenAddress to a []byte of 2 length any2AnyMsg.TokenAmounts[0].DestTokenAddress = []byte{0, 0} - mockExtraDataCodec := &mocks.ExtraDataCodec{} - mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) + mockExtraDataCodec.On("DecodeDestExecDataToMap", mock.Anything).Return(map[string]any{ "destGasAmount": uint32(10), - }, nil) - mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + }, nil).Maybe() + mockExtraDataCodec.On("DecodeExtraArgsToMap", mock.Anything).Return(map[string]any{ "ComputeUnits": uint32(1000), "AccountIsWritableBitmap": uint64(10), "Accounts": [][32]byte{ @@ -81,8 +81,8 @@ func TestMessageHasher_InvalidDestinationTokenAddress(t *testing.T) { [32]byte(config.ReceiverTargetAccountPDA.Bytes()), [32]byte(solana.SystemProgramID.Bytes()), }, - }, nil) - msgHasher := NewMessageHasherV1(logger.Test(t), mockExtraDataCodec) + }, nil).Maybe() + msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) _, err := msgHasher.Hash(testutils.Context(t), any2AnyMsg) require.Error(t, err) } diff --git a/core/capabilities/ccip/ccipsolana/pluginconfig.go b/core/capabilities/ccip/ccipsolana/pluginconfig.go new file mode 100644 index 00000000000..8be28efec0a --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/pluginconfig.go @@ -0,0 +1,23 @@ +package ccipsolana + +import ( + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// InitializePluginConfig returns a pluginConfig for Solana chains. +func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { + return ccipcommon.PluginConfig{ + CommitPluginCodec: NewCommitPluginCodecV1(), + ExecutePluginCodec: NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: NewMessageHasherV1(lggr.Named(chainsel.FamilySolana).Named("MessageHasherV1"), extraDataCodec), + TokenDataEncoder: NewSolanaTokenDataEncoder(), + GasEstimateProvider: NewGasEstimateProvider(extraDataCodec), + RMNCrypto: nil, + ContractTransmitterFactory: ocrimpls.NewSVMContractTransmitterFactory(extraDataCodec), + } +} diff --git a/core/capabilities/ccip/common/addresscodec.go b/core/capabilities/ccip/common/addresscodec.go index b72666b906f..7fc20a292aa 100644 --- a/core/capabilities/ccip/common/addresscodec.go +++ b/core/capabilities/ccip/common/addresscodec.go @@ -4,16 +4,9 @@ import ( "fmt" chainsel "github.com/smartcontractkit/chain-selectors" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -// ChainSpecificAddressCodec is an interface that defines the methods for encoding and decoding addresses -type ChainSpecificAddressCodec interface { - AddressBytesToString([]byte) (string, error) - AddressStringToBytes(string) ([]byte, error) -} - // AddressCodec is a struct that holds the chain specific address codecs type AddressCodec struct { EVMAddressCodec ChainSpecificAddressCodec @@ -21,28 +14,12 @@ type AddressCodec struct { AptosAddressCodec ChainSpecificAddressCodec } -// AddressCodecParams is a struct that holds the parameters for creating a AddressCodec -type AddressCodecParams struct { - evmAddressCodec ChainSpecificAddressCodec - solanaAddressCodec ChainSpecificAddressCodec - aptosAddressCodec ChainSpecificAddressCodec -} - -// NewAddressCodecParams is a constructor for AddressCodecParams -func NewAddressCodecParams(evmAddressCodec ChainSpecificAddressCodec, solanaAddressCodec ChainSpecificAddressCodec, aptosAddressCodec ChainSpecificAddressCodec) AddressCodecParams { - return AddressCodecParams{ - evmAddressCodec: evmAddressCodec, - solanaAddressCodec: solanaAddressCodec, - aptosAddressCodec: aptosAddressCodec, - } -} - -// NewAddressCodec is a constructor for AddressCodec -func NewAddressCodec(params AddressCodecParams) AddressCodec { +// NewAddressCodec is a constructor for NewAddressCodec +func NewAddressCodec(evmAddrCodec, solanaAddrCodec, aptosAddressCodec ChainSpecificAddressCodec) AddressCodec { return AddressCodec{ - EVMAddressCodec: params.evmAddressCodec, - SolanaAddressCodec: params.solanaAddressCodec, - AptosAddressCodec: params.aptosAddressCodec, + EVMAddressCodec: evmAddrCodec, + SolanaAddressCodec: solanaAddrCodec, + AptosAddressCodec: aptosAddressCodec, } } diff --git a/core/capabilities/ccip/common/common.go b/core/capabilities/ccip/common/common.go index bb1de6679c1..e768072c337 100644 --- a/core/capabilities/ccip/common/common.go +++ b/core/capabilities/ccip/common/common.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/crypto" - + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) @@ -31,3 +31,21 @@ func HashedCapabilityID(capabilityLabelledName, capabilityVersion string) (r [32 copy(r[:], h) return r, nil } + +type OffChainConfig struct { + Commit *pluginconfig.CommitOffchainConfig + Execute *pluginconfig.ExecuteOffchainConfig +} + +func (ofc OffChainConfig) CommitEmpty() bool { + return ofc.Commit == nil +} + +func (ofc OffChainConfig) ExecEmpty() bool { + return ofc.Execute == nil +} + +// IsValid Exactly one of both plugins should be empty at any given time. +func (ofc OffChainConfig) IsValid() bool { + return (ofc.CommitEmpty() && !ofc.ExecEmpty()) || (!ofc.CommitEmpty() && ofc.ExecEmpty()) +} diff --git a/core/capabilities/ccip/common/crcwconfig.go b/core/capabilities/ccip/common/crcwconfig.go new file mode 100644 index 00000000000..d251b6e1709 --- /dev/null +++ b/core/capabilities/ccip/common/crcwconfig.go @@ -0,0 +1,71 @@ +package common + +import ( + "context" + "fmt" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// ChainReaderProviderOpts is a struct that contains the parameters for GetChainReader. +type ChainReaderProviderOpts struct { + Lggr logger.Logger + Relayer loop.Relayer + ChainID string + DestChainID string + HomeChainID string + Ofc OffChainConfig + ChainSelector cciptypes.ChainSelector + ChainFamily string +} + +// ChainWriterProviderOpts is a struct that contains the parameters for GetChainWriter. +type ChainWriterProviderOpts struct { + ChainID string + Relayer loop.Relayer + Transmitters map[types.RelayID][]string + ExecBatchGasLimit uint64 + ChainFamily string + OfframpProgramAddress []byte +} + +// ChainRWProvider is an interface that defines the methods to get a ContractReader and a ContractWriter. +type ChainRWProvider interface { + GetChainReader(ctx context.Context, params ChainReaderProviderOpts) (types.ContractReader, error) + GetChainWriter(ctx context.Context, params ChainWriterProviderOpts) (types.ContractWriter, error) +} + +// MultiChainRW is a struct that implements the ChainRWProvider interface for all chains. +type MultiChainRW struct { + cwProviderMap map[string]ChainRWProvider +} + +// NewCRCW is a constructor for MultiChainRW. +func NewCRCW(cwProviderMap map[string]ChainRWProvider) *MultiChainRW { + return &MultiChainRW{ + cwProviderMap: cwProviderMap, + } +} + +// GetChainReader returns a new ContractReader base on relay chain family. +func (c *MultiChainRW) GetChainReader(ctx context.Context, params ChainReaderProviderOpts) (types.ContractReader, error) { + provider, exist := c.cwProviderMap[params.ChainFamily] + if !exist { + return nil, fmt.Errorf("unsupported chain family %s", params.ChainFamily) + } + + return provider.GetChainReader(ctx, params) +} + +// GetChainWriter returns a new ContractWriter based on relay chain family. +func (c *MultiChainRW) GetChainWriter(ctx context.Context, params ChainWriterProviderOpts) (types.ContractWriter, error) { + provider, exist := c.cwProviderMap[params.ChainFamily] + if !exist { + return nil, fmt.Errorf("unsupported chain family %s", params.ChainFamily) + } + + return provider.GetChainWriter(ctx, params) +} diff --git a/core/capabilities/ccip/common/default/default.go b/core/capabilities/ccip/common/default/default.go new file mode 100644 index 00000000000..e74bd3e6b68 --- /dev/null +++ b/core/capabilities/ccip/common/default/default.go @@ -0,0 +1,22 @@ +package defaults + +import ( + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// DefaultExtraDataCodec is the default ExtraDataCodec for CCIP initialized with all supported chain families. +var DefaultExtraDataCodec = common.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ccipsolana.ExtraDataCodec{}, ccipaptos.ExtraDataDecoder{}) + +// DefaultAddressCodec is the default AddressCodec for CCIP initialized with all supported chain families. +var DefaultAddressCodec = common.NewAddressCodec(ccipevm.AddressCodec{}, ccipsolana.AddressCodec{}, ccipaptos.AddressCodec{}) + +var DefaultCRCW = common.NewCRCW(map[string]common.ChainRWProvider{ + chainsel.FamilyEVM: ccipevm.ChainCWProvider{}, + chainsel.FamilySolana: ccipsolana.ChainRWProvider{}, + chainsel.FamilyAptos: ccipaptos.ChainCWProvider{}, +}) diff --git a/core/capabilities/ccip/common/extradatacodec.go b/core/capabilities/ccip/common/extradatacodec.go index 3382d46415e..d7f0edebd9e 100644 --- a/core/capabilities/ccip/common/extradatacodec.go +++ b/core/capabilities/ccip/common/extradatacodec.go @@ -8,54 +8,24 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ) -// ExtraDataCodec is an interface for decoding extra args and dest exec data into a chain-agnostic map[string]any representation -type ExtraDataCodec interface { - // DecodeExtraArgs reformat bytes into a chain agnostic map[string]any representation for extra args - DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) - // DecodeTokenAmountDestExecData reformat bytes to chain-agnostic map[string]any for tokenAmount DestExecData field - DecodeTokenAmountDestExecData(destExecData cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) +// ExtraDataCodec is a struct that holds the chain specific extra data codec +type ExtraDataCodec struct { + EVMExtraDataCodec SourceChainExtraDataCodec + SolanaExtraDataCodec SourceChainExtraDataCodec + AptosExtraDataCodec SourceChainExtraDataCodec } -// ExtraDataDecoder is an interface for decoding extra args and dest exec data into a map[string]any representation -type ExtraDataDecoder interface { - DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) - DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) -} - -// RealExtraDataCodec is a concrete implementation of ExtraDataCodec -type RealExtraDataCodec struct { - EVMExtraDataDecoder ExtraDataDecoder - SolanaExtraDataDecoder ExtraDataDecoder - AptosExtraDataDecoder ExtraDataDecoder -} - -// ExtraDataCodecParams is a struct that holds the parameters for creating a RealExtraDataCodec -type ExtraDataCodecParams struct { - evmExtraDataDecoder ExtraDataDecoder - solanaExtraDataDecoder ExtraDataDecoder - aptosExtraDataDecoder ExtraDataDecoder -} - -// NewExtraDataCodecParams is a constructor for ExtraDataCodecParams -func NewExtraDataCodecParams(evmDecoder ExtraDataDecoder, solanaDecoder ExtraDataDecoder, aptosDecoder ExtraDataDecoder) ExtraDataCodecParams { - return ExtraDataCodecParams{ - evmExtraDataDecoder: evmDecoder, - solanaExtraDataDecoder: solanaDecoder, - aptosExtraDataDecoder: aptosDecoder, - } -} - -// NewExtraDataCodec is a constructor for RealExtraDataCodec -func NewExtraDataCodec(params ExtraDataCodecParams) RealExtraDataCodec { - return RealExtraDataCodec{ - EVMExtraDataDecoder: params.evmExtraDataDecoder, - SolanaExtraDataDecoder: params.solanaExtraDataDecoder, - AptosExtraDataDecoder: params.aptosExtraDataDecoder, +// NewExtraDataCodec is a constructor for ExtraDataCodec +func NewExtraDataCodec(evmExtraDataCodec, solanaExtraDataCodec, aptosExtraDataCodec SourceChainExtraDataCodec) ExtraDataCodec { + return ExtraDataCodec{ + EVMExtraDataCodec: evmExtraDataCodec, + SolanaExtraDataCodec: solanaExtraDataCodec, + AptosExtraDataCodec: aptosExtraDataCodec, } } // DecodeExtraArgs reformats bytes into a chain agnostic map[string]any representation for extra args -func (c RealExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) { +func (c ExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) { if len(extraArgs) == 0 { // return empty map if extraArgs is empty return nil, nil @@ -68,13 +38,13 @@ func (c RealExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceCha switch family { case chainsel.FamilyEVM: - return c.EVMExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + return c.EVMExtraDataCodec.DecodeExtraArgsToMap(extraArgs) case chainsel.FamilySolana: - return c.SolanaExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + return c.SolanaExtraDataCodec.DecodeExtraArgsToMap(extraArgs) case chainsel.FamilyAptos: - return c.AptosExtraDataDecoder.DecodeExtraArgsToMap(extraArgs) + return c.AptosExtraDataCodec.DecodeExtraArgsToMap(extraArgs) default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) @@ -82,7 +52,7 @@ func (c RealExtraDataCodec) DecodeExtraArgs(extraArgs cciptypes.Bytes, sourceCha } // DecodeTokenAmountDestExecData reformats bytes to chain-agnostic map[string]any for tokenAmount DestExecData field -func (c RealExtraDataCodec) DecodeTokenAmountDestExecData(destExecData cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) { +func (c ExtraDataCodec) DecodeTokenAmountDestExecData(destExecData cciptypes.Bytes, sourceChainSelector cciptypes.ChainSelector) (map[string]any, error) { if len(destExecData) == 0 { // return empty map if destExecData is empty return nil, nil @@ -95,13 +65,13 @@ func (c RealExtraDataCodec) DecodeTokenAmountDestExecData(destExecData cciptypes switch family { case chainsel.FamilyEVM: - return c.EVMExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + return c.EVMExtraDataCodec.DecodeDestExecDataToMap(destExecData) case chainsel.FamilySolana: - return c.SolanaExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + return c.SolanaExtraDataCodec.DecodeDestExecDataToMap(destExecData) case chainsel.FamilyAptos: - return c.AptosExtraDataDecoder.DecodeDestExecDataToMap(destExecData) + return c.AptosExtraDataCodec.DecodeDestExecDataToMap(destExecData) default: return nil, fmt.Errorf("unsupported family for extra args type %s", family) diff --git a/core/capabilities/ccip/common/mocks/chain_specific_address_codec.go b/core/capabilities/ccip/common/mocks/chain_specific_address_codec.go new file mode 100644 index 00000000000..71632f970bd --- /dev/null +++ b/core/capabilities/ccip/common/mocks/chain_specific_address_codec.go @@ -0,0 +1,146 @@ +// Code generated by mockery v2.53.0. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// ChainSpecificAddressCodec is an autogenerated mock type for the ChainSpecificAddressCodec type +type ChainSpecificAddressCodec struct { + mock.Mock +} + +type ChainSpecificAddressCodec_Expecter struct { + mock *mock.Mock +} + +func (_m *ChainSpecificAddressCodec) EXPECT() *ChainSpecificAddressCodec_Expecter { + return &ChainSpecificAddressCodec_Expecter{mock: &_m.Mock} +} + +// AddressBytesToString provides a mock function with given fields: _a0 +func (_m *ChainSpecificAddressCodec) AddressBytesToString(_a0 []byte) (string, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for AddressBytesToString") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (string, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func([]byte) string); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainSpecificAddressCodec_AddressBytesToString_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddressBytesToString' +type ChainSpecificAddressCodec_AddressBytesToString_Call struct { + *mock.Call +} + +// AddressBytesToString is a helper method to define mock.On call +// - _a0 []byte +func (_e *ChainSpecificAddressCodec_Expecter) AddressBytesToString(_a0 interface{}) *ChainSpecificAddressCodec_AddressBytesToString_Call { + return &ChainSpecificAddressCodec_AddressBytesToString_Call{Call: _e.mock.On("AddressBytesToString", _a0)} +} + +func (_c *ChainSpecificAddressCodec_AddressBytesToString_Call) Run(run func(_a0 []byte)) *ChainSpecificAddressCodec_AddressBytesToString_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]byte)) + }) + return _c +} + +func (_c *ChainSpecificAddressCodec_AddressBytesToString_Call) Return(_a0 string, _a1 error) *ChainSpecificAddressCodec_AddressBytesToString_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainSpecificAddressCodec_AddressBytesToString_Call) RunAndReturn(run func([]byte) (string, error)) *ChainSpecificAddressCodec_AddressBytesToString_Call { + _c.Call.Return(run) + return _c +} + +// AddressStringToBytes provides a mock function with given fields: _a0 +func (_m *ChainSpecificAddressCodec) AddressStringToBytes(_a0 string) ([]byte, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for AddressStringToBytes") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(string) ([]byte, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(string) []byte); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainSpecificAddressCodec_AddressStringToBytes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddressStringToBytes' +type ChainSpecificAddressCodec_AddressStringToBytes_Call struct { + *mock.Call +} + +// AddressStringToBytes is a helper method to define mock.On call +// - _a0 string +func (_e *ChainSpecificAddressCodec_Expecter) AddressStringToBytes(_a0 interface{}) *ChainSpecificAddressCodec_AddressStringToBytes_Call { + return &ChainSpecificAddressCodec_AddressStringToBytes_Call{Call: _e.mock.On("AddressStringToBytes", _a0)} +} + +func (_c *ChainSpecificAddressCodec_AddressStringToBytes_Call) Run(run func(_a0 string)) *ChainSpecificAddressCodec_AddressStringToBytes_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *ChainSpecificAddressCodec_AddressStringToBytes_Call) Return(_a0 []byte, _a1 error) *ChainSpecificAddressCodec_AddressStringToBytes_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainSpecificAddressCodec_AddressStringToBytes_Call) RunAndReturn(run func(string) ([]byte, error)) *ChainSpecificAddressCodec_AddressStringToBytes_Call { + _c.Call.Return(run) + return _c +} + +// NewChainSpecificAddressCodec creates a new instance of ChainSpecificAddressCodec. 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 NewChainSpecificAddressCodec(t interface { + mock.TestingT + Cleanup(func()) +}) *ChainSpecificAddressCodec { + mock := &ChainSpecificAddressCodec{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/ccip/common/mocks/extra_data_codec.go b/core/capabilities/ccip/common/mocks/extra_data_codec.go deleted file mode 100644 index 806b8c2a305..00000000000 --- a/core/capabilities/ccip/common/mocks/extra_data_codec.go +++ /dev/null @@ -1,154 +0,0 @@ -// Code generated by mockery v2.53.0. DO NOT EDIT. - -package mocks - -import ( - ccipocr3 "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - - mock "github.com/stretchr/testify/mock" -) - -// ExtraDataCodec is an autogenerated mock type for the ExtraDataCodec type -type ExtraDataCodec struct { - mock.Mock -} - -type ExtraDataCodec_Expecter struct { - mock *mock.Mock -} - -func (_m *ExtraDataCodec) EXPECT() *ExtraDataCodec_Expecter { - return &ExtraDataCodec_Expecter{mock: &_m.Mock} -} - -// DecodeExtraArgs provides a mock function with given fields: extraArgs, sourceChainSelector -func (_m *ExtraDataCodec) DecodeExtraArgs(extraArgs ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]interface{}, error) { - ret := _m.Called(extraArgs, sourceChainSelector) - - if len(ret) == 0 { - panic("no return value specified for DecodeExtraArgs") - } - - var r0 map[string]interface{} - var r1 error - if rf, ok := ret.Get(0).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) (map[string]interface{}, error)); ok { - return rf(extraArgs, sourceChainSelector) - } - if rf, ok := ret.Get(0).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) map[string]interface{}); ok { - r0 = rf(extraArgs, sourceChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]interface{}) - } - } - - if rf, ok := ret.Get(1).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) error); ok { - r1 = rf(extraArgs, sourceChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ExtraDataCodec_DecodeExtraArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DecodeExtraArgs' -type ExtraDataCodec_DecodeExtraArgs_Call struct { - *mock.Call -} - -// DecodeExtraArgs is a helper method to define mock.On call -// - extraArgs ccipocr3.Bytes -// - sourceChainSelector ccipocr3.ChainSelector -func (_e *ExtraDataCodec_Expecter) DecodeExtraArgs(extraArgs interface{}, sourceChainSelector interface{}) *ExtraDataCodec_DecodeExtraArgs_Call { - return &ExtraDataCodec_DecodeExtraArgs_Call{Call: _e.mock.On("DecodeExtraArgs", extraArgs, sourceChainSelector)} -} - -func (_c *ExtraDataCodec_DecodeExtraArgs_Call) Run(run func(extraArgs ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector)) *ExtraDataCodec_DecodeExtraArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(ccipocr3.Bytes), args[1].(ccipocr3.ChainSelector)) - }) - return _c -} - -func (_c *ExtraDataCodec_DecodeExtraArgs_Call) Return(_a0 map[string]interface{}, _a1 error) *ExtraDataCodec_DecodeExtraArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ExtraDataCodec_DecodeExtraArgs_Call) RunAndReturn(run func(ccipocr3.Bytes, ccipocr3.ChainSelector) (map[string]interface{}, error)) *ExtraDataCodec_DecodeExtraArgs_Call { - _c.Call.Return(run) - return _c -} - -// DecodeTokenAmountDestExecData provides a mock function with given fields: destExecData, sourceChainSelector -func (_m *ExtraDataCodec) DecodeTokenAmountDestExecData(destExecData ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector) (map[string]interface{}, error) { - ret := _m.Called(destExecData, sourceChainSelector) - - if len(ret) == 0 { - panic("no return value specified for DecodeTokenAmountDestExecData") - } - - var r0 map[string]interface{} - var r1 error - if rf, ok := ret.Get(0).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) (map[string]interface{}, error)); ok { - return rf(destExecData, sourceChainSelector) - } - if rf, ok := ret.Get(0).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) map[string]interface{}); ok { - r0 = rf(destExecData, sourceChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]interface{}) - } - } - - if rf, ok := ret.Get(1).(func(ccipocr3.Bytes, ccipocr3.ChainSelector) error); ok { - r1 = rf(destExecData, sourceChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ExtraDataCodec_DecodeTokenAmountDestExecData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DecodeTokenAmountDestExecData' -type ExtraDataCodec_DecodeTokenAmountDestExecData_Call struct { - *mock.Call -} - -// DecodeTokenAmountDestExecData is a helper method to define mock.On call -// - destExecData ccipocr3.Bytes -// - sourceChainSelector ccipocr3.ChainSelector -func (_e *ExtraDataCodec_Expecter) DecodeTokenAmountDestExecData(destExecData interface{}, sourceChainSelector interface{}) *ExtraDataCodec_DecodeTokenAmountDestExecData_Call { - return &ExtraDataCodec_DecodeTokenAmountDestExecData_Call{Call: _e.mock.On("DecodeTokenAmountDestExecData", destExecData, sourceChainSelector)} -} - -func (_c *ExtraDataCodec_DecodeTokenAmountDestExecData_Call) Run(run func(destExecData ccipocr3.Bytes, sourceChainSelector ccipocr3.ChainSelector)) *ExtraDataCodec_DecodeTokenAmountDestExecData_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(ccipocr3.Bytes), args[1].(ccipocr3.ChainSelector)) - }) - return _c -} - -func (_c *ExtraDataCodec_DecodeTokenAmountDestExecData_Call) Return(_a0 map[string]interface{}, _a1 error) *ExtraDataCodec_DecodeTokenAmountDestExecData_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ExtraDataCodec_DecodeTokenAmountDestExecData_Call) RunAndReturn(run func(ccipocr3.Bytes, ccipocr3.ChainSelector) (map[string]interface{}, error)) *ExtraDataCodec_DecodeTokenAmountDestExecData_Call { - _c.Call.Return(run) - return _c -} - -// NewExtraDataCodec creates a new instance of ExtraDataCodec. 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 NewExtraDataCodec(t interface { - mock.TestingT - Cleanup(func()) -}) *ExtraDataCodec { - mock := &ExtraDataCodec{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/ccip/common/mocks/source_chain_extra_data_codec.go b/core/capabilities/ccip/common/mocks/source_chain_extra_data_codec.go new file mode 100644 index 00000000000..c9b4ec4caef --- /dev/null +++ b/core/capabilities/ccip/common/mocks/source_chain_extra_data_codec.go @@ -0,0 +1,152 @@ +// Code generated by mockery v2.53.0. DO NOT EDIT. + +package mocks + +import ( + ccipocr3 "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + mock "github.com/stretchr/testify/mock" +) + +// SourceChainExtraDataCodec is an autogenerated mock type for the SourceChainExtraDataCodec type +type SourceChainExtraDataCodec struct { + mock.Mock +} + +type SourceChainExtraDataCodec_Expecter struct { + mock *mock.Mock +} + +func (_m *SourceChainExtraDataCodec) EXPECT() *SourceChainExtraDataCodec_Expecter { + return &SourceChainExtraDataCodec_Expecter{mock: &_m.Mock} +} + +// DecodeDestExecDataToMap provides a mock function with given fields: destExecData +func (_m *SourceChainExtraDataCodec) DecodeDestExecDataToMap(destExecData ccipocr3.Bytes) (map[string]interface{}, error) { + ret := _m.Called(destExecData) + + if len(ret) == 0 { + panic("no return value specified for DecodeDestExecDataToMap") + } + + var r0 map[string]interface{} + var r1 error + if rf, ok := ret.Get(0).(func(ccipocr3.Bytes) (map[string]interface{}, error)); ok { + return rf(destExecData) + } + if rf, ok := ret.Get(0).(func(ccipocr3.Bytes) map[string]interface{}); ok { + r0 = rf(destExecData) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]interface{}) + } + } + + if rf, ok := ret.Get(1).(func(ccipocr3.Bytes) error); ok { + r1 = rf(destExecData) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DecodeDestExecDataToMap' +type SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call struct { + *mock.Call +} + +// DecodeDestExecDataToMap is a helper method to define mock.On call +// - destExecData ccipocr3.Bytes +func (_e *SourceChainExtraDataCodec_Expecter) DecodeDestExecDataToMap(destExecData interface{}) *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call { + return &SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call{Call: _e.mock.On("DecodeDestExecDataToMap", destExecData)} +} + +func (_c *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call) Run(run func(destExecData ccipocr3.Bytes)) *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(ccipocr3.Bytes)) + }) + return _c +} + +func (_c *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call) Return(_a0 map[string]interface{}, _a1 error) *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call) RunAndReturn(run func(ccipocr3.Bytes) (map[string]interface{}, error)) *SourceChainExtraDataCodec_DecodeDestExecDataToMap_Call { + _c.Call.Return(run) + return _c +} + +// DecodeExtraArgsToMap provides a mock function with given fields: extraArgs +func (_m *SourceChainExtraDataCodec) DecodeExtraArgsToMap(extraArgs ccipocr3.Bytes) (map[string]interface{}, error) { + ret := _m.Called(extraArgs) + + if len(ret) == 0 { + panic("no return value specified for DecodeExtraArgsToMap") + } + + var r0 map[string]interface{} + var r1 error + if rf, ok := ret.Get(0).(func(ccipocr3.Bytes) (map[string]interface{}, error)); ok { + return rf(extraArgs) + } + if rf, ok := ret.Get(0).(func(ccipocr3.Bytes) map[string]interface{}); ok { + r0 = rf(extraArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]interface{}) + } + } + + if rf, ok := ret.Get(1).(func(ccipocr3.Bytes) error); ok { + r1 = rf(extraArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DecodeExtraArgsToMap' +type SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call struct { + *mock.Call +} + +// DecodeExtraArgsToMap is a helper method to define mock.On call +// - extraArgs ccipocr3.Bytes +func (_e *SourceChainExtraDataCodec_Expecter) DecodeExtraArgsToMap(extraArgs interface{}) *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call { + return &SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call{Call: _e.mock.On("DecodeExtraArgsToMap", extraArgs)} +} + +func (_c *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call) Run(run func(extraArgs ccipocr3.Bytes)) *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(ccipocr3.Bytes)) + }) + return _c +} + +func (_c *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call) Return(_a0 map[string]interface{}, _a1 error) *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call) RunAndReturn(run func(ccipocr3.Bytes) (map[string]interface{}, error)) *SourceChainExtraDataCodec_DecodeExtraArgsToMap_Call { + _c.Call.Return(run) + return _c +} + +// NewSourceChainExtraDataCodec creates a new instance of SourceChainExtraDataCodec. 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 NewSourceChainExtraDataCodec(t interface { + mock.TestingT + Cleanup(func()) +}) *SourceChainExtraDataCodec { + mock := &SourceChainExtraDataCodec{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/ccip/common/msgfieldscodec.go b/core/capabilities/ccip/common/msgfieldscodec.go new file mode 100644 index 00000000000..0a68233fd07 --- /dev/null +++ b/core/capabilities/ccip/common/msgfieldscodec.go @@ -0,0 +1,20 @@ +package common + +import cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + +// ChainSpecificAddressCodec is an interface that defines the methods for encoding and decoding addresses for a specific chain +type ChainSpecificAddressCodec interface { + // AddressBytesToString converts an address from bytes to string + AddressBytesToString([]byte) (string, error) + // AddressStringToBytes converts an address from string to bytes + AddressStringToBytes(string) ([]byte, error) +} + +// SourceChainExtraDataCodec is an interface for decoding source chain specific extra args and dest exec data into a map[string]any representation for a specific chain +// For chain A to chain B message, this interface will be the chain A specific codec +type SourceChainExtraDataCodec interface { + // DecodeExtraArgsToMap reformat bytes into a chain agnostic map[string]any representation for extra args + DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) + // DecodeDestExecDataToMap reformat bytes into a chain agnostic map[string]interface{} representation for dest exec data + DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) +} diff --git a/core/capabilities/ccip/common/pluginconfig.go b/core/capabilities/ccip/common/pluginconfig.go new file mode 100644 index 00000000000..2901e736885 --- /dev/null +++ b/core/capabilities/ccip/common/pluginconfig.go @@ -0,0 +1,54 @@ +package common + +import ( + "fmt" + + chainsel "github.com/smartcontractkit/chain-selectors" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// PluginConfig is a struct that contains the configuration for a plugin. +type PluginConfig struct { + CommitPluginCodec cciptypes.CommitPluginCodec + ExecutePluginCodec cciptypes.ExecutePluginCodec + MessageHasher cciptypes.MessageHasher + TokenDataEncoder cciptypes.TokenDataEncoder + GasEstimateProvider cciptypes.EstimateProvider + RMNCrypto cciptypes.RMNCrypto + ContractTransmitterFactory cctypes.ContractTransmitterFactory + // PriceOnlyCommitFn optional method override for price only commit reports. + PriceOnlyCommitFn string +} + +// PluginConfigFactory is a factory for creating PluginConfig instances. +type PluginConfigFactory struct { + EVMPluginConfig PluginConfig + SolanaPluginConfig PluginConfig + AptosPluginConfig PluginConfig +} + +// NewPluginConfigFactory is a constructor for PluginConfigFactory. +func NewPluginConfigFactory(evmPluginConfig, solanaPluginConfig, aptosPluginConfig PluginConfig) *PluginConfigFactory { + return &PluginConfigFactory{ + EVMPluginConfig: evmPluginConfig, + SolanaPluginConfig: solanaPluginConfig, + AptosPluginConfig: aptosPluginConfig, + } +} + +// CreatePluginConfig creates a PluginConfig instance based on the chain family. +func (f *PluginConfigFactory) CreatePluginConfig(chainFamily string) (PluginConfig, error) { + switch chainFamily { + case chainsel.FamilyEVM: + return f.EVMPluginConfig, nil + case chainsel.FamilySolana: + return f.SolanaPluginConfig, nil + case chainsel.FamilyAptos: + return f.AptosPluginConfig, nil + default: + return PluginConfig{}, fmt.Errorf("unsupported chain family: %s", chainFamily) + } +} diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index e4b89ca4ca2..6a22ca30df0 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -325,7 +325,23 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, "token_amounts": { NewName: "TokenAmounts", - SubFieldRenames: nil, // TODO + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_pool_address": { + NewName: "SourcePoolAddress", + }, + "dest_token_address": { + NewName: "DestTokenAddress", + }, + "extra_data": { + NewName: "ExtraData", + }, + "amount": { + NewName: "Amount", + }, + "dest_exec_data": { + NewName: "DestExecData", + }, + }, }, }, }, diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 7dc8a7b1e7f..57dc454f481 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -9,9 +9,7 @@ import ( "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + defaults "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/default" "github.com/avast/retry-go/v4" ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -205,12 +203,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services return nil, fmt.Errorf("failed to get chain selector from chain ID %d", homeChainChainID) } - addressCodec := common.NewAddressCodec( - common.NewAddressCodecParams( - ccipevm.AddressCodec{}, - ccipsolana.AddressCodec{}, - ccipaptos.AddressCodec{}, - )) + addressCodec := defaults.DefaultAddressCodec // if bootstrappers are provided we assume that the node is a plugin oracle. // the reason for this is that bootstrap oracles do not need to be aware diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index 855cc3a47f9..89fc1df7431 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -7,9 +7,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -28,7 +25,15 @@ type AptosExecCallArgs struct { } // AptosContractTransmitterFactory implements the transmitter factory for Aptos chains. -type AptosContractTransmitterFactory struct{} +type AptosContractTransmitterFactory struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +func NewAptosContractTransmitterFactory(extraDataCodec ccipcommon.ExtraDataCodec) *AptosContractTransmitterFactory { + return &AptosContractTransmitterFactory{ + extraDataCodec: extraDataCodec, + } +} // NewAptosCommitCalldataFunc returns a ToCalldataFunc for Aptos commits that omits any Info object. func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { @@ -36,7 +41,7 @@ func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { rawReportCtx [2][32]byte, report ocr3types.ReportWithInfo[[]byte], signatures [][96]byte, - _ ccipcommon.ExtraDataCodec, + _ *ccipcommon.ExtraDataCodec, ) (string, string, any, error) { return consts.ContractNameOffRamp, commitMethod, @@ -71,7 +76,7 @@ var AptosExecCallDataFunc = func( rawReportCtx [2][32]byte, report ocr3types.ReportWithInfo[[]byte], signatures [][96]byte, - _ ccipcommon.ExtraDataCodec, + _ *ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) { return consts.ContractNameOffRamp, consts.MethodExecute, @@ -94,8 +99,6 @@ func (f *AptosContractTransmitterFactory) NewExecTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toEd25519CalldataFn: AptosExecCallDataFunc, - extraDataCodec: ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), - ), + extraDataCodec: f.extraDataCodec, } } diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 09e79744290..c572b8fb44a 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -28,14 +28,14 @@ type ToCalldataFunc func( report ocr3types.ReportWithInfo[[]byte], rs, ss [][32]byte, vs [32]byte, - codec ccipcommon.ExtraDataCodec, + codec *ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) type ToEd25519CalldataFunc func( rawReportCtx [2][32]byte, report ocr3types.ReportWithInfo[[]byte], signatures [][96]byte, - codec ccipcommon.ExtraDataCodec, + codec *ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) var _ ocr3types.ContractTransmitter[[]byte] = &ccipTransmitter{} @@ -63,7 +63,7 @@ func XXXNewContractTransmitterTestsOnly( report ocr3types.ReportWithInfo[[]byte], rs, ss [][32]byte, vs [32]byte, - extraDataCodec ccipcommon.ExtraDataCodec) (string, string, any, error) { + extraDataCodec *ccipcommon.ExtraDataCodec) (string, string, any, error) { _, _, args, err := toCalldataFn(rawReportCtx, report, rs, ss, vs, extraDataCodec) return contractName, method, args, err } @@ -118,7 +118,7 @@ func (c *ccipTransmitter) Transmit( } // chain writer takes in the raw calldata and packs it on its own. - contract, method, args, err = c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) + contract, method, args, err = c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, &c.extraDataCodec) if err != nil { return fmt.Errorf("failed to generate ecdsa call data: %w", err) } @@ -134,7 +134,7 @@ func (c *ccipTransmitter) Transmit( signatures = append(signatures, sigBytes) } - contract, method, args, err = c.toEd25519CalldataFn(rawReportCtx, reportWithInfo, signatures, c.extraDataCodec) + contract, method, args, err = c.toEd25519CalldataFn(rawReportCtx, reportWithInfo, signatures, &c.extraDataCodec) if err != nil { return fmt.Errorf("failed to generate ed25519 call data: %w", err) } diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 5b63341b8f3..a146a0c403f 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -15,6 +15,8 @@ import ( "github.com/jmoiron/sqlx" "github.com/stretchr/testify/require" + defaults "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/default" + "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -36,9 +38,6 @@ import ( evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -50,8 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) func Test_ContractTransmitter_TransmitWithoutSignatures(t *testing.T) { @@ -189,13 +186,7 @@ func abiEncodeUint32(data uint32) ([]byte, error) { // Test EVM -> SVM extra data decoding in contract transmitter func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { - extraDataCodec := ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams( - ccipevm.ExtraDataDecoder{}, - ccipsolana.ExtraDataDecoder{}, - ccipaptos.ExtraDataDecoder{}, - ), - ) + extraDataCodec := defaults.DefaultExtraDataCodec t.Run("fails when multiple reports are included", func(t *testing.T) { reports := []ccipocr3.ExecutePluginReportSingleChain{{}, {}} reportWithInfo := ccipocr3.ExecuteReportInfo{ @@ -209,7 +200,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { Report: randomReport(t, 96), Info: encodedExecReport, } - _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, extraDataCodec) + _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, &extraDataCodec) require.Contains(t, err.Error(), "unexpected report length, expected 1, got 2") }) t.Run("fails when multiple report contains multiple messages", func(t *testing.T) { @@ -227,7 +218,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { Report: randomReport(t, 96), Info: encodedExecReport, } - _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, extraDataCodec) + _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, &extraDataCodec) require.Contains(t, err.Error(), "unexpected message length, expected 1, got 2") }) t.Run("fails with invalid extra args", func(t *testing.T) { @@ -259,7 +250,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { Info: encodedExecReport, } - _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, extraDataCodec) + _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, &extraDataCodec) require.Contains(t, err.Error(), "unknown extra args tag") }) t.Run("fails with invalid extra exec data", func(t *testing.T) { @@ -295,7 +286,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { Info: encodedExecReport, } - _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, extraDataCodec) + _, _, _, err = ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, &extraDataCodec) require.Contains(t, err.Error(), "failed to decode token amount dest exec data: decode dest gas amount: abi decode uint32: abi: cannot marshal in to go type: length insufficient 4 require 32") }) t.Run("Successfully decodes valid EVM -> SOL report", func(t *testing.T) { @@ -333,7 +324,7 @@ func TestSVMExecCallDataFuncExtraDataDecoding(t *testing.T) { Info: encodedExecReport, } - _, _, args, err := ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, extraDataCodec) + _, _, args, err := ocrimpls.SVMExecCalldataFunc([2][32]byte{}, rwi, nil, nil, [32]byte{}, &extraDataCodec) require.NoError(t, err) expectedArgs, ok := args.(ocrimpls.SVMExecCallArgs) diff --git a/core/capabilities/ccip/ocrimpls/evm_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/evm_contract_transmitter_factory.go index bfa3d298430..2388f2317d1 100644 --- a/core/capabilities/ccip/ocrimpls/evm_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/evm_contract_transmitter_factory.go @@ -33,7 +33,16 @@ type EVMExecCallArgs struct { } // EVMContractTransmitterFactory implements the transmitter factory for EVM chains. -type EVMContractTransmitterFactory struct{} +type EVMContractTransmitterFactory struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +// NewEVMContractTransmitterFactory returns a new EVMContractTransmitterFactory. +func NewEVMContractTransmitterFactory(extraDataCodec ccipcommon.ExtraDataCodec) *EVMContractTransmitterFactory { + return &EVMContractTransmitterFactory{ + extraDataCodec: extraDataCodec, + } +} // EVMExecCallDataFunc builds the execute call data for EVM. var EVMExecCallDataFunc = func( @@ -41,7 +50,7 @@ var EVMExecCallDataFunc = func( report ocr3types.ReportWithInfo[[]byte], _, _ [][32]byte, _ [32]byte, - _ ccipcommon.ExtraDataCodec, + _ *ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) { return consts.ContractNameOffRamp, consts.MethodExecute, @@ -58,7 +67,7 @@ func NewEVMCommitCalldataFunc(commitMethod string) ToCalldataFunc { report ocr3types.ReportWithInfo[[]byte], rs, ss [][32]byte, vs [32]byte, - _ ccipcommon.ExtraDataCodec, + _ *ccipcommon.ExtraDataCodec, ) (string, string, any, error) { return consts.ContractNameOffRamp, commitMethod, @@ -87,6 +96,7 @@ func (f *EVMContractTransmitterFactory) NewCommitTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toCalldataFn: NewEVMCommitCalldataFunc(commitMethod), + extraDataCodec: f.extraDataCodec, } } @@ -103,5 +113,6 @@ func (f *EVMContractTransmitterFactory) NewExecTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toCalldataFn: EVMExecCallDataFunc, + extraDataCodec: f.extraDataCodec, } } diff --git a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go index abb9e495957..cece3340240 100644 --- a/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/svm_contract_transmitter_factory.go @@ -9,9 +9,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" "github.com/smartcontractkit/chainlink/v2/core/logger" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" @@ -42,7 +39,16 @@ type SVMExecCallArgs struct { } // SVMContractTransmitterFactory implements the transmitter factory for SVM chains. -type SVMContractTransmitterFactory struct{} +type SVMContractTransmitterFactory struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +// NewSVMContractTransmitterFactory returns a new SVMContractTransmitterFactory. +func NewSVMContractTransmitterFactory(extraDataCodec ccipcommon.ExtraDataCodec) *SVMContractTransmitterFactory { + return &SVMContractTransmitterFactory{ + extraDataCodec: extraDataCodec, + } +} // SVMExecCalldataFunc builds the execute call data for SVM. var SVMExecCalldataFunc = func( @@ -50,7 +56,7 @@ var SVMExecCalldataFunc = func( report ocr3types.ReportWithInfo[[]byte], _, _ [][32]byte, _ [32]byte, - extraDataCodec ccipcommon.ExtraDataCodec, + extraDataCodec *ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) { var info ccipocr3.ExecuteReportInfo if len(report.Info) != 0 { @@ -87,7 +93,7 @@ func NewSVMCommitCalldataFunc(defaultMethod, priceOnlyMethod string) ToCalldataF report ocr3types.ReportWithInfo[[]byte], rs, ss [][32]byte, vs [32]byte, - _ ccipcommon.ExtraDataCodec, + _ *ccipcommon.ExtraDataCodec, ) (string, string, any, error) { var info ccipocr3.CommitReportInfo if len(report.Info) != 0 { @@ -119,7 +125,7 @@ func NewSVMCommitCalldataFunc(defaultMethod, priceOnlyMethod string) ToCalldataF } // decodeExecData decodes the extra data from an execute report. -func decodeExecData(report ccipocr3.ExecuteReportInfo, codec ccipcommon.ExtraDataCodec) (ccipcommon.ExtraDataDecoded, error) { +func decodeExecData(report ccipocr3.ExecuteReportInfo, codec *ccipcommon.ExtraDataCodec) (ccipcommon.ExtraDataDecoded, error) { // only one report one message, since this is a stop-gap solution for solana if len(report.AbstractReports) != 1 { return ccipcommon.ExtraDataDecoded{}, fmt.Errorf("unexpected report length, expected 1, got %d", len(report.AbstractReports)) @@ -162,7 +168,7 @@ func (f *SVMContractTransmitterFactory) NewCommitTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toCalldataFn: NewSVMCommitCalldataFunc(defaultMethod, priceOnlyMethod), - extraDataCodec: nil, + extraDataCodec: f.extraDataCodec, } } @@ -179,8 +185,6 @@ func (f *SVMContractTransmitterFactory) NewExecTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toCalldataFn: SVMExecCalldataFunc, - extraDataCodec: ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), - ), + extraDataCodec: f.extraDataCodec, } } diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 21727297ebf..9534ac0e229 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -2,35 +2,27 @@ package oraclecreator import ( "context" - "encoding/json" "errors" "fmt" "io" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/gagliardetto/solana-go" "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/libocr/commontypes" libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + defaults "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/default" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - aptosconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/aptos" - solanaconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/solana" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" @@ -40,87 +32,24 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/chainwriter" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) var _ cctypes.OracleCreator = &pluginOracleCreator{} -var extraDataCodec = ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams( - ccipevm.ExtraDataDecoder{}, - ccipsolana.ExtraDataDecoder{}, - ccipaptos.ExtraDataDecoder{}, - ), -) - -var plugins = map[string]plugin{ - chainsel.FamilyEVM: { - CommitPluginCodec: ccipevm.NewCommitPluginCodecV1(), - ExecutePluginCodec: ccipevm.NewExecutePluginCodecV1(extraDataCodec), - MessageHasher: func(lggr logger.Logger) cciptypes.MessageHasher { - return ccipevm.NewMessageHasherV1(lggr, extraDataCodec) - }, - TokenDataEncoder: ccipevm.NewEVMTokenDataEncoder(), - GasEstimateProvider: ccipevm.NewGasEstimateProvider(extraDataCodec), - RMNCrypto: func(lggr logger.Logger) cciptypes.RMNCrypto { return ccipevm.NewEVMRMNCrypto(lggr) }, - ContractTransmitterFactory: &ocrimpls.EVMContractTransmitterFactory{}, - }, - chainsel.FamilySolana: { - CommitPluginCodec: ccipsolana.NewCommitPluginCodecV1(), - ExecutePluginCodec: ccipsolana.NewExecutePluginCodecV1(extraDataCodec), - MessageHasher: func(lggr logger.Logger) cciptypes.MessageHasher { - return ccipsolana.NewMessageHasherV1(lggr, extraDataCodec) - }, - TokenDataEncoder: ccipsolana.NewSolanaTokenDataEncoder(), - GasEstimateProvider: ccipsolana.NewGasEstimateProvider(extraDataCodec), - RMNCrypto: func(lggr logger.Logger) cciptypes.RMNCrypto { return nil }, - PriceOnlyCommitFn: consts.MethodCommitPriceOnly, - ContractTransmitterFactory: &ocrimpls.SVMContractTransmitterFactory{}, - }, - chainsel.FamilyAptos: { - CommitPluginCodec: ccipaptos.NewCommitPluginCodecV1(), - ExecutePluginCodec: ccipaptos.NewExecutePluginCodecV1(extraDataCodec), - MessageHasher: func(lggr logger.Logger) cciptypes.MessageHasher { - return ccipaptos.NewMessageHasherV1(lggr, extraDataCodec) - }, - TokenDataEncoder: ccipaptos.NewAptosTokenDataEncoder(), - GasEstimateProvider: ccipaptos.NewGasEstimateProvider(), - RMNCrypto: func(lggr logger.Logger) cciptypes.RMNCrypto { return nil }, - PriceOnlyCommitFn: consts.MethodCommitPriceOnly, - ContractTransmitterFactory: &ocrimpls.AptosContractTransmitterFactory{}, - }, -} const ( defaultCommitGasLimit = 500_000 defaultExecGasLimit = 6_500_000 ) -type plugin struct { - CommitPluginCodec cciptypes.CommitPluginCodec - ExecutePluginCodec cciptypes.ExecutePluginCodec - MessageHasher func(lggr logger.Logger) cciptypes.MessageHasher - TokenDataEncoder cciptypes.TokenDataEncoder - GasEstimateProvider cciptypes.EstimateProvider - RMNCrypto func(lggr logger.Logger) cciptypes.RMNCrypto - ContractTransmitterFactory ContractTransmitterFactory - // PriceOnlyCommitFn optional method override for price only commit reports. - PriceOnlyCommitFn string -} - // pluginOracleCreator creates oracles that reference plugins running // in the same process as the chainlink node, i.e not LOOPPs. type pluginOracleCreator struct { @@ -203,6 +132,11 @@ func (i *pluginOracleCreator) Create(ctx context.Context, donID uint32, config c return nil, fmt.Errorf("failed to get public config from OCR config: %w", err) } + pluginConfig, err := initializerPluginConfig(destChainFamily, i.lggr) + if err != nil { + return nil, fmt.Errorf("failed to initialize plugin config: %w", err) + } + i.lggr.Infow("Creating plugin using OCR3 settings", "plugin", pluginType.String(), "chainSelector", chainSelector, @@ -228,6 +162,7 @@ func (i *pluginOracleCreator) Create(ctx context.Context, donID uint32, config c return nil, err } + i.lggr.Infow("offramp address", "offrampAddrStr", config.Config.OfframpAddress, "selector", config.Config.ChainSelector) contractReaders, chainWriters, err := i.createReadersAndWriters( ctx, destChainID, @@ -264,7 +199,7 @@ func (i *pluginOracleCreator) Create(ctx context.Context, donID uint32, config c // TODO: Extract the correct transmitter address from the destsFromAccount factory, transmitter, err := i.createFactoryAndTransmitter( - donID, config, destRelayID, contractReaders, chainWriters, destChainWriter, destFromAccounts, publicConfig, offrampAddrStr) + donID, config, destRelayID, contractReaders, chainWriters, destChainWriter, destFromAccounts, publicConfig, destChainID, pluginConfig, offrampAddrStr) if err != nil { return nil, fmt.Errorf("failed to create factory and transmitter: %w", err) } @@ -326,26 +261,12 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( destChainWriter types.ContractWriter, destFromAccounts []string, publicConfig ocr3confighelper.PublicConfig, + destChainID string, + pluginConfig ccipcommon.PluginConfig, offrampAddrStr string, ) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { var factory ocr3types.ReportingPluginFactory[[]byte] var transmitter ocr3types.ContractTransmitter[[]byte] - - chainID, err := chainsel.GetChainIDFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, nil, fmt.Errorf("unsupported chain selector %d %w", config.Config.ChainSelector, err) - } - - chainFamily, err := chainsel.GetSelectorFamily(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, nil, fmt.Errorf("unsupported chain selector %d %w", config.Config.ChainSelector, err) - } - plugin, exists := plugins[chainFamily] - if !exists { - return nil, nil, fmt.Errorf("unsupported chain %v", chainFamily) - } - messageHasher := plugin.MessageHasher(i.lggr.Named(chainFamily).Named("MessageHasherV1")) - if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { if !i.peerWrapper.IsStarted() { return nil, nil, errors.New("peer wrapper is not started") @@ -361,7 +282,6 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( publicConfig.DeltaRound, ) - rmnCrypto := plugin.RMNCrypto(i.lggr.Named(chainFamily).Named("RMNCrypto")) factory = commitocr3.NewCommitPluginFactory( commitocr3.CommitPluginFactoryParams{ Lggr: i.lggr. @@ -371,24 +291,23 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( Named(offrampAddrStr), DonID: donID, OcrConfig: ccipreaderpkg.OCR3ConfigWithMeta(config), - CommitCodec: plugin.CommitPluginCodec, - MsgHasher: messageHasher, + CommitCodec: pluginConfig.CommitPluginCodec, + MsgHasher: pluginConfig.MessageHasher, AddrCodec: i.addressCodec, HomeChainReader: i.homeChainReader, HomeChainSelector: i.homeChainSelector, ContractReaders: contractReaders, ContractWriters: chainWriters, RmnPeerClient: rmnPeerClient, - RmnCrypto: rmnCrypto}) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPCommit") - transmitter = plugins[chainFamily].ContractTransmitterFactory.NewCommitTransmitter( - i.lggr.Named("CCIPCommitTransmitter"). - Named(destRelayID.String()), + RmnCrypto: pluginConfig.RMNCrypto}) + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, destChainID, "CCIPCommit") + transmitter = pluginConfig.ContractTransmitterFactory.NewCommitTransmitter( + i.lggr.Named("CCIPCommitTransmitter").Named(destRelayID.String()), destChainWriter, ocrtypes.Account(destFromAccounts[0]), offrampAddrStr, consts.MethodCommit, - plugins[chainFamily].PriceOnlyCommitFn, + pluginConfig.PriceOnlyCommitFn, ) } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { factory = execocr3.NewExecutePluginFactory( @@ -399,25 +318,24 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( Named(offrampAddrStr), DonID: donID, OcrConfig: ccipreaderpkg.OCR3ConfigWithMeta(config), - ExecCodec: plugin.ExecutePluginCodec, - MsgHasher: messageHasher, + ExecCodec: pluginConfig.ExecutePluginCodec, + MsgHasher: pluginConfig.MessageHasher, AddrCodec: i.addressCodec, HomeChainReader: i.homeChainReader, - TokenDataEncoder: plugin.TokenDataEncoder, - EstimateProvider: plugin.GasEstimateProvider, + TokenDataEncoder: pluginConfig.TokenDataEncoder, + EstimateProvider: pluginConfig.GasEstimateProvider, ContractReaders: contractReaders, ContractWriters: chainWriters, }) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPExec") - transmitter = plugins[chainFamily].ContractTransmitterFactory.NewExecTransmitter( - i.lggr.Named("CCIPExecTransmitter"). - Named(destRelayID.String()), + factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, destChainID, "CCIPExec") + transmitter = pluginConfig.ContractTransmitterFactory.NewExecTransmitter( + i.lggr.Named("CCIPExecTransmitter").Named(destRelayID.String()), destChainWriter, ocrtypes.Account(destFromAccounts[0]), offrampAddrStr, ) } else { - return nil, nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) + return nil, nil, fmt.Errorf("unsupported Plugin type %d", config.Config.PluginType) } return factory, transmitter, nil } @@ -441,8 +359,8 @@ func (i *pluginOracleCreator) createReadersAndWriters( } var execBatchGasLimit uint64 - if !ofc.execEmpty() { - execBatchGasLimit = ofc.exec().BatchGasLimit + if !ofc.ExecEmpty() { + execBatchGasLimit = ofc.Execute.BatchGasLimit } else { // Set the default here so chain writer config validation doesn't fail. // For commit, this won't be used, so its harmless. @@ -454,6 +372,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, fmt.Errorf("failed to get chain ID from chain selector %d: %w", i.homeChainSelector, err) } + crcw := defaults.DefaultCRCW contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) chainWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) for relayID, relayer := range i.relayers { @@ -465,14 +384,18 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID, err1) } - if _, exists := plugins[relayChainFamily]; !exists { - i.lggr.Debugw("createReadersAndWriters: skipping unsupported relayer", "chainID", chainID, "family", relayChainFamily) - continue - } - - cr, err1 := createChainReader(ctx, i.lggr, relayer, chainID, destChainID, homeChainID, ofc, chainSelector, relayChainFamily) + cr, err1 := crcw.GetChainReader(ctx, ccipcommon.ChainReaderProviderOpts{ + Lggr: i.lggr, + Relayer: relayer, + ChainID: chainID, + DestChainID: destChainID, + HomeChainID: homeChainID, + Ofc: ofc, + ChainSelector: chainSelector, + ChainFamily: relayChainFamily, + }) if err1 != nil { - return nil, nil, fmt.Errorf("failed to get chain reader config: %w", err1) + return nil, nil, err1 } if chainID == destChainID && destChainFamily == relayChainFamily { @@ -492,15 +415,14 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chainID, err2) } - cw, err1 := createChainWriter( - ctx, - chainID, - relayer, - i.transmitters, - execBatchGasLimit, - relayChainFamily, - config.Config.OfframpAddress, - ) + cw, err1 := crcw.GetChainWriter(ctx, ccipcommon.ChainWriterProviderOpts{ + ChainID: chainID, + Relayer: relayer, + Transmitters: i.transmitters, + ExecBatchGasLimit: execBatchGasLimit, + ChainFamily: relayChainFamily, + OfframpProgramAddress: config.Config.OfframpAddress, + }) if err1 != nil { return nil, nil, err1 } @@ -518,227 +440,47 @@ func (i *pluginOracleCreator) createReadersAndWriters( func decodeAndValidateOffchainConfig( pluginType cctypes.PluginType, publicConfig ocr3confighelper.PublicConfig, -) (offChainConfig, error) { - var ofc offChainConfig +) (ccipcommon.OffChainConfig, error) { + var ofc ccipcommon.OffChainConfig if pluginType == cctypes.PluginTypeCCIPExec { execOffchainCfg, err1 := pluginconfig.DecodeExecuteOffchainConfig(publicConfig.ReportingPluginConfig) if err1 != nil { - return offChainConfig{}, fmt.Errorf("failed to decode execute offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) + return ccipcommon.OffChainConfig{}, fmt.Errorf("failed to decode execute offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) } if err2 := execOffchainCfg.Validate(); err2 != nil { - return offChainConfig{}, fmt.Errorf("failed to validate execute offchain config: %w", err2) + return ccipcommon.OffChainConfig{}, fmt.Errorf("failed to validate execute offchain config: %w", err2) } - ofc.execOffchainConfig = &execOffchainCfg + ofc.Execute = &execOffchainCfg } else if pluginType == cctypes.PluginTypeCCIPCommit { commitOffchainCfg, err1 := pluginconfig.DecodeCommitOffchainConfig(publicConfig.ReportingPluginConfig) if err1 != nil { - return offChainConfig{}, fmt.Errorf("failed to decode commit offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) + return ccipcommon.OffChainConfig{}, fmt.Errorf("failed to decode commit offchain config: %w, raw: %s", err1, string(publicConfig.ReportingPluginConfig)) } if err2 := commitOffchainCfg.ApplyDefaultsAndValidate(); err2 != nil { - return offChainConfig{}, fmt.Errorf("failed to validate commit offchain config: %w", err2) - } - ofc.commitOffchainConfig = &commitOffchainCfg - } - if !ofc.isValid() { - return offChainConfig{}, errors.New("invalid offchain config: both commit and exec configs are either set or unset") - } - return ofc, nil -} - -func createChainReader( - ctx context.Context, - lggr logger.Logger, - relayer loop.Relayer, - chainID string, - destChainID string, - homeChainID string, - ofc offChainConfig, - chainSelector cciptypes.ChainSelector, - chainFamily string, -) (types.ContractReader, error) { - // TODO: create a chain writer constructor interface and define family specific implementations in oraclecreator.plugin - switch chainFamily { - case relay.NetworkEVM: - var chainReaderConfig evmrelaytypes.ChainReaderConfig - if chainID == destChainID { - chainReaderConfig = evmconfig.DestReaderConfig - } else { - chainReaderConfig = evmconfig.SourceReaderConfig - } - - if !ofc.commitEmpty() && ofc.commit().PriceFeedChainSelector == chainSelector { - lggr.Debugw("Adding feed reader config", "chainID", chainID) - chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.FeedReaderConfig) - } - - if isUSDCEnabled(ofc) { - lggr.Debugw("Adding USDC reader config", "chainID", chainID) - chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.USDCReaderConfig) - } - - if chainID == homeChainID { - lggr.Debugw("Adding home chain reader config", "chainID", chainID) - chainReaderConfig = evmconfig.MergeReaderConfigs(chainReaderConfig, evmconfig.HomeChainReaderConfigRaw) - } - - marshaledConfig, err := json.Marshal(chainReaderConfig) - if err != nil { - return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) + return ccipcommon.OffChainConfig{}, fmt.Errorf("failed to validate commit offchain config: %w", err2) } - - cr, err := relayer.NewContractReader(ctx, marshaledConfig) - if err != nil { - return nil, fmt.Errorf("failed to create chain reader: %w", err) - } - - return cr, nil - case relay.NetworkSolana: - var err error - var cfg config.ContractReader - if chainID == destChainID { - cfg, err = solanaconfig.DestContractReaderConfig() - if err != nil { - return nil, fmt.Errorf("failed to get Solana dest contract reader config: %w", err) - } - } else { - cfg, err = solanaconfig.SourceContractReaderConfig() - if err != nil { - return nil, fmt.Errorf("failed to get Solana source contract reader config: %w", err) - } - } - - marshaledConfig, err := json.Marshal(cfg) - if err != nil { - return nil, fmt.Errorf("failed to marshal chain reader config: %w", err) - } - - cr, err := relayer.NewContractReader(ctx, marshaledConfig) - if err != nil { - return nil, fmt.Errorf("failed to create chain reader: %w", err) - } - - return cr, nil - - case relay.NetworkAptos: - cfg, err := aptosconfig.GetChainReaderConfig() - if err != nil { - return nil, fmt.Errorf("failed to get Aptos chain reader config: %w", err) - } - marshaledConfig, err := json.Marshal(cfg) - if err != nil { - return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) - } - - cr, err := relayer.NewContractReader(ctx, marshaledConfig) - if err != nil { - return nil, fmt.Errorf("failed to create chain reader: %w", err) - } - - // wrap the chain reader for LOOP specific behavior - cr = aptosloop.NewLoopChainReader(lggr, cr) - - return cr, nil - - default: - return nil, fmt.Errorf("unsupported chain family %s", chainFamily) + ofc.Commit = &commitOffchainCfg } -} -func isUSDCEnabled(ofc offChainConfig) bool { - if ofc.execEmpty() { - return false + if !ofc.IsValid() { + return ccipcommon.OffChainConfig{}, errors.New("invalid offchain config: both commit and exec configs are either set or unset") } - - return ofc.exec().IsUSDCEnabled() + return ofc, nil } -func createChainWriter( - ctx context.Context, - chainID string, - relayer loop.Relayer, - transmitters map[types.RelayID][]string, - execBatchGasLimit uint64, - chainFamily string, - offrampAddress []byte, -) (types.ContractWriter, error) { - var err error - var chainWriterConfig []byte - transmitter, ok := transmitters[types.NewRelayID(chainFamily, chainID)] - // TODO: create a chain writer constructor interface and define family specific implementations in oraclecreator.plugin - switch chainFamily { - case relay.NetworkSolana: - var solConfig chainwriter.ChainWriterConfig - var offrampProgramAddress solana.PublicKey - // NOTE: this function can still be called with EVM inputs, and PublicKeyFromBytes will panic on addresses with len=20 - // technically we only need the writer to do fee estimation so this doesn't matter and we can use a zero address - if len(offrampAddress) == solana.PublicKeyLength { - offrampProgramAddress = solana.PublicKeyFromBytes(offrampAddress) - } - if solConfig, err = solanaconfig.GetSolanaChainWriterConfig(offrampProgramAddress.String(), transmitter[0]); err != nil { - return nil, fmt.Errorf("failed to get Solana chain writer config: %w", err) - } - if chainWriterConfig, err = json.Marshal(solConfig); err != nil { - return nil, fmt.Errorf("failed to marshal Solana chain writer config: %w", err) - } - case relay.NetworkEVM: - var evmConfig evmrelaytypes.ChainWriterConfig - fromAddress := common.Address{} - if ok { - fromAddress = common.HexToAddress(transmitter[0]) - } - if evmConfig, err = evmconfig.ChainWriterConfigRaw( - fromAddress, - defaultCommitGasLimit, - execBatchGasLimit); err != nil { - return nil, fmt.Errorf("failed to create EVM chain writer config: %w", err) - } - if chainWriterConfig, err = json.Marshal(evmConfig); err != nil { - return nil, fmt.Errorf("failed to marshal EVM chain writer config: %w", err) - } - case relay.NetworkAptos: - cfg, err := aptosconfig.GetChainWriterConfig(transmitter[0]) - if err != nil { - return nil, fmt.Errorf("failed to get Aptos chain writer config: %w", err) - } - if chainWriterConfig, err = json.Marshal(cfg); err != nil { - return nil, fmt.Errorf("failed to marshal Aptos chain writer config: %w", err) - } - default: - return nil, fmt.Errorf("unknown chain family %s", chainFamily) - } - - cw, err := relayer.NewContractWriter(ctx, chainWriterConfig) +// initializerPluginConfig initializes the plugin config for the given chain family. +func initializerPluginConfig(destChainFamily string, lggr logger.Logger) (ccipcommon.PluginConfig, error) { + extraDataCodec := defaults.DefaultExtraDataCodec + pluginConfig, err := ccipcommon.NewPluginConfigFactory( + ccipevm.InitializePluginConfig(lggr, extraDataCodec), + ccipsolana.InitializePluginConfig(lggr, extraDataCodec), + ccipaptos.InitializePluginConfig(lggr, extraDataCodec), + ).CreatePluginConfig(destChainFamily) if err != nil { - return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID, err) + return ccipcommon.PluginConfig{}, fmt.Errorf("failed to create plugin config: %w", err) } - return cw, nil -} - -type offChainConfig struct { - commitOffchainConfig *pluginconfig.CommitOffchainConfig - execOffchainConfig *pluginconfig.ExecuteOffchainConfig -} - -func (ofc offChainConfig) commitEmpty() bool { - return ofc.commitOffchainConfig == nil -} - -func (ofc offChainConfig) execEmpty() bool { - return ofc.execOffchainConfig == nil -} - -func (ofc offChainConfig) commit() *pluginconfig.CommitOffchainConfig { - return ofc.commitOffchainConfig -} - -func (ofc offChainConfig) exec() *pluginconfig.ExecuteOffchainConfig { - return ofc.execOffchainConfig -} - -// Exactly one of both plugins should be empty at any given time. -func (ofc offChainConfig) isValid() bool { - return (ofc.commitEmpty() && !ofc.execEmpty()) || (!ofc.commitEmpty() && ofc.execEmpty()) + return pluginConfig, nil } func defaultLocalConfig() ocrtypes.LocalConfig { diff --git a/core/capabilities/ccip/oraclecreator/contract_transmitter_factory.go b/core/capabilities/ccip/types/contract_transmitter_factory.go similarity index 97% rename from core/capabilities/ccip/oraclecreator/contract_transmitter_factory.go rename to core/capabilities/ccip/types/contract_transmitter_factory.go index b67b187a307..a7fa47ccb61 100644 --- a/core/capabilities/ccip/oraclecreator/contract_transmitter_factory.go +++ b/core/capabilities/ccip/types/contract_transmitter_factory.go @@ -1,4 +1,4 @@ -package oraclecreator +package types import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" diff --git a/core/capabilities/remote/executable/client_test.go b/core/capabilities/remote/executable/client_test.go index 079f06de832..4ab7fa4a583 100644 --- a/core/capabilities/remote/executable/client_test.go +++ b/core/capabilities/remote/executable/client_test.go @@ -84,6 +84,7 @@ func Test_Client_DonTopologies(t *testing.T) { } func Test_Client_TransmissionSchedules(t *testing.T) { + tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-104") ctx := testutils.Context(t) responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { diff --git a/core/capabilities/remote/executable/request/transmit_schedule_event.go b/core/capabilities/remote/executable/request/transmit_schedule_event.go index 4017ac0180f..012300479d6 100644 --- a/core/capabilities/remote/executable/request/transmit_schedule_event.go +++ b/core/capabilities/remote/executable/request/transmit_schedule_event.go @@ -4,5 +4,5 @@ package request const ( TransmissionEventSchema = "/workflows/v1/transmit_schedule_event.proto" TransmissionEventProtoPkg = "workflows.v1" - TransmissionEventEntity = "TransmitScheduleEvent" + TransmissionEventEntity = "TransmissionsScheduledEvent" ) diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index aad42cd4518..3e852d1dbbf 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -277,7 +277,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) ctx := testutils.Context(t) - orm := log.NewORM(helper.db, cltest.FixtureChainID) + orm := log.NewORM(helper.db, *testutils.FixtureChainID) listener := helper.newLogListenerWithJob("one") listener.SkipMarkingConsumed(true) @@ -303,7 +303,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) ctx := testutils.Context(t) - orm := log.NewORM(helper.db, cltest.FixtureChainID) + orm := log.NewORM(helper.db, *testutils.FixtureChainID) contract1.On("ParseLog", log1).Return(flux_aggregator_wrapper.FluxAggregatorNewRound{}, nil) contract2.On("ParseLog", log2).Return(flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{}, nil) @@ -330,7 +330,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) ctx := testutils.Context(t) - orm := log.NewORM(helper.db, cltest.FixtureChainID) + orm := log.NewORM(helper.db, *testutils.FixtureChainID) listener := helper.newLogListenerWithJob("one") listener2 := helper.newLogListenerWithJob("two") @@ -355,7 +355,7 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) ctx := testutils.Context(t) - orm := log.NewORM(helper.db, cltest.FixtureChainID) + orm := log.NewORM(helper.db, *testutils.FixtureChainID) listener := helper.newLogListenerWithJob("one") listener2 := helper.newLogListenerWithJob("two") helper.simulateHeads(t, listener, listener2, contract1, contract2, confs, blocks.Slice(8, 9), orm, nil, nil) @@ -1026,7 +1026,7 @@ func TestBroadcaster_Register_ResubscribesToMostRecentlySeenBlock(t *testing.T) mockEth := &clienttest.MockEth{EthClient: ethClient} chchRawLogs := make(chan testutils.RawSub[types.Log], backfillTimes) chStarted := make(chan struct{}) - ethClient.On("ConfiguredChainID", mock.Anything).Return(&cltest.FixtureChainID) + ethClient.On("ConfiguredChainID", mock.Anything).Return(testutils.FixtureChainID) ethClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything). Return( func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription { @@ -1144,7 +1144,8 @@ func TestBroadcaster_Register_ResubscribesToMostRecentlySeenBlock(t *testing.T) t.Fatal("did not subscribe") } - cltest.EventuallyExpectationsMet(t, ethClient, testutils.WaitTimeout(t), time.Second) + assert.Eventually(t, func() bool { return ethClient.AssertExpectations(t) }, + testutils.WaitTimeout(t), time.Second) } func TestBroadcaster_ReceivesAllLogsWhenResubscribing(t *testing.T) { @@ -1678,7 +1679,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := testutils.NewSqlxDB(t) - orm := log.NewORM(db, cltest.FixtureChainID) + orm := log.NewORM(db, *testutils.FixtureChainID) lb := log.NewTestBroadcaster(orm, ethClient, config, lggr, highestSeenHead, mailMon) kst := cltest.NewKeyStore(t, db) @@ -1942,11 +1943,11 @@ func (listener *simpleLogListener) handleLogBroadcast(ctx context.Context, lb lo } func (listener *simpleLogListener) WasAlreadyConsumed(ctx context.Context, broadcast log.Broadcast) (bool, error) { - return log.NewORM(listener.db, cltest.FixtureChainID).WasBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().Index, listener.jobID) + return log.NewORM(listener.db, *testutils.FixtureChainID).WasBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().Index, listener.jobID) } func (listener *simpleLogListener) MarkConsumed(ctx context.Context, broadcast log.Broadcast) error { - return log.NewORM(listener.db, cltest.FixtureChainID).MarkBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().BlockNumber, broadcast.RawLog().Index, listener.jobID) + return log.NewORM(listener.db, *testutils.FixtureChainID).MarkBroadcastConsumed(ctx, broadcast.RawLog().BlockHash, broadcast.RawLog().BlockNumber, broadcast.RawLog().Index, listener.jobID) } type mockEthClientExpectedCalls struct { @@ -1960,7 +1961,7 @@ type mockEthClientExpectedCalls struct { func newMockEthClient(t *testing.T, chchRawLogs chan<- testutils.RawSub[types.Log], blockHeight int64, expectedCalls mockEthClientExpectedCalls) *clienttest.MockEth { ethClient := clienttest.NewClient(t) mockEth := &clienttest.MockEth{EthClient: ethClient} - mockEth.EthClient.On("ConfiguredChainID", mock.Anything).Return(&cltest.FixtureChainID) + mockEth.EthClient.On("ConfiguredChainID", mock.Anything).Return(testutils.FixtureChainID) mockEth.EthClient.On("SubscribeFilterLogs", mock.Anything, mock.Anything, mock.Anything). Return( func(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) ethereum.Subscription { diff --git a/core/chains/evm/txmgr/broadcaster_benchmark_test.go b/core/chains/evm/txmgr/broadcaster_benchmark_test.go index c64a2f346aa..7a4fb786a28 100644 --- a/core/chains/evm/txmgr/broadcaster_benchmark_test.go +++ b/core/chains/evm/txmgr/broadcaster_benchmark_test.go @@ -9,8 +9,11 @@ import ( gethCommon "github.com/ethereum/go-ethereum/common" "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/chainlink-evm/pkg/keys" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -25,7 +28,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) // happy path @@ -34,7 +36,7 @@ func BenchmarkEthBroadcaster_ProcessUnstartedEthTxs_Success(b *testing.B) { ctx := tests.Context(b) ethClient := clienttest.NewClientWithDefaultChainID(b) - txStore := cltest.NewTestTxStore(b, db) + txStore := txmgrtest.NewTestTxStore(b, db) memKeystore := keystest.NewMemoryChainStore() ethKeyStore := keys.NewChainStore(memKeystore, ethClient.ConfiguredChainID()) fromAddress := memKeystore.MustCreate(b) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 6a703b90610..e91c375b751 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -29,6 +29,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-framework/chains/fees" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" @@ -49,7 +50,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) var dbListenerCfg txmgr.ListenerConfig = testListenerConfig{} @@ -100,7 +100,7 @@ func NewTestEthBroadcaster( func TestEthBroadcaster_Lifecycle(t *testing.T) { db := testutils.NewIndependentSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) ethClient := clienttest.NewClientWithDefaultChainID(t) memKS := keystest.NewMemoryChainStore() @@ -163,7 +163,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { // Failure to load next sequnce map should not fail Broadcaster startup func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) ethClient := clienttest.NewClientWithDefaultChainID(t) memKS := keystest.NewMemoryChainStore() @@ -201,7 +201,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { db := testutils.NewSqlxDB(t) ctx := t.Context() - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -574,7 +574,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { func TestEthBroadcaster_TransmitChecking(t *testing.T) { db := testutils.NewSqlxDB(t) ctx := t.Context() - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -657,7 +657,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testing.T) { // non-transactional DB needed because we deliberately test for FK violation db := testutils.NewIndependentSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ccfg := configtest.NewChainScopedConfig(t, nil) evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM()) ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -722,7 +722,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -774,7 +774,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("cannot be more than one transaction per address in an unfinished state", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() firstInProgress := txmgr.Tx{ @@ -807,7 +807,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce but never broadcast", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -847,7 +847,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast but it fatally errored before we could save", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -885,7 +885,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast and is now in mempool", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -922,7 +922,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast and now the transaction has been confirmed", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -960,7 +960,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and then failed to reach node for some reason and node is still down", func(t *testing.T) { failedToReachNodeError := context.DeadlineExceeded db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -997,7 +997,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { t.Run("previous run assigned nonce and broadcast transaction then crashed and rebooted with a different configured gas price", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1065,7 +1065,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { encodedPayload := []byte{0, 1} db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1151,8 +1151,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { }) t.Run("with callback", func(t *testing.T) { - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) etx := txmgr.Tx{ FromAddress: fromAddress, ToAddress: toAddress, @@ -1692,7 +1692,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) encodedPayload := []byte{0, 1} db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1763,7 +1763,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { localNonce := 0 db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := keystest.NewMemoryChainStore().MustCreate(t) kst := &keystest.FakeChainStore{ @@ -1814,7 +1814,7 @@ func TestEthBroadcaster_Trigger(t *testing.T) { // Simple sanity check to make sure it doesn't block db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) evmcfg := configtest.NewChainScopedConfig(t, nil) ethKeyStore := &keystest.FakeChainStore{} ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -1836,7 +1836,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { c.NonceAutoSync = ptr(true) }) evmTxmCfg := txmgr.NewEvmTxmConfig(evmcfg.EVM()) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1871,7 +1871,7 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) @@ -1910,7 +1910,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) evmcfg := configtest.NewChainScopedConfig(t, nil) diff --git a/core/chains/evm/txmgr/confirmer_benchmark_test.go b/core/chains/evm/txmgr/confirmer_benchmark_test.go index 64af7abe020..e8ec0511990 100644 --- a/core/chains/evm/txmgr/confirmer_benchmark_test.go +++ b/core/chains/evm/txmgr/confirmer_benchmark_test.go @@ -13,15 +13,15 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func BenchmarkEthConfirmer(b *testing.B) { db := testutils.NewSqlxDB(b) - txStore := cltest.NewTestTxStore(b, db) + txStore := txmgrtest.NewTestTxStore(b, db) ethClient := clienttest.NewClientWithDefaultChainID(b) evmcfg := configtest.NewChainScopedConfig(b, func(c *toml.EVMConfig) { c.GasEstimator.PriceMax = assets.GWei(500) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 23c30ad70f1..8697ff202dc 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -26,6 +26,7 @@ import ( txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" "github.com/smartcontractkit/chainlink-framework/multinode" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink-evm/pkg/client" @@ -40,11 +41,10 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func newBroadcastLegacyEthTxAttempt(t testing.TB, etxID int64, gasPrice ...int64) txmgr.TxAttempt { - attempt := cltest.NewLegacyEthTxAttempt(t, etxID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etxID) attempt.State = txmgrtypes.TxAttemptBroadcast if len(gasPrice) > 0 { gp := gasPrice[0] @@ -64,7 +64,7 @@ func newTxReceipt(hash gethCommon.Hash, blockNumber int, txIndex uint) evmtypes. } func newInProgressLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int64) txmgr.TxAttempt { - attempt := cltest.NewLegacyEthTxAttempt(t, etxID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etxID) attempt.State = txmgrtypes.TxAttemptInProgress if len(gasPrice) > 0 { gp := gasPrice[0] @@ -74,7 +74,7 @@ func newInProgressLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int6 } func mustInsertInProgressEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress gethCommon.Address) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.State = txmgrcommon.TxInProgress n := evmtypes.Nonce(nonce) etx.Sequence = &n @@ -84,7 +84,7 @@ func mustInsertInProgressEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, nonce } func mustInsertConfirmedEthTx(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress gethCommon.Address) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.State = txmgrcommon.TxConfirmed n := evmtypes.Nonce(nonce) etx.Sequence = &n @@ -182,7 +182,7 @@ func TestEthConfirmer_CheckForConfirmation(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) evmcfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.PriceMax = assets.GWei(500) @@ -416,7 +416,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := t.Context() ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -444,7 +444,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { ec := newEthConfirmer(t, txStore, ethClient, evmcfg, ethKeyStore, nil) t.Run("returns nothing when there are no transactions", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Empty(t, etxs) @@ -454,24 +454,24 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { nonce++ t.Run("returns nothing when the transaction is in_progress", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Empty(t, etxs) }) // This one has BroadcastBeforeBlockNum set as nil... which can happen, but it should be ignored - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ t.Run("ignores unconfirmed transactions with nil BroadcastBeforeBlockNum", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Empty(t, etxs) }) - etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx1 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ attempt1_1 := etx1.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt @@ -483,13 +483,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) t.Run("returns nothing when the transaction is unconfirmed with an attempt that is recent", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) assert.Empty(t, etxs) }) - etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx2 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ attempt2_1 := etx2.TxAttempts[0] dbAttempt = txmgr.DbEthTxAttempt{} @@ -497,13 +497,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, tooNew, attempt2_1.ID)) t.Run("returns nothing when the transaction has attempts that are too new", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) assert.Empty(t, etxs) }) - etxWithoutAttempts := cltest.NewEthTx(fromAddress) + etxWithoutAttempts := txmgrtest.NewEthTx(fromAddress) { n := evmtypes.Nonce(nonce) etxWithoutAttempts.Sequence = &n @@ -516,14 +516,14 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { nonce++ t.Run("does nothing if the transaction is from a different address than the one given", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmOtherAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmOtherAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) assert.Empty(t, etxs) }) t.Run("returns the transaction if it is unconfirmed and has no attempts (note that this is an invariant violation, but we handle it anyway)", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 1) @@ -537,7 +537,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.Empty(t, etxs) }) - etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx3 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ attempt3_1 := etx3.TxAttempts[0] dbAttempt = txmgr.DbEthTxAttempt{} @@ -545,14 +545,14 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_1.ID)) // NOTE: It should ignore qualifying eth_txes from a different address - etxOther := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, evmOtherAddress) + etxOther := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, evmOtherAddress) attemptOther1 := etxOther.TxAttempts[0] dbAttempt = txmgr.DbEthTxAttempt{} dbAttempt.FromTxAttempt(&attemptOther1) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attemptOther1.ID)) t.Run("returns the transaction if it is unconfirmed with an attempt that is older than gasBumpThreshold blocks", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -561,7 +561,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { }) t.Run("returns nothing if threshold is zero", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, 0, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, 0, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Empty(t, etxs) @@ -575,13 +575,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { // etxWithoutAttempts (nonce 5) // etx3 (nonce 6) - ready for bump // etx4 (nonce 7) - ready for bump - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 4, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 4, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 1) // returns etxWithoutAttempts only - eligible for gas bumping because it technically doesn't have any attempts within gasBumpThreshold blocks assert.Equal(t, etxWithoutAttempts.ID, etxs[0].ID) - etxs, err = ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 5, 0, &cltest.FixtureChainID) + etxs, err = ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 5, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) // includes etxWithoutAttempts, etx3 and etx4 @@ -589,13 +589,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { assert.Equal(t, etx3.ID, etxs[1].ID) // Zero limit disables it - etxs, err = ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 0, 0, &cltest.FixtureChainID) + etxs, err = ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 0, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) // includes etxWithoutAttempts, etx3 and etx4 }) - etx4 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx4 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ attempt4_1 := etx4.TxAttempts[0] dbAttempt = txmgr.DbEthTxAttempt{} @@ -604,13 +604,13 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { t.Run("ignores pending transactions for another key", func(t *testing.T) { // Re-use etx3 nonce for another key, it should not affect the results for this key - etxOther := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, (*etx3.Sequence).Int64(), evmOtherAddress) + etxOther := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, (*etx3.Sequence).Int64(), evmOtherAddress) aOther := etxOther.TxAttempts[0] dbAttempt = txmgr.DbEthTxAttempt{} dbAttempt.FromTxAttempt(&aOther) require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, aOther.ID)) - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 6, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 6, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 3) // includes etxWithoutAttempts, etx3 and etx4 @@ -625,7 +625,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) t.Run("returns the transaction if it is unconfirmed with two attempts that are older than gasBumpThreshold blocks", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 3) @@ -640,7 +640,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_3)) t.Run("does not return the transaction if it has some older but one newer attempt", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -659,7 +659,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { // This attempt has insufficient_eth, but there is also another attempt4_1 // which is old enough, so this will be caught by both queries and should // not be duplicated - attempt4_2 := cltest.NewLegacyEthTxAttempt(t, etx4.ID) + attempt4_2 := txmgrtest.NewLegacyEthTxAttempt(t, etx4.ID) attempt4_2.State = txmgrtypes.TxAttemptInsufficientFunds attempt4_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(40000)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) @@ -677,7 +677,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt6_2)) t.Run("returns unique attempts requiring resubmission due to insufficient eth, ordered by nonce asc", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 4) @@ -692,7 +692,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { }) t.Run("applies limit", func(t *testing.T) { - etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 2, &cltest.FixtureChainID) + etxs, err := ec.FindTxsRequiringRebroadcast(t.Context(), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 2, testutils.FixtureChainID) require.NoError(t, err) require.Len(t, etxs, 2) @@ -718,7 +718,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing }) ctx := t.Context() - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() estimator := gasmocks.NewEvmEstimator(t) @@ -739,7 +739,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing nonce := int64(0) originalBroadcastAt := time.Unix(1616509100, 0) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) attempt1 := etx.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt dbAttempt.FromTxAttempt(&attempt1) @@ -764,7 +764,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing }) ctx := t.Context() - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() estimator := gasmocks.NewEvmEstimator(t) @@ -807,7 +807,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := t.Context() ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -826,7 +826,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { nonce := int64(0) originalBroadcastAt := time.Unix(1616509100, 0) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) attempt1_1 := etx.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1_1.ID)) @@ -865,7 +865,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("does nothing if no transactions require bumping", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -876,7 +876,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("re-sends previous transaction on keystore error", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := keystest.NewMemoryChainStore().MustCreate(t) kst := &keystest.FakeChainStore{ Addresses: keystest.Addresses{fromAddress}, @@ -906,7 +906,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("does nothing and continues on fatal error", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -926,7 +926,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("creates new attempt with higher gas price if transaction has an attempt older than threshold", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -954,7 +954,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("does nothing if there is an attempt without BroadcastBeforeBlockNum set", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -971,7 +971,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("creates new attempt with higher gas price if transaction is already in mempool (e.g. due to previous crash before we could save the new attempt)", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -999,7 +999,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("saves new attempt even for transaction that has already been confirmed (nonce already used)", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -1030,7 +1030,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("saves in-progress attempt on temporary error and returns error", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -1082,7 +1082,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, ethClient.ConfiguredChainID()) @@ -1114,7 +1114,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("resubmits at the old price and does not create a new attempt if one of the bumped transactions would exceed EVM.GasEstimator.PriceMax", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) priceMax := assets.GWei(30) newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.PriceMax = priceMax @@ -1146,7 +1146,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("resubmits at the old price and does not create a new attempt if the current price is exactly EVM.GasEstimator.PriceMax", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) priceMax := assets.GWei(30) newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.PriceMax = priceMax @@ -1177,7 +1177,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("EIP-1559: bumps using EIP-1559 rules when existing attempts are of type 0x2", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.BumpMin = assets.GWei(1) }) @@ -1209,7 +1209,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("EIP-1559: resubmits at the old price and does not create a new attempt if one of the bumped EIP-1559 transactions would have its tip cap exceed EVM.GasEstimator.PriceMax", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.PriceMax = assets.NewWeiI(1) }) @@ -1239,7 +1239,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Run("EIP-1559: re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) newCfg := configtest.NewChainScopedConfig(t, func(c *toml.EVMConfig) { c.GasEstimator.BumpMin = assets.GWei(1) }) @@ -1277,7 +1277,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1314,7 +1314,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh ethClient := clienttest.NewClientWithDefaultChainID(t) ec := newEthConfirmer(t, txStore, ethClient, evmcfg, kst, nil) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ legacyAttempt := etx.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt @@ -1356,7 +1356,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := t.Context() ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -1369,7 +1369,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { oldEnough := int64(19) nonce := int64(0) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) nonce++ attempt1_1 := etx.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt @@ -1490,7 +1490,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing. t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := t.Context() ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -1511,7 +1511,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing. t.Run("terminally stuck transaction replaced with purge attempt", func(t *testing.T) { originalBroadcastAt := time.Unix(1616509100, 0) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) nonce++ attempt1_1 := etx.TxAttempts[0] var dbAttempt txmgr.DbEthTxAttempt @@ -1542,7 +1542,7 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -1551,8 +1551,8 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, config.EVM().ChainID()) mustInsertInProgressEthTx(t, txStore, 0, fromAddress) - etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) - etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + etx1 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) + etx2 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) gasPriceWei := gas.EvmFee{GasPrice: assets.GWei(52)} overrideGasLimit := uint64(20000) @@ -1643,7 +1643,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() ethKeyStore := &keystest.FakeChainStore{Addresses: keystest.Addresses{fromAddress}} ethClient := clienttest.NewClientWithDefaultChainID(t) diff --git a/core/chains/evm/txmgr/evm_tx_store_benchmark_test.go b/core/chains/evm/txmgr/evm_tx_store_benchmark_test.go index 4e8d3077bc9..85d3dbd89c5 100644 --- a/core/chains/evm/txmgr/evm_tx_store_benchmark_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_benchmark_test.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func NewTestTxStore(t testing.TB, db *sqlx.DB) txmgr.TestEvmTxStore { @@ -165,7 +164,7 @@ func BenchmarkFindConfirmedTxesReceipts(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { b.StartTimer() - receipts, err := txStore.FindConfirmedTxesReceipts(tests.Context(b), finalizedBlockNum, &cltest.FixtureChainID) + receipts, err := txStore.FindConfirmedTxesReceipts(tests.Context(b), finalizedBlockNum, testutils.FixtureChainID) b.StopTimer() require.NoError(b, err) require.Len(b, receipts, bs.size) diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 36b60bf04a8..da5fc47a8f2 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" @@ -31,22 +32,21 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func TestORM_TransactionsWithAttempts(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) // tx1 - tx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, fromAddress) // tx2 + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) // tx1 + tx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, fromAddress) // tx2 // add 2nd attempt to tx2 blockNum := int64(3) - attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum @@ -80,17 +80,17 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { func TestORM_Transactions(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) // tx1 - tx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, fromAddress) // tx2 + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) // tx1 + tx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, fromAddress) // tx2 // add 2nd attempt to tx2 blockNum := int64(3) - attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum @@ -118,31 +118,31 @@ func TestORM(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - orm := cltest.NewTestTxStore(t, db) + orm := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() ctx := tests.Context(t) var etx txmgr.Tx t.Run("InsertTx", func(t *testing.T) { - etx = cltest.NewEthTx(fromAddress) + etx = txmgrtest.NewEthTx(fromAddress) require.NoError(t, orm.InsertTx(ctx, &etx)) assert.Greater(t, int(etx.ID), 0) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) }) var attemptL txmgr.TxAttempt var attemptD txmgr.TxAttempt t.Run("InsertTxAttempt", func(t *testing.T) { - attemptD = cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) + attemptD = txmgrtest.NewDynamicFeeEthTxAttempt(t, etx.ID) require.NoError(t, orm.InsertTxAttempt(ctx, &attemptD)) assert.Greater(t, int(attemptD.ID), 0) - cltest.AssertCount(t, db, "evm.tx_attempts", 1) + txmgrtest.AssertCount(t, db, "evm.tx_attempts", 1) - attemptL = cltest.NewLegacyEthTxAttempt(t, etx.ID) + attemptL = txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attemptL.State = txmgrtypes.TxAttemptBroadcast attemptL.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(42)} require.NoError(t, orm.InsertTxAttempt(ctx, &attemptL)) assert.Greater(t, int(attemptL.ID), 0) - cltest.AssertCount(t, db, "evm.tx_attempts", 2) + txmgrtest.AssertCount(t, db, "evm.tx_attempts", 2) }) var r txmgr.Receipt t.Run("InsertReceipt", func(t *testing.T) { @@ -151,7 +151,7 @@ func TestORM(t *testing.T) { r.ID = id require.NoError(t, err) assert.Greater(t, int(r.ID), 0) - cltest.AssertCount(t, db, "evm.receipts", 1) + txmgrtest.AssertCount(t, db, "evm.receipts", 1) }) t.Run("FindTxWithAttempts", func(t *testing.T) { var err error @@ -184,17 +184,17 @@ func TestORM(t *testing.T) { func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { db := testutils.NewSqlxDB(t) - orm := cltest.NewTestTxStore(t, db) + orm := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() - tx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, orm, 0, 1, fromAddress) // tx1 - tx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, orm, 1, 2, fromAddress) // tx2 + tx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, orm, 0, 1, fromAddress) // tx1 + tx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, orm, 1, 2, fromAddress) // tx2 // add 2nd attempt to tx2 blockNum := int64(3) - attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum @@ -207,8 +207,8 @@ func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { // tx 3 has no attempts mustCreateUnstartedGeneratedTx(t, orm, fromAddress, testutils.FixtureChainID) - cltest.MustInsertUnconfirmedEthTx(t, orm, 3, fromAddress) // tx4 - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, orm, 4, fromAddress) // tx5 + txmgrtest.MustInsertUnconfirmedEthTx(t, orm, 3, fromAddress) // tx4 + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, orm, 4, fromAddress) // tx5 var count int err = db.Get(&count, `SELECT count(*) FROM evm.txes`) @@ -233,7 +233,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() @@ -246,10 +246,10 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { }) // Mix up the insert order to assure that they come out sorted by nonce not implicitly or by ID - e1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, time.Unix(1616509200, 0)) + e1 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, time.Unix(1616509200, 0)) e3 := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 3, fromAddress, time.Unix(1616509400, 0)) - e0 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, time.Unix(1616509100, 0)) - e2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress, time.Unix(1616509300, 0)) + e0 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, time.Unix(1616509100, 0)) + e2 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress, time.Unix(1616509300, 0)) etxs := []txmgr.Tx{ e0, @@ -265,17 +265,17 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { attempt3_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) - attempt4_2 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) + attempt4_2 := txmgrtest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) attempt4_2.TxFee.GasTipCap = assets.NewWeiI(10) attempt4_2.TxFee.GasFeeCap = assets.NewWeiI(20) attempt4_2.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) - attempt4_4 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) + attempt4_4 := txmgrtest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) attempt4_4.TxFee.GasTipCap = assets.NewWeiI(30) attempt4_4.TxFee.GasFeeCap = assets.NewWeiI(40) attempt4_4.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_4)) - attempt4_3 := cltest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) + attempt4_3 := txmgrtest.NewDynamicFeeEthTxAttempt(t, etxs[3].ID) attempt4_3.TxFee.GasTipCap = assets.NewWeiI(20) attempt4_3.TxFee.GasFeeCap = assets.NewWeiI(30) attempt4_3.State = txmgrtypes.TxAttemptBroadcast @@ -318,7 +318,7 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - orm := cltest.NewTestTxStore(t, db) + orm := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("does not update when broadcast_at is NULL", func(t *testing.T) { @@ -343,7 +343,7 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { ctx := tests.Context(t) time1 := time.Now() - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.Sequence = new(types.Nonce) etx.State = txmgrcommon.TxUnconfirmed etx.BroadcastAt = &time1 @@ -366,10 +366,10 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { db := testutils.NewSqlxDB(t) cfg := configtest.NewChainScopedConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) chainID := ethClient.ConfiguredChainID() ctx := tests.Context(t) @@ -406,8 +406,8 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { }) t.Run("only updates evm.tx_attempts for the current chain", func(t *testing.T) { - etxThisChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, cfg.EVM().ChainID()) - etxOtherChain := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, testutils.SimulatedChainID) + etxThisChain := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, cfg.EVM().ChainID()) + etxOtherChain := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, testutils.SimulatedChainID) require.NoError(t, txStore.SetBroadcastBeforeBlockNum(tests.Context(t), headNum, chainID)) @@ -432,7 +432,7 @@ func TestORM_UpdateTxConfirmed(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() etx0 := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 0, fromAddress, txmgrtypes.TxAttemptBroadcast) @@ -458,11 +458,11 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() ctx := tests.Context(t) - tx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 100, fromAddress) + tx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 100, fromAddress) require.Len(t, tx1.TxAttempts, 1) tx2 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, 100) @@ -504,12 +504,12 @@ func TestORM_PreloadTxes(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("loads eth transaction", func(t *testing.T) { // insert etx with attempt - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(7), fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(7), fromAddress) // create unloaded attempt unloadedAttempt := txmgr.TxAttempt{TxID: etx.ID} @@ -536,7 +536,7 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -555,7 +555,7 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -579,43 +579,43 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { minConfirmations := int64(2) // Suspended run waiting for callback - runID1 := cltest.MustInsertPipelineRun(t, db) - trID1 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID1) + runID1 := testutils.MustInsertPipelineRun(t, db) + trID1 := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID1) testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, runID1) - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) + etx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) attempt1 := etx1.TxAttempts[0] etxBlockNum := mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt1.Hash).BlockNumber testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &trID1, minConfirmations, etx1.ID) // Callback to pipeline service completed. Should be ignored - runID2 := cltest.MustInsertPipelineRun(t, db) - trID2 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID2) + runID2 := testutils.MustInsertPipelineRun(t, db) + trID2 := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID2) testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'completed', outputs = '""'::jsonb, finished_at = NOW() WHERE id = $1`, runID2) - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress) + etx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`) attempt2 := etx2.TxAttempts[0] mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, attempt2.Hash) testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &trID2, minConfirmations, etx2.ID) // Suspended run younger than minConfirmations. Should be ignored - runID3 := cltest.MustInsertPipelineRun(t, db) - trID3 := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID3) + runID3 := testutils.MustInsertPipelineRun(t, db) + trID3 := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID3) testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, runID3) - etx3 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 5, 1, fromAddress) + etx3 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 5, 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": false}'`) attempt3 := etx3.TxAttempts[0] mustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt3.Hash) testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &trID3, minConfirmations, etx3.ID) // Tx not marked for callback. Should be ignore - etx4 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress) + etx4 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress) attempt4 := etx4.TxAttempts[0] mustInsertEthReceipt(t, txStore, head.Number, head.Hash, attempt4.Hash) testutils.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx4.ID) // Unconfirmed Tx without receipts. Should be ignored - etx5 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress) + etx5 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET min_confirmations = $1 WHERE id = $2`, minConfirmations, etx5.ID) // Search evm.txes table for tx requiring callback @@ -645,7 +645,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) cfg := configtest.NewChainScopedConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("returns nil error if no results", func(t *testing.T) { @@ -673,7 +673,7 @@ func Test_FindReceiptWithIdempotencyKey(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() ctx := t.Context() @@ -687,26 +687,26 @@ func Test_FindReceiptWithIdempotencyKey(t *testing.T) { t.Run("returns receipt if it exists", func(t *testing.T) { var etx txmgr.Tx // insert tx - etx = cltest.NewEthTx(fromAddress) + etx = txmgrtest.NewEthTx(fromAddress) etx.IdempotencyKey = &idempotencyKey require.NoError(t, txStore.InsertTx(ctx, &etx)) assert.Greater(t, int(etx.ID), 0) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) // insert attempt var attemptL txmgr.TxAttempt var attemptD txmgr.TxAttempt - attemptD = cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) + attemptD = txmgrtest.NewDynamicFeeEthTxAttempt(t, etx.ID) require.NoError(t, txStore.InsertTxAttempt(ctx, &attemptD)) assert.Greater(t, int(attemptD.ID), 0) - cltest.AssertCount(t, db, "evm.tx_attempts", 1) + txmgrtest.AssertCount(t, db, "evm.tx_attempts", 1) - attemptL = cltest.NewLegacyEthTxAttempt(t, etx.ID) + attemptL = txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attemptL.State = txmgrtypes.TxAttemptBroadcast attemptL.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(42)} require.NoError(t, txStore.InsertTxAttempt(ctx, &attemptL)) assert.Greater(t, int(attemptL.ID), 0) - cltest.AssertCount(t, db, "evm.tx_attempts", 2) + txmgrtest.AssertCount(t, db, "evm.tx_attempts", 2) // insert receipt var r txmgr.Receipt @@ -715,7 +715,7 @@ func Test_FindReceiptWithIdempotencyKey(t *testing.T) { r.ID = id require.NoError(t, err) assert.Greater(t, int(r.ID), 0) - cltest.AssertCount(t, db, "evm.receipts", 1) + txmgrtest.AssertCount(t, db, "evm.receipts", 1) res, err := txStore.FindReceiptWithIdempotencyKey(ctx, idempotencyKey, etx.ChainID) require.NoError(t, err) @@ -729,7 +729,7 @@ func TestORM_FindTxWithSequence(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("returns nil if no results", func(t *testing.T) { @@ -739,7 +739,7 @@ func TestORM_FindTxWithSequence(t *testing.T) { }) t.Run("returns transaction if it exists", func(t *testing.T) { - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 777, 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 777, 1, fromAddress) require.Equal(t, types.Nonce(777), *etx.Sequence) res, err := txStore.FindTxWithSequence(tests.Context(t), fromAddress, types.Nonce(777)) @@ -752,7 +752,7 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() ctx := tests.Context(t) @@ -823,7 +823,7 @@ func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -834,7 +834,7 @@ func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { }) t.Run("verify broadcast time", func(t *testing.T) { - tx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 123, fromAddress) + tx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, 123, fromAddress) broadcastAt, err := txStore.FindEarliestUnconfirmedBroadcastTime(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) require.True(t, broadcastAt.Ptr().Equal(*tx.BroadcastAt)) @@ -845,7 +845,7 @@ func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() fromAddress2 := testutils.NewAddress() @@ -875,7 +875,7 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -898,7 +898,7 @@ func TestORM_SaveSentAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -922,7 +922,7 @@ func TestORM_SaveConfirmedAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -946,7 +946,7 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("deletes in_progress attempt", func(t *testing.T) { @@ -967,13 +967,13 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("saves new in_progress attempt if attempt is new", func(t *testing.T) { - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) require.Equal(t, int64(0), attempt.ID) err := txStore.SaveInProgressAttempt(tests.Context(t), &attempt) @@ -1006,7 +1006,7 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -1044,7 +1044,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() @@ -1052,16 +1052,16 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin // Insert order is mixed up to test sorting etx2 := mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 1, fromAddress) - etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - attempt3_2 := cltest.NewLegacyEthTxAttempt(t, etx3.ID) + etx3 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + attempt3_2 := txmgrtest.NewLegacyEthTxAttempt(t, etx3.ID) attempt3_2.State = txmgrtypes.TxAttemptInsufficientFunds attempt3_2.TxFee.GasPrice = assets.NewWeiI(100) require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_2)) etx1 := mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, fromAddress) // These should never be returned - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 3, fromAddress) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 100, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 3, fromAddress) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 100, fromAddress) mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 0, otherAddress) t.Run("returns all eth_txes with at least one attempt that is in insufficient_eth state", func(t *testing.T) { @@ -1104,7 +1104,7 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("load eth tx attempt", func(t *testing.T) { @@ -1118,7 +1118,7 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) { t.Run("load new attempt inserted in current postgres transaction", func(t *testing.T) { etx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 3, 9, time.Now(), fromAddress) - newAttempt := cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) + newAttempt := txmgrtest.NewDynamicFeeEthTxAttempt(t, etx.ID) var dbAttempt txmgr.DbEthTxAttempt dbAttempt.FromTxAttempt(&newAttempt) @@ -1156,14 +1156,14 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("replace eth tx attempt", func(t *testing.T) { etx := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) oldAttempt := etx.TxAttempts[0] - newAttempt := cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) + newAttempt := txmgrtest.NewDynamicFeeEthTxAttempt(t, etx.ID) err := txStore.SaveReplacementInProgressAttempt(tests.Context(t), oldAttempt, &newAttempt) require.NoError(t, err) @@ -1178,7 +1178,7 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -1203,7 +1203,7 @@ func TestORM_UpdateTxFatalErrorAndDeleteAttempts(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("update successful", func(t *testing.T) { @@ -1225,7 +1225,7 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("update successful", func(t *testing.T) { @@ -1255,14 +1255,14 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() nonce := types.Nonce(123) t.Run("update successful", func(t *testing.T) { etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx.Sequence = &nonce - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) err := txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx, &attempt) require.NoError(t, err) @@ -1277,7 +1277,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { etx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx.Sequence = &nonce - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) _, err := db.ExecContext(ctx, "DELETE FROM evm.txes WHERE id = $1", etx.ID) require.NoError(t, err) @@ -1287,7 +1287,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { }) db = testutils.NewSqlxDB(t) - txStore = cltest.NewTestTxStore(t, db) + txStore = txmgrtest.NewTestTxStore(t, db) fromAddress = testutils.NewAddress() t.Run("update replaces abandoned tx with same hash", func(t *testing.T) { @@ -1309,7 +1309,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { etx2 := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) etx2.Sequence = &nonce - attempt2 := cltest.NewLegacyEthTxAttempt(t, etx2.ID) + attempt2 := txmgrtest.NewLegacyEthTxAttempt(t, etx2.ID) attempt2.Hash = etx.TxAttempts[0].Hash // Even though this will initially fail due to idx_eth_tx_attempts_hash constraint, because the conflicting tx has been abandoned @@ -1330,7 +1330,7 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { // Should fail due to idx_eth_tx_attempt_hash constraint err := txStore.UpdateTxUnstartedToInProgress(tests.Context(t), &etx, &etx.TxAttempts[0]) assert.ErrorContains(t, err, "idx_eth_tx_attempts_hash") - txStore = cltest.NewTestTxStore(t, db) // current txStore is poisened now, next test will need fresh one + txStore = txmgrtest.NewTestTxStore(t, db) // current txStore is poisened now, next test will need fresh one }) } @@ -1338,7 +1338,7 @@ func TestORM_GetTxInProgress(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("gets 0 in progress eth transaction", func(t *testing.T) { @@ -1360,7 +1360,7 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() enabled := testutils.NewAddress() @@ -1416,7 +1416,7 @@ func TestORM_GetTxByID(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("no transaction", func(t *testing.T) { @@ -1437,7 +1437,7 @@ func TestORM_GetFatalTransactions(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("gets 0 fatal eth transactions", func(t *testing.T) { @@ -1458,7 +1458,7 @@ func TestORM_HasInProgressTransaction(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) fromAddress := testutils.NewAddress() @@ -1481,15 +1481,15 @@ func TestORM_CountUnconfirmedTransactions(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() otherAddress := testutils.NewAddress() - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, otherAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, otherAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) count, err := txStore.CountUnconfirmedTransactions(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) @@ -1500,15 +1500,15 @@ func TestORM_CountTransactionsByState(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress1 := testutils.NewAddress() fromAddress2 := testutils.NewAddress() fromAddress3 := testutils.NewAddress() - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress1) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress2) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress3) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress1) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress2) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress3) count, err := txStore.CountTransactionsByState(tests.Context(t), txmgrcommon.TxUnconfirmed, testutils.FixtureChainID) require.NoError(t, err) @@ -1519,7 +1519,7 @@ func TestORM_CountUnstartedTransactions(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() otherAddress := testutils.NewAddress() @@ -1527,7 +1527,7 @@ func TestORM_CountUnstartedTransactions(t *testing.T) { mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) mustCreateUnstartedGeneratedTx(t, txStore, otherAddress, testutils.FixtureChainID) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) count, err := txStore.CountUnstartedTransactions(tests.Context(t), fromAddress, testutils.FixtureChainID) require.NoError(t, err) @@ -1538,7 +1538,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() otherAddress := testutils.NewAddress() @@ -1575,7 +1575,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { var n int64 mustInsertInProgressEthTxWithAttempt(t, txStore, types.Nonce(n), fromAddress) n++ - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, n, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, n, fromAddress) n++ t.Run("unconfirmed and in_progress transactions do not count", func(t *testing.T) { @@ -1585,7 +1585,7 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { // deliberately one extra to exceed limit for i := 0; i <= int(maxUnconfirmedTransactions); i++ { - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, n, 42, fromAddress) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, n, 42, fromAddress) n++ } @@ -1662,7 +1662,7 @@ func TestORM_CreateTransaction(t *testing.T) { assert.Equal(t, big.Int(assets.NewEthValue(0)), etx.Value) assert.Equal(t, subject, etx.Subject.UUID) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) var dbEthTx txmgr.DbEthTx require.NoError(t, db.Get(&dbEthTx, `SELECT * FROM evm.txes ORDER BY id ASC LIMIT 1`)) @@ -1714,7 +1714,7 @@ func TestORM_CreateTransaction(t *testing.T) { assert.Equal(t, fromAddress, etx.FromAddress) assert.True(t, etx.SignalCallback) - cltest.AssertCount(t, db, "evm.txes", 3) + txmgrtest.AssertCount(t, db, "evm.txes", 3) var dbEthTx txmgr.DbEthTx require.NoError(t, db.Get(&dbEthTx, `SELECT * FROM evm.txes ORDER BY id DESC LIMIT 1`)) @@ -1754,12 +1754,12 @@ func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() - tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) + tx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, fromAddress) r := newEthReceipt(4, utils.NewHash(), tx.TxAttempts[0].Hash, 0x1) _, err := txStore.InsertReceipt(ctx, &r.Receipt) require.NoError(t, err) @@ -1786,7 +1786,7 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) { t.Run("finds confirmed transaction requiring receipt fetch", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() // Transactions whose attempts should not be picked up for receipt fetch mustInsertFatalErrorEthTx(t, txStore, fromAddress) @@ -1817,7 +1817,7 @@ func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) { t.Run("finds terminally stuck transaction requiring receipt fetch", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() // Transactions whose attempts should not be picked up for receipt fetch mustInsertFatalErrorEthTx(t, txStore, fromAddress) @@ -1849,7 +1849,7 @@ func TestORM_UpdateTxStatesToFinalizedUsingTxHashes(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) broadcast := time.Now() fromAddress := testutils.NewAddress() @@ -1882,7 +1882,7 @@ func TestORM_FindReorgOrIncludedTxs(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) blockNum := int64(100) t.Run("finds re-org'd transactions using the mined tx count", func(t *testing.T) { fromAddress := testutils.NewAddress() @@ -1944,7 +1944,7 @@ func TestORM_UpdateTxFatalError(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() t.Run("successfully marks transaction as fatal with error message", func(t *testing.T) { // Unconfirmed with purge attempt with nonce less than mined tx cound is newly included @@ -1969,7 +1969,7 @@ func TestORM_FindTxesByIDs(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() @@ -1992,7 +1992,7 @@ func TestORM_DeleteReceiptsByTxHash(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() @@ -2018,7 +2018,7 @@ func TestORM_Abandon(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) fromAddress := testutils.NewAddress() etx1 := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, testutils.FixtureChainID) @@ -2062,7 +2062,7 @@ func mustInsertTerminallyStuckTxWithAttempt(t testing.TB, txStore txmgr.TestEvmT Error: null.StringFrom(client.TerminallyStuckMsg), } require.NoError(t, txStore.InsertTx(ctx, &tx)) - attempt := cltest.NewLegacyEthTxAttempt(t, tx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx.ID) attempt.BroadcastBeforeBlockNum = &broadcastBeforeBlockNum attempt.State = txmgrtypes.TxAttemptBroadcast attempt.IsPurgeAttempt = true diff --git a/core/chains/evm/txmgr/finalizer_benchmark_test.go b/core/chains/evm/txmgr/finalizer_benchmark_test.go index 741e680582a..82747bae369 100644 --- a/core/chains/evm/txmgr/finalizer_benchmark_test.go +++ b/core/chains/evm/txmgr/finalizer_benchmark_test.go @@ -18,13 +18,13 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" ) func BenchmarkFinalizer(b *testing.B) { ctx := tests.Context(b) db := testutils.NewSqlxDB(b) - txStore := cltest.NewTestTxStore(b, db) + txStore := txmgrtest.NewTestTxStore(b, db) feeLimit := uint64(10_000) ethClient := clienttest.NewClientWithDefaultChainID(b) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) diff --git a/core/chains/evm/txmgr/finalizer_test.go b/core/chains/evm/txmgr/finalizer_test.go index a4d1e845777..3673ca05c52 100644 --- a/core/chains/evm/txmgr/finalizer_test.go +++ b/core/chains/evm/txmgr/finalizer_test.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" @@ -34,14 +35,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func TestFinalizer_MarkTxFinalized(t *testing.T) { t.Parallel() ctx := t.Context() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) feeLimit := uint64(10_000) ethClient := clienttest.NewClientWithDefaultChainID(t) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) @@ -247,7 +247,7 @@ func insertTxAndAttemptWithIdempotencyKey(tb testing.TB, txStore txmgr.TestEvmTx require.NoError(tb, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) require.NoError(tb, err) - attempt := cltest.NewLegacyEthTxAttempt(tb, tx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(tb, tx.ID) err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(tb, err) return attempt.Hash @@ -257,7 +257,7 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { t.Parallel() ctx := t.Context() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethClient := clienttest.NewClientWithDefaultChainID(t) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) rpcBatchSize := uint32(1) @@ -294,10 +294,10 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { }) servicetest.Run(t, finalizer) - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 1, fromAddress) mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) // Setting both signal_callback and callback_completed to TRUE to simulate a completed pipeline task // It would only be in a state past suspended if the resume callback was called and callback_completed was set to TRUE @@ -316,10 +316,10 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { }) servicetest.Run(t, finalizer) - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress) mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &trID, minConfirmations, etx.ID) @@ -341,11 +341,11 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { }) servicetest.Run(t, finalizer) - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, runID) - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) receipt := mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) @@ -394,11 +394,11 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { }) servicetest.Run(t, finalizer) - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) testutils.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, runID) - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) testutils.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) // receipt is not passed through as a value since it reverted and caused an error @@ -441,10 +441,10 @@ func TestFinalizer_ResumePendingRuns(t *testing.T) { }) servicetest.Run(t, finalizer) - runID := cltest.MustInsertPipelineRun(t, db) - trID := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, runID) + runID := testutils.MustInsertPipelineRun(t, db) + trID := testutils.MustInsertUnfinishedPipelineTaskRun(t, db, runID) - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) testutils.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &trID, minConfirmations, etx.ID) @@ -483,7 +483,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("does nothing if no confirmed transactions without receipts found", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, config.EVM().RPCDefaultBatchSize(), false, txStore, txmClient, ht, metrics) @@ -501,14 +501,14 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("fetches receipt for confirmed transaction without a receipt", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) // Transaction not confirmed yet, receipt is nil ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) elems[0].Result = &types.Receipt{} @@ -527,11 +527,11 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("saves nothing if returned receipt does not match the attempt", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) txmReceipt := types.Receipt{ TxHash: testutils.NewHash(), BlockHash: testutils.NewHash(), @@ -541,7 +541,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { // First transaction confirmed ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = txmReceipt @@ -559,11 +559,11 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("saves nothing if query returns error", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) txmReceipt := types.Receipt{ TxHash: etx.TxAttempts[0].Hash, BlockHash: testutils.NewHash(), @@ -573,7 +573,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { // Batch receipt call fails ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = txmReceipt @@ -592,13 +592,13 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("saves valid receipt returned by client", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) // Insert confirmed transaction without receipt - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) + etx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) txmReceipt := types.Receipt{ TxHash: etx1.TxAttempts[0].Hash, BlockHash: testutils.NewHash(), @@ -609,8 +609,8 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], etx1.TxAttempts[0].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], etx2.TxAttempts[0].Hash, "eth_getTransactionReceipt") + matchTranscationReceipt(b[0], etx1.TxAttempts[0].Hash) && + matchTranscationReceipt(b[1], etx2.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // First transaction confirmed @@ -646,11 +646,11 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("fetches and saves receipts for several attempts in gas price order", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) attempt1 := etx.TxAttempts[0] attempt2 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) attempt3 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 3) @@ -669,9 +669,9 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 3 && - cltest.BatchElemMatchesParams(b[2], attempt1.Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempt2.Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[0], attempt3.Hash, "eth_getTransactionReceipt") + matchTranscationReceipt(b[2], attempt1.Hash) && + matchTranscationReceipt(b[1], attempt2.Hash) && + matchTranscationReceipt(b[0], attempt3.Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // Most expensive attempt still unconfirmed @@ -698,17 +698,17 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("ignores receipt missing BlockHash that comes from querying parity too early", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) receipt := types.Receipt{ TxHash: etx.TxAttempts[0].Hash, Status: uint64(1), } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = receipt @@ -729,11 +729,11 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("does not panic if receipt has BlockHash but is missing some other fields somehow", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) // NOTE: This should never happen, but we shouldn't panic regardless receipt := types.Receipt{ TxHash: etx.TxAttempts[0].Hash, @@ -741,7 +741,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { Status: uint64(1), } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = receipt @@ -761,11 +761,11 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("simulate on revert", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) attempt := etx.TxAttempts[0] txmReceipt := types.Receipt{ TxHash: attempt.Hash, @@ -777,7 +777,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { // First attempt is confirmed and reverted ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], attempt.Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) // First attempt still unconfirmed @@ -807,12 +807,12 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("find receipt for old transaction, avoid marking as fatal", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, true, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) txmReceipt := types.Receipt{ TxHash: etx.TxAttempts[0].Hash, @@ -824,7 +824,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { // Transaction receipt is nil ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = txmReceipt @@ -841,16 +841,16 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { t.Run("old transaction failed to find receipt, marked as fatal", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, true, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) + etx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) // Transaction receipt is nil ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) elems[0].Result = &types.Receipt{} @@ -881,7 +881,7 @@ func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { ethClient.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Maybe() // Should fetch attempts list from txstore - attempt := cltest.NewLegacyEthTxAttempt(t, 0) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, 0) txStore.On("FindAttemptsRequiringReceiptFetch", mock.Anything, mock.Anything).Return([]txmgr.TxAttempt{attempt}, nil).Once() require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) // Should use the attempts cache for receipt fetch @@ -912,7 +912,7 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { t.Run("fetch and store receipts from multiple batch calls", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() rpcBatchSize := uint32(2) finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) @@ -931,8 +931,8 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], attempts[4].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempts[3].Hash, "eth_getTransactionReceipt") + matchTranscationReceipt(b[0], attempts[4].Hash) && + matchTranscationReceipt(b[1], attempts[3].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) elems[0].Result = &types.Receipt{} @@ -940,16 +940,15 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { }).Once() ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], attempts[2].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempts[1].Hash, "eth_getTransactionReceipt") + matchTranscationReceipt(b[0], attempts[2].Hash) && + matchTranscationReceipt(b[1], attempts[1].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) elems[0].Result = &types.Receipt{} elems[1].Result = &types.Receipt{} }).Once() ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], attempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], attempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) elems[0].Result = &types.Receipt{} @@ -960,14 +959,14 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { t.Run("continue to fetch and store receipts after batch call error", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() rpcBatchSize := uint32(1) finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht, metrics) // Insert confirmed transactions without receipts - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) + etx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) + etx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) txmReceipt := types.Receipt{ TxHash: etx2.TxAttempts[0].Hash, @@ -978,12 +977,10 @@ func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], etx1.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx1.TxAttempts[0].Hash) })).Return(errors.New("batch call failed")).Once() ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], etx2.TxAttempts[0].Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], etx2.TxAttempts[0].Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = txmReceipt // confirmed @@ -1023,7 +1020,7 @@ func TestFinalizer_FetchAndStoreReceipts_HandlesNonFwdTxsWithForwardingEnabled(t head.Parent.Store(latestFinalizedHead) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht, metrics) @@ -1045,8 +1042,7 @@ func TestFinalizer_FetchAndStoreReceipts_HandlesNonFwdTxsWithForwardingEnabled(t } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") + return len(b) == 1 && matchTranscationReceipt(b[0], attempt.Hash) })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) *(elems[0].Result.(*types.Receipt)) = txmReceipt // confirmed @@ -1082,20 +1078,20 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) { t.Run("does nothing if no old transactions found", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht, metrics) require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, []int64{}, head, latestFinalizedHead)) }) t.Run("marks multiple old transactions as fatal", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht, metrics) // Insert confirmed transaction without receipt - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, latestFinalizedHead.Number, fromAddress) + etx1 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) + etx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, latestFinalizedHead.Number, fromAddress) etxIDs := []int64{etx1.ID, etx2.ID} require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, etxIDs, head, latestFinalizedHead)) @@ -1115,13 +1111,13 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) { t.Run("marks old transaction as fatal, resumes pending task as failed", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht, metrics) finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { return nil }) // Insert confirmed transaction with pending task run - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.State = txmgrcommon.TxConfirmed n := types.Nonce(0) etx.Sequence = &n @@ -1149,13 +1145,13 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) { t.Run("transaction stays confirmed if failure to resume pending task", func(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht, metrics) finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { return errors.New("failure") }) // Insert confirmed transaction with pending task run - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.State = txmgrcommon.TxConfirmed n := types.Nonce(0) etx.Sequence = &n @@ -1181,3 +1177,8 @@ func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) { require.False(t, etx.CallbackCompleted) }) } + +func matchTranscationReceipt(req rpc.BatchElem, arg interface{}) bool { + return req.Method == "eth_getTransactionReceipt" && + len(req.Args) == 1 && req.Args[0] == arg +} diff --git a/core/chains/evm/txmgr/mocks/config.go b/core/chains/evm/txmgr/mocks/config.go deleted file mode 100644 index 7494e3e5b2e..00000000000 --- a/core/chains/evm/txmgr/mocks/config.go +++ /dev/null @@ -1,260 +0,0 @@ -// Code generated by mockery v2.53.0. DO NOT EDIT. - -package mocks - -import ( - chaintype "github.com/smartcontractkit/chainlink-evm/pkg/config/chaintype" - mock "github.com/stretchr/testify/mock" -) - -// Config is an autogenerated mock type for the ChainConfig type -type Config struct { - mock.Mock -} - -type Config_Expecter struct { - mock *mock.Mock -} - -func (_m *Config) EXPECT() *Config_Expecter { - return &Config_Expecter{mock: &_m.Mock} -} - -// ChainType provides a mock function with no fields -func (_m *Config) ChainType() chaintype.ChainType { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for ChainType") - } - - var r0 chaintype.ChainType - if rf, ok := ret.Get(0).(func() chaintype.ChainType); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(chaintype.ChainType) - } - - return r0 -} - -// Config_ChainType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainType' -type Config_ChainType_Call struct { - *mock.Call -} - -// ChainType is a helper method to define mock.On call -func (_e *Config_Expecter) ChainType() *Config_ChainType_Call { - return &Config_ChainType_Call{Call: _e.mock.On("ChainType")} -} - -func (_c *Config_ChainType_Call) Run(run func()) *Config_ChainType_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_ChainType_Call) Return(_a0 chaintype.ChainType) *Config_ChainType_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_ChainType_Call) RunAndReturn(run func() chaintype.ChainType) *Config_ChainType_Call { - _c.Call.Return(run) - return _c -} - -// FinalityDepth provides a mock function with no fields -func (_m *Config) FinalityDepth() uint32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for FinalityDepth") - } - - var r0 uint32 - if rf, ok := ret.Get(0).(func() uint32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint32) - } - - return r0 -} - -// Config_FinalityDepth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FinalityDepth' -type Config_FinalityDepth_Call struct { - *mock.Call -} - -// FinalityDepth is a helper method to define mock.On call -func (_e *Config_Expecter) FinalityDepth() *Config_FinalityDepth_Call { - return &Config_FinalityDepth_Call{Call: _e.mock.On("FinalityDepth")} -} - -func (_c *Config_FinalityDepth_Call) Run(run func()) *Config_FinalityDepth_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_FinalityDepth_Call) Return(_a0 uint32) *Config_FinalityDepth_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_FinalityDepth_Call) RunAndReturn(run func() uint32) *Config_FinalityDepth_Call { - _c.Call.Return(run) - return _c -} - -// FinalityTagEnabled provides a mock function with no fields -func (_m *Config) FinalityTagEnabled() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for FinalityTagEnabled") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Config_FinalityTagEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FinalityTagEnabled' -type Config_FinalityTagEnabled_Call struct { - *mock.Call -} - -// FinalityTagEnabled is a helper method to define mock.On call -func (_e *Config_Expecter) FinalityTagEnabled() *Config_FinalityTagEnabled_Call { - return &Config_FinalityTagEnabled_Call{Call: _e.mock.On("FinalityTagEnabled")} -} - -func (_c *Config_FinalityTagEnabled_Call) Run(run func()) *Config_FinalityTagEnabled_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_FinalityTagEnabled_Call) Return(_a0 bool) *Config_FinalityTagEnabled_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_FinalityTagEnabled_Call) RunAndReturn(run func() bool) *Config_FinalityTagEnabled_Call { - _c.Call.Return(run) - return _c -} - -// NonceAutoSync provides a mock function with no fields -func (_m *Config) NonceAutoSync() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for NonceAutoSync") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Config_NonceAutoSync_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NonceAutoSync' -type Config_NonceAutoSync_Call struct { - *mock.Call -} - -// NonceAutoSync is a helper method to define mock.On call -func (_e *Config_Expecter) NonceAutoSync() *Config_NonceAutoSync_Call { - return &Config_NonceAutoSync_Call{Call: _e.mock.On("NonceAutoSync")} -} - -func (_c *Config_NonceAutoSync_Call) Run(run func()) *Config_NonceAutoSync_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_NonceAutoSync_Call) Return(_a0 bool) *Config_NonceAutoSync_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_NonceAutoSync_Call) RunAndReturn(run func() bool) *Config_NonceAutoSync_Call { - _c.Call.Return(run) - return _c -} - -// RPCDefaultBatchSize provides a mock function with no fields -func (_m *Config) RPCDefaultBatchSize() uint32 { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for RPCDefaultBatchSize") - } - - var r0 uint32 - if rf, ok := ret.Get(0).(func() uint32); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint32) - } - - return r0 -} - -// Config_RPCDefaultBatchSize_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RPCDefaultBatchSize' -type Config_RPCDefaultBatchSize_Call struct { - *mock.Call -} - -// RPCDefaultBatchSize is a helper method to define mock.On call -func (_e *Config_Expecter) RPCDefaultBatchSize() *Config_RPCDefaultBatchSize_Call { - return &Config_RPCDefaultBatchSize_Call{Call: _e.mock.On("RPCDefaultBatchSize")} -} - -func (_c *Config_RPCDefaultBatchSize_Call) Run(run func()) *Config_RPCDefaultBatchSize_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Config_RPCDefaultBatchSize_Call) Return(_a0 uint32) *Config_RPCDefaultBatchSize_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Config_RPCDefaultBatchSize_Call) RunAndReturn(run func() uint32) *Config_RPCDefaultBatchSize_Call { - _c.Call.Return(run) - return _c -} - -// NewConfig creates a new instance of Config. 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 NewConfig(t interface { - mock.TestingT - Cleanup(func()) -}) *Config { - mock := &Config{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/txmgr/mocks/utils.go b/core/chains/evm/txmgr/mocks/utils.go deleted file mode 100644 index 76d2e249489..00000000000 --- a/core/chains/evm/txmgr/mocks/utils.go +++ /dev/null @@ -1,18 +0,0 @@ -package mocks - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-evm/pkg/gas" - "github.com/smartcontractkit/chainlink-evm/pkg/types" - txmgrmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" -) - -type MockEvmTxManager = txmgrmocks.TxManager[*big.Int, *types.Head, common.Address, common.Hash, common.Hash, types.Nonce, gas.EvmFee] - -func NewMockEvmTxManager(t *testing.T) *MockEvmTxManager { - return txmgrmocks.NewTxManager[*big.Int, *types.Head, common.Address, common.Hash, common.Hash, types.Nonce, gas.EvmFee](t) -} diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go index 4edb36a58d5..7917d8ac9d1 100644 --- a/core/chains/evm/txmgr/reaper_test.go +++ b/core/chains/evm/txmgr/reaper_test.go @@ -10,11 +10,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/testutils" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func newReaperWithChainID(t *testing.T, db txmgrtypes.TxHistoryReaper[*big.Int], txConfig txmgrtypes.ReaperTransactionsConfig, cid *big.Int) *txmgr.Reaper { @@ -22,7 +22,7 @@ func newReaperWithChainID(t *testing.T, db txmgrtypes.TxHistoryReaper[*big.Int], } func newReaper(t *testing.T, db txmgrtypes.TxHistoryReaper[*big.Int], txConfig txmgrtypes.ReaperTransactionsConfig) *txmgr.Reaper { - return newReaperWithChainID(t, db, txConfig, &cltest.FixtureChainID) + return newReaperWithChainID(t, db, txConfig, testutils.FixtureChainID) } type reaperConfig struct { @@ -42,7 +42,7 @@ func TestReaper_ReapTxes(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() var nonce int64 oneDayAgo := time.Now().Add(-24 * time.Hour) @@ -67,7 +67,7 @@ func TestReaper_ReapTxes(t *testing.T) { err := r.ReapTxes(42) assert.NoError(t, err) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) }) t.Run("doesn't touch ethtxes with different chain ID", func(t *testing.T) { @@ -78,7 +78,7 @@ func TestReaper_ReapTxes(t *testing.T) { err := r.ReapTxes(42) assert.NoError(t, err) // Didn't delete because eth_tx has chain ID of 0 - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) }) t.Run("deletes finalized evm.txes that exceed the age threshold", func(t *testing.T) { @@ -89,14 +89,14 @@ func TestReaper_ReapTxes(t *testing.T) { err := r.ReapTxes(42) assert.NoError(t, err) // Didn't delete because eth_tx was not old enough - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) testutils.MustExec(t, db, `UPDATE evm.txes SET created_at=$1, state='finalized'`, oneDayAgo) err = r.ReapTxes(42) assert.NoError(t, err) // Now it deleted because the eth_tx was past the age threshold - cltest.AssertCount(t, db, "evm.txes", 0) + txmgrtest.AssertCount(t, db, "evm.txes", 0) }) mustInsertFatalErrorEthTx(t, txStore, fromAddress) @@ -109,14 +109,14 @@ func TestReaper_ReapTxes(t *testing.T) { err := r.ReapTxes(42) assert.NoError(t, err) // Didn't delete because eth_tx was not old enough - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) require.NoError(t, utils.JustError(db.Exec(`UPDATE evm.txes SET created_at=$1`, oneDayAgo))) err = r.ReapTxes(42) assert.NoError(t, err) // Deleted because it is old enough now - cltest.AssertCount(t, db, "evm.txes", 0) + txmgrtest.AssertCount(t, db, "evm.txes", 0) }) mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, 42) @@ -129,13 +129,13 @@ func TestReaper_ReapTxes(t *testing.T) { err := r.ReapTxes(42) assert.NoError(t, err) // Didn't delete because eth_tx was not old enough - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) testutils.MustExec(t, db, `UPDATE evm.txes SET created_at=$1`, oneDayAgo) err = r.ReapTxes(42) assert.NoError(t, err) // Now it deleted because the eth_tx was past the age threshold - cltest.AssertCount(t, db, "evm.txes", 0) + txmgrtest.AssertCount(t, db, "evm.txes", 0) }) } diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go index 7cb04dc3f99..07f3db94466 100644 --- a/core/chains/evm/txmgr/resender_test.go +++ b/core/chains/evm/txmgr/resender_test.go @@ -18,13 +18,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-evm/pkg/keys" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/testutils" ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func Test_EthResender_resendUnconfirmed(t *testing.T) { @@ -43,7 +43,7 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) { fromAddress3 := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) originalBroadcastAt := time.Unix(1616509100, 0) @@ -51,19 +51,19 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) { var addr1TxesRawHex, addr2TxesRawHex, addr3TxesRawHex []string // fewer than EvmMaxInFlightTransactions for i := uint32(0); i < txConfig.MaxInFlight()/2; i++ { - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress, originalBroadcastAt) addr1TxesRawHex = append(addr1TxesRawHex, hexutil.Encode(etx.TxAttempts[0].SignedRawTx)) } // exactly EvmMaxInFlightTransactions for i := uint32(0); i < txConfig.MaxInFlight(); i++ { - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress2, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress2, originalBroadcastAt) addr2TxesRawHex = append(addr2TxesRawHex, hexutil.Encode(etx.TxAttempts[0].SignedRawTx)) } // more than EvmMaxInFlightTransactions for i := uint32(0); i < txConfig.MaxInFlight()*2; i++ { - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress3, originalBroadcastAt) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(i), fromAddress3, originalBroadcastAt) addr3TxesRawHex = append(addr3TxesRawHex, hexutil.Encode(etx.TxAttempts[0].SignedRawTx)) } @@ -119,13 +119,13 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { }) }) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) originalBroadcastAt := time.Unix(1616509100, 0) er := txmgr.NewEvmResender(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTracker(txStore, ethKeyStore, big.NewInt(0), lggr), ethKeyStore, 100*time.Millisecond, ccfg.EVM(), ccfg.EVM().Transactions()) t.Run("alerts only once for unconfirmed transaction attempt within the unconfirmedTxAlertDelay duration", func(t *testing.T) { - _ = cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(1), fromAddress, originalBroadcastAt) + _ = txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, int64(1), fromAddress, originalBroadcastAt) ethClient.On("BatchCallContextAll", mock.Anything, mock.Anything).Return(nil) @@ -150,7 +150,7 @@ func Test_EthResender_Start(t *testing.T) { c.RPCDefaultBatchSize = ptr[uint32](1) }) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) @@ -164,9 +164,9 @@ func Test_EthResender_Start(t *testing.T) { er := txmgr.NewEvmResender(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTracker(txStore, ethKeyStore, big.NewInt(0), lggr), ethKeyStore, 100*time.Millisecond, ccfg.EVM(), ccfg.EVM().Transactions()) originalBroadcastAt := time.Unix(1616509100, 0) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, originalBroadcastAt) - etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, originalBroadcastAt) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress, time.Now().Add(1*time.Hour)) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress, originalBroadcastAt) + etx2 := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress, originalBroadcastAt) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress, time.Now().Add(1*time.Hour)) // First batch of 1 ethClient.On("BatchCallContextAll", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { @@ -187,7 +187,8 @@ func Test_EthResender_Start(t *testing.T) { er.Start(ctx) defer er.Stop() - cltest.EventuallyExpectationsMet(t, ethClient, 5*time.Second, time.Second) + assert.Eventually(t, func() bool { return ethClient.AssertExpectations(t) }, + testutils.WaitTimeout(t), time.Second) }() var dbEtx txmgr.DbEthTx diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go index fcaab8ee956..7e68bb0aa10 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector_test.go +++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-evm/pkg/config/configtest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" @@ -30,7 +31,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) var ( @@ -42,7 +42,7 @@ func TestStuckTxDetector_Disabled(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) fromAddress := testutils.NewAddress() lggr := logger.Test(t) @@ -64,7 +64,7 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) blockNum := int64(100) @@ -108,7 +108,7 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { db := testutils.NewSqlxDB(t) config := configtest.NewChainScopedConfig(t, nil) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) lggr := logger.Test(t) @@ -127,10 +127,10 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { fromAddress1 := testutils.NewAddress() fromAddress2 := testutils.NewAddress() // Insert 2 txs for from address, should only return the lowest nonce txs - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress1) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress1) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress1) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress1) // Insert 1 tx for other from address, should return a tx - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress2) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress2) stuckTxs, err := stuckTxDetector.FindUnconfirmedTxWithLowestNonce(ctx, []common.Address{fromAddress1, fromAddress2}) require.NoError(t, err) @@ -157,8 +157,8 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { t.Run("excludes transactions with a in-progress attempt", func(t *testing.T) { fromAddress := testutils.NewAddress() - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptInProgress require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -169,8 +169,8 @@ func TestStuckTxDetector_FindPotentialStuckTxs(t *testing.T) { t.Run("excludes transactions with an insufficient funds attempt", func(t *testing.T) { fromAddress := testutils.NewAddress() - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptInsufficientFunds require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -184,7 +184,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) lggr := logger.Test(t) @@ -291,7 +291,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) lggr := logger.Test(t) @@ -317,7 +317,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { attempts := tx.TxAttempts[0] // Request still returns transaction by hash, transaction not discarded by network and not considered stuck ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + return matchBatchElemParams(b, attempts.Hash, "zirc_isQuarantined") })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) resp, err := json.Marshal(struct { @@ -338,7 +338,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { attempts := tx.TxAttempts[0] // Request still returns transaction by hash, transaction not discarded by network and not considered stuck ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + return matchBatchElemParams(b, attempts.Hash, "zirc_isQuarantined") })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) resp, err := json.Marshal(struct { @@ -359,7 +359,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { attempts := tx.TxAttempts[0] ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + return matchBatchElemParams(b, attempts.Hash, "zirc_isQuarantined") })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) resp, err := json.Marshal(struct { @@ -379,7 +379,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZircuit(t *testing.T) { attempts := tx.TxAttempts[0] ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "zirc_isQuarantined") + return matchBatchElemParams(b, attempts.Hash, "zirc_isQuarantined") })).Return(fmt.Errorf("failed to fetch rpc")) txs, err := stuckTxDetector.DetectStuckTransactions(ctx, []common.Address{fromAddress}, blockNum) @@ -392,7 +392,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) lggr := logger.Test(t) @@ -410,7 +410,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { attempts := tx.TxAttempts[0] // Request still returns transaction by hash, transaction not discarded by network and not considered stuck ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempts.Hash, "eth_getTransactionByHash") + return matchBatchElemParams(b, attempts.Hash, "eth_getTransactionByHash") })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) resp, err := json.Marshal(evmtypes.Transaction{}) @@ -456,7 +456,7 @@ func TestStuckTxDetector_DetectStuckTransactionsZkEVM(t *testing.T) { // Insert tx with enough attempts for detection fromAddress1 := testutils.NewAddress() etx1 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress1, 1, blockNum, tenGwei) - attempt := cltest.NewLegacyEthTxAttempt(t, etx1.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx1.ID) attempt.TxFee.GasPrice = assets.NewWeiI(2) attempt.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -483,7 +483,7 @@ func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ctx := tests.Context(t) lggr := logger.Test(t) @@ -525,11 +525,11 @@ func TestStuckTxDetector_DetectStuckTransactionsScroll(t *testing.T) { func mustInsertUnconfirmedTxWithBroadcastAttempts(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, numAttempts uint32, latestBroadcastBlockNum int64, latestGasPrice *assets.Wei) txmgr.Tx { ctx := tests.Context(t) - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) // Insert attempts from oldest to newest for i := int64(numAttempts - 1); i >= 0; i-- { blockNum := latestBroadcastBlockNum - i - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.BroadcastBeforeBlockNum = &blockNum @@ -544,10 +544,10 @@ func mustInsertUnconfirmedTxWithBroadcastAttempts(t testing.TB, txStore txmgr.Te // helper function for edge case where broadcast attempt contains empty pointer func mustInsertUnconfirmedTxWithBroadcastAttemptsContainsEmptyBroadcastBeforeBlockNum(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, numAttempts uint32, latestGasPrice *assets.Wei) txmgr.Tx { ctx := tests.Context(t) - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) // Insert attempts from oldest to newest for i := int64(numAttempts - 1); i >= 0; i-- { - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.BroadcastBeforeBlockNum = nil attempt.TxFee = gas.EvmFee{GasPrice: latestGasPrice.Sub(assets.NewWeiI(i))} @@ -559,7 +559,7 @@ func mustInsertUnconfirmedTxWithBroadcastAttemptsContainsEmptyBroadcastBeforeBlo } func mustInsertFatalErrorTxWithError(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, blockNum int64) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.State = txmgrcommon.TxFatalError etx.Error = null.StringFrom("fatal error") broadcastAt := time.Now() @@ -570,7 +570,7 @@ func mustInsertFatalErrorTxWithError(t *testing.T, txStore txmgr.TestEvmTxStore, etx.ChainID = testutils.FixtureChainID require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) ctx := tests.Context(t) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.IsPurgeAttempt = true @@ -586,8 +586,8 @@ func mustInsertFatalErrorTxWithError(t *testing.T, txStore txmgr.TestEvmTxStore, } func mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address) txmgr.Tx { - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) ctx := tests.Context(t) attempt.State = txmgrtypes.TxAttemptBroadcast @@ -609,3 +609,8 @@ func (t testAutoPurgeConfig) Enabled() bool { return t.enabled } func (t testAutoPurgeConfig) Threshold() *uint32 { return t.threshold } func (t testAutoPurgeConfig) MinAttempts() *uint32 { return t.minAttempts } func (t testAutoPurgeConfig) DetectionApiUrl() *url.URL { return t.detectionApiUrl } + +func matchBatchElemParams(req []rpc.BatchElem, arg interface{}, method string) bool { + return len(req) == 1 && req[0].Method == method && + len(req[0].Args) == 1 && req[0].Args[0] == arg +} diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go index cec8bc3298a..a09dc410404 100644 --- a/core/chains/evm/txmgr/tracker_test.go +++ b/core/chains/evm/txmgr/tracker_test.go @@ -17,12 +17,12 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" ) func newTestEvmTrackerSetup(t *testing.T) (*txmgr.Tracker, txmgr.TestEvmTxStore) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) chainID := big.NewInt(0) memKS := keystest.NewMemoryChainStore() addr1 := memKS.MustCreate(t) @@ -68,7 +68,7 @@ func TestEvmTracker_AddressTracking(t *testing.T) { unconfirmedAddr := testutils.NewAddress() confirmedAddr := testutils.NewAddress() _ = mustInsertInProgressEthTxWithAttempt(t, txStore, 123, inProgressAddr) - _ = cltest.MustInsertUnconfirmedEthTx(t, txStore, 123, unconfirmedAddr) + _ = txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, 123, unconfirmedAddr) _ = mustInsertConfirmedEthTxWithReceipt(t, txStore, confirmedAddr, 123, 1) _ = mustCreateUnstartedTx(t, txStore, unstartedAddr, testutils.NewAddress(), []byte{}, 0, big.Int{}, ethClient.ConfiguredChainID()) @@ -121,7 +121,7 @@ func TestEvmTracker_ExceedingTTL(t *testing.T) { addr1 := testutils.NewAddress() addr2 := testutils.NewAddress() tx1 := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, addr1) - tx2 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 123, addr2) + tx2 := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, 123, addr2) tracker.XXXTestSetTTL(time.Nanosecond) servicetest.Run(t, tracker) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 077e303a386..93a76ac602b 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -42,12 +42,12 @@ import ( ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/forwarders" evmtxm "github.com/smartcontractkit/chainlink-evm/pkg/txm" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" ) func makeTestEvmTxm( @@ -115,7 +115,7 @@ func TestTxm_CreateTransaction(t *testing.T) { t.Parallel() db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) @@ -157,7 +157,7 @@ func TestTxm_CreateTransaction(t *testing.T) { assert.Equal(t, big.Int(assets.NewEthValue(0)), etx.Value) assert.Equal(t, subject, etx.Subject.UUID) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) var dbEtx txmgr.DbEthTx require.NoError(t, db.Get(&dbEtx, `SELECT * FROM evm.txes ORDER BY id ASC LIMIT 1`)) @@ -247,7 +247,7 @@ func TestTxm_CreateTransaction(t *testing.T) { Checker: checker, }) assert.NoError(t, err) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) var dbEtx txmgr.DbEthTx require.NoError(t, db.Get(&dbEtx, `SELECT * FROM evm.txes ORDER BY id ASC LIMIT 1`)) @@ -291,7 +291,7 @@ func TestTxm_CreateTransaction(t *testing.T) { Checker: checker, }) assert.NoError(t, err) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) var dbEtx txmgr.DbEthTx require.NoError(t, db.Get(&dbEtx, `SELECT * FROM evm.txes ORDER BY id ASC LIMIT 1`)) @@ -313,7 +313,7 @@ func TestTxm_CreateTransaction(t *testing.T) { // Create mock forwarder, mock authorizedsenders call. form := forwarders.NewORM(db) fwdrAddr := testutils.NewAddress() - fwdr, err := form.CreateForwarder(tests.Context(t), fwdrAddr, ubig.Big(cltest.FixtureChainID)) + fwdr, err := form.CreateForwarder(tests.Context(t), fwdrAddr, ubig.Big(*testutils.FixtureChainID)) require.NoError(t, err) require.Equal(t, fwdr.Address, fwdrAddr) @@ -326,7 +326,7 @@ func TestTxm_CreateTransaction(t *testing.T) { Strategy: txmgrcommon.NewSendEveryStrategy(), }) assert.NoError(t, err) - cltest.AssertCount(t, db, "evm.txes", 1) + txmgrtest.AssertCount(t, db, "evm.txes", 1) var dbEtx txmgr.DbEthTx require.NoError(t, db.Get(&dbEtx, `SELECT * FROM evm.txes ORDER BY id ASC LIMIT 1`)) @@ -427,7 +427,7 @@ func newMockTxStrategy(t testing.TB) *commontxmmocks.TxStrategy { func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() fromAddress := memKS.MustCreate(t) @@ -494,7 +494,7 @@ func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { t.Run("if this key has transactions but no insufficient eth errors, transmits as normal", func(t *testing.T) { payload := []byte("payload3") - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 42, fromAddress) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 42, fromAddress) strategy := newMockTxStrategy(t) strategy.On("Subject").Return(uuid.NullUUID{}) strategy.On("PruneQueue", mock.Anything, mock.Anything).Return(nil, nil) @@ -528,8 +528,8 @@ func TestTxm_Lifecycle(t *testing.T) { kst := &keystest.FakeChainStore{} - head := cltest.Head(42) - finalizedHead := cltest.Head(0) + head := makeHead(42) + finalizedHead := makeHead(0) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Maybe() ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(finalizedHead, nil).Maybe() @@ -568,14 +568,14 @@ func TestTxm_Reset(t *testing.T) { addr2 := memKS.MustCreate(t) ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) // 4 confirmed tx from addr1 for i := int64(0); i < 4; i++ { - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr) } // 2 confirmed from addr2 for i := int64(0); i < 2; i++ { - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr2) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, i, i*42+1, addr2) } ethClient := clienttest.NewClientWithDefaultChainID(t) @@ -589,9 +589,9 @@ func TestTxm_Reset(t *testing.T) { txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), ethKeyStore) require.NoError(t, err) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, addr2) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, addr2) for i := 0; i < 1000; i++ { - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 4+int64(i), addr) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 4+int64(i), addr) } t.Run("returns error if not started", func(t *testing.T) { @@ -629,7 +629,7 @@ func TestTxm_GetTransactionFee(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) feeLimit := uint64(10_000) @@ -681,7 +681,7 @@ func TestTxm_GetTransactionFee(t *testing.T) { err := txStore.InsertTx(ctx, tx) require.NoError(t, err) - attemptD := cltest.NewDynamicFeeEthTxAttempt(t, tx.ID) + attemptD := txmgrtest.NewDynamicFeeEthTxAttempt(t, tx.ID) require.NoError(t, txStore.InsertTxAttempt(ctx, &attemptD)) // insert receipt @@ -713,7 +713,7 @@ func TestTxm_GetTransactionFee(t *testing.T) { err := txStore.InsertTx(ctx, tx) require.NoError(t, err) - attemptD := cltest.NewDynamicFeeEthTxAttempt(t, tx.ID) + attemptD := txmgrtest.NewDynamicFeeEthTxAttempt(t, tx.ID) require.NoError(t, txStore.InsertTxAttempt(ctx, &attemptD)) // insert receipt @@ -734,7 +734,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) { ctx := tests.Context(t) db := testutils.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) memKS := keystest.NewMemoryChainStore() ethKeyStore := keys.NewChainStore(memKS, big.NewInt(0)) feeLimit := uint64(10_000) @@ -851,7 +851,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) { require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) require.NoError(t, err) - attempt := cltest.NewLegacyEthTxAttempt(t, tx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx.ID) err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(t, err) // Insert receipt for unfinalized block num @@ -880,7 +880,7 @@ func TestTxm_GetTransactionStatus(t *testing.T) { require.NoError(t, err) tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) require.NoError(t, err) - attempt := cltest.NewLegacyEthTxAttempt(t, tx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx.ID) err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(t, err) // Insert receipt for finalized block num @@ -1024,13 +1024,13 @@ func mustInsertRevertedEthReceipt(t *testing.T, txStore txmgr.TestEvmTxStore, bl // Inserts into evm.receipts but does not update evm.txes or evm.tx_attempts func mustInsertConfirmedEthTxWithReceipt(t testing.TB, txStore txmgr.TestEvmTxStore, fromAddress common.Address, nonce, blockNum int64) (etx txmgr.Tx) { - etx = cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, nonce, blockNum, fromAddress) + etx = txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, nonce, blockNum, fromAddress) mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx.TxAttempts[0].Hash) return etx } func mustInsertFatalErrorEthTx(t testing.TB, txStore txmgr.TestEvmTxStore, fromAddress common.Address) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) etx.Error = null.StringFrom("something exploded") etx.State = txmgrcommon.TxFatalError @@ -1039,8 +1039,8 @@ func mustInsertFatalErrorEthTx(t testing.TB, txStore txmgr.TestEvmTxStore, fromA } func mustInsertUnconfirmedEthTxWithAttemptState(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, txAttemptState txmgrtypes.TxAttemptState, opts ...interface{}) txmgr.Tx { - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) ctx := tests.Context(t) tx := testutils.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) @@ -1057,8 +1057,8 @@ func mustInsertUnconfirmedEthTxWithAttemptState(t testing.TB, txStore txmgr.Test } func mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { - etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) - attempt := cltest.NewDynamicFeeEthTxAttempt(t, etx.ID) + etx := txmgrtest.MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) + attempt := txmgrtest.NewDynamicFeeEthTxAttempt(t, etx.ID) ctx := tests.Context(t) addr := testutils.NewAddress() @@ -1087,7 +1087,7 @@ func mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t *testing.T, txSt func mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address) txmgr.Tx { timeNow := time.Now() - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) ctx := tests.Context(t) etx.BroadcastAt = &timeNow @@ -1096,7 +1096,7 @@ func mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t *testing.T, txStore etx.Sequence = &n etx.State = txmgrcommon.TxUnconfirmed require.NoError(t, txStore.InsertTx(ctx, &etx)) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) tx := testutils.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) @@ -1114,7 +1114,7 @@ func mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t *testing.T, txStore func mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, broadcastBeforeBlockNum int64, broadcastAt time.Time, fromAddress common.Address) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) ctx := tests.Context(t) etx.BroadcastAt = &broadcastAt @@ -1123,7 +1123,7 @@ func mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( etx.Sequence = &n etx.State = txmgrcommon.TxConfirmedMissingReceipt require.NoError(t, txStore.InsertTx(ctx, &etx)) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) attempt.BroadcastBeforeBlockNum = &broadcastBeforeBlockNum attempt.State = txmgrtypes.TxAttemptBroadcast require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) @@ -1132,13 +1132,13 @@ func mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( } func mustInsertInProgressEthTxWithAttempt(t testing.TB, txStore txmgr.TestEvmTxStore, nonce evmtypes.Nonce, fromAddress common.Address) txmgr.Tx { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) ctx := tests.Context(t) etx.Sequence = &nonce etx.State = txmgrcommon.TxInProgress require.NoError(t, txStore.InsertTx(ctx, &etx)) - attempt := cltest.NewLegacyEthTxAttempt(t, etx.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, etx.ID) tx := evmtestutils.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) rlp := new(bytes.Buffer) require.NoError(t, tx.EncodeRLP(rlp)) @@ -1200,7 +1200,7 @@ func mustCreateUnstartedTxFromEvmTxRequest(t testing.TB, txStore txmgr.EvmTxStor } func mustInsertUnstartedTx(t testing.TB, txStore txmgr.TestEvmTxStore, fromAddress common.Address) { - etx := cltest.NewEthTx(fromAddress) + etx := txmgrtest.NewEthTx(fromAddress) ctx := tests.Context(t) require.NoError(t, txStore.InsertTx(ctx, &etx)) } @@ -1227,3 +1227,8 @@ func txRequestWithIdempotencyKey(idempotencyKey string) func(*txmgr.TxRequest) { tx.IdempotencyKey = &idempotencyKey } } + +func makeHead(num int64) *evmtypes.Head { + h := evmtypes.NewHead(big.NewInt(num), evmtestutils.NewHash(), evmtestutils.NewHash(), ubig.New(evmtestutils.FixtureChainID)) + return &h +} diff --git a/core/chains/evm/txmgr/txmgrtest/utils.go b/core/chains/evm/txmgr/txmgrtest/utils.go new file mode 100644 index 00000000000..3eef714d90b --- /dev/null +++ b/core/chains/evm/txmgr/txmgrtest/utils.go @@ -0,0 +1,140 @@ +package txmgrtest + +import ( + "bytes" + "fmt" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-evm/pkg/assets" + "github.com/smartcontractkit/chainlink-evm/pkg/gas" + evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" + "github.com/smartcontractkit/chainlink-evm/pkg/types" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" + txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" + txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" +) + +func NewTestTxStore(t testing.TB, ds sqlutil.DataSource) txmgr.TestEvmTxStore { + return txmgr.NewTxStore(ds, logger.Test(t)) +} + +func NewEthTx(fromAddress common.Address) txmgr.Tx { + return txmgr.Tx{ + FromAddress: fromAddress, + ToAddress: evmtestutils.NewAddress(), + EncodedPayload: []byte{1, 2, 3}, + Value: big.Int(assets.NewEthValue(142)), + FeeLimit: uint64(1000000000), + State: txmgrcommon.TxUnstarted, + } +} + +func MustInsertUnconfirmedEthTx(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { + broadcastAt := time.Now() + chainID := evmtestutils.FixtureChainID + for _, opt := range opts { + switch v := opt.(type) { + case time.Time: + broadcastAt = v + case *big.Int: + chainID = v + } + } + etx := NewEthTx(fromAddress) + + etx.BroadcastAt = &broadcastAt + etx.InitialBroadcastAt = &broadcastAt + n := types.Nonce(nonce) + etx.Sequence = &n + etx.State = txmgrcommon.TxUnconfirmed + etx.ChainID = chainID + require.NoError(t, txStore.InsertTx(evmtestutils.Context(t), &etx)) + return etx +} + +func MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { + etx := MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) + attempt := NewLegacyEthTxAttempt(t, etx.ID) + ctx := evmtestutils.Context(t) + + tx := evmtestutils.NewLegacyTransaction(uint64(nonce), evmtestutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) + rlp := new(bytes.Buffer) + require.NoError(t, tx.EncodeRLP(rlp)) + attempt.SignedRawTx = rlp.Bytes() + + attempt.State = txmgrtypes.TxAttemptBroadcast + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + return etx +} + +func MustInsertConfirmedEthTxWithLegacyAttempt(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, broadcastBeforeBlockNum int64, fromAddress common.Address) txmgr.Tx { + timeNow := time.Now() + etx := NewEthTx(fromAddress) + ctx := evmtestutils.Context(t) + + etx.BroadcastAt = &timeNow + etx.InitialBroadcastAt = &timeNow + n := types.Nonce(nonce) + etx.Sequence = &n + etx.State = txmgrcommon.TxConfirmed + etx.MinConfirmations.SetValid(6) + require.NoError(t, txStore.InsertTx(ctx, &etx)) + attempt := NewLegacyEthTxAttempt(t, etx.ID) + attempt.BroadcastBeforeBlockNum = &broadcastBeforeBlockNum + attempt.State = txmgrtypes.TxAttemptBroadcast + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + etx.TxAttempts = append(etx.TxAttempts, attempt) + return etx +} + +func NewLegacyEthTxAttempt(t testing.TB, etxID int64) txmgr.TxAttempt { + gasPrice := assets.NewWeiI(1) + return txmgr.TxAttempt{ + ChainSpecificFeeLimit: 42, + TxID: etxID, + TxFee: gas.EvmFee{GasPrice: gasPrice}, + // Just a random signed raw tx that decodes correctly + // Ignore all actual values + SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), + Hash: utils.NewHash(), + State: txmgrtypes.TxAttemptInProgress, + } +} + +func NewDynamicFeeEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { + gasTipCap := assets.NewWeiI(1) + gasFeeCap := assets.NewWeiI(1) + return txmgr.TxAttempt{ + TxType: 0x2, + TxID: etxID, + TxFee: gas.EvmFee{ + DynamicFee: gas.DynamicFee{GasTipCap: gasTipCap, GasFeeCap: gasFeeCap}, + }, + // Just a random signed raw tx that decodes correctly + // Ignore all actual values + SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), + Hash: utils.NewHash(), + State: txmgrtypes.TxAttemptInProgress, + ChainSpecificFeeLimit: 42, + } +} + +func AssertCount(t testing.TB, ds sqlutil.DataSource, tableName string, expected int64) { + t.Helper() + ctx := evmtestutils.Context(t) + var count int64 + err := ds.GetContext(ctx, &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + require.NoError(t, err) + require.Equal(t, expected, count) +} diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index 40294c1f6b1..cca2e1fa445 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -13,6 +13,7 @@ import ( "github.com/urfave/cli" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -32,8 +33,8 @@ func TestShell_IndexTransactions(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetDB()) - tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) + tx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] // page 1 @@ -73,8 +74,8 @@ func TestShell_ShowTransaction(t *testing.T) { db := app.GetDB() _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, db) - tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) + txStore := txmgrtest.NewTestTxStore(t, db) + tx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) attempt := tx.TxAttempts[0] set := flag.NewFlagSet("test get tx", 0) @@ -97,8 +98,8 @@ func TestShell_IndexTxAttempts(t *testing.T) { _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - txStore := cltest.NewTestTxStore(t, app.GetDB()) - tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) + tx := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // page 1 set := flag.NewFlagSet("test txattempts", 0) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 2fea909b33f..2c2f0e7e611 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -17,6 +17,7 @@ import ( "github.com/urfave/cli" "github.com/smartcontractkit/chainlink-common/pkg/types/core" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -286,8 +287,8 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { keyStore := cltest.NewKeyStore(t, sqlxDB) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) - txStore := cltest.NewTestTxStore(t, sqlxDB) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 42, fromAddress) + txStore := txmgrtest.NewTestTxStore(t, sqlxDB) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 42, fromAddress) lggr := logger.TestLogger(t) @@ -368,8 +369,8 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) - txStore := cltest.NewTestTxStore(t, sqlxDB) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(test.nonce), 42, fromAddress) + txStore := txmgrtest.NewTestTxStore(t, sqlxDB) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(test.nonce), 42, fromAddress) lggr := logger.TestLogger(t) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index f95c112f505..01082e65fcf 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -1271,18 +1271,6 @@ func MockApplicationEthCalls(t *testing.T, app *TestApplication, ethClient *clie ethClient.On("Close").Return().Maybe() } -func BatchElemMatchesParams(req rpc.BatchElem, arg interface{}, method string) bool { - return req.Method == method && - len(req.Args) == 1 && req.Args[0] == arg -} - -func BatchElemMustMatchParams(t *testing.T, req rpc.BatchElem, hash common.Hash, method string) { - t.Helper() - if !BatchElemMatchesParams(req, hash, method) { - t.Fatalf("Batch hash %v does not match expected %v", req.Args[0], hash) - } -} - // SimulateIncomingHeads spawns a goroutine which sends a stream of heads and closes the returned channel when finished. func SimulateIncomingHeads(t *testing.T, heads []*evmtypes.Head, headTrackables ...evmheads.Trackable) (done chan struct{}) { // Build the full chain of heads @@ -1440,36 +1428,6 @@ func (fn HeadTrackableFunc) OnNewLongestChain(ctx context.Context, head *evmtype fn(ctx, head) } -type testifyExpectationsAsserter interface { - AssertExpectations(t mock.TestingT) bool -} - -type fakeT struct{} - -func (ft fakeT) Logf(format string, args ...interface{}) {} -func (ft fakeT) Errorf(format string, args ...interface{}) {} -func (ft fakeT) FailNow() {} - -func EventuallyExpectationsMet(t *testing.T, mock testifyExpectationsAsserter, timeout time.Duration, interval time.Duration) { - t.Helper() - - chTimeout := time.After(timeout) - for { - var ft fakeT - success := mock.AssertExpectations(ft) - if success { - return - } - select { - case <-chTimeout: - mock.AssertExpectations(t) - t.FailNow() - default: - time.Sleep(interval) - } - } -} - func AssertCount(t testing.TB, ds sqlutil.DataSource, tableName string, expected int64) { testutils.AssertCount(t, ds, tableName, expected) } @@ -1515,10 +1473,6 @@ func MustWebURL(t *testing.T, s string) *models.WebURL { return (*models.WebURL)(uri) } -func NewTestTxStore(t testing.TB, ds sqlutil.DataSource) txmgr.TestEvmTxStore { - return txmgr.NewTxStore(ds, logger.TestLogger(t)) -} - // ClearDBTables deletes all rows from the given tables func ClearDBTables(t *testing.T, db *sqlx.DB, tables ...string) { tx, err := db.Beginx() diff --git a/core/internal/cltest/factories.go b/core/internal/cltest/factories.go index 90bc31f8ec4..0d14af4196c 100644 --- a/core/internal/cltest/factories.go +++ b/core/internal/cltest/factories.go @@ -1,19 +1,15 @@ package cltest import ( - "bytes" "encoding/json" "flag" "fmt" "math/big" mathrand "math/rand" "net/url" - "strconv" "testing" - "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/jmoiron/sqlx" @@ -24,20 +20,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/bridges" - txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" - txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" - - "github.com/smartcontractkit/chainlink-evm/pkg/assets" - "github.com/smartcontractkit/chainlink-evm/pkg/gas" "github.com/smartcontractkit/chainlink-evm/pkg/heads" - evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" evmutils "github.com/smartcontractkit/chainlink-evm/pkg/utils" ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/flux_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/auth" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -138,109 +127,6 @@ func EmptyCLIContext() *cli.Context { return cli.NewContext(nil, set, nil) } -func NewEthTx(fromAddress common.Address) txmgr.Tx { - return txmgr.Tx{ - FromAddress: fromAddress, - ToAddress: testutils.NewAddress(), - EncodedPayload: []byte{1, 2, 3}, - Value: big.Int(assets.NewEthValue(142)), - FeeLimit: uint64(1000000000), - State: txmgrcommon.TxUnstarted, - } -} - -func MustInsertUnconfirmedEthTx(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { - broadcastAt := time.Now() - chainID := &FixtureChainID - for _, opt := range opts { - switch v := opt.(type) { - case time.Time: - broadcastAt = v - case *big.Int: - chainID = v - } - } - etx := NewEthTx(fromAddress) - - etx.BroadcastAt = &broadcastAt - etx.InitialBroadcastAt = &broadcastAt - n := evmtypes.Nonce(nonce) - etx.Sequence = &n - etx.State = txmgrcommon.TxUnconfirmed - etx.ChainID = chainID - require.NoError(t, txStore.InsertTx(testutils.Context(t), &etx)) - return etx -} - -func MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, nonce int64, fromAddress common.Address, opts ...interface{}) txmgr.Tx { - etx := MustInsertUnconfirmedEthTx(t, txStore, nonce, fromAddress, opts...) - attempt := NewLegacyEthTxAttempt(t, etx.ID) - ctx := testutils.Context(t) - - tx := evmtestutils.NewLegacyTransaction(uint64(nonce), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) - rlp := new(bytes.Buffer) - require.NoError(t, tx.EncodeRLP(rlp)) - attempt.SignedRawTx = rlp.Bytes() - - attempt.State = txmgrtypes.TxAttemptBroadcast - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - return etx -} - -func MustInsertConfirmedEthTxWithLegacyAttempt(t testing.TB, txStore txmgr.TestEvmTxStore, nonce int64, broadcastBeforeBlockNum int64, fromAddress common.Address) txmgr.Tx { - timeNow := time.Now() - etx := NewEthTx(fromAddress) - ctx := testutils.Context(t) - - etx.BroadcastAt = &timeNow - etx.InitialBroadcastAt = &timeNow - n := evmtypes.Nonce(nonce) - etx.Sequence = &n - etx.State = txmgrcommon.TxConfirmed - etx.MinConfirmations.SetValid(6) - require.NoError(t, txStore.InsertTx(ctx, &etx)) - attempt := NewLegacyEthTxAttempt(t, etx.ID) - attempt.BroadcastBeforeBlockNum = &broadcastBeforeBlockNum - attempt.State = txmgrtypes.TxAttemptBroadcast - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - etx.TxAttempts = append(etx.TxAttempts, attempt) - return etx -} - -func NewLegacyEthTxAttempt(t testing.TB, etxID int64) txmgr.TxAttempt { - gasPrice := assets.NewWeiI(1) - return txmgr.TxAttempt{ - ChainSpecificFeeLimit: 42, - TxID: etxID, - TxFee: gas.EvmFee{GasPrice: gasPrice}, - // Just a random signed raw tx that decodes correctly - // Ignore all actual values - SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), - Hash: evmutils.NewHash(), - State: txmgrtypes.TxAttemptInProgress, - } -} - -func NewDynamicFeeEthTxAttempt(t *testing.T, etxID int64) txmgr.TxAttempt { - gasTipCap := assets.NewWeiI(1) - gasFeeCap := assets.NewWeiI(1) - return txmgr.TxAttempt{ - TxType: 0x2, - TxID: etxID, - TxFee: gas.EvmFee{ - DynamicFee: gas.DynamicFee{GasTipCap: gasTipCap, GasFeeCap: gasFeeCap}, - }, - // Just a random signed raw tx that decodes correctly - // Ignore all actual values - SignedRawTx: hexutil.MustDecode("0xf889808504a817c8008307a12094000000000000000000000000000000000000000080a400000000000000000000000000000000000000000000000000000000000000000000000025a0838fe165906e2547b9a052c099df08ec891813fea4fcdb3c555362285eb399c5a070db99322490eb8a0f2270be6eca6e3aedbc49ff57ef939cf2774f12d08aa85e"), - Hash: evmutils.NewHash(), - State: txmgrtypes.TxAttemptInProgress, - ChainSpecificFeeLimit: 42, - } -} - type RandomKey struct { Nonce int64 Disabled bool @@ -408,23 +294,6 @@ func MustInsertUpkeepForRegistry(t *testing.T, db *sqlx.DB, registry keeper.Regi return upkeep } -func MustInsertPipelineRun(t *testing.T, db *sqlx.DB) (runID int64) { - require.NoError(t, db.Get(&runID, `INSERT INTO pipeline_runs (state,pipeline_spec_id,pruning_key,created_at) VALUES ($1, 0, 0, NOW()) RETURNING id`, "running")) - return runID -} - -func MustInsertPipelineSpec(t *testing.T, db *sqlx.DB) (spec pipeline.Spec) { - err := db.Get(&spec, `INSERT INTO pipeline_specs (dot_dag_source,created_at) VALUES ('',NOW()) RETURNING *`) - require.NoError(t, err) - return -} - -func MustInsertUnfinishedPipelineTaskRun(t *testing.T, db *sqlx.DB, pipelineRunID int64) (trID uuid.UUID) { - /* #nosec G404 */ - require.NoError(t, db.Get(&trID, `INSERT INTO pipeline_task_runs (dot_id, pipeline_run_id, id, type, created_at) VALUES ($1,$2,$3, '', NOW()) RETURNING id`, strconv.Itoa(mathrand.Int()), pipelineRunID, uuid.New())) - return trID -} - func RawNewRoundLog(t *testing.T, contractAddr common.Address, blockHash common.Hash, blockNumber uint64, logIndex uint, removed bool) types.Log { t.Helper() topic := (flux_aggregator_wrapper.FluxAggregatorNewRound{}).Topic() diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 7389939b1db..9bfe47fd959 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -32,13 +32,13 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.10.0 @@ -381,8 +381,8 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250502210357-2df484128afa // indirect @@ -393,14 +393,14 @@ require ( 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/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 // indirect github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.10 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250422175525-b7575d96bd4d // indirect github.com/smartcontractkit/freeport v0.1.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/mcms v0.18.0 // indirect + github.com/smartcontractkit/mcms v0.19.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index fab299d8702..a9bd2c46b4a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1256,24 +1256,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1294,8 +1294,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 h1:ks1FuQQ6f7PY/97VFXxtZhAyWZaT0NCvhT+1wKgyOt0= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4/go.mod h1:zw3QH/GTvPl/7Cjyw+y4cJYnP16QHTEh7wWLJQd9lM8= github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 h1:+kwLuO9kcq1+ZbRUQjxX1SQmzlL2M6ZP6+L0xQMtmkU= @@ -1312,10 +1312,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go index be029fdba6c..b704fcd71d8 100644 --- a/core/services/blockhashstore/bhs_test.go +++ b/core/services/blockhashstore/bhs_test.go @@ -12,8 +12,8 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" "github.com/smartcontractkit/chainlink-evm/pkg/types" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 301fcbe4624..8120cc2f320 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -1813,6 +1813,10 @@ func TestFluxMonitor_DoesNotDoubleSubmit(t *testing.T) { }) } +// This is a flaky test: inserting time.Sleep(15 * time.Second) in its end makes it failing with an unexpected call. +// For now, we let it use a custom EventuallyExpectationsMet instead of assert.Eventually because it flakes +// with the latter approach (somehow assert.Eventually gives it a little bit more time, and then it fails +// with the same unexpected call). func TestFluxMonitor_DrumbeatTicker(t *testing.T) { t.Parallel() @@ -1925,9 +1929,39 @@ func TestFluxMonitor_DrumbeatTicker(t *testing.T) { waitTime := 15 * time.Second interval := 50 * time.Millisecond - cltest.EventuallyExpectationsMet(t, tm.logBroadcaster, waitTime, interval) - cltest.EventuallyExpectationsMet(t, tm.fluxAggregator, waitTime, interval) - cltest.EventuallyExpectationsMet(t, tm.orm, waitTime, interval) - cltest.EventuallyExpectationsMet(t, tm.pipelineORM, waitTime, interval) - cltest.EventuallyExpectationsMet(t, tm.contractSubmitter, waitTime, interval) + eventuallyExpectationsMet(t, tm.logBroadcaster, waitTime, interval) + eventuallyExpectationsMet(t, tm.fluxAggregator, waitTime, interval) + eventuallyExpectationsMet(t, tm.orm, waitTime, interval) + eventuallyExpectationsMet(t, tm.pipelineORM, waitTime, interval) + eventuallyExpectationsMet(t, tm.contractSubmitter, waitTime, interval) +} + +type testifyExpectationsAsserter interface { + AssertExpectations(t mock.TestingT) bool +} + +type fakeT struct{} + +func (ft fakeT) Logf(format string, args ...interface{}) {} +func (ft fakeT) Errorf(format string, args ...interface{}) {} +func (ft fakeT) FailNow() {} + +func eventuallyExpectationsMet(t *testing.T, mock testifyExpectationsAsserter, timeout time.Duration, interval time.Duration) { + t.Helper() + + chTimeout := time.After(timeout) + for { + var ft fakeT + success := mock.AssertExpectations(ft) + if success { + return + } + select { + case <-chTimeout: + mock.AssertExpectations(t) + t.FailNow() + default: + time.Sleep(interval) + } + } } diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index 5fb908dfa25..831b4e1f0f1 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -14,10 +14,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/headreporter/prometheus_reporter_test.go index 782130d447d..cf41f849fb6 100644 --- a/core/services/headreporter/prometheus_reporter_test.go +++ b/core/services/headreporter/prometheus_reporter_test.go @@ -15,6 +15,8 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/heads/headstest" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -62,13 +64,13 @@ func Test_PrometheusReporter(t *testing.T) { t.Run("with unconfirmed evm.txes", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) + txStore := txmgrtest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + etx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) + txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) require.NoError(t, txStore.UpdateTxAttemptBroadcastBeforeBlockNum(testutils.Context(t), etx.ID, 7)) backend := headreporter.NewMockPrometheusBackend(t) @@ -96,9 +98,9 @@ func Test_PrometheusReporter(t *testing.T) { db := pgtest.NewSqlxDB(t) pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_task_runs_pipeline_run_id_fkey DEFERRED`) - cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) - cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) - cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 2) + evmtestutils.MustInsertUnfinishedPipelineTaskRun(t, db, 1) + evmtestutils.MustInsertUnfinishedPipelineTaskRun(t, db, 1) + evmtestutils.MustInsertUnfinishedPipelineTaskRun(t, db, 2) backend := headreporter.NewMockPrometheusBackend(t) backend.On("SetUnconfirmedTransactions", big.NewInt(0), int64(0)).Return() diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index df8a126beac..a66c2a13a12 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -24,8 +24,9 @@ import ( evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-evm/pkg/utils" ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" + + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index dbe1a5aa795..a8efad370a6 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink-evm/pkg/utils" ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" @@ -115,8 +116,8 @@ func Test_EthKeyStore(t *testing.T) { cltest.AssertCount(t, db, statesTableName, 1) // add one eth_tx - txStore := cltest.NewTestTxStore(t, db) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 42, key.Address) + txStore := txmgrtest.NewTestTxStore(t, db) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 42, key.Address) _, err = ethKeyStore.Delete(ctx, key.ID()) require.NoError(t, err) diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index d733d040690..c9b3246d4bd 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -13,7 +13,8 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" diff --git a/core/services/ocr2/plugins/ccip/transmitter/transmitter_test.go b/core/services/ocr2/plugins/ccip/transmitter/transmitter_test.go index 316be398cf6..87694484d09 100644 --- a/core/services/ocr2/plugins/ccip/transmitter/transmitter_test.go +++ b/core/services/ocr2/plugins/ccip/transmitter/transmitter_test.go @@ -14,9 +14,10 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" ubig "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" + + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go index 518869d8244..dfc41b55ef1 100644 --- a/core/services/ocrcommon/peer_wrapper_test.go +++ b/core/services/ocrcommon/peer_wrapper_test.go @@ -125,7 +125,7 @@ func Test_SingletonPeerWrapper_Close(t *testing.T) { c.P2P.V2.DeltaReconcile = commonconfig.MustNewDuration(1 * time.Second) p2paddresses := []string{ - "127.0.0.1:17193", + fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t)), } c.P2P.V2.ListenAddresses = ptr(p2paddresses) c.P2P.V2.AnnounceAddresses = ptr(p2paddresses) diff --git a/core/services/ocrcommon/transmitter_test.go b/core/services/ocrcommon/transmitter_test.go index 885e3febe09..2c4ba232ead 100644 --- a/core/services/ocrcommon/transmitter_test.go +++ b/core/services/ocrcommon/transmitter_test.go @@ -11,9 +11,9 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index bdd481374dc..e9b661b3805 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-evm/pkg/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -190,7 +191,7 @@ func TestInsertFinishedRuns(t *testing.T) { _, err = db.Exec(`SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`) require.NoError(t, err) - ps := cltest.MustInsertPipelineSpec(t, db) + ps := mustInsertPipelineSpec(t, db) var runs []*pipeline.Run for i := 0; i < 3; i++ { @@ -854,7 +855,7 @@ func Test_Prune(t *testing.T) { porm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) torm := newTestORM(porm, db) - ps1 := cltest.MustInsertPipelineSpec(t, db) + ps1 := mustInsertPipelineSpec(t, db) // We need a job_pipeline_specs entry to test the pruning mechanism err := torm.AddJobPipelineSpecWithoutConstraints(testutils.Context(t), ps1.ID, ps1.ID) @@ -879,7 +880,7 @@ func Test_Prune(t *testing.T) { mustInsertPipelineRunWithStatus(t, db, ps1.ID, pipeline.RunStatusCompleted, jobID) } - ps2 := cltest.MustInsertPipelineSpec(t, db) + ps2 := mustInsertPipelineSpec(t, db) jobID2 := ps2.ID // ps2 has: @@ -940,3 +941,9 @@ func mustInsertPipelineRunWithStatus(t *testing.T, db *sqlx.DB, pipelineSpecID i require.NoError(t, db.Get(&runID, `INSERT INTO pipeline_runs (state,pipeline_spec_id,pruning_key,finished_at,outputs,all_errors,fatal_errors,created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW()) RETURNING id`, status, pipelineSpecID, jobID, finishedAt, outputs, allErrors, fatalErrors)) return runID } + +func mustInsertPipelineSpec(t *testing.T, db *sqlx.DB) (spec pipeline.Spec) { + err := db.Get(&spec, `INSERT INTO pipeline_specs (dot_dag_source,created_at) VALUES ('',NOW()) RETURNING *`) + require.NoError(t, err) + return +} diff --git a/core/services/pipeline/task.eth_call_test.go b/core/services/pipeline/task.eth_call_test.go index 0b33f6b71d2..6f14b2cea9e 100644 --- a/core/services/pipeline/task.eth_call_test.go +++ b/core/services/pipeline/task.eth_call_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" diff --git a/core/services/pipeline/task.eth_tx_test.go b/core/services/pipeline/task.eth_tx_test.go index 0e1e96593fc..c13e6fb3f73 100644 --- a/core/services/pipeline/task.eth_tx_test.go +++ b/core/services/pipeline/task.eth_tx_test.go @@ -12,9 +12,9 @@ import ( clnull "github.com/smartcontractkit/chainlink-common/pkg/utils/null" txmgrcommon "github.com/smartcontractkit/chainlink-framework/chains/txmgr" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go index b2ada5cc33b..00859643505 100644 --- a/core/services/relay/evm/chain_writer_test.go +++ b/core/services/relay/evm/chain_writer_test.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/gas" gasmocks "github.com/smartcontractkit/chainlink-evm/pkg/gas/mocks" rollupmocks "github.com/smartcontractkit/chainlink-evm/pkg/gas/rollups/mocks" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) diff --git a/core/services/relay/evm/evm_service_test.go b/core/services/relay/evm/evm_service_test.go index b86431c6ad3..aae57b16603 100644 --- a/core/services/relay/evm/evm_service_test.go +++ b/core/services/relay/evm/evm_service_test.go @@ -10,12 +10,13 @@ import ( "github.com/stretchr/testify/require" gethtypes "github.com/ethereum/go-ethereum/core/types" + evmtypes "github.com/smartcontractkit/chainlink-common/pkg/types/chains/evm" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" "github.com/smartcontractkit/chainlink-evm/pkg/heads/headstest" "github.com/smartcontractkit/chainlink-evm/pkg/logpoller" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" pollermocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink-evm/pkg/types" diff --git a/core/services/relay/evm/functions/contract_transmitter_test.go b/core/services/relay/evm/functions/contract_transmitter_test.go index 192d02ff4c6..b2f129ef1d5 100644 --- a/core/services/relay/evm/functions/contract_transmitter_test.go +++ b/core/services/relay/evm/functions/contract_transmitter_test.go @@ -18,10 +18,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" "github.com/smartcontractkit/chainlink-evm/pkg/keys/keystest" + txmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" commontxmmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" lpmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/encoding" diff --git a/core/services/relay/evm/statuschecker/txm_status_checker_test.go b/core/services/relay/evm/statuschecker/txm_status_checker_test.go index 7a682d708e2..6f63d2d6960 100644 --- a/core/services/relay/evm/statuschecker/txm_status_checker_test.go +++ b/core/services/relay/evm/statuschecker/txm_status_checker_test.go @@ -11,8 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/common/txmgr/mocks" ) func Test_CheckMessageStatus(t *testing.T) { diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index f936606ac31..0317fafdd8d 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -17,20 +17,19 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink-evm/pkg/heads/headstest" - "github.com/smartcontractkit/chainlink-evm/pkg/keys" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "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" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" forwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" + 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" pollermocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -39,6 +38,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/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" ) diff --git a/core/services/versioning/orm.go b/core/services/versioning/orm.go index 5f6e3e60222..033da9904d7 100644 --- a/core/services/versioning/orm.go +++ b/core/services/versioning/orm.go @@ -3,6 +3,7 @@ package versioning import ( "context" "database/sql" + "os" "time" "github.com/Masterminds/semver/v3" @@ -46,7 +47,9 @@ func (o *orm) UpsertNodeVersion(ctx context.Context, version NodeVersion) error } return sqlutil.TransactDataSource(ctx, o.ds, nil, func(tx sqlutil.DataSource) error { - if _, _, err := CheckVersion(ctx, tx, logger.NullLogger, version.Version); err != nil { + if os.Getenv("CL_SKIP_APP_VERSION_CHECK") == "true" { + o.lggr.Warnw("Skipping app version check", "appVersion", version.Version) + } else if _, _, err := CheckVersion(ctx, tx, logger.NullLogger, version.Version); err != nil { return err } diff --git a/core/services/versioning/orm_test.go b/core/services/versioning/orm_test.go index 44c63f60d04..a54fba4ba36 100644 --- a/core/services/versioning/orm_test.go +++ b/core/services/versioning/orm_test.go @@ -14,49 +14,77 @@ import ( ) func TestORM_NodeVersion_UpsertNodeVersion(t *testing.T) { - ctx := testutils.Context(t) + ctx := t.Context() db := pgtest.NewSqlxDB(t) - orm := NewORM(db, logger.TestLogger(t)) - err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) - require.NoError(t, err) + t.Run("With App Version Check", func(t *testing.T) { + orm := NewORM(db, logger.TestLogger(t)) - ver, err := orm.FindLatestNodeVersion(ctx) + err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) + require.NoError(t, err) - require.NoError(t, err) - require.NotNil(t, ver) - require.Equal(t, "9.9.8", ver.Version) - require.NotZero(t, ver.CreatedAt) + ver, err := orm.FindLatestNodeVersion(ctx) - // Testing Upsert - require.NoError(t, orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8"))) + require.NoError(t, err) + require.NotNil(t, ver) + require.Equal(t, "9.9.8", ver.Version) + require.NotZero(t, ver.CreatedAt) - err = orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.7")) - require.Error(t, err) - assert.Contains(t, err.Error(), "Application version (9.9.7) is lower than database version (9.9.8). Only Chainlink 9.9.8 or higher can be run on this database") + // Testing Upsert + require.NoError(t, orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8"))) - require.NoError(t, orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.9"))) + err = orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.7")) + require.Error(t, err) + assert.Contains(t, err.Error(), "Application version (9.9.7) is lower than database version (9.9.8). Only Chainlink 9.9.8 or higher can be run on this database") - var count int - err = db.QueryRowx(`SELECT count(*) FROM node_versions`).Scan(&count) - require.NoError(t, err) - assert.Equal(t, 1, count) + require.NoError(t, orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.9"))) - ver, err = orm.FindLatestNodeVersion(ctx) + var count int + err = db.QueryRowx(`SELECT count(*) FROM node_versions`).Scan(&count) + require.NoError(t, err) + assert.Equal(t, 1, count) - require.NoError(t, err) - require.NotNil(t, ver) - require.Equal(t, "9.9.9", ver.Version) + ver, err = orm.FindLatestNodeVersion(ctx) - // invalid semver returns error - err = orm.UpsertNodeVersion(ctx, NewNodeVersion("random_12345")) - require.Error(t, err) - assert.Contains(t, err.Error(), "\"random_12345\" is not valid semver: Invalid Semantic Version") + require.NoError(t, err) + require.NotNil(t, ver) + require.Equal(t, "9.9.9", ver.Version) - ver, err = orm.FindLatestNodeVersion(ctx) - require.NoError(t, err) - require.NotNil(t, ver) - require.Equal(t, "9.9.9", ver.Version) + // invalid semver returns error + err = orm.UpsertNodeVersion(ctx, NewNodeVersion("random_12345")) + require.Error(t, err) + assert.Contains(t, err.Error(), "\"random_12345\" is not valid semver: Invalid Semantic Version") + + ver, err = orm.FindLatestNodeVersion(ctx) + require.NoError(t, err) + require.NotNil(t, ver) + require.Equal(t, "9.9.9", ver.Version) + }) + t.Run("Without App Version Check", func(t *testing.T) { + orm := NewORM(db, logger.TestLogger(t)) + // Set the environment variable to skip the app version check + t.Setenv("CL_SKIP_APP_VERSION_CHECK", "true") + + err := orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.8")) + require.NoError(t, err) + + ver, err := orm.FindLatestNodeVersion(ctx) + + require.NoError(t, err) + require.NotNil(t, ver) + require.Equal(t, "9.9.8", ver.Version) + require.NotZero(t, ver.CreatedAt) + + // previous version allowed + err = orm.UpsertNodeVersion(ctx, NewNodeVersion("9.9.7")) + require.NoError(t, err) + ver, err = orm.FindLatestNodeVersion(ctx) + + require.NoError(t, err) + require.NotNil(t, ver) + require.Equal(t, "9.9.7", ver.Version) + require.NotZero(t, ver.CreatedAt) + }) } func Test_Version_CheckVersion(t *testing.T) { @@ -95,6 +123,7 @@ func Test_Version_CheckVersion(t *testing.T) { require.NoError(t, err) assert.Equal(t, "9.9.9", appv.String()) assert.Equal(t, "9.9.8", dbv.String()) + } func TestORM_CheckVersion_CCIP(t *testing.T) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 8f22278b8c4..73a2e4e3aba 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -157,13 +157,13 @@ func (e *Engine) Start(_ context.Context) error { // validate if adding another workflow would exceed either the global or per owner engine count limit ownerAllow, globalAllow := e.workflowLimits.Allow(e.workflow.owner) if !globalAllow { - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner).incrementWorkflowLimitGlobalCounter(ctx) + e.metrics.incrementWorkflowLimitGlobalCounter(ctx) logCustMsg(ctx, e.cma.With(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner), types.ErrGlobalWorkflowCountLimitReached.Error(), e.logger) return types.ErrGlobalWorkflowCountLimitReached } if !ownerAllow { - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner).incrementWorkflowLimitPerOwnerCounter(ctx) + e.metrics.incrementWorkflowLimitPerOwnerCounter(ctx) logCustMsg(ctx, e.cma.With(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner), types.ErrPerOwnerWorkflowCountLimitReached.Error(), e.logger) return types.ErrPerOwnerWorkflowCountLimitReached } @@ -649,13 +649,13 @@ func (e *Engine) finishExecution(ctx context.Context, cma custmsg.MessageEmitter if exists { // send metering report to beholder if err = events.EmitMeteringReport(ctx, cma, report.Message()); err != nil { - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, executionID).incrementWorkflowMissingMeteringReport(ctx) + e.metrics.incrementWorkflowMissingMeteringReport(ctx) l.Warn(fmt.Sprintf("metering report send to beholder error %s", err)) } // send metering report to billing if billing client is not nil if err = e.sendMeteringReportToBilling(ctx, report, e.workflow.id, executionID); err != nil { - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, executionID).incrementWorkflowMissingMeteringReport(ctx) + e.metrics.incrementWorkflowMissingMeteringReport(ctx) l.Warn(fmt.Sprintf("metering report send to billing error %s", err)) } } @@ -735,14 +735,14 @@ func (e *Engine) worker(ctx context.Context) { e.onRateLimit(executionID) e.logger.With(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner, platform.KeyWorkflowExecutionID, executionID).Errorf("failed to start execution: per sender rate limit exceeded") logCustMsg(ctx, e.cma.With(platform.KeyCapabilityID, te.ID), "failed to start execution: per sender rate limit exceeded", e.logger) - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, executionID, platform.KeyTriggerID, te.ID, platform.KeyWorkflowOwner, e.workflow.owner).incrementWorkflowExecutionRateLimitPerUserCounter(ctx) + e.metrics.with(platform.KeyTriggerID, te.ID).incrementWorkflowExecutionRateLimitPerUserCounter(ctx) continue } if !globalAllowed { e.onRateLimit(executionID) e.logger.With(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowOwner, e.workflow.owner, platform.KeyWorkflowExecutionID, executionID).Errorf("failed to start execution: global rate limit exceeded") logCustMsg(ctx, e.cma.With(platform.KeyCapabilityID, te.ID), "failed to start execution: global rate limit exceeded", e.logger) - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, executionID, platform.KeyTriggerID, te.ID, platform.KeyWorkflowOwner, e.workflow.owner).incrementWorkflowExecutionRateLimitGlobalCounter(ctx) + e.metrics.with(platform.KeyTriggerID, te.ID).incrementWorkflowExecutionRateLimitGlobalCounter(ctx) continue } @@ -830,9 +830,9 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { if err := rpt.SetStep(MeteringReportStepRef(stepState.Ref), meteringSteps); err != nil { l.Error(fmt.Sprintf("failed to set metering report step for ref %s: %s", stepState.Ref, err)) } - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, msg.state.ExecutionID).incrementWorkflowMissingMeteringReport(ctx) + e.metrics.with(platform.KeyWorkflowID, e.workflow.id).incrementWorkflowMissingMeteringReport(ctx) } else { - e.metrics.with(platform.KeyWorkflowID, e.workflow.id, platform.KeyWorkflowExecutionID, msg.state.ExecutionID).incrementWorkflowMissingMeteringReport(ctx) + e.metrics.with(platform.KeyWorkflowID, e.workflow.id).incrementWorkflowMissingMeteringReport(ctx) // TODO: to be bumped to error if all capabilities must implement metering l.Warnf("no metering report found for %v", msg.state.ExecutionID) } diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index 04b602a5531..64f6ffa0318 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -672,16 +672,18 @@ func (w *workflowRegistry) syncUsingReconciliationStrategy(ctx context.Context, w.lggr.Debug("shutting down readRegistryStateLoop") return case <-ticker: - workflowMetadata, _, err := w.getWorkflowMetadata(ctx, don, reader) + workflowMetadata, head, err := w.getWorkflowMetadata(ctx, don, reader) if err != nil { w.lggr.Errorw("failed to get registry state", "err", err) continue } + w.lggr.Debugw("preparing events to reconcile", "numWorkflowMetadata", len(workflowMetadata), "blockHeight", head.Height, "numPendingEvents", len(pendingEvents)) events, err := w.generateReconciliationEvents(ctx, pendingEvents, workflowMetadata, don.ID) if err != nil { w.lggr.Errorw("failed to generate reconciliation events", "err", err) continue } + w.lggr.Debugw("generated events to reconcile", "num", len(events)) pendingEvents = map[string]*reconciliationEvent{} @@ -715,7 +717,7 @@ func (w *workflowRegistry) syncUsingReconciliationStrategy(ctx context.Context, } } - w.lggr.Debugw("generated events to reconcile", "num", len(events), "report", reconcileReport) + w.lggr.Debugw("reconciled events", "report", reconcileReport) } } } diff --git a/core/services/workflows/test/wasm/v2/cmd/main.go b/core/services/workflows/test/wasm/v2/cmd/main.go new file mode 100644 index 00000000000..6905e7c5519 --- /dev/null +++ b/core/services/workflows/test/wasm/v2/cmd/main.go @@ -0,0 +1,12 @@ +//go:build wasip1 + +package main + +import ( + testhelpers "github.com/smartcontractkit/chainlink-common/pkg/workflows/testhelpers/v2" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/v2" +) + +func main() { + testhelpers.RunTestWorkflow(wasm.NewDonRunner()) +} diff --git a/core/services/workflows/v2/config.go b/core/services/workflows/v2/config.go index 13b99f72182..95da444b1df 100644 --- a/core/services/workflows/v2/config.go +++ b/core/services/workflows/v2/config.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" + wasmpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/v2/pb" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/ratelimiter" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" @@ -71,7 +72,12 @@ type LifecycleHooks struct { OnInitialized func(err error) OnSubscribedToTriggers func(triggerIDs []string) OnExecutionFinished func(executionID string) - OnRateLimited func(executionID string) + + // TODO(CAPPL-736): handle execution result. + // OnResultReceived exposes the execution result for now. By default, if + // unspecified, it is a no-op and the result is logged. + OnResultReceived func(*wasmpb.ExecutionResult) + OnRateLimited func(executionID string) } func (c *EngineConfig) Validate() error { @@ -159,6 +165,9 @@ func (h *LifecycleHooks) setDefaultHooks() { if h.OnSubscribedToTriggers == nil { h.OnSubscribedToTriggers = func(triggerIDs []string) {} } + if h.OnResultReceived == nil { + h.OnResultReceived = func(res *wasmpb.ExecutionResult) {} + } if h.OnExecutionFinished == nil { h.OnExecutionFinished = func(executionID string) {} } diff --git a/core/services/workflows/v2/engine.go b/core/services/workflows/v2/engine.go index 1ef5773a45f..c36fbb31743 100644 --- a/core/services/workflows/v2/engine.go +++ b/core/services/workflows/v2/engine.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" - cappb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" sdkpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/v2/pb" "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" wasmpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/v2/pb" @@ -288,12 +287,15 @@ func (e *Engine) startExecution(ctx context.Context, wrappedTriggerEvent enqueue // TODO(CAPPL-736): observability return } + // TODO(CAPPL-736): handle execution result e.cfg.Lggr.Debugw("Workflow execution finished", "executionID", executionID, "result", result) + e.cfg.Hooks.OnResultReceived(result) e.cfg.Hooks.OnExecutionFinished(executionID) } -func (e *Engine) CallCapability(ctx context.Context, request *cappb.CapabilityRequest) (*cappb.CapabilityResponse, error) { +// CallCapability handles requests generated by the wasm guest +func (e *Engine) CallCapability(ctx context.Context, request *sdkpb.CapabilityRequest) (*sdkpb.CapabilityResponse, error) { select { case e.capCallsSemaphore <- struct{}{}: // block if too many concurrent capability calls case <-ctx.Done(): @@ -302,14 +304,18 @@ func (e *Engine) CallCapability(ctx context.Context, request *cappb.CapabilityRe defer func() { <-e.capCallsSemaphore }() // TODO (CAPPL-735): use request.Metadata.WorkflowExecutionId to associate the call with a specific execution - capability, err := e.cfg.CapRegistry.GetExecutable(ctx, request.CapabilityId) + capability, err := e.cfg.CapRegistry.GetExecutable(ctx, request.Id) if err != nil { return nil, fmt.Errorf("trigger capability not found: %w", err) } - capReq, err := cappb.CapabilityRequestFromProto(request) - if err != nil { - return nil, fmt.Errorf("failed to convert capability request: %w", err) + capReq := capabilities.CapabilityRequest{ + Payload: request.Payload, + Method: request.Method, + CapabilityId: request.Id, + Metadata: capabilities.RequestMetadata{ + WorkflowExecutionID: request.ExecutionId, + }, } // TODO(CAPPL-737): run with a timeout @@ -317,7 +323,11 @@ func (e *Engine) CallCapability(ctx context.Context, request *cappb.CapabilityRe if err != nil { return nil, fmt.Errorf("failed to execute capability: %w", err) } - return cappb.CapabilityResponseToProto(capResp), nil + return &sdkpb.CapabilityResponse{ + Response: &sdkpb.CapabilityResponse_Payload{ + Payload: capResp.Payload, + }, + }, nil } func (e *Engine) close() error { diff --git a/core/services/workflows/v2/engine_test.go b/core/services/workflows/v2/engine_test.go index 2f16ea755c5..6f29668fa65 100644 --- a/core/services/workflows/v2/engine_test.go +++ b/core/services/workflows/v2/engine_test.go @@ -1,19 +1,30 @@ package v2_test import ( + "context" "errors" "fmt" + "sync" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basicaction" + basicactionmock "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basicaction/basic_actionmock" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basictrigger" + basictriggermock "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/protoc/pkg/test_capabilities/basictrigger/basic_triggermock" regmocks "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" + "github.com/smartcontractkit/chainlink-common/pkg/values" sdkpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/v2/pb" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/sdk/v2/testutils" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" modulemocks "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host/mocks" wasmpb "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/v2/pb" capmocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncerlimiter" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/types" @@ -263,16 +274,150 @@ func TestEngine_Execution(t *testing.T) { require.NoError(t, <-initDoneCh) // successful trigger registration require.Equal(t, []string{"id_0"}, <-subscribedToTriggersCh) - module.EXPECT().Execute(matches.AnyContext, mock.Anything).Return(nil, nil).Once() + mockTriggerEvent := capabilities.TriggerEvent{ + TriggerType: "basic-trigger@1.0.0", + ID: "event_012345", + Payload: nil, + } + + module.EXPECT().Execute(matches.AnyContext, mock.Anything). + Run( + func(_ context.Context, request *wasmpb.ExecuteRequest) { + wantExecID, err := types.GenerateExecutionID(cfg.WorkflowID, mockTriggerEvent.ID) + require.NoError(t, err) + require.Equal(t, wantExecID, request.Id) + require.Equal(t, uint64(0), request.Request.(*wasmpb.ExecuteRequest_Trigger).Trigger.Id) + }, + ). + Return(nil, nil). + Once() + eventCh <- capabilities.TriggerResponse{ - Event: capabilities.TriggerEvent{ - TriggerType: "basic-trigger@1.0.0", - ID: "event_012345", - Payload: nil, - }, + Event: mockTriggerEvent, } <-executionFinishedCh require.NoError(t, engine.Close()) }) } + +func TestEngine_MockCapabilityRegistry_NoDAGBinary(t *testing.T) { + cmd := "core/services/workflows/test/wasm/v2/cmd" + log := logger.TestLogger(t) + binaryB := wasmtest.CreateTestBinary(cmd, false, t) + module, err := host.NewModule(&host.ModuleConfig{ + Logger: log, + IsUncompressed: true, + }, binaryB) + require.NoError(t, err) + + capreg := regmocks.NewCapabilitiesRegistry(t) + + cfg := defaultTestConfig(t) + cfg.Module = module + cfg.CapRegistry = capreg + initDoneCh := make(chan error, 1) + subscribedToTriggersCh := make(chan []string, 1) + resultReceivedCh := make(chan *wasmpb.ExecutionResult, 1) + executionFinishedCh := make(chan string, 1) + cfg.Hooks = v2.LifecycleHooks{ + OnInitialized: func(err error) { + initDoneCh <- err + }, + OnSubscribedToTriggers: func(triggerIDs []string) { + subscribedToTriggersCh <- triggerIDs + }, + OnExecutionFinished: func(executionID string) { + executionFinishedCh <- executionID + }, + OnResultReceived: func(er *wasmpb.ExecutionResult) { + resultReceivedCh <- er + }, + } + + triggerMock, basicActionMock := setupExpectedCalls(t) + wrappedTriggerMock := &testutils.CapabilityWrapper{ + Capability: triggerMock, + } + wrappedActionMock := &testutils.CapabilityWrapper{ + Capability: basicActionMock, + } + + t.Run("OK happy path", func(t *testing.T) { + wantResponse := "Hello, world!" + engine, err := v2.NewEngine(t.Context(), cfg) + require.NoError(t, err) + + capreg.EXPECT(). + LocalNode(matches.AnyContext). + Return(capabilities.Node{}, nil). + Once() + + capreg.EXPECT(). + GetTrigger(matches.AnyContext, wrappedTriggerMock.ID()). + Return(wrappedTriggerMock, nil). + Once() + + capreg.EXPECT(). + GetExecutable(matches.AnyContext, wrappedActionMock.ID()). + Return(wrappedActionMock, nil). + Twice() + + require.NoError(t, engine.Start(t.Context())) + require.NoError(t, <-initDoneCh) + require.Equal(t, []string{wrappedTriggerMock.ID()}, <-subscribedToTriggersCh) + + // Read the result from the hook and assert that the wanted response was + // received. + res := <-resultReceivedCh + switch output := res.Result.(type) { + case *wasmpb.ExecutionResult_Value: + var value values.Value + var execErr error + var unwrapped any + + valuePb := output.Value + value, execErr = values.FromProto(valuePb) + require.NoError(t, execErr) + unwrapped, execErr = value.Unwrap() + require.NoError(t, execErr) + require.Equal(t, wantResponse, unwrapped) + default: + t.Fatalf("unexpected response type %T", output) + } + + execID, err := types.GenerateExecutionID(cfg.WorkflowID, "") + require.NoError(t, err) + + require.Equal(t, execID, <-executionFinishedCh) + require.NoError(t, engine.Close()) + }) +} + +// setupExpectedCalls mocks single call to trigger and two calls to the basic action +// mock capability +func setupExpectedCalls(t *testing.T) ( + *basictriggermock.BasicCapability, + *basicactionmock.BasicActionCapability, +) { + triggerMock := &basictriggermock.BasicCapability{} + triggerMock.Trigger = func(ctx context.Context, input *basictrigger.Config) (*basictrigger.Outputs, error) { + return &basictrigger.Outputs{CoolOutput: "Hello, "}, nil + } + + basicAction := &basicactionmock.BasicActionCapability{} + + firstCall := true + callLock := &sync.Mutex{} + basicAction.PerformAction = func(ctx context.Context, input *basicaction.Inputs) (*basicaction.Outputs, error) { + callLock.Lock() + defer callLock.Unlock() + assert.NotEqual(t, firstCall, input.InputThing, "failed first call assertion") + firstCall = false + if input.InputThing { + return &basicaction.Outputs{AdaptedThing: "!"}, nil + } + return &basicaction.Outputs{AdaptedThing: "world"}, nil + } + return triggerMock, basicAction +} diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index 9e8e7621d63..66f68a57347 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink-evm/pkg/gas" txmgrtypes "github.com/smartcontractkit/chainlink-framework/chains/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -26,18 +27,18 @@ func TestTransactionsController_Index_Success(t *testing.T) { require.NoError(t, app.Start(ctx)) db := app.GetDB() - txStore := cltest.NewTestTxStore(t, app.GetDB()) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) ethKeyStore := cltest.NewKeyStore(t, db).Eth() client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // tx1 - tx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 2, from) // tx2 - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 4, from) // tx3 + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) // tx1 + tx2 := txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 2, from) // tx2 + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 4, from) // tx3 // add second tx attempt for tx2 blockNum := int64(3) - attempt := cltest.NewLegacyEthTxAttempt(t, tx2.ID) + attempt := txmgrtest.NewLegacyEthTxAttempt(t, tx2.ID) attempt.State = txmgrtypes.TxAttemptBroadcast attempt.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(3)} attempt.BroadcastBeforeBlockNum = &blockNum @@ -84,11 +85,11 @@ func TestTransactionsController_Show_Success(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetDB()) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - tx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) + tx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) require.Len(t, tx.TxAttempts, 1) attempt := tx.TxAttempts[0] attempt.Tx = tx @@ -118,10 +119,10 @@ func TestTransactionsController_Show_NotFound(t *testing.T) { ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) - txStore := cltest.NewTestTxStore(t, app.GetDB()) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - tx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) + tx := txmgrtest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, from) require.Len(t, tx.TxAttempts, 1) attempt := tx.TxAttempts[0] diff --git a/core/web/evm_tx_attempts_controller_test.go b/core/web/evm_tx_attempts_controller_test.go index f277f1f37bf..ecab56194df 100644 --- a/core/web/evm_tx_attempts_controller_test.go +++ b/core/web/evm_tx_attempts_controller_test.go @@ -4,6 +4,7 @@ import ( "net/http" "testing" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/txmgrtest" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -20,14 +21,14 @@ func TestTxAttemptsController_Index_Success(t *testing.T) { app := cltest.NewApplicationWithKey(t) require.NoError(t, app.Start(testutils.Context(t))) - txStore := cltest.NewTestTxStore(t, app.GetDB()) + txStore := txmgrtest.NewTestTxStore(t, app.GetDB()) client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, from) - cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 3, from) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 2, from) + txmgrtest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 3, from) resp, cleanup := client.Get("/v2/tx_attempts?size=2") t.Cleanup(cleanup) diff --git a/deployment/ccip/changeset/aptos/config/deploy_chain.go b/deployment/ccip/changeset/aptos/config/deploy_chain.go index c59470ad260..237de8fb7fa 100644 --- a/deployment/ccip/changeset/aptos/config/deploy_chain.go +++ b/deployment/ccip/changeset/aptos/config/deploy_chain.go @@ -4,7 +4,8 @@ import ( "fmt" "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -18,7 +19,7 @@ type DeployAptosChainConfig struct { func (c DeployAptosChainConfig) Validate() error { for cs, args := range c.ContractParamsPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } if err := args.Validate(); err != nil { @@ -79,7 +80,7 @@ type OffRampParams struct { } func (o OffRampParams) Validate() error { - if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } if o.PermissionlessExecutionThreshold == 0 { @@ -98,7 +99,7 @@ type OnRampParams struct { } func (o OnRampParams) Validate() error { - if err := deployment.IsValidChainSelector(o.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(o.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", o.ChainSelector, err) } if o.AllowlistAdmin == (aptos.AccountAddress{}) { diff --git a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go index e14424d9559..28d9a017ce0 100644 --- a/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go +++ b/deployment/ccip/changeset/aptos/cs_deploy_aptos_chain.go @@ -11,11 +11,12 @@ import ( mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) var _ cldf.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} @@ -23,9 +24,9 @@ var _ cldf.ChangeSetV2[config.DeployAptosChainConfig] = DeployAptosChain{} // DeployAptosChain deploys Aptos chain packages and modules type DeployAptosChain struct{} -func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, config config.DeployAptosChainConfig) error { +func (cs DeployAptosChain) VerifyPreconditions(env cldf.Environment, config config.DeployAptosChainConfig) error { // Validate env and prerequisite contracts - state, err := changeset.LoadOnchainStateAptos(env) + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return fmt.Errorf("failed to load existing Aptos onchain state: %w", err) } @@ -56,8 +57,8 @@ func (cs DeployAptosChain) VerifyPreconditions(env deployment.Environment, confi return errors.Join(errs...) } -func (cs DeployAptosChain) Apply(env deployment.Environment, config config.DeployAptosChainConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainStateAptos(env) +func (cs DeployAptosChain) Apply(env cldf.Environment, config config.DeployAptosChainConfig) (cldf.ChangesetOutput, error) { + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } @@ -87,7 +88,7 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo mcmsOperations = append(mcmsOperations, mcmsSeqReport.Output.MCMSOperation) // Save MCMS address - typeAndVersion := cldf.NewTypeAndVersion(changeset.AptosMCMSType, deployment.Version1_6_0) + typeAndVersion := cldf.NewTypeAndVersion(shared.AptosMCMSType, deployment.Version1_6_0) deps.AB.Save(deps.AptosChain.Selector, mcmsSeqReport.Output.MCMSAddress.String(), typeAndVersion) // CCIP Deploy operations @@ -103,7 +104,7 @@ func (cs DeployAptosChain) Apply(env deployment.Environment, config config.Deplo mcmsOperations = append(mcmsOperations, ccipSeqReport.Output.MCMSOperations...) // Save the address of the CCIP object - typeAndVersion = cldf.NewTypeAndVersion(changeset.AptosCCIPType, deployment.Version1_6_0) + typeAndVersion = cldf.NewTypeAndVersion(shared.AptosCCIPType, deployment.Version1_6_0) deps.AB.Save(deps.AptosChain.Selector, ccipSeqReport.Output.CCIPAddress.String(), typeAndVersion) // Generate MCMS proposals diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go index edf99076c3d..570991668fc 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp.go @@ -9,12 +9,12 @@ import ( "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) var _ cldf.ChangeSetV2[v1_6.SetOCR3OffRampConfig] = SetOCR3Offramp{} @@ -22,7 +22,7 @@ var _ cldf.ChangeSetV2[v1_6.SetOCR3OffRampConfig] = SetOCR3Offramp{} // SetOCR3Offramp updates OCR3 Offramp configurations type SetOCR3Offramp struct{} -func (cs SetOCR3Offramp) VerifyPreconditions(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) error { +func (cs SetOCR3Offramp) VerifyPreconditions(env cldf.Environment, config v1_6.SetOCR3OffRampConfig) error { for _, remoteSel := range config.RemoteChainSels { chainFamily, _ := chain_selectors.GetSelectorFamily(remoteSel) if chainFamily != chain_selectors.FamilyAptos { @@ -32,20 +32,24 @@ func (cs SetOCR3Offramp) VerifyPreconditions(env deployment.Environment, config return nil } -func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { +func (cs SetOCR3Offramp) Apply(env cldf.Environment, config v1_6.SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { seqReports := make([]operations.Report[any, any], 0) timeLockProposals := []mcms.TimelockProposal{} - state, err := changeset.LoadOnchainState(env) + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } + ccipState, err := stateview.LoadOnchainState(env) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load EVM onchain state: %w", err) + } for _, remoteSelector := range config.RemoteChainSels { deps := operation.AptosDeps{ AptosChain: env.AptosChains[remoteSelector], - OnChainState: state.AptosChains[remoteSelector], - CCIPOnChainState: state, + OnChainState: state[remoteSelector], + CCIPOnChainState: ccipState, } in := seq.SetOCR3OfframpSeqInput{ HomeChainSelector: config.HomeChainSel, @@ -60,7 +64,7 @@ func (cs SetOCR3Offramp) Apply(env deployment.Environment, config v1_6.SetOCR3Of // Generate MCMS proposals proposal, err := utils.GenerateProposal( deps.AptosChain.Client, - state.AptosChains[remoteSelector].MCMSAddress, + state[remoteSelector].MCMSAddress, deps.AptosChain.Selector, []types.BatchOperation{setOCR3SeqReport.Output}, "Set OCR3 Configs", diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go index 1287572f6fd..7ecb1bb6272 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_ccip.go @@ -8,12 +8,12 @@ import ( "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) var _ cldf.ChangeSetV2[config.UpdateAptosChainConfig] = UpdateAptosChain{} @@ -21,25 +21,29 @@ var _ cldf.ChangeSetV2[config.UpdateAptosChainConfig] = UpdateAptosChain{} // DeployAptosChain deploys Aptos chain packages and modules type UpdateAptosChain struct{} -func (cs UpdateAptosChain) VerifyPreconditions(env deployment.Environment, config config.UpdateAptosChainConfig) error { +func (cs UpdateAptosChain) VerifyPreconditions(env cldf.Environment, config config.UpdateAptosChainConfig) error { // TODO validate if required packages and modules are already deployed return nil } -func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAptosChainConfig) (cldf.ChangesetOutput, error) { +func (cs UpdateAptosChain) Apply(env cldf.Environment, cfg config.UpdateAptosChainConfig) (cldf.ChangesetOutput, error) { timeLockProposals := []mcms.TimelockProposal{} mcmsOperations := []types.BatchOperation{} seqReports := make([]operations.Report[any, any], 0) - state, err := changeset.LoadOnchainState(env) + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } + ccipState, err := stateview.LoadOnchainState(env) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load EVM onchain state: %w", err) + } deps := operation.AptosDeps{ AptosChain: env.AptosChains[cfg.ChainSelector], - OnChainState: state.AptosChains[cfg.ChainSelector], - CCIPOnChainState: state, + OnChainState: state[cfg.ChainSelector], + CCIPOnChainState: ccipState, } // Execute the sequence @@ -53,7 +57,7 @@ func (cs UpdateAptosChain) Apply(env deployment.Environment, cfg config.UpdateAp // Generate MCMS proposals proposal, err := utils.GenerateProposal( deps.AptosChain.Client, - state.AptosChains[cfg.ChainSelector].MCMSAddress, + state[cfg.ChainSelector].MCMSAddress, deps.AptosChain.Selector, mcmsOperations, "Update chain contracts on Aptos chain", diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go index a6997892c07..53140fc7210 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes.go @@ -8,13 +8,13 @@ import ( "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" seq "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/sequence" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/utils" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) var _ cldf.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} @@ -22,7 +22,7 @@ var _ cldf.ChangeSetV2[config.UpdateAptosLanesConfig] = AddAptosLanes{} // AddAptosLane implements adding a new lane to an existing Aptos CCIP deployment type AddAptosLanes struct{} -func (cs AddAptosLanes) VerifyPreconditions(env deployment.Environment, cfg config.UpdateAptosLanesConfig) error { +func (cs AddAptosLanes) VerifyPreconditions(env cldf.Environment, cfg config.UpdateAptosLanesConfig) error { // TODO: Implement verification logic - check chain selector validity, MCMS configuration, etc. // Placeholder implementation to show expected structure @@ -36,7 +36,7 @@ func (cs AddAptosLanes) VerifyPreconditions(env deployment.Environment, cfg conf return nil } -func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptosLanesConfig) (cldf.ChangesetOutput, error) { +func (cs AddAptosLanes) Apply(env cldf.Environment, cfg config.UpdateAptosLanesConfig) (cldf.ChangesetOutput, error) { timeLockProposals := []mcms.TimelockProposal{} mcmsOperations := []types.BatchOperation{} seqReports := make([]operations.Report[any, any], 0) @@ -52,17 +52,21 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos // Add lane on Aptos chains // Execute UpdateAptosLanesSequence for each aptos chain - state, err := changeset.LoadOnchainState(env) + state, err := aptosstate.LoadOnchainStateAptos(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load Aptos onchain state: %w", err) } + ccipState, err := stateview.LoadOnchainState(env) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to load EVM onchain state: %w", err) + } - updateInputsByAptosChain := seq.ConvertToUpdateAptosLanesSeqInput(state.AptosChains, cfg) + updateInputsByAptosChain := seq.ConvertToUpdateAptosLanesSeqInput(state, cfg) for aptosChainSel, sequenceInput := range updateInputsByAptosChain { deps := operation.AptosDeps{ AptosChain: env.AptosChains[aptosChainSel], - OnChainState: state.AptosChains[aptosChainSel], - CCIPOnChainState: state, + OnChainState: state[aptosChainSel], + CCIPOnChainState: ccipState, } // Execute the sequence updateSeqReport, err := operations.ExecuteSequence(env.OperationsBundle, seq.UpdateAptosLanesSequence, deps, sequenceInput) @@ -75,7 +79,7 @@ func (cs AddAptosLanes) Apply(env deployment.Environment, cfg config.UpdateAptos // Generate MCMS proposals proposal, err := utils.GenerateProposal( deps.AptosChain.Client, - state.AptosChains[aptosChainSel].MCMSAddress, + state[aptosChainSel].MCMSAddress, deps.AptosChain.Selector, mcmsOperations, "Update lanes on Aptos chain", diff --git a/deployment/ccip/changeset/aptos/operation/dependencies.go b/deployment/ccip/changeset/aptos/operation/dependencies.go index ca95dc64646..5f4c6bb4f81 100644 --- a/deployment/ccip/changeset/aptos/operation/dependencies.go +++ b/deployment/ccip/changeset/aptos/operation/dependencies.go @@ -3,14 +3,14 @@ package operation import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) type AptosDeps struct { AB *cldf.AddressBookMap - AptosChain deployment.AptosChain + AptosChain cldf.AptosChain // TODO: Refactor this? - OnChainState changeset.AptosCCIPChainState - CCIPOnChainState changeset.CCIPOnChainState + OnChainState aptosstate.CCIPChainState + CCIPOnChainState stateview.CCIPOnChainState } diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 30d59a8c9c6..9cad5a2b3e2 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -9,10 +9,12 @@ import ( aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" aptos_router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router/router" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - config "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/operation" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" + "github.com/smartcontractkit/mcms/types" ) @@ -91,7 +93,7 @@ func updateAptosLanesSequence(b operations.Bundle, deps operation.AptosDeps, in } // Convert config.UpdateAptosLanesConfig into a map[uint64]UpdateAptosLanesSeqInput -func ConvertToUpdateAptosLanesSeqInput(aptosChains map[uint64]changeset.AptosCCIPChainState, cfg config.UpdateAptosLanesConfig) map[uint64]UpdateAptosLanesSeqInput { +func ConvertToUpdateAptosLanesSeqInput(aptosChains map[uint64]aptosstate.CCIPChainState, cfg config.UpdateAptosLanesConfig) map[uint64]UpdateAptosLanesSeqInput { updateInputsByAptosChain := make(map[uint64]UpdateAptosLanesSeqInput) // Group the operations by Aptos chain diff --git a/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane.go b/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane.go index 46bd74bb2de..dd6c388a1af 100644 --- a/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane.go +++ b/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane.go @@ -13,10 +13,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - "github.com/smartcontractkit/chainlink/deployment" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -31,7 +30,7 @@ var ( func(b operations.Bundle, deps Dependencies, input postOpsInput) ([]mcmslib.TimelockProposal, error) { allProposals := input.Proposals proposal, err := proposalutils.AggregateProposals( - deps.Env, deps.EVMMCMSState, deps.SolanaMCMSState, allProposals, nil, + deps.Env, deps.EVMMCMSState, deps.SolanaMCMSState, allProposals, "Adding EVM and Solana lane", input.MCMSConfig) if err != nil { return nil, err @@ -227,7 +226,7 @@ var ( ) type Dependencies struct { - Env deployment.Environment + Env cldf.Environment EVMMCMSState map[uint64]commonstate.MCMSWithTimelockState SolanaMCMSState map[uint64]commonstate.MCMSWithTimelockStateSolana @@ -254,22 +253,22 @@ type csInputs struct { type AddRemoteChainE2EConfig struct { // inputs to be filled by user - SolanaChainSelector uint64 - EVMChainSelector uint64 - IsTestRouter bool - EVMOnRampAllowListEnabled bool - EVMFeeQuoterDestChainInput fee_quoter.FeeQuoterDestChainConfig - InitialSolanaGasPriceForEVMFeeQuoter *big.Int - InitialEVMTokenPricesForEVMFeeQuoter map[common.Address]*big.Int - IsRMNVerificationEnabledOnEVMOffRamp bool - SolanaRouterConfig solana.RouterConfig - SolanaOffRampConfig solana.OffRampConfig - SolanaFeeQuoterConfig solana.FeeQuoterConfig + SolanaChainSelector uint64 + EVMChainSelector uint64 + IsTestRouter bool + EVMOnRampAllowListEnabled bool + EVMFeeQuoterDestChainInput fee_quoter.FeeQuoterDestChainConfig + InitialSolanaGasPriceForEVMFeeQuoter *big.Int + InitialEVMTokenPricesForEVMFeeQuoter map[common.Address]*big.Int + IsRMNVerificationDisabledOnEVMOffRamp bool + SolanaRouterConfig solana.RouterConfig + SolanaOffRampConfig solana.OffRampConfig + SolanaFeeQuoterConfig solana.FeeQuoterConfig MCMSConfig *proposalutils.TimelockConfig } -func (cfg *AddRemoteChainE2EConfig) populateAndValidateIndividualCSConfig(env deployment.Environment, evmState ccipchangeset.CCIPOnChainState) (csInputs, error) { +func (cfg *AddRemoteChainE2EConfig) populateAndValidateIndividualCSConfig(env cldf.Environment, evmState stateview.CCIPOnChainState) (csInputs, error) { var timelockConfig *proposalutils.TimelockConfig if cfg.MCMSConfig != nil { timelockConfig = cfg.MCMSConfig @@ -313,7 +312,7 @@ func (cfg *AddRemoteChainE2EConfig) populateAndValidateIndividualCSConfig(env de cfg.SolanaChainSelector: { IsEnabled: true, TestRouter: cfg.IsTestRouter, - IsRMNVerificationDisabled: cfg.IsRMNVerificationEnabledOnEVMOffRamp, + IsRMNVerificationDisabled: cfg.IsRMNVerificationDisabledOnEVMOffRamp, }, }, }, @@ -380,8 +379,8 @@ func (cfg *AddRemoteChainE2EConfig) populateAndValidateIndividualCSConfig(env de return input, nil } -func addEVMSolanaPreconditions(env deployment.Environment, input AddRemoteChainE2EConfig) error { - evmState, err := ccipchangeset.LoadOnchainState(env) +func addEVMSolanaPreconditions(env cldf.Environment, input AddRemoteChainE2EConfig) error { + evmState, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain evm state: %w", err) } @@ -390,13 +389,13 @@ func addEVMSolanaPreconditions(env deployment.Environment, input AddRemoteChainE timelockConfig = input.MCMSConfig } // Verify evm Chain - if err := ccipchangeset.ValidateChain(env, evmState, input.EVMChainSelector, timelockConfig); err != nil { + if err := stateview.ValidateChain(env, evmState, input.EVMChainSelector, timelockConfig); err != nil { return fmt.Errorf("failed to validate EVM chain %d: %w", input.EVMChainSelector, err) } if _, ok := env.SolChains[input.SolanaChainSelector]; !ok { return fmt.Errorf("failed to find Solana chain in env %d", input.SolanaChainSelector) } - solanaState, err := ccipchangeset.LoadOnchainStateSolana(env) + solanaState, err := stateview.LoadOnchainStateSolana(env) if err != nil { return fmt.Errorf("failed to load onchain solana state: %w", err) } @@ -406,8 +405,8 @@ func addEVMSolanaPreconditions(env deployment.Environment, input AddRemoteChainE return nil } -func addEVMAndSolanaLaneLogic(env deployment.Environment, input AddRemoteChainE2EConfig) (cldf.ChangesetOutput, error) { - evmState, err := ccipchangeset.LoadOnchainState(env) +func addEVMAndSolanaLaneLogic(env cldf.Environment, input AddRemoteChainE2EConfig) (cldf.ChangesetOutput, error) { + evmState, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load evm onchain state: %w", err) } diff --git a/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane_test.go b/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane_test.go index e92f5ac5187..5b1a9e6cf46 100644 --- a/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane_test.go +++ b/deployment/ccip/changeset/crossfamily/v1_6/cs_add_evm_solana_lane_test.go @@ -16,11 +16,13 @@ import ( solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + crossfamily "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/crossfamily/v1_6" ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -40,6 +42,12 @@ func TestAddEVMSolanaLaneBidirectional(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { + if t.Name() == "TestAddEVMSolanaLaneBidirectional/MCMS_enabled" { + tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-758") + } + if t.Name() == "TestAddEVMSolanaLaneBidirectional/MCMS_disabled" { + tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-759") + } t.Parallel() ctx := testcontext.Get(t) tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) @@ -50,7 +58,7 @@ func TestAddEVMSolanaLaneBidirectional(t *testing.T) { require.NotEmpty(t, evmChains) solChain := solChains[0] evmChain := evmChains[0] - evmState, err := ccipchangeset.LoadOnchainState(e) + evmState, err := stateview.LoadOnchainState(e) require.NoError(t, err) var mcmsConfig *proposalutils.TimelockConfig if tc.mcmsEnabled { @@ -91,7 +99,7 @@ func TestAddEVMSolanaLaneBidirectional(t *testing.T) { evmChainState.LinkToken.Address(): testhelpers.DefaultLinkPrice, evmChainState.Weth9.Address(): testhelpers.DefaultWethPrice, }, - IsRMNVerificationEnabledOnEVMOffRamp: true, + IsRMNVerificationDisabledOnEVMOffRamp: true, SolanaRouterConfig: ccipChangesetSolana.RouterConfig{ RouterDestinationConfig: solRouter.DestChainConfig{ AllowListEnabled: true, @@ -114,10 +122,10 @@ func TestAddEVMSolanaLaneBidirectional(t *testing.T) { require.NoError(t, err) // Check that the changeset was applied - evmState, err = ccipchangeset.LoadOnchainState(e) + evmState, err = stateview.LoadOnchainState(e) require.NoError(t, err) - solanaState, err := ccipchangeset.LoadOnchainStateSolana(e) + solanaState, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) // evm changes diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go index 1d6254e5d1d..5894c79f5a3 100644 --- a/deployment/ccip/changeset/cs_prerequisites.go +++ b/deployment/ccip/changeset/cs_prerequisites.go @@ -32,6 +32,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) var ( @@ -42,7 +44,7 @@ var ( // pre-requisite contracts are the contracts which can be reused from previous versions of CCIP // Or the contracts which are already deployed on the chain ( for example, tokens, feeds, etc) // Caller should update the environment's address book with the returned addresses. -func DeployPrerequisitesChangeset(env deployment.Environment, cfg DeployPrerequisiteConfig) (cldf.ChangesetOutput, error) { +func DeployPrerequisitesChangeset(env cldf.Environment, cfg DeployPrerequisiteConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return cldf.ChangesetOutput{}, errors.Wrapf(cldf.ErrInvalidConfig, "%v", err) @@ -86,7 +88,7 @@ func (c DeployPrerequisiteConfig) Validate() error { for _, cfg := range c.Configs { cs := cfg.ChainSelector mapAllChainSelectors[cs] = struct{}{} - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -123,8 +125,8 @@ func WithLegacyDeploymentEnabled(cfg V1_5DeploymentConfig) PrerequisiteOpt { } } -func deployPrerequisiteChainContracts(e deployment.Environment, ab cldf.AddressBook, cfg DeployPrerequisiteConfig) error { - state, err := LoadOnchainState(e) +func deployPrerequisiteChainContracts(e cldf.Environment, ab cldf.AddressBook, cfg DeployPrerequisiteConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err") return err @@ -146,7 +148,7 @@ func deployPrerequisiteChainContracts(e deployment.Environment, ab cldf.AddressB // deployPrerequisiteContracts deploys the contracts that can be ported from previous CCIP version to the new one. // This is only required for staging and test environments where the contracts are not already deployed. -func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, state CCIPOnChainState, chain deployment.Chain, opts ...PrerequisiteOpt) error { +func deployPrerequisiteContracts(e cldf.Environment, ab cldf.AddressBook, state stateview.CCIPOnChainState, chain cldf.Chain, opts ...PrerequisiteOpt) error { deployOpts := &DeployPrerequisiteContractsOpts{} for _, opt := range opts { if opt != nil { @@ -182,18 +184,18 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, // if RMN is not found in state and LegacyDeploymentCfg is provided, deploy RMN contract based on the config case deployOpts.LegacyDeploymentCfg != nil && deployOpts.LegacyDeploymentCfg.RMNConfig != nil: rmn, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*rmn_contract.RMNContract] { + func(chain cldf.Chain) cldf.ContractDeploy[*rmn_contract.RMNContract] { rmnAddress, tx2, rmnC, err2 := rmn_contract.DeployRMNContract( chain.DeployerKey, chain.Client, *deployOpts.LegacyDeploymentCfg.RMNConfig, ) return cldf.ContractDeploy[*rmn_contract.RMNContract]{ - Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: cldf.NewTypeAndVersion(RMN, deployment.Version1_5_0), Err: err2, + Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.RMN, deployment.Version1_5_0), Err: err2, } }) if err != nil { - lggr.Errorw("Failed to deploy RMN", "chain", chain.String(), "err", deployment.MaybeDataErr(err)) + lggr.Errorw("Failed to deploy RMN", "chain", chain.String(), "err", cldf.MaybeDataErr(err)) return err } rmnAddr = rmn.Address @@ -201,13 +203,13 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, // otherwise deploy the mock RMN contract if chainState.MockRMN == nil { rmn, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*mock_rmn_contract.MockRMNContract] { + func(chain cldf.Chain) cldf.ContractDeploy[*mock_rmn_contract.MockRMNContract] { rmnAddress, tx2, rmnC, err2 := mock_rmn_contract.DeployMockRMNContract( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ - Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: cldf.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), Err: err2, + Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.MockRMN, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -222,14 +224,14 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, } if rmnProxy == nil { RMNProxy, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy] { + func(chain cldf.Chain) cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy] { rmnProxyAddr, tx2, rmnProxy2, err2 := rmn_proxy_contract.DeployRMNProxy( chain.DeployerKey, chain.Client, rmnAddr, ) return cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy]{ - Address: rmnProxyAddr, Contract: rmnProxy2, Tx: tx2, Tv: cldf.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), Err: err2, + Address: rmnProxyAddr, Contract: rmnProxy2, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.ARMProxy, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -273,12 +275,12 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, } if tokenAdminReg == nil { tokenAdminRegistry, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( chain.DeployerKey, chain.Client) return cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: cldf.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), Err: err2, + Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.TokenAdminRegistry, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -299,13 +301,13 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, } if len(regAddresses) == 0 { customRegistryModule, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { + func(chain cldf.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( chain.DeployerKey, chain.Client, tokenAdminReg.Address()) return cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(RegistryModule, deployment.Version1_6_0), Err: err2, + Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.RegistryModule, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -341,13 +343,13 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, if weth9Contract == nil { weth, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*weth9.WETH9] { + func(chain cldf.Chain) cldf.ContractDeploy[*weth9.WETH9] { weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*weth9.WETH9]{ - Address: weth9Addr, Contract: weth9c, Tx: tx2, Tv: cldf.NewTypeAndVersion(WETH9, deployment.Version1_0_0), Err: err2, + Address: weth9Addr, Contract: weth9c, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.WETH9, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -363,7 +365,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, // if router is not already deployed, we deploy it if r == nil { routerContract, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*router.Router] { + func(chain cldf.Chain) cldf.ContractDeploy[*router.Router] { routerAddr, tx2, routerC, err2 := router.DeployRouter( chain.DeployerKey, chain.Client, @@ -371,7 +373,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, rmnProxy.Address(), ) return cldf.ContractDeploy[*router.Router]{ - Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(Router, deployment.Version1_2_0), Err: err2, + Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.Router, deployment.Version1_2_0), Err: err2, } }) if err != nil { @@ -386,7 +388,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, if deployOpts.TokenPoolFactoryEnabled { if tokenPoolFactory == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*token_pool_factory.TokenPoolFactory] { + func(chain cldf.Chain) cldf.ContractDeploy[*token_pool_factory.TokenPoolFactory] { tpfAddr, tx2, contract, err2 := token_pool_factory.DeployTokenPoolFactory( chain.DeployerKey, chain.Client, @@ -399,7 +401,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, r.Address(), ) return cldf.ContractDeploy[*token_pool_factory.TokenPoolFactory]{ - Address: tpfAddr, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(TokenPoolFactory, deployment.Version1_5_1), Err: err2, + Address: tpfAddr, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.TokenPoolFactory, deployment.Version1_5_1), Err: err2, } }, ) @@ -414,19 +416,19 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, // We deploy it here so that we can verify it. All subsequent user deployments would then be verified. if factoryBurnMintERC20 == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*factory_burn_mint_erc20.FactoryBurnMintERC20] { + func(chain cldf.Chain) cldf.ContractDeploy[*factory_burn_mint_erc20.FactoryBurnMintERC20] { factoryBurnMintERC20Addr, tx2, contract, err2 := factory_burn_mint_erc20.DeployFactoryBurnMintERC20( chain.DeployerKey, chain.Client, - string(FactoryBurnMintERC20Symbol), - string(FactoryBurnMintERC20Symbol), + string(shared.FactoryBurnMintERC20Symbol), + string(shared.FactoryBurnMintERC20Symbol), 18, big.NewInt(0), big.NewInt(0), chain.DeployerKey.From, ) return cldf.ContractDeploy[*factory_burn_mint_erc20.FactoryBurnMintERC20]{ - Address: factoryBurnMintERC20Addr, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(FactoryBurnMintERC20Token, deployment.Version1_0_0), Err: err2, + Address: factoryBurnMintERC20Addr, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.FactoryBurnMintERC20Token, deployment.Version1_0_0), Err: err2, } }, ) @@ -440,13 +442,13 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, } if deployOpts.Multicall3Enabled && mc3 == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*multicall3.Multicall3] { + func(chain cldf.Chain) cldf.ContractDeploy[*multicall3.Multicall3] { multicall3Addr, tx2, multicall3Wrapper, err2 := multicall3.DeployMulticall3( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*multicall3.Multicall3]{ - Address: multicall3Addr, Contract: multicall3Wrapper, Tx: tx2, Tv: cldf.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), Err: err2, + Address: multicall3Addr, Contract: multicall3Wrapper, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.Multicall3, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -473,14 +475,14 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, } if chainState.Receiver == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { + func(chain cldf.Chain) cldf.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( chain.DeployerKey, chain.Client, false, ) return cldf.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ - Address: receiverAddr, Contract: receiver, Tx: tx, Tv: cldf.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), Err: err2, + Address: receiverAddr, Contract: receiver, Tx: tx, Tv: cldf.NewTypeAndVersion(shared.CCIPReceiver, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -498,7 +500,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, return fmt.Errorf("failed to get link token address for chain %s: %w", chain.String(), err1) } _, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*price_registry_1_2_0.PriceRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*price_registry_1_2_0.PriceRegistry] { priceRegAddr, tx2, priceRegAddrC, err2 := price_registry_1_2_0.DeployPriceRegistry( chain.DeployerKey, chain.Client, @@ -508,7 +510,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, ) return cldf.ContractDeploy[*price_registry_1_2_0.PriceRegistry]{ Address: priceRegAddr, Contract: priceRegAddrC, Tx: tx2, - Tv: cldf.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0), Err: err2, + Tv: cldf.NewTypeAndVersion(shared.PriceRegistry, deployment.Version1_2_0), Err: err2, } }) if err != nil { @@ -524,7 +526,7 @@ func deployPrerequisiteContracts(e deployment.Environment, ab cldf.AddressBook, func deployUSDC( lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, addresses cldf.AddressBook, rmnProxy common.Address, router common.Address, @@ -536,20 +538,20 @@ func deployUSDC( error, ) { token, err := cldf.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, tokenContract, err2 := burn_mint_erc677.DeployBurnMintERC677( chain.DeployerKey, chain.Client, - USDCName, - string(USDCSymbol), - UsdcDecimals, + shared.USDCName, + string(shared.USDCSymbol), + shared.UsdcDecimals, big.NewInt(0), ) return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: tokenContract, Tx: tx, - Tv: cldf.NewTypeAndVersion(USDCToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.USDCToken, deployment.Version1_0_0), Err: err2, } }) @@ -569,7 +571,7 @@ func deployUSDC( } transmitter, err := cldf.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) cldf.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { + func(chain cldf.Chain) cldf.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { transmitterAddress, tx, transmitterContract, err2 := mock_usdc_token_transmitter.DeployMockE2EUSDCTransmitter( chain.DeployerKey, chain.Client, @@ -581,7 +583,7 @@ func deployUSDC( Address: transmitterAddress, Contract: transmitterContract, Tx: tx, - Tv: cldf.NewTypeAndVersion(USDCMockTransmitter, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.USDCMockTransmitter, deployment.Version1_0_0), Err: err2, } }) @@ -591,7 +593,7 @@ func deployUSDC( } messenger, err := cldf.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { + func(chain cldf.Chain) cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( chain.DeployerKey, chain.Client, @@ -602,7 +604,7 @@ func deployUSDC( Address: messengerAddress, Contract: messengerContract, Tx: tx, - Tv: cldf.NewTypeAndVersion(USDCTokenMessenger, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenMessenger, deployment.Version1_0_0), Err: err2, } }) @@ -612,7 +614,7 @@ func deployUSDC( } tokenPool, err := cldf.DeployContract(lggr, chain, addresses, - func(chain deployment.Chain) cldf.ContractDeploy[*usdc_token_pool.USDCTokenPool] { + func(chain cldf.Chain) cldf.ContractDeploy[*usdc_token_pool.USDCTokenPool] { tokenPoolAddress, tx, tokenPoolContract, err2 := usdc_token_pool.DeployUSDCTokenPool( chain.DeployerKey, chain.Client, @@ -626,7 +628,7 @@ func deployUSDC( Address: tokenPoolAddress, Contract: tokenPoolContract, Tx: tx, - Tv: cldf.NewTypeAndVersion(USDCTokenPool, deployment.Version1_5_1), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenPool, deployment.Version1_5_1), Err: err2, } }) diff --git a/deployment/ccip/changeset/cs_prerequisites_test.go b/deployment/ccip/changeset/cs_prerequisites_test.go index d7bf780bdd2..4a1c264be9e 100644 --- a/deployment/ccip/changeset/cs_prerequisites_test.go +++ b/deployment/ccip/changeset/cs_prerequisites_test.go @@ -7,6 +7,7 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -34,7 +35,7 @@ func TestDeployPrerequisites(t *testing.T) { require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.NotNil(t, state.Chains[newChain].Weth9) require.NotNil(t, state.Chains[newChain].TokenAdminRegistry) diff --git a/deployment/ccip/changeset/globals/config.go b/deployment/ccip/changeset/globals/config.go index 81ba417df8c..96f1efc8f54 100644 --- a/deployment/ccip/changeset/globals/config.go +++ b/deployment/ccip/changeset/globals/config.go @@ -1,8 +1,11 @@ package globals import ( + "fmt" "time" + "dario.cat/mergo" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" @@ -15,8 +18,8 @@ const ( ConfigTypeCandidate ConfigType = "candidate" // ========= Changeset Defaults ========= PermissionLessExecutionThreshold = 1 * time.Hour - RemoteGasPriceBatchWriteFrequency = 30 * time.Minute - TokenPriceBatchWriteFrequency = 30 * time.Minute + RemoteGasPriceBatchWriteFrequency = 20 * time.Minute + TokenPriceBatchWriteFrequency = 2 * time.Hour // Building batches with 6.5m and transmit with 8m to account for overhead. BatchGasLimit = 6_500_000 InflightCacheExpiry = 1 * time.Minute @@ -89,4 +92,20 @@ var ( // Remaining fields cannot be statically set: // TokenDataObservers: , // Must be configured in CLD } + + DefaultCommitOffChainCfgForEth = withCommitOffchainConfigOverrides( + DefaultCommitOffChainCfg, + pluginconfig.CommitOffchainConfig{ + RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(2 * time.Hour), + TokenPriceBatchWriteFrequency: *config.MustNewDuration(12 * time.Hour), + }, + ) ) + +func withCommitOffchainConfigOverrides(base pluginconfig.CommitOffchainConfig, overrides pluginconfig.CommitOffchainConfig) pluginconfig.CommitOffchainConfig { + outcome := base + if err := mergo.Merge(&outcome, overrides, mergo.WithOverride); err != nil { + panic(fmt.Sprintf("error while building an OCR config %v", err)) + } + return outcome +} diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go index 428335d6bfd..d6fe6945174 100644 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ b/deployment/ccip/changeset/internal/deploy_home_chain.go @@ -26,9 +26,10 @@ import ( capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" ) @@ -55,7 +56,7 @@ func LatestCCIPDON(registry *capabilities_registry.CapabilitiesRegistry) (*capab var ccipDON capabilities_registry.CapabilitiesRegistryDONInfo for _, don := range dons { if len(don.CapabilityConfigurations) == 1 && - don.CapabilityConfigurations[0].CapabilityId == ccip.CCIPCapabilityID && + don.CapabilityConfigurations[0].CapabilityId == shared.CCIPCapabilityID && don.Id > ccipDON.Id { ccipDON = don } @@ -73,7 +74,7 @@ func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHom var donIDs []uint32 for _, don := range dons { if len(don.CapabilityConfigurations) == 1 && - don.CapabilityConfigurations[0].CapabilityId == ccip.CCIPCapabilityID { + don.CapabilityConfigurations[0].CapabilityId == shared.CCIPCapabilityID { configs, err := ccipHome.GetAllConfigs(nil, don.Id, uint8(types.PluginTypeCCIPCommit)) if err != nil { return 0, fmt.Errorf("get all commit configs from cciphome: %w", err) @@ -92,7 +93,7 @@ func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHom // more than one DON is an error if len(donIDs) > 1 { - return 0, fmt.Errorf("more than one DON found for (chain selector %d, ccip capability id %x) pair", chainSelector, ccip.CCIPCapabilityID[:]) + return 0, fmt.Errorf("more than one DON found for (chain selector %d, ccip capability id %x) pair", chainSelector, shared.CCIPCapabilityID[:]) } // no DON found - don ID of 0 indicates that (this is the case in the CR as well). diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go index db1b5c4e500..e8063d46f93 100644 --- a/deployment/ccip/changeset/save_existing_test.go +++ b/deployment/ccip/changeset/save_existing_test.go @@ -11,7 +11,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -38,22 +39,22 @@ func TestSaveExistingCCIP(t *testing.T) { }, { Address: common.BigToAddress(big.NewInt(2)).String(), - TypeAndVersion: cldf.NewTypeAndVersion(changeset.WETH9, deployment.Version1_0_0), + TypeAndVersion: cldf.NewTypeAndVersion(shared.WETH9, deployment.Version1_0_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(3)).String(), - TypeAndVersion: cldf.NewTypeAndVersion(changeset.TokenAdminRegistry, deployment.Version1_5_0), + TypeAndVersion: cldf.NewTypeAndVersion(shared.TokenAdminRegistry, deployment.Version1_5_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(4)).String(), - TypeAndVersion: cldf.NewTypeAndVersion(changeset.RegistryModule, deployment.Version1_6_0), + TypeAndVersion: cldf.NewTypeAndVersion(shared.RegistryModule, deployment.Version1_6_0), ChainSelector: chain2, }, { Address: common.BigToAddress(big.NewInt(5)).String(), - TypeAndVersion: cldf.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0), + TypeAndVersion: cldf.NewTypeAndVersion(shared.Router, deployment.Version1_2_0), ChainSelector: chain2, }, }, @@ -63,7 +64,7 @@ func TestSaveExistingCCIP(t *testing.T) { require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.Equal(t, state.Chains[chain1].LinkToken.Address(), common.BigToAddress(big.NewInt(1))) require.Equal(t, state.Chains[chain1].Weth9.Address(), common.BigToAddress(big.NewInt(2))) diff --git a/deployment/ccip/changeset/solana/cs_add_remote_chain.go b/deployment/ccip/changeset/solana/cs_add_remote_chain.go index d459d9e545c..d0e0eebabae 100644 --- a/deployment/ccip/changeset/solana/cs_add_remote_chain.go +++ b/deployment/ccip/changeset/solana/cs_add_remote_chain.go @@ -20,7 +20,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -48,8 +50,8 @@ type RouterConfig struct { IsUpdate bool } -func (cfg *AddRemoteChainToRouterConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg *AddRemoteChainToRouterConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -62,7 +64,7 @@ func (cfg *AddRemoteChainToRouterConfig) Validate(e deployment.Environment) erro return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } routerProgramAddress, routerConfigPDA, _ := chainState.GetRouterInfo() @@ -78,7 +80,7 @@ func (cfg *AddRemoteChainToRouterConfig) Validate(e deployment.Environment) erro if remote == routerConfigAccount.SvmChainSelector { return fmt.Errorf("cannot add remote chain %d with same chain selector as current chain %d", remote, cfg.ChainSelector) } - if err := state.ValidateRamp(remote, ccipChangeset.OnRamp); err != nil { + if err := state.ValidateRamp(remote, shared.OnRamp); err != nil { return err } routerDestChainPDA, err := solState.FindDestChainStatePDA(remote, routerProgramAddress) @@ -96,12 +98,12 @@ func (cfg *AddRemoteChainToRouterConfig) Validate(e deployment.Environment) erro } // Adds new remote chain configurations -func AddRemoteChainToRouter(e deployment.Environment, cfg AddRemoteChainToRouterConfig) (cldf.ChangesetOutput, error) { +func AddRemoteChainToRouter(e cldf.Environment, cfg AddRemoteChainToRouterConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -128,8 +130,8 @@ func AddRemoteChainToRouter(e deployment.Environment, cfg AddRemoteChainToRouter } func doAddRemoteChainToRouter( - e deployment.Environment, - s ccipChangeset.CCIPOnChainState, + e cldf.Environment, + s stateview.CCIPOnChainState, cfg AddRemoteChainToRouterConfig, ab cldf.AddressBook) ([]mcmsTypes.Transaction, error) { txns := make([]mcmsTypes.Transaction, 0) @@ -139,11 +141,11 @@ func doAddRemoteChainToRouter( chainState := s.SolChains[chainSel] ccipRouterID, routerConfigPDA, _ := s.SolChains[chainSel].GetRouterInfo() offRampID := s.SolChains[chainSel].OffRamp - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -155,7 +157,7 @@ func doAddRemoteChainToRouter( chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -181,7 +183,7 @@ func doAddRemoteChainToRouter( } e.Logger.Infow("update router config for remote chain", "remoteChainSel", remoteChainSel) if routerUsingMCMS { - tx, err := BuildMCMSTxn(routerIx, ccipRouterID.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(routerIx, ccipRouterID.String(), shared.Router) if err != nil { return txns, fmt.Errorf("failed to create update router config transaction: %w", err) } @@ -225,7 +227,7 @@ func doAddRemoteChainToRouter( if routerUsingMCMS { // build transactions if mcms for _, ix := range []solana.Instruction{routerIx, routerOfframpIx} { - tx, err := BuildMCMSTxn(ix, ccipRouterID.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ix, ccipRouterID.String(), shared.Router) if err != nil { return txns, fmt.Errorf("failed to create add router config transaction: %w", err) } @@ -239,7 +241,7 @@ func doAddRemoteChainToRouter( } } // add to address book - tv := cldf.NewTypeAndVersion(ccipChangeset.RemoteDest, deployment.Version1_0_0) + tv := cldf.NewTypeAndVersion(shared.RemoteDest, deployment.Version1_0_0) remoteChainSelStr := strconv.FormatUint(remoteChainSel, 10) tv.AddLabel(remoteChainSelStr) err = ab.Save(chainSel, routerRemoteStatePDA.String(), tv) @@ -274,8 +276,8 @@ type FeeQuoterConfig struct { IsUpdate bool } -func (cfg *AddRemoteChainToFeeQuoterConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg *AddRemoteChainToFeeQuoterConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -288,7 +290,7 @@ func (cfg *AddRemoteChainToFeeQuoterConfig) Validate(e deployment.Environment) e if err := validateFeeQuoterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}); err != nil { return err } supportedChains := state.SupportedChains() @@ -296,7 +298,7 @@ func (cfg *AddRemoteChainToFeeQuoterConfig) Validate(e deployment.Environment) e if _, ok := supportedChains[remote]; !ok { return fmt.Errorf("remote chain %d is not supported", remote) } - if err := state.ValidateRamp(remote, ccipChangeset.OnRamp); err != nil { + if err := state.ValidateRamp(remote, shared.OnRamp); err != nil { return err } fqRemoteChainPDA, _, err := solState.FindFqDestChainPDA(remote, chainState.FeeQuoter) @@ -314,12 +316,12 @@ func (cfg *AddRemoteChainToFeeQuoterConfig) Validate(e deployment.Environment) e } // Adds new remote chain configurations -func AddRemoteChainToFeeQuoter(e deployment.Environment, cfg AddRemoteChainToFeeQuoterConfig) (cldf.ChangesetOutput, error) { +func AddRemoteChainToFeeQuoter(e cldf.Environment, cfg AddRemoteChainToFeeQuoterConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -346,8 +348,8 @@ func AddRemoteChainToFeeQuoter(e deployment.Environment, cfg AddRemoteChainToFee } func doAddRemoteChainToFeeQuoter( - e deployment.Environment, - s ccipChangeset.CCIPOnChainState, + e cldf.Environment, + s stateview.CCIPOnChainState, cfg AddRemoteChainToFeeQuoterConfig, ab cldf.AddressBook) ([]mcmsTypes.Transaction, error) { txns := make([]mcmsTypes.Transaction, 0) @@ -357,11 +359,11 @@ func doAddRemoteChainToFeeQuoter( chainState := s.SolChains[chainSel] feeQuoterID := s.SolChains[chainSel].FeeQuoter offRampID := s.SolChains[chainSel].OffRamp - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") lookUpTableEntries := make([]solana.PublicKey, 0) @@ -372,7 +374,7 @@ func doAddRemoteChainToFeeQuoter( chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "", ) @@ -410,7 +412,7 @@ func doAddRemoteChainToFeeQuoter( return txns, fmt.Errorf("failed to generate instructions: %w", err) } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(feeQuoterIx, feeQuoterID.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(feeQuoterIx, feeQuoterID.String(), shared.FeeQuoter) if err != nil { return txns, fmt.Errorf("failed to create transaction: %w", err) } @@ -449,8 +451,8 @@ type OffRampConfig struct { IsUpdate bool } -func (cfg *AddRemoteChainToOffRampConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg *AddRemoteChainToOffRampConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -463,7 +465,7 @@ func (cfg *AddRemoteChainToOffRampConfig) Validate(e deployment.Environment) err if err := validateOffRampConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.OffRamp: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.OffRamp: true}); err != nil { return err } @@ -472,7 +474,7 @@ func (cfg *AddRemoteChainToOffRampConfig) Validate(e deployment.Environment) err if _, ok := supportedChains[remote]; !ok { return fmt.Errorf("remote chain %d is not supported", remote) } - if err := state.ValidateRamp(remote, ccipChangeset.OnRamp); err != nil { + if err := state.ValidateRamp(remote, shared.OnRamp); err != nil { return err } offRampRemoteStatePDA, _, err := solState.FindOfframpSourceChainPDA(remote, chainState.OffRamp) @@ -490,12 +492,12 @@ func (cfg *AddRemoteChainToOffRampConfig) Validate(e deployment.Environment) err } // Adds new remote chain configurations -func AddRemoteChainToOffRamp(e deployment.Environment, cfg AddRemoteChainToOffRampConfig) (cldf.ChangesetOutput, error) { +func AddRemoteChainToOffRamp(e cldf.Environment, cfg AddRemoteChainToOffRampConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -522,8 +524,8 @@ func AddRemoteChainToOffRamp(e deployment.Environment, cfg AddRemoteChainToOffRa } func doAddRemoteChainToOffRamp( - e deployment.Environment, - s ccipChangeset.CCIPOnChainState, + e cldf.Environment, + s stateview.CCIPOnChainState, cfg AddRemoteChainToOffRampConfig, ab cldf.AddressBook) ([]mcmsTypes.Transaction, error) { txns := make([]mcmsTypes.Transaction, 0) @@ -532,11 +534,11 @@ func doAddRemoteChainToOffRamp( chain := e.SolChains[chainSel] chainState := s.SolChains[chainSel] offRampID := s.SolChains[chainSel].OffRamp - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") lookUpTableEntries := make([]solana.PublicKey, 0) @@ -546,7 +548,7 @@ func doAddRemoteChainToOffRamp( chain, chainState, cfg.MCMS, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "", ) @@ -584,7 +586,7 @@ func doAddRemoteChainToOffRamp( ).ValidateAndBuild() e.Logger.Infow("add offramp config for remote chain", "remoteChainSel", remoteChainSel) remoteChainSelStr := strconv.FormatUint(remoteChainSel, 10) - tv := cldf.NewTypeAndVersion(ccipChangeset.RemoteSource, deployment.Version1_0_0) + tv := cldf.NewTypeAndVersion(shared.RemoteSource, deployment.Version1_0_0) tv.AddLabel(remoteChainSelStr) err = ab.Save(chainSel, offRampRemoteStatePDA.String(), tv) if err != nil { @@ -595,7 +597,7 @@ func doAddRemoteChainToOffRamp( return txns, fmt.Errorf("failed to generate instructions: %w", err) } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(offRampIx, offRampID.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(offRampIx, offRampID.String(), shared.OffRamp) if err != nil { return txns, fmt.Errorf("failed to create transaction: %w", err) } @@ -618,7 +620,7 @@ func doAddRemoteChainToOffRamp( return txns, nil } -func getSourceChainConfig(s ccipChangeset.CCIPOnChainState, remoteChainSel uint64, enabledAsSource bool) (solOffRamp.SourceChainConfig, error) { +func getSourceChainConfig(s stateview.CCIPOnChainState, remoteChainSel uint64, enabledAsSource bool) (solOffRamp.SourceChainConfig, error) { var onRampAddress solOffRamp.OnRampAddress // already verified, skipping errcheck addressBytes, _ := s.GetOnRampAddressBytes(remoteChainSel) @@ -635,8 +637,8 @@ func getSourceChainConfig(s ccipChangeset.CCIPOnChainState, remoteChainSel uint6 return validSourceChainConfig, nil } -func extendLookupTable(e deployment.Environment, chain deployment.SolChain, offRampID solana.PublicKey, lookUpTableEntries []solana.PublicKey) error { - addressLookupTable, err := ccipChangeset.FetchOfframpLookupTable(e.GetContext(), chain, offRampID) +func extendLookupTable(e cldf.Environment, chain cldf.SolChain, offRampID solana.PublicKey, lookUpTableEntries []solana.PublicKey) error { + addressLookupTable, err := solanastateview.FetchOfframpLookupTable(e.GetContext(), chain, offRampID) if err != nil { return fmt.Errorf("failed to get offramp reference addresses: %w", err) } diff --git a/deployment/ccip/changeset/solana/cs_billing.go b/deployment/ccip/changeset/solana/cs_billing.go index de0778daff8..6506f02bc00 100644 --- a/deployment/ccip/changeset/solana/cs_billing.go +++ b/deployment/ccip/changeset/solana/cs_billing.go @@ -19,8 +19,9 @@ import ( ata "github.com/gagliardetto/solana-go/programs/associated-token-account" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -40,14 +41,14 @@ type BillingTokenConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg *BillingTokenConfig) Validate(e deployment.Environment) error { +func (cfg *BillingTokenConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] if err := validateFeeQuoterConfig(chain, chainState); err != nil { return err @@ -55,7 +56,7 @@ func (cfg *BillingTokenConfig) Validate(e deployment.Environment) error { if _, err := chainState.TokenToTokenProgram(tokenPubKey); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}); err != nil { return err } // check if already setup @@ -72,9 +73,9 @@ func (cfg *BillingTokenConfig) Validate(e deployment.Environment) error { } func AddBillingToken( - e deployment.Environment, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, billingTokenConfig solFeeQuoter.BillingTokenConfig, mcms *proposalutils.TimelockConfig, isUpdate bool, @@ -84,16 +85,16 @@ func AddBillingToken( txns := make([]mcmsTypes.Transaction, 0) tokenPubKey := solana.MustPublicKeyFromBase58(billingTokenConfig.Mint.String()) tokenBillingPDA, _, _ := solState.FindFqBillingTokenConfigPDA(tokenPubKey, feeQuoterAddress) - // we dont need to handle test router here because we explicitly create this and token2022Receiver for test router + // we dont need to handle test router here because we explicitly create this and token Receiver for test router billingSignerPDA, _, _ := solState.FindFeeBillingSignerPDA(routerAddress) tokenProgramID, _ := chainState.TokenToTokenProgram(tokenPubKey) - token2022Receiver, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenProgramID, tokenPubKey, billingSignerPDA) + tokenReceiver, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenProgramID, tokenPubKey, billingSignerPDA) feeQuoterConfigPDA, _, _ := solState.FindFqConfigPDA(feeQuoterAddress) - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") @@ -102,7 +103,7 @@ func AddBillingToken( chain, chainState, mcms, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "", ) @@ -122,7 +123,7 @@ func AddBillingToken( tokenBillingPDA, tokenProgramID, tokenPubKey, - token2022Receiver, + tokenReceiver, authority, // ccip admin billingSignerPDA, ata.ProgramID, @@ -133,7 +134,7 @@ func AddBillingToken( return txns, fmt.Errorf("failed to generate instructions: %w", err) } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(ixConfig, chainState.FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(ixConfig, chainState.FeeQuoter.String(), shared.FeeQuoter) if err != nil { return txns, fmt.Errorf("failed to create transaction: %w", err) } @@ -147,12 +148,12 @@ func AddBillingToken( return txns, nil } -func AddBillingTokenChangeset(e deployment.Environment, cfg BillingTokenConfig) (cldf.ChangesetOutput, error) { +func AddBillingTokenChangeset(e cldf.Environment, cfg BillingTokenConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] solFeeQuoter.SetProgramID(chainState.FeeQuoter) @@ -193,37 +194,37 @@ type TokenTransferFeeForRemoteChainConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg TokenTransferFeeForRemoteChainConfig) Validate(e deployment.Environment) error { +func (cfg TokenTransferFeeForRemoteChainConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] if err := validateFeeQuoterConfig(chain, chainState); err != nil { return fmt.Errorf("fee quoter validation failed: %w", err) } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}) } // TODO: rename this, i dont think this is for billing, this is more for token transfer config/fees -func AddTokenTransferFeeForRemoteChain(e deployment.Environment, cfg TokenTransferFeeForRemoteChainConfig) (cldf.ChangesetOutput, error) { +func AddTokenTransferFeeForRemoteChain(e cldf.Environment, cfg TokenTransferFeeForRemoteChainConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) remoteBillingPDA, _, _ := solState.FindFqPerChainPerTokenConfigPDA(cfg.RemoteChainSelector, tokenPubKey, chainState.FeeQuoter) - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") @@ -232,7 +233,7 @@ func AddTokenTransferFeeForRemoteChain(e deployment.Environment, cfg TokenTransf chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") solFeeQuoter.SetProgramID(chainState.FeeQuoter) @@ -260,7 +261,7 @@ func AddTokenTransferFeeForRemoteChain(e deployment.Environment, cfg TokenTransf e.Logger.Infow("Token billing set for remote chain", "chainSelector ", cfg.ChainSelector, "remoteChainSelector ", cfg.RemoteChainSelector, "tokenPubKey", tokenPubKey.String()) if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(ix, chainState.FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(ix, chainState.FeeQuoter.String(), shared.FeeQuoter) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -286,8 +287,8 @@ type UpdatePricesConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdatePricesConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg UpdatePricesConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -296,7 +297,7 @@ func (cfg UpdatePricesConfig) Validate(e deployment.Environment) error { if err := validateFeeQuoterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}); err != nil { return err } if cfg.PriceUpdater.IsZero() { @@ -322,12 +323,12 @@ func (cfg UpdatePricesConfig) Validate(e deployment.Environment) error { return nil } -func UpdatePrices(e deployment.Environment, cfg UpdatePricesConfig) (cldf.ChangesetOutput, error) { +func UpdatePrices(e cldf.Environment, cfg UpdatePricesConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -336,11 +337,11 @@ func UpdatePrices(e deployment.Environment, cfg UpdatePricesConfig) (cldf.Change chain := e.SolChains[chainSel] chainState := s.SolChains[chainSel] feeQuoterID := s.SolChains[chainSel].FeeQuoter - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") @@ -354,7 +355,7 @@ func UpdatePrices(e deployment.Environment, cfg UpdatePricesConfig) (cldf.Change chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") raw := solFeeQuoter.NewUpdatePricesInstruction( @@ -378,7 +379,7 @@ func UpdatePrices(e deployment.Environment, cfg UpdatePricesConfig) (cldf.Change } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].FeeQuoter.String(), shared.FeeQuoter) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -412,8 +413,8 @@ const ( RemoveUpdater ) -func (cfg ModifyPriceUpdaterConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg ModifyPriceUpdaterConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -422,7 +423,7 @@ func (cfg ModifyPriceUpdaterConfig) Validate(e deployment.Environment) error { if err := validateFeeQuoterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}); err != nil { return err } if cfg.PriceUpdater.IsZero() { @@ -431,12 +432,12 @@ func (cfg ModifyPriceUpdaterConfig) Validate(e deployment.Environment) error { return nil } -func ModifyPriceUpdater(e deployment.Environment, cfg ModifyPriceUpdaterConfig) (cldf.ChangesetOutput, error) { +func ModifyPriceUpdater(e cldf.Environment, cfg ModifyPriceUpdaterConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -445,11 +446,11 @@ func ModifyPriceUpdater(e deployment.Environment, cfg ModifyPriceUpdaterConfig) chain := e.SolChains[chainSel] chainState := s.SolChains[chainSel] feeQuoterID := s.SolChains[chainSel].FeeQuoter - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") @@ -463,7 +464,7 @@ func ModifyPriceUpdater(e deployment.Environment, cfg ModifyPriceUpdaterConfig) chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "", ) @@ -490,7 +491,7 @@ func ModifyPriceUpdater(e deployment.Environment, cfg ModifyPriceUpdaterConfig) } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].FeeQuoter.String(), shared.FeeQuoter) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -518,12 +519,12 @@ type WithdrawBilledFundsConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg WithdrawBilledFundsConfig) Validate(e deployment.Environment) error { +func (cfg WithdrawBilledFundsConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -535,15 +536,15 @@ func (cfg WithdrawBilledFundsConfig) Validate(e deployment.Environment) error { if err := validateFeeAggregatorConfig(chain, chainState); err != nil { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}) } -func WithdrawBilledFunds(e deployment.Environment, cfg WithdrawBilledFundsConfig) (cldf.ChangesetOutput, error) { +func WithdrawBilledFunds(e cldf.Environment, cfg WithdrawBilledFundsConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := ccipChangeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -557,11 +558,11 @@ func WithdrawBilledFunds(e deployment.Environment, cfg WithdrawBilledFundsConfig tokenReceiverPDA, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenProgramID, tokenPubKey, billingSignerPDA) feeAggregatorATA, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenProgramID, tokenPubKey, chainState.GetFeeAggregator(chain)) routerConfigPDA, _, _ := solState.FindConfigPDA(chainState.Router) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") @@ -571,7 +572,7 @@ func WithdrawBilledFunds(e deployment.Environment, cfg WithdrawBilledFundsConfig chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -594,7 +595,7 @@ func WithdrawBilledFunds(e deployment.Environment, cfg WithdrawBilledFundsConfig } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ix, s.SolChains[chainSel].Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -620,8 +621,8 @@ type SetMaxFeeJuelsPerMsgConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg SetMaxFeeJuelsPerMsgConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg SetMaxFeeJuelsPerMsgConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -635,24 +636,24 @@ func (cfg SetMaxFeeJuelsPerMsgConfig) Validate(e deployment.Environment) error { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true}) } -func SetMaxFeeJuelsPerMsg(e deployment.Environment, cfg SetMaxFeeJuelsPerMsgConfig) (cldf.ChangesetOutput, error) { +func SetMaxFeeJuelsPerMsg(e cldf.Environment, cfg SetMaxFeeJuelsPerMsgConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] fqConfig, _, _ := solState.FindConfigPDA(chainState.FeeQuoter) - fqUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + fqUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") @@ -662,7 +663,7 @@ func SetMaxFeeJuelsPerMsg(e deployment.Environment, cfg SetMaxFeeJuelsPerMsgConf chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") instruction, err := solFeeQuoter.NewSetMaxFeeJuelsPerMsgInstruction( @@ -675,7 +676,7 @@ func SetMaxFeeJuelsPerMsg(e deployment.Environment, cfg SetMaxFeeJuelsPerMsgConf } if fqUsingMCMS { - tx, err := BuildMCMSTxn(instruction, chainState.FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(instruction, chainState.FeeQuoter.String(), shared.FeeQuoter) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } diff --git a/deployment/ccip/changeset/solana/cs_build_solana.go b/deployment/ccip/changeset/solana/cs_build_solana.go index e1dc2fc8b2b..06167b8fbab 100644 --- a/deployment/ccip/changeset/solana/cs_build_solana.go +++ b/deployment/ccip/changeset/solana/cs_build_solana.go @@ -13,8 +13,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - cs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" ) @@ -30,23 +29,23 @@ const ( // Map program names to their Rust file paths (relative to the Anchor project root) // Needed for upgrades in place var programToFileMap = map[cldf.ContractType]string{ - cs.Router: "programs/ccip-router/src/lib.rs", - cs.CCIPCommon: "programs/ccip-common/src/lib.rs", - cs.FeeQuoter: "programs/fee-quoter/src/lib.rs", - cs.OffRamp: "programs/ccip-offramp/src/lib.rs", - cs.BurnMintTokenPool: "programs/burnmint-token-pool/src/lib.rs", - cs.LockReleaseTokenPool: "programs/lockrelease-token-pool/src/lib.rs", - cs.RMNRemote: "programs/rmn-remote/src/lib.rs", + shared.Router: "programs/ccip-router/src/lib.rs", + shared.CCIPCommon: "programs/ccip-common/src/lib.rs", + shared.FeeQuoter: "programs/fee-quoter/src/lib.rs", + shared.OffRamp: "programs/ccip-offramp/src/lib.rs", + shared.BurnMintTokenPool: "programs/burnmint-token-pool/src/lib.rs", + shared.LockReleaseTokenPool: "programs/lockrelease-token-pool/src/lib.rs", + shared.RMNRemote: "programs/rmn-remote/src/lib.rs", types.AccessControllerProgram: "programs/access-controller/src/lib.rs", types.ManyChainMultisigProgram: "programs/mcm/src/lib.rs", types.RBACTimelockProgram: "programs/timelock/src/lib.rs", } var programToVanityKey = map[cldf.ContractType]string{ - cs.Router: "Ccip", - cs.FeeQuoter: "FeeQ", - cs.OffRamp: "off", - cs.RMNRemote: "Rmn", + shared.Router: "Ccip", + shared.FeeQuoter: "FeeQ", + shared.OffRamp: "off", + shared.RMNRemote: "Rmn", } type LocalBuildConfig struct { @@ -82,7 +81,7 @@ func runCommand(command string, args []string, workDir string) (string, error) { } // Clone and checkout the specific revision of the repo -func cloneRepo(e deployment.Environment, revision string, forceClean bool) error { +func cloneRepo(e cldf.Environment, revision string, forceClean bool) error { // Check if the repository already exists if forceClean { e.Logger.Debugw("Cleaning repository", "dir", cloneDir) @@ -123,7 +122,7 @@ func cloneRepo(e deployment.Environment, revision string, forceClean bool) error } // Replace keys in Rust files -func replaceKeys(e deployment.Environment) error { +func replaceKeys(e cldf.Environment) error { solanaDir := filepath.Join(cloneDir, anchorDir, "..") e.Logger.Debugw("Replacing keys", "solanaDir", solanaDir) output, err := runCommand("make", []string{"docker-update-contracts"}, solanaDir) @@ -133,7 +132,7 @@ func replaceKeys(e deployment.Environment) error { return nil } -func replaceKeysForUpgrade(e deployment.Environment, keys map[cldf.ContractType]string) error { +func replaceKeysForUpgrade(e cldf.Environment, keys map[cldf.ContractType]string) error { e.Logger.Debug("Replacing keys in Rust files...") for program, key := range keys { programStr := string(program) @@ -160,8 +159,8 @@ func replaceKeysForUpgrade(e deployment.Environment, keys map[cldf.ContractType] } func syncRouterAndCommon() error { - routerFileName := programToFileMap[cs.Router] - commonFileName := programToFileMap[cs.CCIPCommon] + routerFileName := programToFileMap[shared.Router] + commonFileName := programToFileMap[shared.CCIPCommon] routerFile := filepath.Join(cloneDir, anchorDir, routerFileName) commonFile := filepath.Join(cloneDir, anchorDir, commonFileName) file, err := os.Open(routerFile) @@ -196,7 +195,7 @@ func syncRouterAndCommon() error { return os.WriteFile(commonFile, []byte(updatedContent), 0600) } -func generateVanityKeys(e deployment.Environment, keys map[cldf.ContractType]string) error { +func generateVanityKeys(e cldf.Environment, keys map[cldf.ContractType]string) error { e.Logger.Debug("Generating vanity keys...") for program, prefix := range programToVanityKey { _, exists := keys[program] @@ -260,7 +259,7 @@ func copyFile(srcFile string, destDir string) error { } // Build the project with Anchor -func buildProject(e deployment.Environment) error { +func buildProject(e cldf.Environment) error { solanaDir := filepath.Join(cloneDir, anchorDir, "..") e.Logger.Debugw("Building project", "solanaDir", solanaDir) args := []string{"docker-build-contracts"} @@ -271,7 +270,7 @@ func buildProject(e deployment.Environment) error { return nil } -func buildLocally(e deployment.Environment, config BuildSolanaConfig) error { +func buildLocally(e cldf.Environment, config BuildSolanaConfig) error { e.Logger.Debugw("Starting local build process", "destinationDir", config.DestinationDir) // Clone the repository if err := cloneRepo(e, config.GitCommitSha, config.LocalBuild.CleanGitDir); err != nil { @@ -344,7 +343,7 @@ func buildLocally(e deployment.Environment, config BuildSolanaConfig) error { return nil } -func BuildSolana(e deployment.Environment, config BuildSolanaConfig) error { +func BuildSolana(e cldf.Environment, config BuildSolanaConfig) error { if !config.LocalBuild.BuildLocally { e.Logger.Debug("Downloading Solana CCIP program artifacts...") err := memory.DownloadSolanaCCIPProgramArtifacts(e.GetContext(), config.DestinationDir, e.Logger, config.GitCommitSha) diff --git a/deployment/ccip/changeset/solana/cs_chain_contracts.go b/deployment/ccip/changeset/solana/cs_chain_contracts.go index d19e320edc7..1321fe0606c 100644 --- a/deployment/ccip/changeset/solana/cs_chain_contracts.go +++ b/deployment/ccip/changeset/solana/cs_chain_contracts.go @@ -15,13 +15,14 @@ import ( solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solTestReceiver "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/test_ccip_receiver" - solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" csState "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -39,23 +40,23 @@ var _ cldf.ChangeSet[SetUpgradeAuthorityConfig] = SetUpgradeAuthorityChangeset // GetTokenProgramID returns the program ID for the given token program name func GetTokenProgramID(programName cldf.ContractType) (solana.PublicKey, error) { tokenPrograms := map[cldf.ContractType]solana.PublicKey{ - ccipChangeset.SPLTokens: solana.TokenProgramID, - ccipChangeset.SPL2022Tokens: solana.Token2022ProgramID, + shared.SPLTokens: solana.TokenProgramID, + shared.SPL2022Tokens: solana.Token2022ProgramID, } programID, ok := tokenPrograms[programName] if !ok { - return solana.PublicKey{}, fmt.Errorf("invalid token program: %s. Must be one of: %s, %s", programName, ccipChangeset.SPLTokens, ccipChangeset.SPL2022Tokens) + return solana.PublicKey{}, fmt.Errorf("invalid token program: %s. Must be one of: %s, %s", programName, shared.SPLTokens, shared.SPL2022Tokens) } return programID, nil } -func commonValidation(e deployment.Environment, selector uint64, tokenPubKey solana.PublicKey) error { +func commonValidation(e cldf.Environment, selector uint64, tokenPubKey solana.PublicKey) error { chain, ok := e.SolChains[selector] if !ok { return fmt.Errorf("chain selector %d not found in environment", selector) } - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -81,7 +82,7 @@ func commonValidation(e deployment.Environment, selector uint64, tokenPubKey sol return nil } -func validateRouterConfig(chain deployment.SolChain, chainState ccipChangeset.SolCCIPChainState) error { +func validateRouterConfig(chain cldf.SolChain, chainState solanastateview.CCIPChainState) error { _, routerConfigPDA, err := chainState.GetRouterInfo() if err != nil { return err @@ -94,14 +95,14 @@ func validateRouterConfig(chain deployment.SolChain, chainState ccipChangeset.So return nil } -func validateFeeAggregatorConfig(chain deployment.SolChain, chainState ccipChangeset.SolCCIPChainState) error { +func validateFeeAggregatorConfig(chain cldf.SolChain, chainState solanastateview.CCIPChainState) error { if chainState.GetFeeAggregator(chain).IsZero() { return fmt.Errorf("fee aggregator not found in existing state, set the fee aggregator first for chain %d", chain.Selector) } return nil } -func validateFeeQuoterConfig(chain deployment.SolChain, chainState ccipChangeset.SolCCIPChainState) error { +func validateFeeQuoterConfig(chain cldf.SolChain, chainState solanastateview.CCIPChainState) error { if chainState.FeeQuoter.IsZero() { return fmt.Errorf("fee quoter not found in existing state, deploy the fee quoter first for chain %d", chain.Selector) } @@ -114,7 +115,7 @@ func validateFeeQuoterConfig(chain deployment.SolChain, chainState ccipChangeset return nil } -func validateOffRampConfig(chain deployment.SolChain, chainState ccipChangeset.SolCCIPChainState) error { +func validateOffRampConfig(chain cldf.SolChain, chainState solanastateview.CCIPChainState) error { if chainState.OffRamp.IsZero() { return fmt.Errorf("offramp not found in existing state, deploy the offramp first for chain %d", chain.Selector) } @@ -137,9 +138,9 @@ type OffRampRefAddressesConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg OffRampRefAddressesConfig) Validate(e deployment.Environment) error { +func (cfg OffRampRefAddressesConfig) Validate(e cldf.Environment) error { chain := e.SolChains[cfg.ChainSelector] - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -147,14 +148,14 @@ func (cfg OffRampRefAddressesConfig) Validate(e deployment.Environment) error { if !chainExists { return fmt.Errorf("chain %s not found in existing state, deploy the link token first", chain.String()) } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.OffRamp: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.OffRamp: true}) } func UpdateOffRampRefAddresses( - e deployment.Environment, + e cldf.Environment, config OffRampRefAddressesConfig, ) (cldf.ChangesetOutput, error) { - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) chain := e.SolChains[config.ChainSelector] if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) @@ -194,11 +195,11 @@ func UpdateOffRampRefAddresses( rmnRemoteToSet = config.RMNRemote } - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") authority := GetAuthorityForIxn( @@ -206,7 +207,7 @@ func UpdateOffRampRefAddresses( chain, chainState, config.MCMS, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "", ) @@ -225,7 +226,7 @@ func UpdateOffRampRefAddresses( } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(ix, chainState.OffRamp.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(ix, chainState.OffRamp.String(), shared.OffRamp) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -248,18 +249,19 @@ func UpdateOffRampRefAddresses( type SetUpgradeAuthorityConfig struct { ChainSelector uint64 NewUpgradeAuthority solana.PublicKey - SetAfterInitialDeploy bool // set all of the programs after the initial deploy - SetOffRamp bool // offramp not upgraded in place, so may need to set separately - SetMCMSPrograms bool // these all deploy at once so just set them all - TransferKeys []solana.PublicKey // any keys not covered by the above e.g. partner programs + SetAfterInitialDeploy bool // set all of the programs after the initial deploy + SetOffRamp bool // offramp not upgraded in place, so may need to set separately + SetMCMSPrograms bool // these all deploy at once so just set them all + TransferKeys []solana.PublicKey // any keys not covered by the above e.g. partner programs + MCMS *proposalutils.TimelockConfig // if set, assumes current upgrade authority is the timelock } func SetUpgradeAuthorityChangeset( - e deployment.Environment, + e cldf.Environment, config SetUpgradeAuthorityConfig, ) (cldf.ChangesetOutput, error) { chain := e.SolChains[config.ChainSelector] - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return cldf.ChangesetOutput{}, err @@ -270,7 +272,7 @@ func SetUpgradeAuthorityChangeset( } programs := make([]solana.PublicKey, 0) if config.SetAfterInitialDeploy { - programs = append(programs, chainState.Router, chainState.FeeQuoter, chainState.RMNRemote, chainState.BurnMintTokenPools[ccipChangeset.CLLMetadata], chainState.LockReleaseTokenPools[ccipChangeset.CLLMetadata]) + programs = append(programs, chainState.Router, chainState.FeeQuoter, chainState.RMNRemote, chainState.BurnMintTokenPools[shared.CLLMetadata], chainState.LockReleaseTokenPools[shared.CLLMetadata]) } if config.SetOffRamp { programs = append(programs, chainState.OffRamp) @@ -298,24 +300,56 @@ func SetUpgradeAuthorityChangeset( return cldf.ChangesetOutput{}, fmt.Errorf("failed to get program address for chain %s", chain.String()) } } + currentAuthority := chain.DeployerKey.PublicKey() + if config.MCMS != nil { + timelockSignerPDA, err := FetchTimelockSigner(e, chain.Selector) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to get timelock signer: %w", err) + } + currentAuthority = timelockSignerPDA + } e.Logger.Infow("Setting upgrade authority", "newUpgradeAuthority", config.NewUpgradeAuthority.String()) + mcmsTxns := make([]mcmsTypes.Transaction, 0) for _, programID := range programs { - if err := setUpgradeAuthority(&e, &chain, programID, chain.DeployerKey, &config.NewUpgradeAuthority, false); err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to set upgrade authority: %w", err) + ixn := setUpgradeAuthority(&e, &chain, programID, currentAuthority, config.NewUpgradeAuthority, false) + if config.MCMS == nil { + if err := chain.Confirm([]solana.Instruction{ixn}); err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err) + } + } else { + tx, err := BuildMCMSTxn( + ixn, + solana.BPFLoaderUpgradeableProgramID.String(), + cldf.ContractType(solana.BPFLoaderUpgradeableProgramID.String())) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) + } + mcmsTxns = append(mcmsTxns, *tx) + } + } + if len(mcmsTxns) > 0 { + proposal, err := BuildProposalsForTxns( + e, config.ChainSelector, "proposal to SetUpgradeAuthority in Solana", config.MCMS.MinDelay, mcmsTxns) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to build proposal: %w", err) } + return cldf.ChangesetOutput{ + MCMSTimelockProposals: []mcms.TimelockProposal{*proposal}, + }, nil } return cldf.ChangesetOutput{}, nil } // setUpgradeAuthority creates a transaction to set the upgrade authority for a program func setUpgradeAuthority( - e *deployment.Environment, - chain *deployment.SolChain, + e *cldf.Environment, + chain *cldf.SolChain, programID solana.PublicKey, - currentUpgradeAuthority *solana.PrivateKey, - newUpgradeAuthority *solana.PublicKey, + currentUpgradeAuthority solana.PublicKey, + newUpgradeAuthority solana.PublicKey, isBuffer bool, -) error { +) solana.Instruction { + e.Logger.Infow("Setting upgrade authority", "programID", programID.String(), "currentUpgradeAuthority", currentUpgradeAuthority.String(), "newUpgradeAuthority", newUpgradeAuthority.String()) // Buffers use the program account as the program data account programDataSlice := solana.NewAccountMeta(programID, true, false) if !isBuffer { @@ -326,8 +360,8 @@ func setUpgradeAuthority( keys := solana.AccountMetaSlice{ programDataSlice, // Program account (writable) - solana.NewAccountMeta(currentUpgradeAuthority.PublicKey(), false, true), // Current upgrade authority (signer) - solana.NewAccountMeta(*newUpgradeAuthority, false, false), // New upgrade authority + solana.NewAccountMeta(currentUpgradeAuthority, false, true), // Current upgrade authority (signer) + solana.NewAccountMeta(newUpgradeAuthority, false, false), // New upgrade authority } instruction := solana.NewInstruction( @@ -337,12 +371,7 @@ func setUpgradeAuthority( []byte{4, 0, 0, 0}, // 4-byte SetAuthority instruction identifier ) - if err := chain.Confirm([]solana.Instruction{instruction}, solCommonUtil.AddSigners(*currentUpgradeAuthority)); err != nil { - return fmt.Errorf("failed to confirm setUpgradeAuthority: %w", err) - } - e.Logger.Infow("Set upgrade authority", "programID", programID.String(), "newUpgradeAuthority", newUpgradeAuthority.String()) - - return nil + return instruction } type SetFeeAggregatorConfig struct { @@ -351,8 +380,8 @@ type SetFeeAggregatorConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg SetFeeAggregatorConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg SetFeeAggregatorConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -366,7 +395,7 @@ func (cfg SetFeeAggregatorConfig) Validate(e deployment.Environment) error { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } @@ -386,22 +415,22 @@ func (cfg SetFeeAggregatorConfig) Validate(e deployment.Environment) error { return nil } -func SetFeeAggregator(e deployment.Environment, cfg SetFeeAggregatorConfig) (cldf.ChangesetOutput, error) { +func SetFeeAggregator(e cldf.Environment, cfg SetFeeAggregatorConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] feeAggregatorPubKey := solana.MustPublicKeyFromBase58(cfg.FeeAggregator) routerConfigPDA, _, _ := solState.FindConfigPDA(chainState.Router) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") @@ -411,7 +440,7 @@ func SetFeeAggregator(e deployment.Environment, cfg SetFeeAggregatorConfig) (cld chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -426,7 +455,7 @@ func SetFeeAggregator(e deployment.Environment, cfg SetFeeAggregatorConfig) (cld } if routerUsingMCMS { - tx, err := BuildMCMSTxn(instruction, chainState.Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(instruction, chainState.Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -455,8 +484,8 @@ type DeployForTestConfig struct { IsUpgrade bool } -func (cfg DeployForTestConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg DeployForTestConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -469,7 +498,7 @@ func (cfg DeployForTestConfig) Validate(e deployment.Environment) error { return validateRouterConfig(chain, chainState) } -func DeployReceiverForTest(e deployment.Environment, cfg DeployForTestConfig) (cldf.ChangesetOutput, error) { +func DeployReceiverForTest(e cldf.Environment, cfg DeployForTestConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } @@ -484,7 +513,7 @@ func DeployReceiverForTest(e deployment.Environment, cfg DeployForTestConfig) (c e.Logger.Debugw("Skipping solana build as no build config provided") } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] ab := cldf.NewMemoryAddressBook() @@ -494,13 +523,13 @@ func DeployReceiverForTest(e deployment.Environment, cfg DeployForTestConfig) (c if !cfg.IsUpgrade { //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.Receiver.IsZero() { - receiverAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.Receiver, deployment.Version1_0_0, false, "") + receiverAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.Receiver, deployment.Version1_0_0, false, "") if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to deploy program: %w", err) } } else if cfg.ReceiverVersion != nil { // this block is for re-deploying with a new version - receiverAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.Receiver, *cfg.ReceiverVersion, false, "") + receiverAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.Receiver, *cfg.ReceiverVersion, false, "") if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to deploy program: %w", err) } @@ -512,7 +541,7 @@ func DeployReceiverForTest(e deployment.Environment, cfg DeployForTestConfig) (c externalExecutionConfigPDA, _, _ := solana.FindProgramAddress([][]byte{[]byte("external_execution_config")}, receiverAddress) instruction, ixErr := solTestReceiver.NewInitializeInstruction( chainState.Router, - ccipChangeset.FindReceiverTargetAccount(receiverAddress), + solanastateview.FindReceiverTargetAccount(receiverAddress), externalExecutionConfigPDA, chain.DeployerKey.PublicKey(), solana.SystemProgramID, @@ -532,7 +561,7 @@ func DeployReceiverForTest(e deployment.Environment, cfg DeployForTestConfig) (c SpillAddress: chain.DeployerKey.PublicKey(), UpgradeAuthority: chain.DeployerKey.PublicKey(), }, - }, cfg.ReceiverVersion, chainState.Receiver, ccipChangeset.Receiver) + }, cfg.ReceiverVersion, chainState.Receiver, shared.Receiver) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -547,8 +576,8 @@ type SetLinkTokenConfig struct { ChainSelector uint64 } -func (cfg SetLinkTokenConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg SetLinkTokenConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -561,11 +590,11 @@ func (cfg SetLinkTokenConfig) Validate(e deployment.Environment) error { return validateRouterConfig(chain, chainState) } -func SetLinkToken(e deployment.Environment, cfg SetLinkTokenConfig) (cldf.ChangesetOutput, error) { +func SetLinkToken(e cldf.Environment, cfg SetLinkTokenConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] routerConfigPDA, _, _ := solState.FindConfigPDA(chainState.Router) diff --git a/deployment/ccip/changeset/solana/cs_chain_contracts_test.go b/deployment/ccip/changeset/solana/cs_chain_contracts_test.go index bc90faf9f81..68f9c28064d 100644 --- a/deployment/ccip/changeset/solana/cs_chain_contracts_test.go +++ b/deployment/ccip/changeset/solana/cs_chain_contracts_test.go @@ -23,11 +23,13 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -36,7 +38,7 @@ import ( ) // token setup -func deployTokenAndMint(t *testing.T, tenv deployment.Environment, solChain uint64, walletPubKeys []string) (deployment.Environment, solana.PublicKey, error) { +func deployTokenAndMint(t *testing.T, tenv cldf.Environment, solChain uint64, walletPubKeys []string) (cldf.Environment, solana.PublicKey, error) { mintMap := make(map[string]uint64) for _, key := range walletPubKeys { mintMap[key] = uint64(1000) @@ -46,7 +48,7 @@ func deployTokenAndMint(t *testing.T, tenv deployment.Environment, solChain uint cldf.CreateLegacyChangeSet(ccipChangesetSolana.DeploySolanaToken), ccipChangesetSolana.DeploySolanaTokenConfig{ ChainSelector: solChain, - TokenProgramName: ccipChangeset.SPL2022Tokens, + TokenProgramName: shared.SPLTokens, TokenDecimals: 9, TokenSymbol: "TEST_TOKEN", ATAList: walletPubKeys, @@ -56,9 +58,9 @@ func deployTokenAndMint(t *testing.T, tenv deployment.Environment, solChain uint ) addresses, err := e.ExistingAddresses.AddressesForChain(solChain) //nolint:staticcheck // addressbook still valid require.NoError(t, err) - tokenAddress := ccipChangeset.FindSolanaAddress( + tokenAddress := solanastateview.FindSolanaAddress( cldf.TypeAndVersion{ - Type: ccipChangeset.SPL2022Tokens, + Type: shared.SPLTokens, Version: deployment.Version1_0_0, Labels: cldf.NewLabelSet("TEST_TOKEN"), }, @@ -81,7 +83,7 @@ func TestAddRemoteChainWithoutMcms(t *testing.T) { func doTestAddRemoteChain(t *testing.T, mcms bool) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) e := tenv.Env - _, err := ccipChangeset.LoadOnchainStateSolana(tenv.Env) + _, err := stateview.LoadOnchainStateSolana(tenv.Env) require.NoError(t, err) evmChains := tenv.Env.AllChainSelectors() solChain := tenv.Env.AllChainSelectorsSolana()[0] @@ -169,7 +171,7 @@ func doTestAddRemoteChain(t *testing.T, mcms bool) { ) require.NoError(t, err) - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) var offRampSourceChain solOffRamp.SourceChain @@ -212,7 +214,7 @@ func doTestAddRemoteChain(t *testing.T, mcms bool) { require.NoError(t, err) - state, err = ccipChangeset.LoadOnchainStateSolana(e) + state, err = stateview.LoadOnchainStateSolana(e) require.NoError(t, err) err = e.SolChains[solChain].GetAccountDataBorshInto(e.GetContext(), offRampEvmSourceChainPDA, &offRampSourceChain) @@ -288,7 +290,7 @@ func doTestAddRemoteChain(t *testing.T, mcms bool) { require.NoError(t, err) - state, err = ccipChangeset.LoadOnchainStateSolana(e) + state, err = stateview.LoadOnchainStateSolana(e) require.NoError(t, err) err = e.SolChains[solChain].GetAccountDataBorshInto(e.GetContext(), offRampEvmSourceChainPDA, &offRampSourceChain) @@ -313,7 +315,7 @@ func doTestBilling(t *testing.T, mcms bool) { e, tokenAddress, err := deployTokenAndMint(t, tenv.Env, solChain, []string{}) require.NoError(t, err) - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) validTimestamp := int64(100) value := [28]uint8{} @@ -523,7 +525,7 @@ func doTestBilling(t *testing.T, mcms bool) { // just send funds to the router manually rather than run e2e billingSignerPDA, _, _ := solState.FindFeeBillingSignerPDA(state.SolChains[solChain].Router) - billingSignerATA, _, _ := solTokenUtil.FindAssociatedTokenAddress(solana.Token2022ProgramID, tokenAddress, billingSignerPDA) + billingSignerATA, _, _ := solTokenUtil.FindAssociatedTokenAddress(solana.TokenProgramID, tokenAddress, billingSignerPDA) e, _, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ commonchangeset.Configure( cldf.CreateLegacyChangeSet(ccipChangesetSolana.MintSolanaToken), @@ -542,7 +544,7 @@ func doTestBilling(t *testing.T, mcms bool) { _, billingResult, err := solTokenUtil.TokenBalance(e.GetContext(), e.SolChains[solChain].Client, billingSignerATA, cldf.SolDefaultCommitment) require.NoError(t, err) require.Equal(t, 1000, billingResult) - feeAggregatorATA, _, _ := solTokenUtil.FindAssociatedTokenAddress(solana.Token2022ProgramID, tokenAddress, feeAggregator) + feeAggregatorATA, _, _ := solTokenUtil.FindAssociatedTokenAddress(solana.TokenProgramID, tokenAddress, feeAggregator) _, feeAggResult, err := solTokenUtil.TokenBalance(e.GetContext(), e.SolChains[solChain].Client, feeAggregatorATA, cldf.SolDefaultCommitment) require.NoError(t, err) e, _, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ @@ -583,7 +585,7 @@ func doTestTokenAdminRegistry(t *testing.T, mcms bool) { solChain := tenv.Env.AllChainSelectorsSolana()[0] e, tokenAddress, err := deployTokenAndMint(t, tenv.Env, solChain, []string{}) require.NoError(t, err) - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) linkTokenAddress := state.SolChains[solChain].LinkToken newAdminNonTimelock, _ := solana.NewRandomPrivateKey() @@ -719,7 +721,7 @@ func TestTokenAdminRegistryWithoutMcms(t *testing.T) { } // pool lookup table test -func doTestPoolLookupTable(t *testing.T, e deployment.Environment, mcms bool, tokenMetadata string) { +func doTestPoolLookupTable(t *testing.T, e cldf.Environment, mcms bool, tokenMetadata string) { ctx := testcontext.Get(t) solChain := e.AllChainSelectorsSolana()[0] @@ -757,7 +759,7 @@ func doTestPoolLookupTable(t *testing.T, e deployment.Environment, mcms bool, to ), ) require.NoError(t, err) - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) lookupTablePubKey := state.SolChains[solChain].TokenPoolLookupTable[tokenAddress][pool][tokenMetadata] @@ -813,13 +815,13 @@ func doTestPoolLookupTable(t *testing.T, e deployment.Environment, mcms bool, to func TestPoolLookupTableWithMcms(t *testing.T) { t.Parallel() tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) - doTestPoolLookupTable(t, tenv.Env, true, ccipChangeset.CLLMetadata) + doTestPoolLookupTable(t, tenv.Env, true, shared.CLLMetadata) } func TestPoolLookupTableWithoutMcms(t *testing.T) { t.Parallel() tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) - doTestPoolLookupTable(t, tenv.Env, false, ccipChangeset.CLLMetadata) + doTestPoolLookupTable(t, tenv.Env, false, shared.CLLMetadata) } func TestDeployCCIPContracts(t *testing.T) { diff --git a/deployment/ccip/changeset/solana/cs_deploy_chain.go b/deployment/ccip/changeset/solana/cs_deploy_chain.go index a0c93862a52..6e2391a2a0b 100644 --- a/deployment/ccip/changeset/solana/cs_deploy_chain.go +++ b/deployment/ccip/changeset/solana/cs_deploy_chain.go @@ -17,8 +17,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -43,16 +45,16 @@ var _ cldf.ChangeSet[DeployChainContractsConfig] = DeployChainContractsChangeset func getTypeToProgramDeployName() map[cldf.ContractType]string { return map[cldf.ContractType]string{ - ccipChangeset.Router: deployment.RouterProgramName, - ccipChangeset.OffRamp: deployment.OffRampProgramName, - ccipChangeset.FeeQuoter: deployment.FeeQuoterProgramName, - ccipChangeset.BurnMintTokenPool: deployment.BurnMintTokenPoolProgramName, - ccipChangeset.LockReleaseTokenPool: deployment.LockReleaseTokenPoolProgramName, - ccipChangeset.RMNRemote: deployment.RMNRemoteProgramName, - types.AccessControllerProgram: deployment.AccessControllerProgramName, - types.ManyChainMultisigProgram: deployment.McmProgramName, - types.RBACTimelockProgram: deployment.TimelockProgramName, - ccipChangeset.Receiver: deployment.ReceiverProgramName, + shared.Router: deployment.RouterProgramName, + shared.OffRamp: deployment.OffRampProgramName, + shared.FeeQuoter: deployment.FeeQuoterProgramName, + shared.BurnMintTokenPool: deployment.BurnMintTokenPoolProgramName, + shared.LockReleaseTokenPool: deployment.LockReleaseTokenPoolProgramName, + shared.RMNRemote: deployment.RMNRemoteProgramName, + types.AccessControllerProgram: deployment.AccessControllerProgramName, + types.ManyChainMultisigProgram: deployment.McmProgramName, + types.RBACTimelockProgram: deployment.TimelockProgramName, + shared.Receiver: deployment.ReceiverProgramName, } } @@ -100,7 +102,7 @@ type UpgradeConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpgradeConfig) Validate(e deployment.Environment, chainSelector uint64) error { +func (cfg UpgradeConfig) Validate(e cldf.Environment, chainSelector uint64) error { if cfg.NewFeeQuoterVersion == nil && cfg.NewRouterVersion == nil && cfg.NewOffRampVersion == nil { return nil } @@ -116,11 +118,11 @@ func (cfg UpgradeConfig) Validate(e deployment.Environment, chainSelector uint64 return nil } -func (c DeployChainContractsConfig) Validate(e deployment.Environment) error { - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { +func (c DeployChainContractsConfig) Validate(e cldf.Environment) error { + if err := cldf.IsValidChainSelector(c.HomeChainSelector); err != nil { return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSelector, err) } - if err := deployment.IsValidChainSelector(c.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(c.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", c.ChainSelector, err) } family, _ := chainsel.GetSelectorFamily(c.ChainSelector) @@ -130,7 +132,7 @@ func (c DeployChainContractsConfig) Validate(e deployment.Environment) error { if err := c.UpgradeConfig.Validate(e, c.ChainSelector); err != nil { return fmt.Errorf("invalid UpgradeConfig: %w", err) } - existingState, err := ccipChangeset.LoadOnchainState(e) + existingState, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load existing onchain state: %w", err) } @@ -154,12 +156,12 @@ func (c DeployChainContractsConfig) Validate(e deployment.Environment) error { return nil } -func DeployChainContractsChangeset(e deployment.Environment, c DeployChainContractsConfig) (cldf.ChangesetOutput, error) { +func DeployChainContractsChangeset(e cldf.Environment, c DeployChainContractsConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(e); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) } newAddresses := cldf.NewMemoryAddressBook() - existingState, _ := ccipChangeset.LoadOnchainState(e) + existingState, _ := stateview.LoadOnchainState(e) err := v1_6.ValidateHomeChainState(e, c.HomeChainSelector, existingState) if err != nil { return cldf.ChangesetOutput{}, err @@ -231,8 +233,8 @@ func DeployChainContractsChangeset(e deployment.Environment, c DeployChainContra // DeployAndMaybeSaveToAddressBook deploys a program to the Solana chain and saves it to the address book // if it is not an upgrade. It returns the program ID of the deployed program. func DeployAndMaybeSaveToAddressBook( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ab cldf.AddressBook, contractType cldf.ContractType, version semver.Version, @@ -242,7 +244,7 @@ func DeployAndMaybeSaveToAddressBook( overallocate := true // by default we want to overallocate buffers, but if metadata is set (i.e. we're managing partner programs) // we want to set the overallocate flag to false - if metadata != "" && metadata != ccipChangeset.CLLMetadata { + if metadata != "" && metadata != shared.CLLMetadata { overallocate = false } programID, err := chain.DeployProgram(e.Logger, programName, isUpgrade, overallocate) @@ -267,14 +269,14 @@ func DeployAndMaybeSaveToAddressBook( } func deployChainContractsSolana( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ab cldf.AddressBook, config DeployChainContractsConfig, ) ([]mcmsTypes.BatchOperation, error) { // we may need to gather instructions and submit them as part of MCMS batches := make([]mcmsTypes.BatchOperation, 0) - s, err := ccipChangeset.LoadOnchainStateSolana(e) + s, err := stateview.LoadOnchainStateSolana(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return batches, err @@ -293,14 +295,14 @@ func deployChainContractsSolana( var feeQuoterAddress solana.PublicKey //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.FeeQuoter.IsZero() { - feeQuoterAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.FeeQuoter, deployment.Version1_0_0, false, "") + feeQuoterAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.FeeQuoter, deployment.Version1_0_0, false, "") if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewFeeQuoterVersion != nil { // fee quoter updated in place feeQuoterAddress = chainState.FeeQuoter - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewFeeQuoterVersion, chainState.FeeQuoter, ccipChangeset.FeeQuoter) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewFeeQuoterVersion, chainState.FeeQuoter, shared.FeeQuoter) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -322,14 +324,14 @@ func deployChainContractsSolana( //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.Router.IsZero() { // deploy router - ccipRouterProgram, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.Router, deployment.Version1_0_0, false, "") + ccipRouterProgram, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.Router, deployment.Version1_0_0, false, "") if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewRouterVersion != nil { // router updated in place ccipRouterProgram = chainState.Router - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewRouterVersion, chainState.Router, ccipChangeset.Router) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewRouterVersion, chainState.Router, shared.Router) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -351,20 +353,20 @@ func deployChainContractsSolana( //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.OffRamp.IsZero() { // deploy offramp - offRampAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.OffRamp, deployment.Version1_0_0, false, "") + offRampAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.OffRamp, deployment.Version1_0_0, false, "") if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewOffRampVersion != nil { - tv := cldf.NewTypeAndVersion(ccipChangeset.OffRamp, *config.UpgradeConfig.NewOffRampVersion) + tv := cldf.NewTypeAndVersion(shared.OffRamp, *config.UpgradeConfig.NewOffRampVersion) existingAddresses, err := e.ExistingAddresses.AddressesForChain(chain.Selector) if err != nil { return batches, fmt.Errorf("failed to get existing addresses: %w", err) } - offRampAddress = ccipChangeset.FindSolanaAddress(tv, existingAddresses) + offRampAddress = solanastateview.FindSolanaAddress(tv, existingAddresses) if offRampAddress.IsZero() { // deploy offramp, not upgraded in place so upgrade is false - offRampAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.OffRamp, *config.UpgradeConfig.NewOffRampVersion, false, "") + offRampAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.OffRamp, *config.UpgradeConfig.NewOffRampVersion, false, "") if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } @@ -383,7 +385,7 @@ func deployChainContractsSolana( return batches, fmt.Errorf("failed to build instruction: %w", err) } if config.UpgradeConfig.MCMS != nil { - priceUpdaterTx, err := BuildMCMSTxn(priceUpdaterix, feeQuoterAddress.String(), ccipChangeset.FeeQuoter) + priceUpdaterTx, err := BuildMCMSTxn(priceUpdaterix, feeQuoterAddress.String(), shared.FeeQuoter) if err != nil { return batches, fmt.Errorf("failed to create price updater transaction: %w", err) } @@ -397,7 +399,7 @@ func deployChainContractsSolana( } } } else { - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewOffRampVersion, chainState.OffRamp, ccipChangeset.OffRamp) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewOffRampVersion, chainState.OffRamp, shared.OffRamp) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -418,13 +420,13 @@ func deployChainContractsSolana( // RMN REMOTE DEPLOY var rmnRemoteAddress solana.PublicKey if chainState.RMNRemote.IsZero() { - rmnRemoteAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.RMNRemote, deployment.Version1_0_0, false, "") + rmnRemoteAddress, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.RMNRemote, deployment.Version1_0_0, false, "") if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewRMNRemoteVersion != nil { rmnRemoteAddress = chainState.RMNRemote - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewRMNRemoteVersion, chainState.RMNRemote, ccipChangeset.RMNRemote) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewRMNRemoteVersion, chainState.RMNRemote, shared.RMNRemote) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -509,19 +511,19 @@ func deployChainContractsSolana( // TOKEN POOLS DEPLOY var burnMintTokenPool solana.PublicKey - metadata := ccipChangeset.CLLMetadata + metadata := shared.CLLMetadata if config.BurnMintTokenPoolMetadata != "" { metadata = config.BurnMintTokenPoolMetadata } //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.BurnMintTokenPools[metadata].IsZero() { - burnMintTokenPool, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.BurnMintTokenPool, deployment.Version1_0_0, false, metadata) + burnMintTokenPool, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.BurnMintTokenPool, deployment.Version1_0_0, false, metadata) if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewBurnMintTokenPoolVersion != nil { burnMintTokenPool = chainState.BurnMintTokenPools[metadata] - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewBurnMintTokenPoolVersion, chainState.BurnMintTokenPools[metadata], ccipChangeset.BurnMintTokenPool) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewBurnMintTokenPoolVersion, chainState.BurnMintTokenPools[metadata], shared.BurnMintTokenPool) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -538,19 +540,19 @@ func deployChainContractsSolana( } var lockReleaseTokenPool solana.PublicKey - metadata = ccipChangeset.CLLMetadata + metadata = shared.CLLMetadata if config.LockReleaseTokenPoolMetadata != "" { metadata = config.LockReleaseTokenPoolMetadata } //nolint:gocritic // this is a false positive, we need to check if the address is zero if chainState.LockReleaseTokenPools[metadata].IsZero() { - lockReleaseTokenPool, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, ccipChangeset.LockReleaseTokenPool, deployment.Version1_0_0, false, metadata) + lockReleaseTokenPool, err = DeployAndMaybeSaveToAddressBook(e, chain, ab, shared.LockReleaseTokenPool, deployment.Version1_0_0, false, metadata) if err != nil { return batches, fmt.Errorf("failed to deploy program: %w", err) } } else if config.UpgradeConfig.NewLockReleaseTokenPoolVersion != nil { lockReleaseTokenPool = chainState.LockReleaseTokenPools[metadata] - newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewLockReleaseTokenPoolVersion, chainState.LockReleaseTokenPools[metadata], ccipChangeset.LockReleaseTokenPool) + newTxns, err := generateUpgradeTxns(e, chain, ab, config, config.UpgradeConfig.NewLockReleaseTokenPoolVersion, chainState.LockReleaseTokenPools[metadata], shared.LockReleaseTokenPool) if err != nil { return batches, fmt.Errorf("failed to generate upgrade txns: %w", err) } @@ -679,8 +681,8 @@ func deployChainContractsSolana( // INITIALIZE FUNCTIONS func initializeRouter( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ccipRouterProgram solana.PublicKey, linkTokenAddress solana.PublicKey, feeQuoterAddress solana.PublicKey, @@ -719,8 +721,8 @@ func initializeRouter( } func initializeFeeQuoter( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ccipRouterProgram solana.PublicKey, linkTokenAddress solana.PublicKey, feeQuoterAddress solana.PublicKey, @@ -770,8 +772,8 @@ func initializeFeeQuoter( } func initializeOffRamp( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ccipRouterProgram solana.PublicKey, feeQuoterAddress solana.PublicKey, rmnRemoteAddress solana.PublicKey, @@ -826,8 +828,8 @@ func initializeOffRamp( } func initializeRMNRemote( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, rmnRemoteProgram solana.PublicKey, ) error { e.Logger.Debugw("Initializing rmn remote", "chain", chain.String(), "rmnRemoteProgram", rmnRemoteProgram.String()) @@ -857,8 +859,8 @@ func initializeRMNRemote( // UPGRADE FUNCTIONS func generateUpgradeTxns( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, ab cldf.AddressBook, config DeployChainContractsConfig, newVersion *semver.Version, @@ -871,8 +873,9 @@ func generateUpgradeTxns( if err != nil { return txns, fmt.Errorf("failed to deploy program: %w", err) } - if err := setUpgradeAuthority(&e, &chain, bufferProgram, chain.DeployerKey, config.UpgradeConfig.UpgradeAuthority.ToPointer(), true); err != nil { - return txns, fmt.Errorf("failed to set upgrade authority: %w", err) + ixn := setUpgradeAuthority(&e, &chain, bufferProgram, chain.DeployerKey.PublicKey(), config.UpgradeConfig.UpgradeAuthority, true) + if err := chain.Confirm([]solana.Instruction{ixn}); err != nil { + return txns, fmt.Errorf("failed to confirm setUpgradeAuthority: %w", err) } upgradeIxn, err := generateUpgradeIxn( &e, @@ -939,7 +942,7 @@ func generateUpgradeTxns( } func generateUpgradeIxn( - e *deployment.Environment, + e *cldf.Environment, programID solana.PublicKey, bufferAddress solana.PublicKey, spillAddress solana.PublicKey, @@ -970,8 +973,8 @@ func generateUpgradeIxn( } func generateExtendIxn( - e *deployment.Environment, - chain deployment.SolChain, + e *cldf.Environment, + chain cldf.SolChain, programID solana.PublicKey, bufferAddress solana.PublicKey, payer solana.PublicKey, @@ -1020,7 +1023,7 @@ func generateExtendIxn( } func generateCloseBufferIxn( - e *deployment.Environment, + e *cldf.Environment, bufferAddress solana.PublicKey, recipient solana.PublicKey, upgradeAuthority solana.PublicKey, @@ -1042,7 +1045,7 @@ func generateCloseBufferIxn( } // HELPER FUNCTIONS -func GetSolProgramSize(e *deployment.Environment, chain deployment.SolChain, programID solana.PublicKey) (int, error) { +func GetSolProgramSize(e *cldf.Environment, chain cldf.SolChain, programID solana.PublicKey) (int, error) { accountInfo, err := chain.Client.GetAccountInfoWithOpts(e.GetContext(), programID, &rpc.GetAccountInfoOpts{ Commitment: cldf.SolDefaultCommitment, }) @@ -1056,7 +1059,7 @@ func GetSolProgramSize(e *deployment.Environment, chain deployment.SolChain, pro return programBytes, nil } -func getSolProgramData(e deployment.Environment, chain deployment.SolChain, programID solana.PublicKey) (struct { +func getSolProgramData(e cldf.Environment, chain cldf.SolChain, programID solana.PublicKey) (struct { DataType uint32 Address solana.PublicKey }, error) { @@ -1083,7 +1086,7 @@ type CloseBuffersConfig struct { Buffers []string } -func CloseBuffersChangeset(e deployment.Environment, cfg CloseBuffersConfig) (cldf.ChangesetOutput, error) { +func CloseBuffersChangeset(e cldf.Environment, cfg CloseBuffersConfig) (cldf.ChangesetOutput, error) { for _, buffer := range cfg.Buffers { if err := e.SolChains[cfg.ChainSelector].CloseBuffers(e.Logger, buffer); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to close buffer: %w", err) diff --git a/deployment/ccip/changeset/solana/cs_deploy_chain_test.go b/deployment/ccip/changeset/solana/cs_deploy_chain_test.go index 44fa42f3fa6..b3f92c38cb0 100644 --- a/deployment/ccip/changeset/solana/cs_deploy_chain_test.go +++ b/deployment/ccip/changeset/solana/cs_deploy_chain_test.go @@ -13,11 +13,12 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" @@ -35,8 +36,8 @@ const ( NewSha = "cb02e90f9d6d1dd65f534c60a77bb1e3384a42cb" ) -func verifyProgramSizes(t *testing.T, e deployment.Environment) { - state, err := ccipChangeset.LoadOnchainStateSolana(e) +func verifyProgramSizes(t *testing.T, e cldf.Environment) { + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) addresses, err := e.ExistingAddresses.AddressesForChain(e.AllChainSelectorsSolana()[0]) require.NoError(t, err) @@ -46,14 +47,14 @@ func verifyProgramSizes(t *testing.T, e deployment.Environment) { deployment.RouterProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].Router, deployment.OffRampProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].OffRamp, deployment.FeeQuoterProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].FeeQuoter, - deployment.BurnMintTokenPoolProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].BurnMintTokenPools[ccipChangeset.CLLMetadata], - deployment.LockReleaseTokenPoolProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].LockReleaseTokenPools[ccipChangeset.CLLMetadata], + deployment.BurnMintTokenPoolProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].BurnMintTokenPools[shared.CLLMetadata], + deployment.LockReleaseTokenPoolProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].LockReleaseTokenPools[shared.CLLMetadata], deployment.AccessControllerProgramName: chainState.AccessControllerProgram, deployment.TimelockProgramName: chainState.TimelockProgram, deployment.McmProgramName: chainState.McmProgram, deployment.RMNRemoteProgramName: state.SolChains[e.AllChainSelectorsSolana()[0]].RMNRemote, } - for program, sizeBytes := range deployment.GetSolanaProgramBytes() { + for program, sizeBytes := range cldf.GetSolanaProgramBytes() { t.Logf("Verifying program %s size is at least %d bytes", program, sizeBytes) programDataAccount, _, _ := solana.FindProgramAddress([][]byte{programsToState[program].Bytes()}, solana.BPFLoaderUpgradeableProgramID) programDataSize, err := ccipChangesetSolana.GetSolProgramSize(&e, e.SolChains[e.AllChainSelectorsSolana()[0]], programDataAccount) @@ -62,7 +63,7 @@ func verifyProgramSizes(t *testing.T, e deployment.Environment) { } } -func initialDeployCS(t *testing.T, e deployment.Environment, buildConfig *ccipChangesetSolana.BuildSolanaConfig) []commonchangeset.ConfiguredChangeSet { +func initialDeployCS(t *testing.T, e cldf.Environment, buildConfig *ccipChangesetSolana.BuildSolanaConfig) []commonchangeset.ConfiguredChangeSet { evmSelectors := e.AllChainSelectors() homeChainSel := evmSelectors[0] solChainSelectors := e.AllChainSelectorsSolana() @@ -206,7 +207,7 @@ func TestUpgrade(t *testing.T) { }) upgradeAuthority := timelockSignerPDA // upgradeAuthority := e.SolChains[solChainSelectors[0]].DeployerKey.PublicKey() - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) verifyProgramSizes(t, e) addresses, err := e.ExistingAddresses.AddressesForChain(e.AllChainSelectorsSolana()[0]) @@ -260,15 +261,15 @@ func TestUpgrade(t *testing.T) { CleanDestinationDir: true, CleanGitDir: true, UpgradeKeys: map[cldf.ContractType]string{ - ccipChangeset.Router: state.SolChains[solChainSelectors[0]].Router.String(), - ccipChangeset.FeeQuoter: state.SolChains[solChainSelectors[0]].FeeQuoter.String(), - ccipChangeset.BurnMintTokenPool: state.SolChains[solChainSelectors[0]].BurnMintTokenPools[ccipChangeset.CLLMetadata].String(), - ccipChangeset.LockReleaseTokenPool: state.SolChains[solChainSelectors[0]].LockReleaseTokenPools[ccipChangeset.CLLMetadata].String(), - ccipChangeset.OffRamp: state.SolChains[solChainSelectors[0]].OffRamp.String(), - types.AccessControllerProgram: chainState.AccessControllerProgram.String(), - types.RBACTimelockProgram: chainState.TimelockProgram.String(), - types.ManyChainMultisigProgram: chainState.McmProgram.String(), - ccipChangeset.RMNRemote: state.SolChains[solChainSelectors[0]].RMNRemote.String(), + shared.Router: state.SolChains[solChainSelectors[0]].Router.String(), + shared.FeeQuoter: state.SolChains[solChainSelectors[0]].FeeQuoter.String(), + shared.BurnMintTokenPool: state.SolChains[solChainSelectors[0]].BurnMintTokenPools[shared.CLLMetadata].String(), + shared.LockReleaseTokenPool: state.SolChains[solChainSelectors[0]].LockReleaseTokenPools[shared.CLLMetadata].String(), + shared.OffRamp: state.SolChains[solChainSelectors[0]].OffRamp.String(), + types.AccessControllerProgram: chainState.AccessControllerProgram.String(), + types.RBACTimelockProgram: chainState.TimelockProgram.String(), + types.ManyChainMultisigProgram: chainState.McmProgram.String(), + shared.RMNRemote: state.SolChains[solChainSelectors[0]].RMNRemote.String(), }, }, }, @@ -287,7 +288,7 @@ func TestUpgrade(t *testing.T) { }) require.NoError(t, err) testhelpers.ValidateSolanaState(t, e, solChainSelectors) - state, err = ccipChangeset.LoadOnchainStateSolana(e) + state, err = stateview.LoadOnchainStateSolana(e) require.NoError(t, err) oldOffRampAddress := state.SolChains[solChainSelectors[0]].OffRamp // add a second offramp address @@ -318,7 +319,7 @@ func TestUpgrade(t *testing.T) { }) require.NoError(t, err) // verify the offramp address is different - state, err = ccipChangeset.LoadOnchainStateSolana(e) + state, err = stateview.LoadOnchainStateSolana(e) require.NoError(t, err) newOffRampAddress := state.SolChains[solChainSelectors[0]].OffRamp require.NotEqual(t, oldOffRampAddress, newOffRampAddress) @@ -331,13 +332,13 @@ func TestUpgrade(t *testing.T) { numFeeQuoters := 0 numOffRamps := 0 for _, address := range addresses { - if address.Type == ccipChangeset.Router { + if address.Type == shared.Router { numRouters++ } - if address.Type == ccipChangeset.FeeQuoter { + if address.Type == shared.FeeQuoter { numFeeQuoters++ } - if address.Type == ccipChangeset.OffRamp { + if address.Type == shared.OffRamp { numOffRamps++ } } diff --git a/deployment/ccip/changeset/solana/cs_disable_remote_chain.go b/deployment/ccip/changeset/solana/cs_disable_remote_chain.go index af9f92e38e8..7e829d72726 100644 --- a/deployment/ccip/changeset/solana/cs_disable_remote_chain.go +++ b/deployment/ccip/changeset/solana/cs_disable_remote_chain.go @@ -16,9 +16,9 @@ import ( solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - cs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -31,8 +31,8 @@ type DisableRemoteChainConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg DisableRemoteChainConfig) Validate(e deployment.Environment) error { - state, err := cs.LoadOnchainState(e) +func (cfg DisableRemoteChainConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -47,7 +47,7 @@ func (cfg DisableRemoteChainConfig) Validate(e deployment.Environment) error { if err := validateOffRampConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true, ccipChangeset.OffRamp: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true, shared.OffRamp: true}); err != nil { return err } var routerConfigAccount solRouter.Config @@ -62,7 +62,7 @@ func (cfg DisableRemoteChainConfig) Validate(e deployment.Environment) error { if remote == routerConfigAccount.SvmChainSelector { return fmt.Errorf("cannot disable remote chain %d with same chain selector as current chain %d", remote, cfg.ChainSelector) } - if err := state.ValidateRamp(remote, cs.OnRamp); err != nil { + if err := state.ValidateRamp(remote, shared.OnRamp); err != nil { return err } routerDestChainPDA, err := solState.FindDestChainStatePDA(remote, chainState.Router) @@ -78,12 +78,12 @@ func (cfg DisableRemoteChainConfig) Validate(e deployment.Environment) error { return nil } -func DisableRemoteChain(e deployment.Environment, cfg DisableRemoteChainConfig) (cldf.ChangesetOutput, error) { +func DisableRemoteChain(e cldf.Environment, cfg DisableRemoteChainConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := cs.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -108,8 +108,8 @@ func DisableRemoteChain(e deployment.Environment, cfg DisableRemoteChainConfig) } func doDisableRemoteChain( - e deployment.Environment, - s cs.CCIPOnChainState, + e cldf.Environment, + s stateview.CCIPOnChainState, cfg DisableRemoteChainConfig) ([]mcmsTypes.Transaction, error) { txns := make([]mcmsTypes.Transaction, 0) ixns := make([]solana.Instruction, 0) @@ -118,18 +118,18 @@ func doDisableRemoteChain( chainState := s.SolChains[chainSel] feeQuoterID := s.SolChains[chainSel].FeeQuoter offRampID := s.SolChains[chainSel].OffRamp - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") @@ -144,7 +144,7 @@ func doDisableRemoteChain( chain, chainState, cfg.MCMS, - cs.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "", ) @@ -158,7 +158,7 @@ func doDisableRemoteChain( return txns, fmt.Errorf("failed to generate instructions: %w", err) } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(feeQuoterIx, feeQuoterID.String(), cs.FeeQuoter) + tx, err := BuildMCMSTxn(feeQuoterIx, feeQuoterID.String(), shared.FeeQuoter) if err != nil { return txns, fmt.Errorf("failed to create transaction: %w", err) } @@ -173,7 +173,7 @@ func doDisableRemoteChain( chain, chainState, cfg.MCMS, - cs.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") offRampIx, err := solOffRamp.NewDisableSourceChainSelectorInstruction( @@ -186,7 +186,7 @@ func doDisableRemoteChain( return txns, fmt.Errorf("failed to generate instructions: %w", err) } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(offRampIx, offRampID.String(), cs.OffRamp) + tx, err := BuildMCMSTxn(offRampIx, offRampID.String(), shared.OffRamp) if err != nil { return txns, fmt.Errorf("failed to create transaction: %w", err) } diff --git a/deployment/ccip/changeset/solana/cs_e2e.go b/deployment/ccip/changeset/solana/cs_e2e.go new file mode 100644 index 00000000000..b099aeac761 --- /dev/null +++ b/deployment/ccip/changeset/solana/cs_e2e.go @@ -0,0 +1,180 @@ +package solana + +import ( + "fmt" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" +) + +// use this changeset to add a token pool and lookup table +var _ cldf.ChangeSet[E2ETokenPoolConfig] = E2ETokenPool + +type E2ETokenPoolConfig struct { + AddTokenPoolAndLookupTable []TokenPoolConfig + AddTokenPoolLookupTable []TokenPoolLookupTableConfig + RegisterTokenAdminRegistry []RegisterTokenAdminRegistryConfig + AcceptAdminRoleTokenAdminRegistry []AcceptAdminRoleTokenAdminRegistryConfig + SetPool []SetPoolConfig + RemoteChainTokenPool []RemoteChainTokenPoolConfig + ConfigureTokenPoolContractsChangesets []v1_5_1.ConfigureTokenPoolContractsConfig +} + +func E2ETokenPool(e cldf.Environment, cfg E2ETokenPoolConfig) (cldf.ChangesetOutput, error) { + finalOutput := cldf.ChangesetOutput{} + defer func(e cldf.Environment) { + e.Logger.Info("SolanaE2ETokenPool changeset completed") + e.Logger.Info("Final output: ", finalOutput.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + }(e) + + for _, tokenPoolConfig := range cfg.AddTokenPoolAndLookupTable { + output, err := AddTokenPoolAndLookupTable(e, tokenPoolConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to add token pool lookup table: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, tokenPoolConfig := range cfg.AddTokenPoolLookupTable { + output, err := AddTokenPoolLookupTable(e, tokenPoolConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to add token pool lookup table: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, registerConfig := range cfg.RegisterTokenAdminRegistry { + output, err := RegisterTokenAdminRegistry(e, registerConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to register token admin registry: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, acceptConfig := range cfg.AcceptAdminRoleTokenAdminRegistry { + output, err := AcceptAdminRoleTokenAdminRegistry(e, acceptConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to accept admin role token admin registry: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, setPoolConfig := range cfg.SetPool { + output, err := SetPool(e, setPoolConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to set pool: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, remoteChainConfig := range cfg.RemoteChainTokenPool { + output, err := SetupTokenPoolForRemoteChain(e, remoteChainConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to remote chain token pool config: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, configureTokenPoolConfig := range cfg.ConfigureTokenPoolContractsChangesets { + output, err := v1_5_1.ConfigureTokenPoolContractsChangeset(e, configureTokenPoolConfig) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to configure token pool contracts: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + + return finalOutput, nil +} + +type E2ETokenConfig struct { + DeploySolanaToken []DeploySolanaTokenConfig + UploadTokenMetadata []UploadTokenMetadataConfig + SetTokenAuthority []SetTokenAuthorityConfig +} + +func E2EToken(e cldf.Environment, cfg E2ETokenConfig) (cldf.ChangesetOutput, error) { + finalOutput := cldf.ChangesetOutput{} + defer func(e cldf.Environment) { + e.Logger.Info("E2EToken changeset completed") + e.Logger.Info("Final output: ", finalOutput.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + }(e) + + for _, config := range cfg.DeploySolanaToken { + output, err := DeploySolanaToken(e, config) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to deploy solana token: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, config := range cfg.UploadTokenMetadata { + output, err := UploadTokenMetadata(e, config) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to upload token metadata: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + for _, config := range cfg.SetTokenAuthority { + output, err := SetTokenAuthority(e, config) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to register token admin registry: %w", err) + } + err = finalOutput.AddressBook.Merge(output.AddressBook) //nolint:staticcheck // Addressbook is deprecated, but we still use it for the time being + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to merge address book: %w", err) + } + if len(output.MCMSTimelockProposals) > 0 { + finalOutput.MCMSTimelockProposals = append(finalOutput.MCMSTimelockProposals, output.MCMSTimelockProposals...) + } + } + + return finalOutput, nil +} diff --git a/deployment/ccip/changeset/solana/cs_idl.go b/deployment/ccip/changeset/solana/cs_idl.go index 6d143b56420..70ac6059c1a 100644 --- a/deployment/ccip/changeset/solana/cs_idl.go +++ b/deployment/ccip/changeset/solana/cs_idl.go @@ -20,7 +20,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -57,7 +57,7 @@ func parseAnchorVersion(output string) (string, error) { } // create Anchor.toml file to simulate anchor workspace -func writeAnchorToml(e deployment.Environment, filename, anchorVersion, cluster, wallet string) error { +func writeAnchorToml(e cldf.Environment, filename, anchorVersion, cluster, wallet string) error { e.Logger.Debugw("Writing Anchor.toml", "filename", filename, "anchorVersion", anchorVersion, "cluster", cluster, "wallet", wallet) config := map[string]interface{}{ "toolchain": map[string]string{ @@ -89,7 +89,7 @@ func writeAnchorToml(e deployment.Environment, filename, anchorVersion, cluster, } // resolve artifacts based on sha and write anchor.toml file to simulate anchor workspace -func repoSetup(e deployment.Environment, chain deployment.SolChain, gitCommitSha string) error { +func repoSetup(e cldf.Environment, chain cldf.SolChain, gitCommitSha string) error { e.Logger.Debug("Downloading Solana CCIP program artifacts...") err := memory.DownloadSolanaCCIPProgramArtifacts(e.GetContext(), chain.ProgramsPath, e.Logger, gitCommitSha) if err != nil { @@ -116,7 +116,7 @@ func repoSetup(e deployment.Environment, chain deployment.SolChain, gitCommitSha } // update IDL with program ID -func updateIDL(e deployment.Environment, idlFile string, programID string) error { +func updateIDL(e cldf.Environment, idlFile string, programID string) error { e.Logger.Debug("Reading IDL") idlBytes, err := os.ReadFile(idlFile) if err != nil { @@ -146,7 +146,7 @@ func updateIDL(e deployment.Environment, idlFile string, programID string) error } // get IDL file and update with program ID -func getIDL(e deployment.Environment, programsPath, programID string, programName string) (string, error) { +func getIDL(e cldf.Environment, programsPath, programID string, programName string) (string, error) { idlFile := filepath.Join(programsPath, programName+".json") if _, err := os.Stat(idlFile); err != nil { return "", fmt.Errorf("idl file not found: %w", err) @@ -160,7 +160,7 @@ func getIDL(e deployment.Environment, programsPath, programID string, programNam } // initialize IDL for a program -func idlInit(e deployment.Environment, programsPath, programID, programName string) error { +func idlInit(e cldf.Environment, programsPath, programID, programName string) error { idlFile, err := getIDL(e, programsPath, programID, programName) if err != nil { return fmt.Errorf("error getting IDL: %w", err) @@ -179,7 +179,7 @@ func idlInit(e deployment.Environment, programsPath, programID, programName stri } // set IDL authority for a program -func setIdlAuthority(e deployment.Environment, newAuthority, programsPath, programID, programName, bufferAccount string) error { +func setIdlAuthority(e cldf.Environment, newAuthority, programsPath, programID, programName, bufferAccount string) error { e.Logger.Infow("Setting IDL authority", "programName", programName, "newAuthority", newAuthority) args := []string{"idl", "set-authority", "-n", newAuthority, "-p", programID} if bufferAccount != "" { @@ -195,7 +195,7 @@ func setIdlAuthority(e deployment.Environment, newAuthority, programsPath, progr } // get IDL address for a program -func getIDLAddress(e deployment.Environment, programID solana.PublicKey) (solana.PublicKey, error) { +func getIDLAddress(e cldf.Environment, programID solana.PublicKey) (solana.PublicKey, error) { base, _, _ := solana.FindProgramAddress([][]byte{}, programID) idlAddress, _ := solana.CreateWithSeed(base, "anchor:idl", programID) e.Logger.Infof("IDL Address: %s", idlAddress.String()) @@ -214,7 +214,7 @@ func parseIdlBuffer(output string) (string, error) { } // write IDL buffer for a program -func writeBuffer(e deployment.Environment, programsPath, programID, programName string) (solana.PublicKey, error) { +func writeBuffer(e cldf.Environment, programsPath, programID, programName string) (solana.PublicKey, error) { idlFile, err := getIDL(e, programsPath, programID, programName) if err != nil { return solana.PublicKey{}, fmt.Errorf("error getting IDL: %w", err) @@ -239,7 +239,7 @@ func writeBuffer(e deployment.Environment, programsPath, programID, programName } // generate set buffer ix using solana-go sdk -func setBufferIx(e deployment.Environment, programID, buffer, authority solana.PublicKey) (solana.GenericInstruction, error) { +func setBufferIx(e cldf.Environment, programID, buffer, authority solana.PublicKey) (solana.GenericInstruction, error) { idlAddress, err := getIDLAddress(e, programID) if err != nil { return solana.GenericInstruction{}, fmt.Errorf("error getting idl address for %s: %w", programID.String(), err) @@ -260,7 +260,7 @@ func setBufferIx(e deployment.Environment, programID, buffer, authority solana.P } // generate upgrade IDL ix for a program via timelock -func upgradeIDLIx(e deployment.Environment, programsPath, programID, programName string, c IDLConfig) (*mcmsTypes.Transaction, error) { +func upgradeIDLIx(e cldf.Environment, programsPath, programID, programName string, c IDLConfig) (*mcmsTypes.Transaction, error) { timelockSignerPDA, err := FetchTimelockSigner(e, c.ChainSelector) if err != nil { return nil, fmt.Errorf("error loading timelockSignerPDA: %w", err) @@ -294,15 +294,15 @@ func upgradeIDLIx(e deployment.Environment, programsPath, programID, programName return nil, nil } -func (c IDLConfig) Validate(e deployment.Environment) error { - if err := deployment.IsValidChainSelector(c.ChainSelector); err != nil { +func (c IDLConfig) Validate(e cldf.Environment) error { + if err := cldf.IsValidChainSelector(c.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", c.ChainSelector, err) } family, _ := chainsel.GetSelectorFamily(c.ChainSelector) if family != chainsel.FamilySolana { return fmt.Errorf("chain %d is not a solana chain", c.ChainSelector) } - existingState, err := ccipChangeset.LoadOnchainState(e) + existingState, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load existing onchain state: %w", err) } @@ -351,12 +351,12 @@ func (c IDLConfig) Validate(e deployment.Environment) error { } // changeset to upload idl for a program -func UploadIDL(e deployment.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { +func UploadIDL(e cldf.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(e); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error validating idl config: %w", err) } chain := e.SolChains[c.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[c.ChainSelector] if err := repoSetup(e, chain, c.GitCommitSha); err != nil { @@ -432,11 +432,11 @@ func UploadIDL(e deployment.Environment, c IDLConfig) (cldf.ChangesetOutput, err } // changeset to set idl authority for a program to timelock -func SetAuthorityIDL(e deployment.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { +func SetAuthorityIDL(e cldf.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(e); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error validating idl config: %w", err) } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[c.ChainSelector] chain := e.SolChains[c.ChainSelector] @@ -521,12 +521,12 @@ func SetAuthorityIDL(e deployment.Environment, c IDLConfig) (cldf.ChangesetOutpu // set buffer authority to timelock using anchor cli // generate set buffer ix using solana-go sdk // build mcms txn to upgrade idl -func UpgradeIDL(e deployment.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { +func UpgradeIDL(e cldf.Environment, c IDLConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(e); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error validating idl config: %w", err) } chain := e.SolChains[c.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[c.ChainSelector] if err := repoSetup(e, chain, c.GitCommitSha); err != nil { diff --git a/deployment/ccip/changeset/solana/cs_ops.go b/deployment/ccip/changeset/solana/cs_ops.go index 1f490b6415e..a5dd5d8f412 100644 --- a/deployment/ccip/changeset/solana/cs_ops.go +++ b/deployment/ccip/changeset/solana/cs_ops.go @@ -16,8 +16,9 @@ import ( solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -42,8 +43,8 @@ type SetDefaultCodeVersionConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg SetDefaultCodeVersionConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg SetDefaultCodeVersionConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -58,38 +59,38 @@ func (cfg SetDefaultCodeVersionConfig) Validate(e deployment.Environment) error if err := validateFeeQuoterConfig(chain, chainState); err != nil { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.FeeQuoter: true, ccipChangeset.OffRamp: true, ccipChangeset.Router: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.FeeQuoter: true, shared.OffRamp: true, shared.Router: true}) } -func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionConfig) (cldf.ChangesetOutput, error) { +func SetDefaultCodeVersion(e cldf.Environment, cfg SetDefaultCodeVersionConfig) (cldf.ChangesetOutput, error) { e.Logger.Infow("Setting default code version", "chain_selector", cfg.ChainSelector, "new_code_version", cfg.VersionEnum) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") - feeQuoterUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + feeQuoterUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") txns := make([]mcmsTypes.Transaction, 0) @@ -99,7 +100,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") solRouter.SetProgramID(chainState.Router) @@ -114,7 +115,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -128,7 +129,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo chain, chainState, cfg.MCMS, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") solOffRamp.SetProgramID(chainState.OffRamp) @@ -142,7 +143,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), shared.OffRamp) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -156,7 +157,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo chain, chainState, cfg.MCMS, - ccipChangeset.FeeQuoter, + shared.FeeQuoter, solana.PublicKey{}, "") solFeeQuoter.SetProgramID(chainState.FeeQuoter) @@ -170,7 +171,7 @@ func SetDefaultCodeVersion(e deployment.Environment, cfg SetDefaultCodeVersionCo } if feeQuoterUsingMCMS { - tx, err := BuildMCMSTxn(ixn3, chainState.FeeQuoter.String(), ccipChangeset.FeeQuoter) + tx, err := BuildMCMSTxn(ixn3, chainState.FeeQuoter.String(), shared.FeeQuoter) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -205,8 +206,8 @@ type UpdateSvmChainSelectorConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateSvmChainSelectorConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg UpdateSvmChainSelectorConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -218,32 +219,32 @@ func (cfg UpdateSvmChainSelectorConfig) Validate(e deployment.Environment) error if err := validateOffRampConfig(chain, chainState); err != nil { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true, ccipChangeset.OffRamp: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true, shared.OffRamp: true}) } -func UpdateSvmChainSelector(e deployment.Environment, cfg UpdateSvmChainSelectorConfig) (cldf.ChangesetOutput, error) { +func UpdateSvmChainSelector(e cldf.Environment, cfg UpdateSvmChainSelectorConfig) (cldf.ChangesetOutput, error) { e.Logger.Infow("Updating SVM chain selector", "old_chain_selector", cfg.OldChainSelector, "new_chain_selector", cfg.NewChainSelector) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.OldChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.OldChainSelector] routerConfigPDA, _, _ := solState.FindConfigPDA(chainState.Router) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") txns := make([]mcmsTypes.Transaction, 0) @@ -253,7 +254,7 @@ func UpdateSvmChainSelector(e deployment.Environment, cfg UpdateSvmChainSelector chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") solRouter.SetProgramID(chainState.Router) @@ -268,7 +269,7 @@ func UpdateSvmChainSelector(e deployment.Environment, cfg UpdateSvmChainSelector } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -282,7 +283,7 @@ func UpdateSvmChainSelector(e deployment.Environment, cfg UpdateSvmChainSelector chain, chainState, cfg.MCMS, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") solOffRamp.SetProgramID(chainState.OffRamp) @@ -296,7 +297,7 @@ func UpdateSvmChainSelector(e deployment.Environment, cfg UpdateSvmChainSelector } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), shared.OffRamp) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -331,8 +332,8 @@ type UpdateEnableManualExecutionAfterConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateEnableManualExecutionAfterConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg UpdateEnableManualExecutionAfterConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -341,24 +342,24 @@ func (cfg UpdateEnableManualExecutionAfterConfig) Validate(e deployment.Environm if err := validateOffRampConfig(chain, chainState); err != nil { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.OffRamp: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.OffRamp: true}) } -func UpdateEnableManualExecutionAfter(e deployment.Environment, cfg UpdateEnableManualExecutionAfterConfig) (cldf.ChangesetOutput, error) { +func UpdateEnableManualExecutionAfter(e cldf.Environment, cfg UpdateEnableManualExecutionAfterConfig) (cldf.ChangesetOutput, error) { e.Logger.Infow("Updating enable manual execution after", "chain_selector", cfg.ChainSelector, "enable_manual_execution_after", cfg.EnableManualExecution) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] - offRampUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + offRampUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") txns := make([]mcmsTypes.Transaction, 0) @@ -368,7 +369,7 @@ func UpdateEnableManualExecutionAfter(e deployment.Environment, cfg UpdateEnable chain, chainState, cfg.MCMS, - ccipChangeset.OffRamp, + shared.OffRamp, solana.PublicKey{}, "") solOffRamp.SetProgramID(chainState.OffRamp) @@ -382,7 +383,7 @@ func UpdateEnableManualExecutionAfter(e deployment.Environment, cfg UpdateEnable } if offRampUsingMCMS { - tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(ixn2, chainState.OffRamp.String(), shared.OffRamp) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -425,8 +426,8 @@ type ConfigureCCIPVersionConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg ConfigureCCIPVersionConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg ConfigureCCIPVersionConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -444,24 +445,24 @@ func (cfg ConfigureCCIPVersionConfig) Validate(e deployment.Environment) error { if err != nil { return fmt.Errorf("remote %d is not configured on solana chain %d", cfg.DestChainSelector, cfg.ChainSelector) } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}) } -func ConfigureCCIPVersion(e deployment.Environment, cfg ConfigureCCIPVersionConfig) (cldf.ChangesetOutput, error) { +func ConfigureCCIPVersion(e cldf.Environment, cfg ConfigureCCIPVersionConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] destChainStatePDA, _ := solState.FindDestChainStatePDA(cfg.DestChainSelector, chainState.Router) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") txns := make([]mcmsTypes.Transaction, 0) @@ -471,7 +472,7 @@ func ConfigureCCIPVersion(e deployment.Environment, cfg ConfigureCCIPVersionConf chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") solRouter.SetProgramID(chainState.Router) @@ -500,7 +501,7 @@ func ConfigureCCIPVersion(e deployment.Environment, cfg ConfigureCCIPVersionConf } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -535,8 +536,8 @@ type RemoveOffRampConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg RemoveOffRampConfig) Validate(e deployment.Environment) error { - state, err := ccipChangeset.LoadOnchainState(e) +func (cfg RemoveOffRampConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -545,23 +546,23 @@ func (cfg RemoveOffRampConfig) Validate(e deployment.Environment) error { if err := validateRouterConfig(chain, chainState); err != nil { return err } - return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}) + return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}) } -func RemoveOffRamp(e deployment.Environment, cfg RemoveOffRampConfig) (cldf.ChangesetOutput, error) { +func RemoveOffRamp(e cldf.Environment, cfg RemoveOffRampConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") txns := make([]mcmsTypes.Transaction, 0) @@ -571,7 +572,7 @@ func RemoveOffRamp(e deployment.Environment, cfg RemoveOffRampConfig) (cldf.Chan chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") solRouter.SetProgramID(chainState.Router) @@ -588,7 +589,7 @@ func RemoveOffRamp(e deployment.Environment, cfg RemoveOffRampConfig) (cldf.Chan } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ixn, chainState.Router.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } diff --git a/deployment/ccip/changeset/solana/cs_set_ocr3.go b/deployment/ccip/changeset/solana/cs_set_ocr3.go index cef5ff795c9..b2634164366 100644 --- a/deployment/ccip/changeset/solana/cs_set_ocr3.go +++ b/deployment/ccip/changeset/solana/cs_set_ocr3.go @@ -16,11 +16,11 @@ import ( solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" csState "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -47,8 +47,8 @@ func btoi(b bool) uint8 { // run after the candidate is confirmed to be working correctly. // Multichain is especially helpful for NOP rotations where we have // to touch all the chain to change signers. -func SetOCR3ConfigSolana(e deployment.Environment, cfg v1_6.SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func SetOCR3ConfigSolana(e cldf.Environment, cfg v1_6.SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -63,7 +63,7 @@ func SetOCR3ConfigSolana(e deployment.Environment, cfg v1_6.SetOCR3OffRampConfig return cldf.ChangesetOutput{}, fmt.Errorf("chain %d is not a solana chain", remote) } chain := e.SolChains[remote] - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, cfg.MCMS != nil, state.SolChains[remote].OffRamp, ccipChangeset.OffRamp, solana.PublicKey{}); err != nil { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, cfg.MCMS != nil, state.SolChains[remote].OffRamp, shared.OffRamp, solana.PublicKey{}); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to validate ownership: %w", err) } } @@ -146,7 +146,7 @@ func SetOCR3ConfigSolana(e deployment.Environment, cfg v1_6.SetOCR3OffRampConfig return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err) } } else { - tx, err := BuildMCMSTxn(instruction, state.SolChains[remote].OffRamp.String(), ccipChangeset.OffRamp) + tx, err := BuildMCMSTxn(instruction, state.SolChains[remote].OffRamp.String(), shared.OffRamp) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -178,9 +178,9 @@ func SetOCR3ConfigSolana(e deployment.Environment, cfg v1_6.SetOCR3OffRampConfig } func isOCR3ConfigSetOnOffRampSolana( - e deployment.Environment, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, args []internal.MultiOCR3BaseOCRConfigArgsSolana, ) (bool, error) { var configAccount solOffRamp.Config diff --git a/deployment/ccip/changeset/solana/cs_solana_token.go b/deployment/ccip/changeset/solana/cs_solana_token.go index 7dccb0dabc4..af6990f8a19 100644 --- a/deployment/ccip/changeset/solana/cs_solana_token.go +++ b/deployment/ccip/changeset/solana/cs_solana_token.go @@ -10,7 +10,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" solToken "github.com/gagliardetto/solana-go/programs/token" @@ -30,8 +30,7 @@ var _ cldf.ChangeSet[CreateSolanaTokenATAConfig] = CreateSolanaTokenATA // use this changeset to set the authority of a token var _ cldf.ChangeSet[SetTokenAuthorityConfig] = SetTokenAuthority -func getMintIxs(e deployment.Environment, chain deployment.SolChain, tokenprogramID, mint solana.PublicKey, amountToAddress map[string]uint64) ([]solana.Instruction, error) { - instructions := []solana.Instruction{} +func getMintIxs(e cldf.Environment, chain cldf.SolChain, tokenprogramID, mint solana.PublicKey, amountToAddress map[string]uint64) error { for toAddress, amount := range amountToAddress { e.Logger.Infof("Minting %d to %s", amount, toAddress) toAddressBase58 := solana.MustPublicKeyFromBase58(toAddress) @@ -39,15 +38,17 @@ func getMintIxs(e deployment.Environment, chain deployment.SolChain, tokenprogra ata, _, _ := solTokenUtil.FindAssociatedTokenAddress(tokenprogramID, mint, toAddressBase58) mintToI, err := solTokenUtil.MintTo(amount, tokenprogramID, mint, ata, chain.DeployerKey.PublicKey()) if err != nil { - return nil, err + return err + } + if err := chain.Confirm([]solana.Instruction{mintToI}); err != nil { + e.Logger.Errorw("Failed to confirm instructions for minting", "chain", chain.String(), "err", err) + return err } - instructions = append(instructions, mintToI) } - return instructions, nil + return nil } -func createATAIx(e deployment.Environment, chain deployment.SolChain, tokenprogramID, mint solana.PublicKey, ataList []string) ([]solana.Instruction, error) { - instructions := []solana.Instruction{} +func createATAIx(e cldf.Environment, chain cldf.SolChain, tokenprogramID, mint solana.PublicKey, ataList []string) error { for _, ata := range ataList { e.Logger.Infof("Creating ATA for account %s for token %s", ata, mint.String()) createATAIx, _, err := solTokenUtil.CreateAssociatedTokenAccount( @@ -57,11 +58,14 @@ func createATAIx(e deployment.Environment, chain deployment.SolChain, tokenprogr chain.DeployerKey.PublicKey(), ) if err != nil { - return nil, err + return err + } + if err := chain.Confirm([]solana.Instruction{createATAIx}); err != nil { + e.Logger.Errorw("Failed to confirm instructions for ATA creation", "chain", chain.String(), "err", err) + return err } - instructions = append(instructions, createATAIx) } - return instructions, nil + return nil } // TODO: add option to set token mint authority by taking in its public key @@ -76,7 +80,7 @@ type DeploySolanaTokenConfig struct { MintAmountToAddress map[string]uint64 // address -> amount } -func NewTokenInstruction(chain deployment.SolChain, cfg DeploySolanaTokenConfig) ([]solana.Instruction, solana.PrivateKey, error) { +func NewTokenInstruction(chain cldf.SolChain, cfg DeploySolanaTokenConfig) ([]solana.Instruction, solana.PrivateKey, error) { tokenprogramID, err := GetTokenProgramID(cfg.TokenProgramName) if err != nil { return nil, nil, err @@ -112,7 +116,7 @@ func NewTokenInstruction(chain deployment.SolChain, cfg DeploySolanaTokenConfig) return instructions, mintPrivKey, nil } -func DeploySolanaToken(e deployment.Environment, cfg DeploySolanaTokenConfig) (cldf.ChangesetOutput, error) { +func DeploySolanaToken(e cldf.Environment, cfg DeploySolanaTokenConfig) (cldf.ChangesetOutput, error) { chain, ok := e.SolChains[cfg.ChainSelector] if !ok { return cldf.ChangesetOutput{}, fmt.Errorf("chain %d not found in environment", cfg.ChainSelector) @@ -129,23 +133,21 @@ func DeploySolanaToken(e deployment.Environment, cfg DeploySolanaTokenConfig) (c return cldf.ChangesetOutput{}, err } - // ata ix - ataIxs, err := createATAIx(e, chain, tokenprogramID, mint, cfg.ATAList) + err = chain.Confirm(instructions, solCommonUtil.AddSigners(mintPrivKey)) if err != nil { + e.Logger.Errorw("Failed to confirm instructions for token deployment", "chain", chain.String(), "err", err) return cldf.ChangesetOutput{}, err } - instructions = append(instructions, ataIxs...) - // mint ix - mintIxs, err := getMintIxs(e, chain, tokenprogramID, mint, cfg.MintAmountToAddress) + // ata ix + err = createATAIx(e, chain, tokenprogramID, mint, cfg.ATAList) if err != nil { return cldf.ChangesetOutput{}, err } - instructions = append(instructions, mintIxs...) - err = chain.Confirm(instructions, solCommonUtil.AddSigners(mintPrivKey)) + // mint ix + err = getMintIxs(e, chain, tokenprogramID, mint, cfg.MintAmountToAddress) if err != nil { - e.Logger.Errorw("Failed to confirm instructions for token deployment", "chain", chain.String(), "err", err) return cldf.ChangesetOutput{}, err } @@ -171,10 +173,10 @@ type MintSolanaTokenConfig struct { AmountToAddress map[string]uint64 // address -> amount } -func (cfg MintSolanaTokenConfig) Validate(e deployment.Environment) error { +func (cfg MintSolanaTokenConfig) Validate(e cldf.Environment) error { chain := e.SolChains[cfg.ChainSelector] tokenAddress := solana.MustPublicKeyFromBase58(cfg.TokenPubkey) - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return err } @@ -200,14 +202,14 @@ func (cfg MintSolanaTokenConfig) Validate(e deployment.Environment) error { return nil } -func MintSolanaToken(e deployment.Environment, cfg MintSolanaTokenConfig) (cldf.ChangesetOutput, error) { +func MintSolanaToken(e cldf.Environment, cfg MintSolanaTokenConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, err } // get chain chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] // get addresses tokenAddress := solana.MustPublicKeyFromBase58(cfg.TokenPubkey) @@ -215,16 +217,10 @@ func MintSolanaToken(e deployment.Environment, cfg MintSolanaTokenConfig) (cldf. tokenprogramID, _ := chainState.TokenToTokenProgram(tokenAddress) // get mint instructions - instructions, err := getMintIxs(e, chain, tokenprogramID, tokenAddress, cfg.AmountToAddress) + err = getMintIxs(e, chain, tokenprogramID, tokenAddress, cfg.AmountToAddress) if err != nil { return cldf.ChangesetOutput{}, err } - // confirm instructions - err = chain.Confirm(instructions) - if err != nil { - e.Logger.Errorw("Failed to confirm instructions for token minting", "chain", chain.String(), "err", err) - return cldf.ChangesetOutput{}, err - } e.Logger.Infow("Minted tokens on", "chain", cfg.ChainSelector, "for token", tokenAddress.String()) return cldf.ChangesetOutput{}, nil @@ -237,9 +233,9 @@ type CreateSolanaTokenATAConfig struct { ATAList []string // addresses to create ATAs for } -func CreateSolanaTokenATA(e deployment.Environment, cfg CreateSolanaTokenATAConfig) (cldf.ChangesetOutput, error) { +func CreateSolanaTokenATA(e cldf.Environment, cfg CreateSolanaTokenATAConfig) (cldf.ChangesetOutput, error) { chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenprogramID, err := chainState.TokenToTokenProgram(cfg.TokenPubkey) @@ -248,15 +244,8 @@ func CreateSolanaTokenATA(e deployment.Environment, cfg CreateSolanaTokenATAConf } // create instructions for each ATA - instructions, err := createATAIx(e, chain, tokenprogramID, cfg.TokenPubkey, cfg.ATAList) - if err != nil { - return cldf.ChangesetOutput{}, err - } - - // confirm instructions - err = chain.Confirm(instructions) + err = createATAIx(e, chain, tokenprogramID, cfg.TokenPubkey, cfg.ATAList) if err != nil { - e.Logger.Errorw("Failed to confirm instructions for ATA creation", "chain", chain.String(), "err", err) return cldf.ChangesetOutput{}, err } e.Logger.Infow("Created ATAs on", "chain", cfg.ChainSelector, "for token", cfg.TokenPubkey.String(), "numATAs", len(cfg.ATAList)) @@ -271,9 +260,9 @@ type SetTokenAuthorityConfig struct { NewAuthority solana.PublicKey } -func SetTokenAuthority(e deployment.Environment, cfg SetTokenAuthorityConfig) (cldf.ChangesetOutput, error) { +func SetTokenAuthority(e cldf.Environment, cfg SetTokenAuthorityConfig) (cldf.ChangesetOutput, error) { chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenprogramID, err := chainState.TokenToTokenProgram(cfg.TokenPubkey) @@ -304,25 +293,39 @@ func SetTokenAuthority(e deployment.Environment, cfg SetTokenAuthorityConfig) (c } type UploadTokenMetadataConfig struct { - ChainSelector uint64 - TokenPubkey solana.PublicKey - TokenMetaDataFile string + ChainSelector uint64 + TokenPubkey solana.PublicKey + TokenMetaDataFile string + TokenUpdateAuthority solana.PublicKey } -func UploadTokenMetadata(e deployment.Environment, cfg UploadTokenMetadataConfig) (cldf.ChangesetOutput, error) { +func UploadTokenMetadata(e cldf.Environment, cfg UploadTokenMetadataConfig) (cldf.ChangesetOutput, error) { chain := e.SolChains[cfg.ChainSelector] e.Logger.Infow("Uploading token metadata", "tokenPubkey", cfg.TokenPubkey.String()) _, _ = runCommand("solana", []string{"config", "set", "--url", chain.URL}, chain.ProgramsPath) _, _ = runCommand("solana", []string{"config", "set", "--keypair", chain.KeypairPath}, chain.ProgramsPath) - args := []string{"create", "metadata", "--mint", cfg.TokenPubkey.String(), "--metadata", cfg.TokenMetaDataFile} - e.Logger.Info(args) - output, err := runCommand("metaboss", args, chain.ProgramsPath) - e.Logger.Debugw("metaboss output", "output", output) - if err != nil { - e.Logger.Debugw("metaboss create error", "error", err) - return cldf.ChangesetOutput{}, fmt.Errorf("error uploading token metadata: %w", err) + if cfg.TokenMetaDataFile == "" { + args := []string{"create", "metadata", "--mint", cfg.TokenPubkey.String(), "--metadata", cfg.TokenMetaDataFile} + e.Logger.Info(args) + output, err := runCommand("metaboss", args, chain.ProgramsPath) + e.Logger.Debugw("metaboss output", "output", output) + if err != nil { + e.Logger.Debugw("metaboss create error", "error", err) + return cldf.ChangesetOutput{}, fmt.Errorf("error uploading token metadata: %w", err) + } + e.Logger.Infow("Token metadata uploaded", "tokenPubkey", cfg.TokenPubkey.String()) + } + if !cfg.TokenUpdateAuthority.IsZero() { + args := []string{"set", "update-authority", "--account", cfg.TokenPubkey.String(), "--new-update-authority", cfg.TokenUpdateAuthority.String()} + e.Logger.Info(args) + output, err := runCommand("metaboss", args, chain.ProgramsPath) + e.Logger.Debugw("metaboss output", "output", output) + if err != nil { + e.Logger.Debugw("metaboss set error", "error", err) + return cldf.ChangesetOutput{}, fmt.Errorf("error uploading token metadata: %w", err) + } + e.Logger.Infow("Token metadata update authority set", "tokenPubkey", cfg.TokenPubkey.String(), "updateAuthority", cfg.TokenUpdateAuthority.String()) } - e.Logger.Infow("Token metadata uploaded", "tokenPubkey", cfg.TokenPubkey.String()) return cldf.ChangesetOutput{}, nil } diff --git a/deployment/ccip/changeset/solana/cs_solana_token_test.go b/deployment/ccip/changeset/solana/cs_solana_token_test.go index c70bfbf9aa2..e609f09497c 100644 --- a/deployment/ccip/changeset/solana/cs_solana_token_test.go +++ b/deployment/ccip/changeset/solana/cs_solana_token_test.go @@ -14,8 +14,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" @@ -36,7 +37,7 @@ func TestSolanaTokenOps(t *testing.T) { cldf.CreateLegacyChangeSet(changeset_solana.DeploySolanaToken), changeset_solana.DeploySolanaTokenConfig{ ChainSelector: solChain1, - TokenProgramName: ccipChangeset.SPL2022Tokens, + TokenProgramName: shared.SPL2022Tokens, TokenDecimals: 9, TokenSymbol: "TEST_TOKEN", }, @@ -52,7 +53,7 @@ func TestSolanaTokenOps(t *testing.T) { cldf.CreateLegacyChangeSet(changeset_solana.DeploySolanaToken), changeset_solana.DeploySolanaTokenConfig{ ChainSelector: solChain1, - TokenProgramName: ccipChangeset.SPLTokens, + TokenProgramName: shared.SPLTokens, MintPrivateKey: privKey, TokenDecimals: 9, TokenSymbol: "SPL_TEST_TOKEN", @@ -63,9 +64,9 @@ func TestSolanaTokenOps(t *testing.T) { addresses, err := e.ExistingAddresses.AddressesForChain(solChain1) //nolint:staticcheck // addressbook still valid require.NoError(t, err) - tokenAddress := ccipChangeset.FindSolanaAddress( + tokenAddress := solanastateview.FindSolanaAddress( cldf.TypeAndVersion{ - Type: ccipChangeset.SPL2022Tokens, + Type: shared.SPL2022Tokens, Version: deployment.Version1_0_0, Labels: cldf.NewLabelSet("TEST_TOKEN"), }, @@ -129,7 +130,7 @@ func TestSolanaTokenOps(t *testing.T) { cldf.CreateLegacyChangeSet(changeset_solana.DeploySolanaToken), changeset_solana.DeploySolanaTokenConfig{ ChainSelector: solChain1, - TokenProgramName: ccipChangeset.SPL2022Tokens, + TokenProgramName: shared.SPLTokens, TokenDecimals: 9, TokenSymbol: "TEST_TOKEN_2", ATAList: []string{deployerKey.String(), testUserPubKey.String()}, @@ -143,18 +144,18 @@ func TestSolanaTokenOps(t *testing.T) { require.NoError(t, err) addresses, err = e.ExistingAddresses.AddressesForChain(solChain1) //nolint:staticcheck // addressbook still valid require.NoError(t, err) - tokenAddress2 := ccipChangeset.FindSolanaAddress( + tokenAddress2 := solanastateview.FindSolanaAddress( cldf.TypeAndVersion{ - Type: ccipChangeset.SPL2022Tokens, + Type: shared.SPLTokens, Version: deployment.Version1_0_0, Labels: cldf.NewLabelSet("TEST_TOKEN_2"), }, addresses, ) - testUserATA2, _, err := solTokenUtil.FindAssociatedTokenAddress(solana.Token2022ProgramID, tokenAddress2, testUserPubKey) + testUserATA2, _, err := solTokenUtil.FindAssociatedTokenAddress(solana.TokenProgramID, tokenAddress2, testUserPubKey) require.NoError(t, err) deployerATA2, _, err := solTokenUtil.FindAssociatedTokenAddress( - solana.Token2022ProgramID, + solana.TokenProgramID, tokenAddress2, e.SolChains[solChain1].DeployerKey.PublicKey(), ) diff --git a/deployment/ccip/changeset/solana/cs_token_admin_registry.go b/deployment/ccip/changeset/solana/cs_token_admin_registry.go index 2d1590c7c3b..3ade2de6b91 100644 --- a/deployment/ccip/changeset/solana/cs_token_admin_registry.go +++ b/deployment/ccip/changeset/solana/cs_token_admin_registry.go @@ -16,8 +16,9 @@ import ( solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -42,7 +43,7 @@ type RegisterTokenAdminRegistryConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg RegisterTokenAdminRegistryConfig) Validate(e deployment.Environment) error { +func (cfg RegisterTokenAdminRegistryConfig) Validate(e cldf.Environment) error { if cfg.RegisterType != ViaGetCcipAdminInstruction && cfg.RegisterType != ViaOwnerInstruction { return fmt.Errorf("invalid register type, valid types are %d and %d", ViaGetCcipAdminInstruction, ViaOwnerInstruction) } @@ -55,13 +56,13 @@ func (cfg RegisterTokenAdminRegistryConfig) Validate(e deployment.Environment) e if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] if err := validateRouterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } routerProgramAddress, _, _ := chainState.GetRouterInfo() @@ -76,12 +77,13 @@ func (cfg RegisterTokenAdminRegistryConfig) Validate(e deployment.Environment) e return nil } -func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { +func RegisterTokenAdminRegistry(e cldf.Environment, cfg RegisterTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("RegisterTokenAdminRegistry", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenPubKey := cfg.TokenPubKey routerProgramAddress, routerConfigPDA, _ := chainState.GetRouterInfo() @@ -93,11 +95,11 @@ func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdmin var instruction *solRouter.Instruction var err error - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") authority := GetAuthorityForIxn( @@ -105,7 +107,7 @@ func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdmin chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") switch cfg.RegisterType { @@ -165,7 +167,7 @@ func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdmin } } if routerUsingMCMS { - tx, err := BuildMCMSTxn(instruction, routerProgramAddress.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(instruction, routerProgramAddress.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -195,12 +197,12 @@ type TransferAdminRoleTokenAdminRegistryConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error { +func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] if err := validateRouterConfig(chain, chainState); err != nil { @@ -211,7 +213,7 @@ func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Envir chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -226,7 +228,7 @@ func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Envir ) } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } routerProgramAddress, _, _ := chainState.GetRouterInfo() @@ -241,11 +243,11 @@ func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Envir return nil } -func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferAdminRoleTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { +func TransferAdminRoleTokenAdminRegistry(e cldf.Environment, cfg TransferAdminRoleTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey) @@ -255,11 +257,11 @@ func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferA tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, routerProgramAddress) newRegistryAdminPubKey := solana.MustPublicKeyFromBase58(cfg.NewRegistryAdminPublicKey) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") authority := GetAuthorityForIxn( @@ -267,7 +269,7 @@ func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferA chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") ix1, err := solRouter.NewTransferAdminRoleTokenAdminRegistryInstruction( @@ -281,7 +283,7 @@ func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferA return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err) } if routerUsingMCMS { - tx, err := BuildMCMSTxn(ix1, routerProgramAddress.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ix1, routerProgramAddress.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -308,18 +310,18 @@ type AcceptAdminRoleTokenAdminRegistryConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error { +func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e cldf.Environment) error { tokenPubKey := cfg.TokenPubKey if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] if err := validateRouterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, solana.PublicKey{}, "", map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } @@ -328,7 +330,7 @@ func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environ chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -352,12 +354,13 @@ func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environ return nil } -func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdminRoleTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { +func AcceptAdminRoleTokenAdminRegistry(e cldf.Environment, cfg AcceptAdminRoleTokenAdminRegistryConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("AcceptAdminRoleTokenAdminRegistry", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenPubKey := cfg.TokenPubKey @@ -366,11 +369,11 @@ func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdmin solRouter.SetProgramID(routerProgramAddress) tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, routerProgramAddress) - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") authority := GetAuthorityForIxn( @@ -378,7 +381,7 @@ func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdmin chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "") ix1, err := solRouter.NewAcceptAdminRoleTokenAdminRegistryInstruction( @@ -392,7 +395,7 @@ func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdmin } if routerUsingMCMS { // We will only be able to accept the admin role if the pending admin is the timelock signer - tx, err := BuildMCMSTxn(ix1, routerProgramAddress.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(ix1, routerProgramAddress.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } diff --git a/deployment/ccip/changeset/solana/cs_token_pool.go b/deployment/ccip/changeset/solana/cs_token_pool.go index 1f63581dd1e..a58be23c164 100644 --- a/deployment/ccip/changeset/solana/cs_token_pool.go +++ b/deployment/ccip/changeset/solana/cs_token_pool.go @@ -28,8 +28,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" ccipChangeset_v1_5_1 "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -40,37 +42,37 @@ var _ cldf.ChangeSet[TokenPoolConfig] = AddTokenPoolAndLookupTable var _ cldf.ChangeSet[RemoteChainTokenPoolConfig] = SetupTokenPoolForRemoteChain func GetActiveTokenPool( - e *deployment.Environment, + e *cldf.Environment, poolType solTestTokenPool.PoolType, selector uint64, metadata string, ) (solana.PublicKey, cldf.ContractType) { - state, _ := ccipChangeset.LoadOnchainState(*e) + state, _ := stateview.LoadOnchainState(*e) chainState := state.SolChains[selector] switch poolType { case solTestTokenPool.BurnAndMint_PoolType: if metadata == "" { - return chainState.BurnMintTokenPools[ccipChangeset.CLLMetadata], ccipChangeset.BurnMintTokenPool + return chainState.BurnMintTokenPools[shared.CLLMetadata], shared.BurnMintTokenPool } - return chainState.BurnMintTokenPools[metadata], ccipChangeset.BurnMintTokenPool + return chainState.BurnMintTokenPools[metadata], shared.BurnMintTokenPool case solTestTokenPool.LockAndRelease_PoolType: if metadata == "" { - return chainState.LockReleaseTokenPools[ccipChangeset.CLLMetadata], ccipChangeset.LockReleaseTokenPool + return chainState.LockReleaseTokenPools[shared.CLLMetadata], shared.LockReleaseTokenPool } - return chainState.LockReleaseTokenPools[metadata], ccipChangeset.LockReleaseTokenPool + return chainState.LockReleaseTokenPools[metadata], shared.LockReleaseTokenPool default: return solana.PublicKey{}, "" } } func validatePoolDeployment( - e *deployment.Environment, + e *cldf.Environment, poolType solTestTokenPool.PoolType, selector uint64, tokenPubKey solana.PublicKey, validatePoolConfig bool, metadata string) error { - state, _ := ccipChangeset.LoadOnchainState(*e) + state, _ := stateview.LoadOnchainState(*e) chainState := state.SolChains[selector] chain := e.SolChains[selector] @@ -155,7 +157,7 @@ type TokenPoolConfig struct { Metadata string } -func (cfg TokenPoolConfig) Validate(e deployment.Environment) error { +func (cfg TokenPoolConfig) Validate(e cldf.Environment) error { if err := commonValidation(e, cfg.ChainSelector, cfg.TokenPubKey); err != nil { return err } @@ -166,13 +168,13 @@ func (cfg TokenPoolConfig) Validate(e deployment.Environment) error { return validatePoolDeployment(&e, *cfg.PoolType, cfg.ChainSelector, cfg.TokenPubKey, false, cfg.Metadata) } -func AddTokenPoolAndLookupTable(e deployment.Environment, cfg TokenPoolConfig) (cldf.ChangesetOutput, error) { - e.Logger.Infow("Adding token pool", "token_pubkey", cfg.TokenPubKey) +func AddTokenPoolAndLookupTable(e cldf.Environment, cfg TokenPoolConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("Adding token pool", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] tokenPubKey := cfg.TokenPubKey tokenPool, _ := GetActiveTokenPool(&e, *cfg.PoolType, cfg.ChainSelector, cfg.Metadata) @@ -304,19 +306,19 @@ func (cfg RateLimiterConfig) Validate() error { } type EVMRemoteConfig struct { - TokenSymbol ccipChangeset.TokenSymbol + TokenSymbol shared.TokenSymbol PoolType cldf.ContractType PoolVersion semver.Version RateLimiterConfig RateLimiterConfig OverrideConfig bool } -func (cfg EVMRemoteConfig) Validate(e deployment.Environment, state ccipChangeset.CCIPOnChainState, evmChainSelector uint64) error { +func (cfg EVMRemoteConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState, evmChainSelector uint64) error { // add evm family check if cfg.TokenSymbol == "" { return errors.New("token symbol must be defined") } - err := deployment.IsValidChainSelector(evmChainSelector) + err := cldf.IsValidChainSelector(evmChainSelector) if err != nil { return fmt.Errorf("failed to validate chain selector %d: %w", evmChainSelector, err) } @@ -329,15 +331,15 @@ func (cfg EVMRemoteConfig) Validate(e deployment.Environment, state ccipChangese return fmt.Errorf("%s does not exist in state", chain.String()) } // Ensure that the inputted type is known - if _, typeOk := ccipChangeset.TokenPoolTypes[cfg.PoolType]; !typeOk { + if _, typeOk := shared.TokenPoolTypes[cfg.PoolType]; !typeOk { return fmt.Errorf("%s is not a known token pool type", cfg.PoolType) } // Ensure that the inputted version is known - if _, versionOk := ccipChangeset.TokenPoolVersions[cfg.PoolVersion]; !versionOk { + if _, versionOk := shared.TokenPoolVersions[cfg.PoolVersion]; !versionOk { return fmt.Errorf("%s is not a known token pool version", cfg.PoolVersion) } // Ensure that a pool with given symbol, type and version is known to the environment - _, getPoolOk := ccipChangeset.GetTokenPoolAddressFromSymbolTypeAndVersion(chainState, chain, cfg.TokenSymbol, cfg.PoolType, cfg.PoolVersion) + _, getPoolOk := ccipChangeset_v1_5_1.GetTokenPoolAddressFromSymbolTypeAndVersion(chainState, chain, cfg.TokenSymbol, cfg.PoolType, cfg.PoolVersion) if !getPoolOk { return fmt.Errorf("token pool does not exist on %s with symbol %s, type %s, and version %s", chain.String(), cfg.TokenSymbol, cfg.PoolType, cfg.PoolVersion) } @@ -354,11 +356,11 @@ type RemoteChainTokenPoolConfig struct { Metadata string } -func (cfg RemoteChainTokenPoolConfig) Validate(e deployment.Environment) error { +func (cfg RemoteChainTokenPoolConfig) Validate(e cldf.Environment) error { if err := commonValidation(e, cfg.SolChainSelector, cfg.SolTokenPubKey); err != nil { return err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.SolChainSelector] chain := e.SolChains[cfg.SolChainSelector] if cfg.SolPoolType == nil { @@ -381,7 +383,7 @@ func (cfg RemoteChainTokenPoolConfig) Validate(e deployment.Environment) error { return nil } -func getOnChainEVMPoolConfig(e deployment.Environment, state ccipChangeset.CCIPOnChainState, evmChainSelector uint64, evmRemoteConfig EVMRemoteConfig) (solBaseTokenPool.RemoteConfig, error) { +func getOnChainEVMPoolConfig(e cldf.Environment, state stateview.CCIPOnChainState, evmChainSelector uint64, evmRemoteConfig EVMRemoteConfig) (solBaseTokenPool.RemoteConfig, error) { evmChain := e.Chains[evmChainSelector] evmChainState := state.Chains[evmChainSelector] evmTokenPool, evmTokenAddress, _, evmErr := ccipChangeset_v1_5_1.GetTokenStateFromPoolEVM(context.Background(), evmRemoteConfig.TokenSymbol, evmRemoteConfig.PoolType, evmRemoteConfig.PoolVersion, evmChain, evmChainState) @@ -407,13 +409,14 @@ func getOnChainEVMPoolConfig(e deployment.Environment, state ccipChangeset.CCIPO return onChainEVMRemoteConfig, nil } -func SetupTokenPoolForRemoteChain(e deployment.Environment, cfg RemoteChainTokenPoolConfig) (cldf.ChangesetOutput, error) { +func SetupTokenPoolForRemoteChain(e cldf.Environment, cfg RemoteChainTokenPoolConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("Setting up token pool for remote chain", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.SolChainSelector] - envState, _ := ccipChangeset.LoadOnchainState(e) + envState, _ := stateview.LoadOnchainState(e) solChainState := envState.SolChains[cfg.SolChainSelector] tokenPubKey := cfg.SolTokenPubKey tokenPool, contractType := GetActiveTokenPool(&e, *cfg.SolPoolType, cfg.SolChainSelector, cfg.Metadata) @@ -421,11 +424,11 @@ func SetupTokenPoolForRemoteChain(e deployment.Environment, cfg RemoteChainToken var txns []mcmsTypes.Transaction switch *cfg.SolPoolType { case solTestTokenPool.BurnAndMint_PoolType: - useMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + useMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, solChainState, - ccipChangeset.BurnMintTokenPool, + shared.BurnMintTokenPool, tokenPubKey, cfg.Metadata, ) @@ -450,11 +453,11 @@ func SetupTokenPoolForRemoteChain(e deployment.Environment, cfg RemoteChainToken case solTestTokenPool.LockAndRelease_PoolType: solLockReleaseTokenPool.SetProgramID(tokenPool) - useMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + useMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, solChainState, - ccipChangeset.LockReleaseTokenPool, + shared.LockReleaseTokenPool, tokenPubKey, cfg.Metadata, ) @@ -495,7 +498,7 @@ func SetupTokenPoolForRemoteChain(e deployment.Environment, cfg RemoteChainToken } // checks if the evmChainSelector is supported for the given token and pool type -func isSupportedChain(chain deployment.SolChain, solTokenPubKey solana.PublicKey, solPoolAddress solana.PublicKey, evmChainSelector uint64) (bool, solTestTokenPool.ChainConfig, error) { +func isSupportedChain(chain cldf.SolChain, solTokenPubKey solana.PublicKey, solPoolAddress solana.PublicKey, evmChainSelector uint64) (bool, solTestTokenPool.ChainConfig, error) { var remoteChainConfigAccount solTestTokenPool.ChainConfig // check if this remote chain is already configured for this token remoteChainConfigPDA, _, err := solTokenUtil.TokenPoolChainConfigPDA(evmChainSelector, solTokenPubKey, solPoolAddress) @@ -510,9 +513,9 @@ func isSupportedChain(chain deployment.SolChain, solTokenPubKey solana.PublicKey } func getNewSetuptInstructionsForBurnMint( - e deployment.Environment, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, cfg RemoteChainTokenPoolConfig, evmChainSelector uint64, rateLimiterConfig RateLimiterConfig, @@ -584,10 +587,10 @@ func getNewSetuptInstructionsForBurnMint( } func getInstructionsForBurnMint( - e deployment.Environment, - chain deployment.SolChain, - envState ccipChangeset.CCIPOnChainState, - solChainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + envState stateview.CCIPOnChainState, + solChainState solanastateview.CCIPChainState, cfg RemoteChainTokenPoolConfig, evmChainSelector uint64, evmRemoteConfig EVMRemoteConfig, @@ -681,9 +684,9 @@ func getInstructionsForBurnMint( } func getNewSetuptInstructionsForLockRelease( - e deployment.Environment, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, cfg RemoteChainTokenPoolConfig, evmChainSelector uint64, rateLimiterConfig RateLimiterConfig, @@ -756,10 +759,10 @@ func getNewSetuptInstructionsForLockRelease( } func getInstructionsForLockRelease( - e deployment.Environment, - chain deployment.SolChain, - envState ccipChangeset.CCIPOnChainState, - solChainState ccipChangeset.SolCCIPChainState, + e cldf.Environment, + chain cldf.SolChain, + envState stateview.CCIPOnChainState, + solChainState solanastateview.CCIPChainState, cfg RemoteChainTokenPoolConfig, evmChainSelector uint64, evmRemoteConfig EVMRemoteConfig, @@ -857,7 +860,7 @@ type TokenPoolLookupTableConfig struct { Metadata string } -func (cfg TokenPoolLookupTableConfig) Validate(e deployment.Environment) error { +func (cfg TokenPoolLookupTableConfig) Validate(e cldf.Environment) error { if err := commonValidation(e, cfg.ChainSelector, cfg.TokenPubKey); err != nil { return err } @@ -867,15 +870,15 @@ func (cfg TokenPoolLookupTableConfig) Validate(e deployment.Environment) error { return validatePoolDeployment(&e, *cfg.PoolType, cfg.ChainSelector, cfg.TokenPubKey, false, cfg.Metadata) } -func AddTokenPoolLookupTable(e deployment.Environment, cfg TokenPoolLookupTableConfig) (cldf.ChangesetOutput, error) { - e.Logger.Infow("Adding token pool lookup table", "token_pubkey", cfg.TokenPubKey) +func AddTokenPoolLookupTable(e cldf.Environment, cfg TokenPoolLookupTableConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("Adding token pool lookup table", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.ChainSelector] ctx := e.GetContext() client := chain.Client - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] authorityPrivKey := chain.DeployerKey // assuming the authority is the deployer key tokenPubKey := cfg.TokenPubKey @@ -915,10 +918,10 @@ func AddTokenPoolLookupTable(e deployment.Environment, cfg TokenPoolLookupTableC return cldf.ChangesetOutput{}, fmt.Errorf("failed to await slot change while extending lookup table: %w", err) } newAddressBook := cldf.NewMemoryAddressBook() - tv := cldf.NewTypeAndVersion(ccipChangeset.TokenPoolLookupTable, deployment.Version1_0_0) + tv := cldf.NewTypeAndVersion(shared.TokenPoolLookupTable, deployment.Version1_0_0) tv.Labels.Add(tokenPubKey.String()) tv.Labels.Add(cfg.PoolType.String()) - metadata := ccipChangeset.CLLMetadata + metadata := shared.CLLMetadata if cfg.Metadata != "" { metadata = cfg.Metadata } @@ -941,7 +944,7 @@ type SetPoolConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg SetPoolConfig) Validate(e deployment.Environment) error { +func (cfg SetPoolConfig) Validate(e cldf.Environment) error { tokenPubKey := cfg.TokenPubKey if err := commonValidation(e, cfg.ChainSelector, tokenPubKey); err != nil { return err @@ -949,13 +952,13 @@ func (cfg SetPoolConfig) Validate(e deployment.Environment) error { if cfg.PoolType == nil { return errors.New("pool type must be defined") } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] if err := validateRouterConfig(chain, chainState); err != nil { return err } - if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, tokenPubKey, cfg.Metadata, map[cldf.ContractType]bool{ccipChangeset.Router: true}); err != nil { + if err := ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, tokenPubKey, cfg.Metadata, map[cldf.ContractType]bool{shared.Router: true}); err != nil { return err } routerProgramAddress, _, _ := chainState.GetRouterInfo() @@ -967,33 +970,41 @@ func (cfg SetPoolConfig) Validate(e deployment.Environment) error { if err := chain.GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount); err != nil { return fmt.Errorf("token admin registry not found for (mint: %s, router: %s), cannot set pool", tokenPubKey.String(), routerProgramAddress.String()) } - if _, ok := chainState.TokenPoolLookupTable[tokenPubKey]; !ok { + metadata := shared.CLLMetadata + if cfg.Metadata != "" { + metadata = cfg.Metadata + } + if lut, ok := chainState.TokenPoolLookupTable[tokenPubKey][*cfg.PoolType][metadata]; !ok || lut.IsZero() { return fmt.Errorf("token pool lookup table not found for (mint: %s)", tokenPubKey.String()) } return nil } // this sets the writable indexes of the token pool lookup table -func SetPool(e deployment.Environment, cfg SetPoolConfig) (cldf.ChangesetOutput, error) { - e.Logger.Infof("Setting pool config for token %s", cfg.TokenPubKey) +func SetPool(e cldf.Environment, cfg SetPoolConfig) (cldf.ChangesetOutput, error) { + e.Logger.Infow("Setting pool config", "cfg", cfg) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] chain := e.SolChains[cfg.ChainSelector] tokenPubKey := cfg.TokenPubKey routerProgramAddress, routerConfigPDA, _ := chainState.GetRouterInfo() solRouter.SetProgramID(routerProgramAddress) tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, routerProgramAddress) - lookupTablePubKey := chainState.TokenPoolLookupTable[tokenPubKey][*cfg.PoolType][cfg.Metadata] - routerUsingMCMS := ccipChangeset.IsSolanaProgramOwnedByTimelock( + metadata := shared.CLLMetadata + if cfg.Metadata != "" { + metadata = cfg.Metadata + } + lookupTablePubKey := chainState.TokenPoolLookupTable[tokenPubKey][*cfg.PoolType][metadata] + routerUsingMCMS := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, - ccipChangeset.Router, + shared.Router, solana.PublicKey{}, "", ) @@ -1002,9 +1013,9 @@ func SetPool(e deployment.Environment, cfg SetPoolConfig) (cldf.ChangesetOutput, chain, chainState, cfg.MCMS, - ccipChangeset.Router, + shared.Router, tokenPubKey, - cfg.Metadata, + metadata, ) base := solRouter.NewSetPoolInstruction( cfg.WritableIndexes, @@ -1022,7 +1033,7 @@ func SetPool(e deployment.Environment, cfg SetPoolConfig) (cldf.ChangesetOutput, } if routerUsingMCMS { - tx, err := BuildMCMSTxn(instruction, routerProgramAddress.String(), ccipChangeset.Router) + tx, err := BuildMCMSTxn(instruction, routerProgramAddress.String(), shared.Router) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err) } @@ -1055,9 +1066,9 @@ type ConfigureTokenPoolAllowListConfig struct { Metadata string } -func (cfg ConfigureTokenPoolAllowListConfig) Validate(e deployment.Environment) error { +func (cfg ConfigureTokenPoolAllowListConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -1077,14 +1088,14 @@ func (cfg ConfigureTokenPoolAllowListConfig) Validate(e deployment.Environment) // input only the ones you want to add // onchain throws error when we pass already configured accounts -func ConfigureTokenPoolAllowList(e deployment.Environment, cfg ConfigureTokenPoolAllowListConfig) (cldf.ChangesetOutput, error) { +func ConfigureTokenPoolAllowList(e cldf.Environment, cfg ConfigureTokenPoolAllowListConfig) (cldf.ChangesetOutput, error) { e.Logger.Infof("Configuring token pool allowlist for token %s", cfg.SolTokenPubKey) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.SolChainSelector] - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1093,7 +1104,7 @@ func ConfigureTokenPoolAllowList(e deployment.Environment, cfg ConfigureTokenPoo var ix solana.Instruction tokenPool, contractType := GetActiveTokenPool(&e, *cfg.PoolType, cfg.SolChainSelector, cfg.Metadata) - tokenPoolUsingMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + tokenPoolUsingMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, @@ -1182,7 +1193,7 @@ type RemoveFromAllowListConfig struct { Metadata string } -func (cfg RemoveFromAllowListConfig) Validate(e deployment.Environment) error { +func (cfg RemoveFromAllowListConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) if err := commonValidation(e, cfg.SolChainSelector, tokenPubKey); err != nil { return err @@ -1190,7 +1201,7 @@ func (cfg RemoveFromAllowListConfig) Validate(e deployment.Environment) error { if cfg.PoolType == nil { return errors.New("pool type must be defined") } - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -1202,14 +1213,14 @@ func (cfg RemoveFromAllowListConfig) Validate(e deployment.Environment) error { return validatePoolDeployment(&e, *cfg.PoolType, cfg.SolChainSelector, tokenPubKey, true, cfg.Metadata) } -func RemoveFromTokenPoolAllowList(e deployment.Environment, cfg RemoveFromAllowListConfig) (cldf.ChangesetOutput, error) { +func RemoveFromTokenPoolAllowList(e cldf.Environment, cfg RemoveFromAllowListConfig) (cldf.ChangesetOutput, error) { e.Logger.Infof("Removing from token pool allowlist for token %s", cfg.SolTokenPubKey) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.SolChainSelector] - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1218,7 +1229,7 @@ func RemoveFromTokenPoolAllowList(e deployment.Environment, cfg RemoveFromAllowL tokenPool, contractType := GetActiveTokenPool(&e, *cfg.PoolType, cfg.SolChainSelector, cfg.Metadata) var ix solana.Instruction - tokenPoolUsingMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + tokenPoolUsingMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, @@ -1325,12 +1336,12 @@ type RebalancerConfig struct { Rebalancer solana.PublicKey } -func (cfg LockReleaseLiquidityOpsConfig) Validate(e deployment.Environment) error { +func (cfg LockReleaseLiquidityOpsConfig) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) if err := commonValidation(e, cfg.SolChainSelector, tokenPubKey); err != nil { return err } - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -1342,21 +1353,21 @@ func (cfg LockReleaseLiquidityOpsConfig) Validate(e deployment.Environment) erro return validatePoolDeployment(&e, solTestTokenPool.LockAndRelease_PoolType, cfg.SolChainSelector, tokenPubKey, true, cfg.Metadata) } -func LockReleaseLiquidityOps(e deployment.Environment, cfg LockReleaseLiquidityOpsConfig) (cldf.ChangesetOutput, error) { +func LockReleaseLiquidityOps(e cldf.Environment, cfg LockReleaseLiquidityOpsConfig) (cldf.ChangesetOutput, error) { e.Logger.Infof("Locking/Unlocking liquidity for token %s", cfg.SolTokenPubKey) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } chain := e.SolChains[cfg.SolChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.SolChainSelector] tokenPool, contractType := GetActiveTokenPool(&e, solTestTokenPool.LockAndRelease_PoolType, cfg.SolChainSelector, cfg.Metadata) solLockReleaseTokenPool.SetProgramID(tokenPool) tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenPubKey, tokenPool) - tokenPoolUsingMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + tokenPoolUsingMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, @@ -1510,9 +1521,9 @@ type SetRouterCfg struct { Router solana.PublicKey } -func (cfg TokenPoolOpsCfg) Validate(e deployment.Environment) error { +func (cfg TokenPoolOpsCfg) Validate(e cldf.Environment) error { tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -1558,7 +1569,7 @@ func (cfg TokenPoolOpsCfg) Validate(e deployment.Environment) error { return ValidateMCMSConfigSolana(e, cfg.MCMS, chain, chainState, tokenPubKey, cfg.Metadata, map[cldf.ContractType]bool{}) } -func TokenPoolOps(e deployment.Environment, cfg TokenPoolOpsCfg) (cldf.ChangesetOutput, error) { +func TokenPoolOps(e cldf.Environment, cfg TokenPoolOpsCfg) (cldf.ChangesetOutput, error) { e.Logger.Infof("Setting pool config for token %s", cfg.SolTokenPubKey) if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err @@ -1566,7 +1577,7 @@ func TokenPoolOps(e deployment.Environment, cfg TokenPoolOpsCfg) (cldf.Changeset chain := e.SolChains[cfg.SolChainSelector] tokenPubKey := solana.MustPublicKeyFromBase58(cfg.SolTokenPubKey) - state, err := ccipChangeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1574,7 +1585,7 @@ func TokenPoolOps(e deployment.Environment, cfg TokenPoolOpsCfg) (cldf.Changeset var ix solana.Instruction ixns := make([]solana.Instruction, 0) tokenPool, contractType := GetActiveTokenPool(&e, *cfg.PoolType, cfg.SolChainSelector, cfg.Metadata) - tokenPoolUsingMcms := ccipChangeset.IsSolanaProgramOwnedByTimelock( + tokenPoolUsingMcms := solanastateview.IsSolanaProgramOwnedByTimelock( &e, chain, chainState, diff --git a/deployment/ccip/changeset/solana/cs_token_pool_test.go b/deployment/ccip/changeset/solana/cs_token_pool_test.go index cb4e0fbb359..244cb7c9dfe 100644 --- a/deployment/ccip/changeset/solana/cs_token_pool_test.go +++ b/deployment/ccip/changeset/solana/cs_token_pool_test.go @@ -20,12 +20,11 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" - + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment" @@ -35,19 +34,19 @@ import ( func TestAddTokenPoolWithoutMcms(t *testing.T) { t.Parallel() tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) - doTestTokenPool(t, tenv.Env, false, ccipChangeset.CLLMetadata) + doTestTokenPool(t, tenv.Env, false, shared.CLLMetadata) } func TestAddTokenPoolWithMcms(t *testing.T) { t.Parallel() tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) - doTestTokenPool(t, tenv.Env, true, ccipChangeset.CLLMetadata) + doTestTokenPool(t, tenv.Env, true, shared.CLLMetadata) } -func deployEVMTokenPool(t *testing.T, e deployment.Environment, evmChain uint64) (deployment.Environment, common.Address, error) { +func deployEVMTokenPool(t *testing.T, e cldf.Environment, evmChain uint64) (cldf.Environment, common.Address, error) { addressBook := cldf.NewMemoryAddressBook() evmToken, err := cldf.DeployContract(e.Logger, e.Chains[evmChain], addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( e.Chains[evmChain].DeployerKey, e.Chains[evmChain].Client, @@ -59,7 +58,7 @@ func deployEVMTokenPool(t *testing.T, e deployment.Environment, evmChain uint64) return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -68,7 +67,7 @@ func deployEVMTokenPool(t *testing.T, e deployment.Environment, evmChain uint64) require.NoError(t, err) e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ evmChain: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: evmToken.Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -76,7 +75,7 @@ func deployEVMTokenPool(t *testing.T, e deployment.Environment, evmChain uint64) return e, evmToken.Address, nil } -func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMetadata string) { +func doTestTokenPool(t *testing.T, e cldf.Environment, mcms bool, tokenMetadata string) { ctx := testcontext.Get(t) evmChain := e.AllChainSelectors()[0] solChain := e.AllChainSelectorsSolana()[0] @@ -85,12 +84,12 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet testUserPubKey := testUser.PublicKey() e, newTokenAddress, err := deployTokenAndMint(t, e, solChain, []string{deployerKey.String(), testUserPubKey.String()}) require.NoError(t, err) - state, err := ccipChangeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) - testUserATA, _, err := solTokenUtil.FindAssociatedTokenAddress(solana.Token2022ProgramID, newTokenAddress, testUserPubKey) + testUserATA, _, err := solTokenUtil.FindAssociatedTokenAddress(solana.TokenProgramID, newTokenAddress, testUserPubKey) require.NoError(t, err) deployerATA, _, err := solTokenUtil.FindAssociatedTokenAddress( - solana.Token2022ProgramID, + solana.TokenProgramID, newTokenAddress, e.SolChains[solChain].DeployerKey.PublicKey(), ) @@ -160,8 +159,8 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet EVMRemoteConfigs: map[uint64]ccipChangesetSolana.EVMRemoteConfig{ evmChain: { TokenSymbol: testhelpers.TestTokenSymbol, - PoolType: changeset.BurnMintTokenPool, // EVM test tokens are always burn and mint - PoolVersion: changeset.CurrentTokenPoolVersion, + PoolType: shared.BurnMintTokenPool, // EVM test tokens are always burn and mint + PoolVersion: shared.CurrentTokenPoolVersion, RateLimiterConfig: ccipChangesetSolana.RateLimiterConfig{ Inbound: rateLimitConfig, Outbound: rateLimitConfig, @@ -207,6 +206,7 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet _, _ = testhelpers.TransferOwnershipSolana( t, &e, solChain, false, ccipChangesetSolana.CCIPContractsToTransfer{ + BurnMintTokenPoolMetadata: tokenMetadata, BurnMintTokenPools: map[solana.PublicKey]solana.PublicKey{ poolConfigPDA: tokenAddress, }, @@ -215,6 +215,7 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet _, _ = testhelpers.TransferOwnershipSolana( t, &e, solChain, false, ccipChangesetSolana.CCIPContractsToTransfer{ + LockReleaseTokenPoolMetadata: tokenMetadata, LockReleaseTokenPools: map[solana.PublicKey]solana.PublicKey{ poolConfigPDA: tokenAddress, }, @@ -258,8 +259,8 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet EVMRemoteConfigs: map[uint64]ccipChangesetSolana.EVMRemoteConfig{ evmChain: { TokenSymbol: testhelpers.TestTokenSymbol, - PoolType: changeset.BurnMintTokenPool, // EVM test tokens are always burn and mint - PoolVersion: changeset.CurrentTokenPoolVersion, + PoolType: shared.BurnMintTokenPool, // EVM test tokens are always burn and mint + PoolVersion: shared.CurrentTokenPoolVersion, RateLimiterConfig: ccipChangesetSolana.RateLimiterConfig{ Inbound: newInboundConfig, Outbound: newOutboundConfig, @@ -338,6 +339,84 @@ func doTestTokenPool(t *testing.T, e deployment.Environment, mcms bool, tokenMet require.NoError(t, err) require.Equal(t, int(50), outVal) require.Equal(t, 9, int(outDec)) + + // transfer away from timelock if metadata is set and not ccipChangeset.CLLMetadata + if mcms && tokenMetadata != "" && tokenMetadata != shared.CLLMetadata { + timelockSignerPDA, err := ccipChangesetSolana.FetchTimelockSigner(e, solChain) + require.NoError(t, err) + e.Logger.Debugf("Transferring away from MCMS for token pool %v", testCase.poolType) + if testCase.poolType == solTestTokenPool.BurnAndMint_PoolType { + e, _, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure( + cldf.CreateLegacyChangeSet(ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolana), + ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolanaConfig{ + MCMSCfg: proposalutils.TimelockConfig{MinDelay: 1 * time.Second}, + CurrentOwner: timelockSignerPDA, + ProposedOwner: deployerKey, + ContractsByChain: map[uint64]ccipChangesetSolana.CCIPContractsToTransfer{ + solChain: ccipChangesetSolana.CCIPContractsToTransfer{ + BurnMintTokenPoolMetadata: tokenMetadata, + BurnMintTokenPools: map[solana.PublicKey]solana.PublicKey{ + poolConfigPDA: tokenAddress, + }, + }, + }, + }, + ), + }) + require.NoError(t, err) + } else if testCase.poolType == solTestTokenPool.LockAndRelease_PoolType { + e, _, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure( + cldf.CreateLegacyChangeSet(ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolana), + ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolanaConfig{ + MCMSCfg: proposalutils.TimelockConfig{MinDelay: 1 * time.Second}, + CurrentOwner: timelockSignerPDA, + ProposedOwner: deployerKey, + ContractsByChain: map[uint64]ccipChangesetSolana.CCIPContractsToTransfer{ + solChain: ccipChangesetSolana.CCIPContractsToTransfer{ + LockReleaseTokenPoolMetadata: tokenMetadata, + LockReleaseTokenPools: map[solana.PublicKey]solana.PublicKey{ + poolConfigPDA: tokenAddress, + }, + }, + }, + }, + ), + }) + require.NoError(t, err) + } + e.Logger.Debugf("MCMS Configured for token pool %v with token address %v", testCase.poolType, tokenAddress) + e, _, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ + // upgrade authority + commonchangeset.Configure( + cldf.CreateLegacyChangeSet(ccipChangesetSolana.SetUpgradeAuthorityChangeset), + ccipChangesetSolana.SetUpgradeAuthorityConfig{ + ChainSelector: solChain, + NewUpgradeAuthority: timelockSignerPDA, + TransferKeys: []solana.PublicKey{ + state.SolChains[solChain].BurnMintTokenPools[tokenMetadata], + state.SolChains[solChain].LockReleaseTokenPools[tokenMetadata], + }, + }, + ), + commonchangeset.Configure( + cldf.CreateLegacyChangeSet(ccipChangesetSolana.SetUpgradeAuthorityChangeset), + ccipChangesetSolana.SetUpgradeAuthorityConfig{ + ChainSelector: solChain, + NewUpgradeAuthority: e.SolChains[solChain].DeployerKey.PublicKey(), + TransferKeys: []solana.PublicKey{ + state.SolChains[solChain].BurnMintTokenPools[tokenMetadata], + state.SolChains[solChain].LockReleaseTokenPools[tokenMetadata], + }, + MCMS: &proposalutils.TimelockConfig{ + MinDelay: 1 * time.Second, + }, + }, + ), + }) + require.NoError(t, err) + } } } } @@ -347,7 +426,6 @@ func TestPartnerTokenPools(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) e := tenv.Env solChainSelectors := e.AllChainSelectorsSolana() - // mcmsConfig := proposalutils.SingleGroupTimelockConfigV2(t) metadata := "partner_testing" e, _, err := commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{commonchangeset.Configure( cldf.CreateLegacyChangeSet(ccipChangesetSolana.DeployChainContractsChangeset), @@ -369,4 +447,5 @@ func TestPartnerTokenPools(t *testing.T) { testhelpers.ValidateSolanaState(t, e, solChainSelectors) doTestTokenPool(t, e, false, metadata) doTestPoolLookupTable(t, e, false, metadata) + doTestTokenPool(t, e, true, metadata) } diff --git a/deployment/ccip/changeset/solana/cs_verify_contracts.go b/deployment/ccip/changeset/solana/cs_verify_contracts.go index 7e928c4bfe5..5e53f79d484 100644 --- a/deployment/ccip/changeset/solana/cs_verify_contracts.go +++ b/deployment/ccip/changeset/solana/cs_verify_contracts.go @@ -6,8 +6,10 @@ import ( "strings" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" csState "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -31,7 +33,7 @@ type VerifyBuildConfig struct { MCMS *proposalutils.TimelockConfig } -func runSolanaVerify(chain deployment.SolChain, programID, libraryName, commitHash, mountPath string, remote bool) error { +func runSolanaVerify(chain cldf.SolChain, programID, libraryName, commitHash, mountPath string, remote bool) error { params := map[string]string{ "Keypair Path": chain.KeypairPath, "Network URL": chain.URL, @@ -93,9 +95,9 @@ func runSolanaVerify(chain deployment.SolChain, programID, libraryName, commitHa return nil } -func VerifyBuild(e deployment.Environment, cfg VerifyBuildConfig) (cldf.ChangesetOutput, error) { +func VerifyBuild(e cldf.Environment, cfg VerifyBuildConfig) (cldf.ChangesetOutput, error) { chain := e.SolChains[cfg.ChainSelector] - state, _ := ccipChangeset.LoadOnchainState(e) + state, _ := stateview.LoadOnchainState(e) chainState := state.SolChains[cfg.ChainSelector] addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) @@ -106,8 +108,8 @@ func VerifyBuild(e deployment.Environment, cfg VerifyBuildConfig) (cldf.Changese if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - bnmMetadata := ccipChangeset.CLLMetadata - lnrMetadata := ccipChangeset.CLLMetadata + bnmMetadata := shared.CLLMetadata + lnrMetadata := shared.CLLMetadata if cfg.BurnMintTokenPoolMetadata != "" { bnmMetadata = cfg.BurnMintTokenPoolMetadata } diff --git a/deployment/ccip/changeset/solana/ownership_transfer_helpers.go b/deployment/ccip/changeset/solana/ownership_transfer_helpers.go index 5ca5f9b7cab..206ba802724 100644 --- a/deployment/ccip/changeset/solana/ownership_transfer_helpers.go +++ b/deployment/ccip/changeset/solana/ownership_transfer_helpers.go @@ -15,10 +15,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - state2 "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) type TransferOwnershipFn func( @@ -44,17 +42,28 @@ func transferAndWrapAcceptOwnership( programID solana.PublicKey, // e.g. token_pool program or router program proposedOwner solana.PublicKey, // e.g. usually, the timelock signer PDA configPDA solana.PublicKey, // e.g. for routerConfigPDA or a token-pool config - deployer solana.PublicKey, // the “from” authority - solChain deployment.SolChain, // used for solChain.Confirm + currentOwner solana.PublicKey, // the “from” authority + solChain cldf.SolChain, // used for solChain.Confirm label cldf.ContractType, // e.g. "Router" or "TokenPool" + timelockSigner solana.PublicKey, // the timelock signer PDA ) (mcmsTypes.Transaction, error) { // 1. Build the instruction that transfers ownership to the timelock - ixTransfer, err := buildTransfer(proposedOwner, configPDA, deployer) + ixTransfer, err := buildTransfer(proposedOwner, configPDA, currentOwner) if err != nil { return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to create transfer ownership instruction: %w", label, err) } - // 2. Confirm on-chain + // if the old owner is the timelock signer, we can skip the on-chain confirmation + // We can't perform the accept ownership step here because the timelock signer is not a signer of the transaction + // 2. Wrap in MCMS transaction or confirm on-chain + if currentOwner.Equals(timelockSigner) { + mcmsTx, err := BuildMCMSTxn(ixTransfer, programID.String(), label) + if err != nil { + return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + } + return *mcmsTx, nil + } + if err := solChain.Confirm([]solana.Instruction{ixTransfer}); err != nil { return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to confirm transfer on-chain: %w", label, err) } @@ -65,26 +74,33 @@ func transferAndWrapAcceptOwnership( return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to create accept ownership instruction: %w", label, err) } - // 4. Wrap in MCMS transaction - mcmsTx, err := BuildMCMSTxn(ixAccept, programID.String(), label) - if err != nil { - return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + // 4. Wrap in MCMS transaction or confirm on-chain + if proposedOwner.Equals(timelockSigner) { + mcmsTx, err := BuildMCMSTxn(ixAccept, programID.String(), label) + if err != nil { + return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + } + + return *mcmsTx, nil } - return *mcmsTx, nil + if err := solChain.Confirm([]solana.Instruction{ixAccept}); err != nil { + return mcmsTypes.Transaction{}, fmt.Errorf("%s: failed to confirm transfer on-chain: %w", label, err) + } + return mcmsTypes.Transaction{}, nil } // transferOwnershipRouter transfers ownership of the router to the timelock. func transferOwnershipRouter( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // The relevant on-chain addresses @@ -94,9 +110,18 @@ func transferOwnershipRouter( // Build specialized closures buildTransfer := func(newOwner, config, authority solana.PublicKey) (solana.Instruction, error) { ccip_router.SetProgramID(routerProgramID) - return ccip_router.NewTransferOwnershipInstruction( + ix, err := ccip_router.NewTransferOwnershipInstruction( newOwner, config, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { ccip_router.SetProgramID(routerProgramID) @@ -108,7 +133,7 @@ func transferOwnershipRouter( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -119,11 +144,12 @@ func transferOwnershipRouter( buildTransfer, buildAccept, routerProgramID, - timelockSignerPDA, // timelock PDA - routerConfigPDA, // config PDA - solChain.DeployerKey.PublicKey(), + proposedOwner, // timelock PDA + routerConfigPDA, // config PDA + currentOwner, solChain, - state2.Router, + shared.Router, + timelockSigner, // the timelock signer PDA ) if err != nil { @@ -136,15 +162,15 @@ func transferOwnershipRouter( // transferOwnershipFeeQuoter transfers ownership of the fee quoter to the timelock. func transferOwnershipFeeQuoter( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // The relevant on-chain addresses @@ -154,9 +180,18 @@ func transferOwnershipFeeQuoter( // Build specialized closures buildTransfer := func(proposedOwner, config, authority solana.PublicKey) (solana.Instruction, error) { fee_quoter.SetProgramID(feeQuoterProgramID) - return fee_quoter.NewTransferOwnershipInstruction( + ix, err := fee_quoter.NewTransferOwnershipInstruction( proposedOwner, config, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { fee_quoter.SetProgramID(feeQuoterProgramID) @@ -168,7 +203,7 @@ func transferOwnershipFeeQuoter( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -179,11 +214,12 @@ func transferOwnershipFeeQuoter( buildTransfer, buildAccept, feeQuoterProgramID, - timelockSignerPDA, // timelock PDA + proposedOwner, // timelock PDA feeQuoterConfigPDA, // config PDA - solChain.DeployerKey.PublicKey(), + currentOwner, solChain, - state2.FeeQuoter, + shared.FeeQuoter, + timelockSigner, // the timelock signer PDA ) if err != nil { @@ -196,15 +232,15 @@ func transferOwnershipFeeQuoter( // transferOwnershipOffRamp transfers ownership of the offRamp to the timelock. func transferOwnershipOffRamp( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // The relevant on-chain addresses @@ -214,9 +250,18 @@ func transferOwnershipOffRamp( // Build specialized closures buildTransfer := func(proposedOwner, config, authority solana.PublicKey) (solana.Instruction, error) { ccip_offramp.SetProgramID(offRampProgramID) - return ccip_offramp.NewTransferOwnershipInstruction( + ix, err := ccip_offramp.NewTransferOwnershipInstruction( proposedOwner, config, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { ccip_offramp.SetProgramID(offRampProgramID) @@ -228,7 +273,7 @@ func transferOwnershipOffRamp( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -239,11 +284,12 @@ func transferOwnershipOffRamp( buildTransfer, buildAccept, offRampProgramID, - timelockSignerPDA, // timelock PDA - offRampConfigPDA, // config PDA - solChain.DeployerKey.PublicKey(), + proposedOwner, // timelock PDA + offRampConfigPDA, // config PDA + currentOwner, solChain, - state2.OffRamp, + shared.OffRamp, + timelockSigner, // the timelock signer PDA ) if err != nil { @@ -256,28 +302,38 @@ func transferOwnershipOffRamp( // transferOwnershipLockMintTokenPools transfers ownership of the lock mint token pools. func transferOwnershipBurnMintTokenPools( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, tokenPoolConfigPDA solana.PublicKey, tokenMint solana.PublicKey, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + tokenPoolMetadata string, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // Build specialized closures buildTransfer := func(proposedOwner, config, authority solana.PublicKey) (solana.Instruction, error) { - burnmint.SetProgramID(state.BurnMintTokenPools[ccipChangeset.CLLMetadata]) - return burnmint.NewTransferOwnershipInstruction( + burnmint.SetProgramID(state.BurnMintTokenPools[tokenPoolMetadata]) + ix, err := burnmint.NewTransferOwnershipInstruction( proposedOwner, config, tokenMint, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { - burnmint.SetProgramID(state.BurnMintTokenPools[ccipChangeset.CLLMetadata]) + burnmint.SetProgramID(state.BurnMintTokenPools[tokenPoolMetadata]) // If the router has its own accept function, use that ix, err := burnmint.NewAcceptOwnershipInstruction( config, tokenMint, newOwnerAuthority, @@ -286,7 +342,7 @@ func transferOwnershipBurnMintTokenPools( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -296,12 +352,13 @@ func transferOwnershipBurnMintTokenPools( tx, err := transferAndWrapAcceptOwnership( buildTransfer, buildAccept, - state.BurnMintTokenPools[ccipChangeset.CLLMetadata], - timelockSignerPDA, // timelock PDA + state.BurnMintTokenPools[tokenPoolMetadata], + proposedOwner, // timelock PDA tokenPoolConfigPDA, // config PDA - solChain.DeployerKey.PublicKey(), + currentOwner, solChain, - state2.BurnMintTokenPool, + shared.BurnMintTokenPool, + timelockSigner, // the timelock signer PDA ) if err != nil { @@ -314,28 +371,38 @@ func transferOwnershipBurnMintTokenPools( // transferOwnershipLockReleaseTokenPools transfers ownership of the lock mint token pools. func transferOwnershipLockReleaseTokenPools( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, tokenPoolConfigPDA solana.PublicKey, tokenMint solana.PublicKey, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + tokenPoolMetadata string, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // Build specialized closures buildTransfer := func(proposedOwner, config, authority solana.PublicKey) (solana.Instruction, error) { - lockrelease.SetProgramID(state.LockReleaseTokenPools[ccipChangeset.CLLMetadata]) - return lockrelease.NewTransferOwnershipInstruction( + lockrelease.SetProgramID(state.LockReleaseTokenPools[tokenPoolMetadata]) + ix, err := lockrelease.NewTransferOwnershipInstruction( proposedOwner, config, tokenMint, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { - lockrelease.SetProgramID(state.LockReleaseTokenPools[ccipChangeset.CLLMetadata]) + lockrelease.SetProgramID(state.LockReleaseTokenPools[tokenPoolMetadata]) // If the router has its own accept function, use that ix, err := lockrelease.NewAcceptOwnershipInstruction( config, tokenMint, newOwnerAuthority, @@ -344,7 +411,7 @@ func transferOwnershipLockReleaseTokenPools( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -354,12 +421,13 @@ func transferOwnershipLockReleaseTokenPools( tx, err := transferAndWrapAcceptOwnership( buildTransfer, buildAccept, - state.LockReleaseTokenPools[ccipChangeset.CLLMetadata], - timelockSignerPDA, // timelock PDA + state.LockReleaseTokenPools[tokenPoolMetadata], + proposedOwner, // timelock PDA tokenPoolConfigPDA, // config PDA - solChain.DeployerKey.PublicKey(), + currentOwner, solChain, - state2.LockReleaseTokenPool, + shared.LockReleaseTokenPool, + timelockSigner, // the timelock signer PDA ) if err != nil { @@ -372,15 +440,15 @@ func transferOwnershipLockReleaseTokenPools( // transferOwnershipRMNRemote transfers ownership of the RMNRemote to the timelock. func transferOwnershipRMNRemote( - ccipState state2.CCIPOnChainState, + ccipState stateview.CCIPOnChainState, chainSelector uint64, - solChain deployment.SolChain, - timelockProgramID solana.PublicKey, - timelockInstanceSeed state.PDASeed, + solChain cldf.SolChain, + currentOwner solana.PublicKey, + proposedOwner solana.PublicKey, + timelockSigner solana.PublicKey, ) ([]mcmsTypes.Transaction, error) { var result []mcmsTypes.Transaction - timelockSignerPDA := state.GetTimelockSignerPDA(timelockProgramID, timelockInstanceSeed) state := ccipState.SolChains[chainSelector] // The relevant on-chain addresses @@ -391,9 +459,18 @@ func transferOwnershipRMNRemote( // Build specialized closures buildTransfer := func(newOwner, config, cursesConfig, authority solana.PublicKey) (solana.Instruction, error) { rmn_remote.SetProgramID(rmnRemoteProgramID) - return rmn_remote.NewTransferOwnershipInstruction( + ix, err := rmn_remote.NewTransferOwnershipInstruction( newOwner, config, cursesConfig, authority, ).ValidateAndBuild() + if err != nil { + return nil, err + } + for _, acc := range ix.Accounts() { + if acc.PublicKey == timelockSigner { + acc.IsSigner = false + } + } + return ix, nil } buildAccept := func(config, newOwnerAuthority solana.PublicKey) (solana.Instruction, error) { rmn_remote.SetProgramID(rmnRemoteProgramID) @@ -405,7 +482,7 @@ func transferOwnershipRMNRemote( return nil, err } for _, acc := range ix.Accounts() { - if acc.PublicKey == newOwnerAuthority { + if acc.PublicKey == timelockSigner { acc.IsSigner = false } } @@ -413,20 +490,30 @@ func transferOwnershipRMNRemote( } programID := rmnRemoteProgramID - proposedOwner := timelockSignerPDA configPDA := rmnRemoteConfigPDA - deployer := solChain.DeployerKey.PublicKey() - label := state2.RMNRemote + label := shared.RMNRemote // We can't reuse the generic transferAndWrapAcceptOwnership function here // because the RMNRemote has an additional cursesConfig account that needs to be transferred. // 1. Build the instruction that transfers ownership to the timelock - ixTransfer, err := buildTransfer(proposedOwner, configPDA, rmnRemoteCursesPDA, deployer) + ixTransfer, err := buildTransfer(proposedOwner, configPDA, rmnRemoteCursesPDA, currentOwner) if err != nil { return nil, fmt.Errorf("%s: failed to create transfer ownership instruction: %w", label, err) } + // if the old owner is the timelock signer, we need to build the accept instruction and submit it + // We can't perform the accept ownership step here because the timelock signer is not a signer of the transaction + if currentOwner.Equals(timelockSigner) { + mcmsTx, err := BuildMCMSTxn(ixTransfer, programID.String(), label) + if err != nil { + return nil, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + } + // we cannot accept ownership afterwards because the proposal needs to execute before accept is valid + result = append(result, *mcmsTx) + return result, nil + } + // 2. Confirm on-chain if err := solChain.Confirm([]solana.Instruction{ixTransfer}); err != nil { return nil, fmt.Errorf("%s: failed to confirm transfer on-chain: %w", label, err) @@ -438,12 +525,20 @@ func transferOwnershipRMNRemote( return nil, fmt.Errorf("%s: failed to create accept ownership instruction: %w", label, err) } - // 4. Wrap in MCMS transaction - mcmsTx, err := BuildMCMSTxn(ixAccept, programID.String(), label) - if err != nil { - return nil, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + if proposedOwner.Equals(timelockSigner) { + // 4. Wrap in MCMS transaction + mcmsTx, err := BuildMCMSTxn(ixAccept, programID.String(), label) + if err != nil { + return nil, fmt.Errorf("%s: failed to create MCMS transaction: %w", label, err) + } + result = append(result, *mcmsTx) + return result, nil + } + + // 4. Confirm on-chain + if err := solChain.Confirm([]solana.Instruction{ixAccept}); err != nil { + return nil, fmt.Errorf("%s: failed to confirm transfer on-chain: %w", label, err) } - result = append(result, *mcmsTx) return result, nil } diff --git a/deployment/ccip/changeset/solana/save_existing_test.go b/deployment/ccip/changeset/solana/save_existing_test.go index f6cea9c3fe2..ebd256ddb14 100644 --- a/deployment/ccip/changeset/solana/save_existing_test.go +++ b/deployment/ccip/changeset/solana/save_existing_test.go @@ -12,7 +12,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -35,7 +36,7 @@ func TestSaveExistingCCIP(t *testing.T) { ExistingContracts: []commonchangeset.Contract{ { Address: solAddr1, - TypeAndVersion: cldf.NewTypeAndVersion(changeset.Router, deployment.Version1_0_0), + TypeAndVersion: cldf.NewTypeAndVersion(shared.Router, deployment.Version1_0_0), ChainSelector: solChain, }, { @@ -50,7 +51,7 @@ func TestSaveExistingCCIP(t *testing.T) { require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.Equal(t, state.SolChains[solChain].Router.String(), solAddr1) require.Equal(t, state.SolChains[solChain].LinkToken.String(), solAddr2) @@ -58,11 +59,11 @@ func TestSaveExistingCCIP(t *testing.T) { func TestSaveExisting(t *testing.T) { t.Parallel() - dummyEnv := deployment.Environment{ + dummyEnv := cldf.Environment{ Name: "dummy", Logger: logger.TestLogger(t), ExistingAddresses: cldf.NewMemoryAddressBook(), - SolChains: map[uint64]deployment.SolChain{ + SolChains: map[uint64]cldf.SolChain{ chainsel.SOLANA_DEVNET.Selector: {}, }, } diff --git a/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock.go b/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock.go index 932be404b09..42bd439df58 100644 --- a/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock.go +++ b/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock.go @@ -13,8 +13,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - state2 "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -28,21 +30,25 @@ type CCIPContractsToTransfer struct { FeeQuoter bool OffRamp bool // Token Pool PDA -> Token Mint - LockReleaseTokenPools map[solana.PublicKey]solana.PublicKey - BurnMintTokenPools map[solana.PublicKey]solana.PublicKey - RMNRemote bool + LockReleaseTokenPools map[solana.PublicKey]solana.PublicKey + BurnMintTokenPools map[solana.PublicKey]solana.PublicKey + LockReleaseTokenPoolMetadata string + BurnMintTokenPoolMetadata string + RMNRemote bool } type TransferCCIPToMCMSWithTimelockSolanaConfig struct { // ContractsByChain is a map of chain selector the contracts we want to transfer. // Each contract set to true will be transferred ContractsByChain map[uint64]CCIPContractsToTransfer + CurrentOwner solana.PublicKey + ProposedOwner solana.PublicKey // MCMSCfg is for the accept ownership proposal MCMSCfg proposalutils.TimelockConfig } // ValidateContracts checks if the required contracts are present on the chain -func ValidateContracts(state state2.SolCCIPChainState, chainSelector uint64, contracts CCIPContractsToTransfer) error { +func ValidateContracts(state solanastateview.CCIPChainState, chainSelector uint64, contracts CCIPContractsToTransfer) error { contractChecks := []struct { enabled bool value solana.PublicKey @@ -63,8 +69,8 @@ func ValidateContracts(state state2.SolCCIPChainState, chainSelector uint64, con return nil } -func (cfg TransferCCIPToMCMSWithTimelockSolanaConfig) Validate(e deployment.Environment) error { - ccipState, err := state2.LoadOnchainStateSolana(e) +func (cfg TransferCCIPToMCMSWithTimelockSolanaConfig) Validate(e cldf.Environment) error { + ccipState, err := stateview.LoadOnchainStateSolana(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -129,7 +135,7 @@ func (cfg TransferCCIPToMCMSWithTimelockSolanaConfig) Validate(e deployment.Envi // the timelock and mcms exist on the chain and that the proposed addresses to transfer ownership // are currently owned by the deployer key. func TransferCCIPToMCMSWithTimelockSolana( - e deployment.Environment, + e cldf.Environment, cfg TransferCCIPToMCMSWithTimelockSolanaConfig, ) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { @@ -137,7 +143,7 @@ func TransferCCIPToMCMSWithTimelockSolana( } var batches []mcmsTypes.BatchOperation - ccipState, err := state2.LoadOnchainStateSolana(e) + ccipState, err := stateview.LoadOnchainStateSolana(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -150,6 +156,19 @@ func TransferCCIPToMCMSWithTimelockSolana( addresses, _ := e.ExistingAddresses.AddressesForChain(chainSelector) mcmState, _ := state.MaybeLoadMCMSWithTimelockChainStateSolana(solChain, addresses) + currentOwner := solChain.DeployerKey.PublicKey() + if !cfg.CurrentOwner.IsZero() { + currentOwner = cfg.CurrentOwner + } + timelockSigner := state.GetTimelockSignerPDA(mcmState.TimelockProgram, mcmState.TimelockSeed) + proposedOwner := timelockSigner + if !cfg.ProposedOwner.IsZero() { + proposedOwner = cfg.ProposedOwner + } + if currentOwner.Equals(proposedOwner) { + return cldf.ChangesetOutput{}, fmt.Errorf("current owner and proposed owner are the same: %s", currentOwner) + } + timelocks[solChain.Selector] = mcmsSolana.ContractAddress( mcmState.TimelockProgram, mcmsSolana.PDASeed(mcmState.TimelockSeed), @@ -161,8 +180,9 @@ func TransferCCIPToMCMSWithTimelockSolana( ccipState, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of router: %w", err) @@ -178,8 +198,9 @@ func TransferCCIPToMCMSWithTimelockSolana( ccipState, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of fee quoter: %w", err) @@ -195,8 +216,9 @@ func TransferCCIPToMCMSWithTimelockSolana( ccipState, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of offRamp: %w", err) @@ -207,14 +229,20 @@ func TransferCCIPToMCMSWithTimelockSolana( }) } for tokenPoolConfigPDA, tokenMint := range contractsToTransfer.LockReleaseTokenPools { + metadata := shared.CLLMetadata + if contractsToTransfer.LockReleaseTokenPoolMetadata != "" { + metadata = contractsToTransfer.LockReleaseTokenPoolMetadata + } mcmsTxs, err := transferOwnershipLockReleaseTokenPools( ccipState, tokenPoolConfigPDA, tokenMint, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + metadata, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of lock-release token pools: %w", err) @@ -226,14 +254,20 @@ func TransferCCIPToMCMSWithTimelockSolana( } for tokenPoolConfigPDA, tokenMint := range contractsToTransfer.BurnMintTokenPools { + metadata := shared.CLLMetadata + if contractsToTransfer.BurnMintTokenPoolMetadata != "" { + metadata = contractsToTransfer.BurnMintTokenPoolMetadata + } mcmsTxs, err := transferOwnershipBurnMintTokenPools( ccipState, tokenPoolConfigPDA, tokenMint, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + metadata, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of burn-mint token pools: %w", err) @@ -249,8 +283,9 @@ func TransferCCIPToMCMSWithTimelockSolana( ccipState, chainSelector, solChain, - mcmState.TimelockProgram, - mcmState.TimelockSeed, + currentOwner, + proposedOwner, + timelockSigner, ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of rmnremote: %w", err) diff --git a/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock_test.go b/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock_test.go index 8dd39a19ac6..d7c827be90a 100644 --- a/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock_test.go +++ b/deployment/ccip/changeset/solana/transfer_ccip_to_mcms_with_timelock_test.go @@ -28,12 +28,14 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" solanachangesets "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -51,8 +53,8 @@ func TestValidateContracts(t *testing.T) { zeroPubkey := solana.PublicKey{} // Zero public key - makeState := func(router, feeQuoter solana.PublicKey) changeset.SolCCIPChainState { - return changeset.SolCCIPChainState{ + makeState := func(router, feeQuoter solana.PublicKey) solanastateview.CCIPChainState { + return solanastateview.CCIPChainState{ Router: router, FeeQuoter: feeQuoter, } @@ -60,7 +62,7 @@ func TestValidateContracts(t *testing.T) { tests := []struct { name string - state changeset.SolCCIPChainState + state solanastateview.CCIPChainState contracts solanachangesets.CCIPContractsToTransfer chainSelector uint64 expectedError string @@ -122,7 +124,7 @@ func TestValidate(t *testing.T) { SolChains: 1, Nodes: 4, }) - envWithInvalidSolChain.SolChains[chainselectors.ETHEREUM_TESTNET_SEPOLIA_LENS_1.Selector] = deployment.SolChain{} + envWithInvalidSolChain.SolChains[chainselectors.ETHEREUM_TESTNET_SEPOLIA_LENS_1.Selector] = cldf.SolChain{} timelockID := mcmsSolana.ContractAddress(solana.MustPublicKeyFromBase58(TimelockProgramID), [32]byte{'t', 'e', 's', 't'}) mcmsID := mcmsSolana.ContractAddress(solana.MustPublicKeyFromBase58(MCMProgramID), [32]byte{'t', 'e', 's', 't'}) err := env.ExistingAddresses.Save(env.AllChainSelectorsSolana()[0], timelockID, cldf.TypeAndVersion{Type: commontypes.RBACTimelock, Version: deployment.Version1_0_0}) @@ -132,7 +134,7 @@ func TestValidate(t *testing.T) { tests := []struct { name string - env deployment.Environment + env cldf.Environment contractsByChain map[uint64]solanachangesets.CCIPContractsToTransfer expectedError string }{ @@ -192,7 +194,7 @@ func TestValidate(t *testing.T) { // prepareEnvironmentForOwnershipTransfer helper that deploys the necessary contracts as pre-requisite to // the transfer ownership changeset. -func prepareEnvironmentForOwnershipTransfer(t *testing.T) (deployment.Environment, changeset.CCIPOnChainState) { +func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, stateview.CCIPOnChainState) { t.Helper() lggr := logger.TestLogger(t) e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ @@ -256,7 +258,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (deployment.Environmen cldf.CreateLegacyChangeSet(solanachangesets.DeploySolanaToken), solanachangesets.DeploySolanaTokenConfig{ ChainSelector: solChain1, - TokenProgramName: changeset.SPL2022Tokens, + TokenProgramName: shared.SPL2022Tokens, TokenDecimals: 9, }, ), @@ -264,7 +266,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (deployment.Environmen cldf.CreateLegacyChangeSet(solanachangesets.DeploySolanaToken), solanachangesets.DeploySolanaTokenConfig{ ChainSelector: solChain1, - TokenProgramName: changeset.SPL2022Tokens, + TokenProgramName: shared.SPLTokens, TokenDecimals: 9, }, ), @@ -284,10 +286,10 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (deployment.Environmen // solana verification testhelpers.ValidateSolanaState(t, e, solChainSelectors) - state, err := changeset.LoadOnchainStateSolana(e) + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0] - tokenAddressBurnMint := state.SolChains[solChain1].SPL2022Tokens[1] + tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0] lnr := test_token_pool.LockAndRelease_PoolType bnm := test_token_pool.BurnAndMint_PoolType @@ -319,10 +321,10 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) { solChain := e.SolChains[solChain1] tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0] + tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0] - tokenAddressBurnMint := state.SolChains[solChain1].SPL2022Tokens[1] - burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, state.SolChains[solChain1].BurnMintTokenPools[ccipChangeset.CLLMetadata]) - lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, state.SolChains[solChain1].LockReleaseTokenPools[ccipChangeset.CLLMetadata]) + burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, state.SolChains[solChain1].BurnMintTokenPools[shared.CLLMetadata]) + lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, state.SolChains[solChain1].LockReleaseTokenPools[shared.CLLMetadata]) timelockSignerPDA, _ := testhelpers.TransferOwnershipSolana( t, &e, @@ -400,3 +402,80 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) { return timelockSignerPDA.String() == programData.Owner.String() }, 30*time.Second, 5*time.Second, "RMNRemote config PDA owner was not changed to timelock signer PDA") } + +func TestTransferCCIPFromMCMSWithTimelockSolana(t *testing.T) { + t.Parallel() + e, state := prepareEnvironmentForOwnershipTransfer(t) + solChain1 := e.AllChainSelectorsSolana()[0] + solChain := e.SolChains[solChain1] + + tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0] + tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0] + + burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, state.SolChains[solChain1].BurnMintTokenPools[shared.CLLMetadata]) + lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, state.SolChains[solChain1].LockReleaseTokenPools[shared.CLLMetadata]) + timelockSignerPDA, _ := testhelpers.TransferOwnershipSolana( + t, + &e, + solChain1, + false, + solanachangesets.CCIPContractsToTransfer{ + Router: true, + FeeQuoter: true, + OffRamp: true, + RMNRemote: true, + BurnMintTokenPools: map[solana.PublicKey]solana.PublicKey{burnMintPoolConfigPDA: tokenAddressBurnMint}, + LockReleaseTokenPools: map[solana.PublicKey]solana.PublicKey{lockReleasePoolConfigPDA: tokenAddressLockRelease}, + }) + // Transfer ownership back to the deployer + e, _, err := commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{ + commonchangeset.Configure( + cldf.CreateLegacyChangeSet(ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolana), + ccipChangesetSolana.TransferCCIPToMCMSWithTimelockSolanaConfig{ + MCMSCfg: proposalutils.TimelockConfig{MinDelay: 1 * time.Second}, + CurrentOwner: timelockSignerPDA, + ProposedOwner: solChain.DeployerKey.PublicKey(), + ContractsByChain: map[uint64]ccipChangesetSolana.CCIPContractsToTransfer{ + solChain1: ccipChangesetSolana.CCIPContractsToTransfer{ + Router: true, + FeeQuoter: true, + OffRamp: true, + RMNRemote: true, + BurnMintTokenPools: map[solana.PublicKey]solana.PublicKey{ + burnMintPoolConfigPDA: tokenAddressBurnMint, + }, + LockReleaseTokenPools: map[solana.PublicKey]solana.PublicKey{ + lockReleasePoolConfigPDA: tokenAddressLockRelease, + }, + }, + }, + }, + ), + }) + require.NoError(t, err) + // we have to accept separate from the changeset because the proposal needs to execute + // just spot check that the ownership transfer happened + config := state.SolChains[solChain1].RouterConfigPDA + ix, err := ccip_router.NewAcceptOwnershipInstruction( + config, solChain.DeployerKey.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, err) + err = solChain.Confirm([]solana.Instruction{ix}) + require.NoError(t, err) + + // lnr + lnrIx, err := lockrelease.NewAcceptOwnershipInstruction( + lockReleasePoolConfigPDA, tokenAddressLockRelease, solChain.DeployerKey.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, err) + err = solChain.Confirm([]solana.Instruction{lnrIx}) + require.NoError(t, err) + + // bnm + bnmIx, err := burnmint.NewAcceptOwnershipInstruction( + burnMintPoolConfigPDA, tokenAddressBurnMint, solChain.DeployerKey.PublicKey(), + ).ValidateAndBuild() + require.NoError(t, err) + err = solChain.Confirm([]solana.Instruction{bnmIx}) + require.NoError(t, err) +} diff --git a/deployment/ccip/changeset/solana/utils.go b/deployment/ccip/changeset/solana/utils.go index 650a4eba2bd..32ab4f80f07 100644 --- a/deployment/ccip/changeset/solana/utils.go +++ b/deployment/ccip/changeset/solana/utils.go @@ -13,18 +13,17 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - ccipChangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - cs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) func ValidateMCMSConfigSolana( - e deployment.Environment, + e cldf.Environment, mcms *proposalutils.TimelockConfig, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, tokenAddress solana.PublicKey, tokenPoolMetadata string, contractsToValidate map[cldf.ContractType]bool) error { @@ -33,35 +32,35 @@ func ValidateMCMSConfigSolana( return fmt.Errorf("failed to validate MCMS config: %w", err) } } - if contractsToValidate[cs.FeeQuoter] { - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.FeeQuoter, cs.FeeQuoter, tokenAddress); err != nil { + if contractsToValidate[shared.FeeQuoter] { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.FeeQuoter, shared.FeeQuoter, tokenAddress); err != nil { return fmt.Errorf("failed to validate ownership for fee quoter: %w", err) } } - if contractsToValidate[cs.Router] { - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.Router, cs.Router, tokenAddress); err != nil { + if contractsToValidate[shared.Router] { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.Router, shared.Router, tokenAddress); err != nil { return fmt.Errorf("failed to validate ownership for router: %w", err) } } - if contractsToValidate[cs.OffRamp] { - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.OffRamp, cs.OffRamp, tokenAddress); err != nil { + if contractsToValidate[shared.OffRamp] { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.OffRamp, shared.OffRamp, tokenAddress); err != nil { return fmt.Errorf("failed to validate ownership for off ramp: %w", err) } } - if contractsToValidate[cs.RMNRemote] { - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.RMNRemote, cs.RMNRemote, tokenAddress); err != nil { + if contractsToValidate[shared.RMNRemote] { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.RMNRemote, shared.RMNRemote, tokenAddress); err != nil { return fmt.Errorf("failed to validate ownership for rmnremote: %w", err) } } if !tokenAddress.IsZero() { - metadata := ccipChangeset.CLLMetadata + metadata := shared.CLLMetadata if tokenPoolMetadata != "" { metadata = tokenPoolMetadata } - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.BurnMintTokenPools[metadata], cs.BurnMintTokenPool, tokenAddress); contractsToValidate[cs.BurnMintTokenPool] && err != nil { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.BurnMintTokenPools[metadata], shared.BurnMintTokenPool, tokenAddress); contractsToValidate[shared.BurnMintTokenPool] && err != nil { return fmt.Errorf("failed to validate ownership for burnmint: %w", err) } - if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.LockReleaseTokenPools[metadata], cs.LockReleaseTokenPool, tokenAddress); contractsToValidate[cs.LockReleaseTokenPool] && err != nil { + if err := solanastateview.ValidateOwnershipSolana(&e, chain, mcms != nil, chainState.LockReleaseTokenPools[metadata], shared.LockReleaseTokenPool, tokenAddress); contractsToValidate[shared.LockReleaseTokenPool] && err != nil { return fmt.Errorf("failed to validate ownership for lockrelease: %w", err) } } @@ -70,7 +69,7 @@ func ValidateMCMSConfigSolana( } func BuildProposalsForTxns( - e deployment.Environment, + e cldf.Environment, chainSelector uint64, description string, minDelay time.Duration, @@ -131,7 +130,7 @@ func BuildMCMSTxn(ixn solana.Instruction, programID string, contractType cldf.Co return &tx, nil } -func FetchTimelockSigner(e deployment.Environment, chainSelector uint64) (solana.PublicKey, error) { +func FetchTimelockSigner(e cldf.Environment, chainSelector uint64) (solana.PublicKey, error) { addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector) if err != nil { return solana.PublicKey{}, fmt.Errorf("failed to load addresses for chain %d: %w", chainSelector, err) @@ -145,9 +144,9 @@ func FetchTimelockSigner(e deployment.Environment, chainSelector uint64) (solana } func GetAuthorityForIxn( - e *deployment.Environment, - chain deployment.SolChain, - chainState ccipChangeset.SolCCIPChainState, + e *cldf.Environment, + chain cldf.SolChain, + chainState solanastateview.CCIPChainState, mcms *proposalutils.TimelockConfig, contractType cldf.ContractType, tokenAddress solana.PublicKey, // used for burnmint and lockrelease @@ -157,7 +156,7 @@ func GetAuthorityForIxn( if err != nil { return chain.DeployerKey.PublicKey() } - if ccipChangeset.IsSolanaProgramOwnedByTimelock(e, chain, chainState, contractType, tokenAddress, tokenMetadata) { + if solanastateview.IsSolanaProgramOwnedByTimelock(e, chain, chainState, contractType, tokenAddress, tokenMetadata) { return timelockSigner } return chain.DeployerKey.PublicKey() diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/changeset/state.go deleted file mode 100644 index c85cf3595e8..00000000000 --- a/deployment/ccip/changeset/state.go +++ /dev/null @@ -1,2117 +0,0 @@ -package changeset - -import ( - "context" - std_errors "errors" - "fmt" - "strconv" - "sync" - - "github.com/Masterminds/semver/v3" - "github.com/aptos-labs/aptos-go-sdk" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" - solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - - "github.com/smartcontractkit/chainlink/deployment/ccip/view/shared" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_from_mint_token_pool" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/link_token" - - "github.com/smartcontractkit/chainlink/deployment/ccip" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" - commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - cciptypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/commit_store" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/factory_burn_mint_erc20" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/log_message_data_receiver" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/token_pool_factory" - price_registry_1_2_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/price_registry" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_mint_token_pool" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_with_from_mint_token_pool" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/lock_release_token_pool" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc20" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc677" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_messenger" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_transmitter" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/usdc_token_pool" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/view" - viewv1_0 "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_0" - "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_2" - viewv1_5 "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5" - viewv1_5_1 "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5_1" - viewv1_6 "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_6" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/deployment/helpers" - - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" - - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/don_id_claimer" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_0_0/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/mock_rmn_contract" - registryModuleOwnerCustomv15 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/registry_module_owner_custom" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/nonce_manager" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" - registryModuleOwnerCustomv16 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/registry_module_owner_custom" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_home" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" - capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/aggregator_v3_interface" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/multicall3" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/weth9" -) - -var ( - // Legacy - CommitStore cldf.ContractType = "CommitStore" - PriceRegistry cldf.ContractType = "PriceRegistry" - RMN cldf.ContractType = "RMN" - - // Not legacy - MockRMN cldf.ContractType = "MockRMN" - RMNRemote cldf.ContractType = "RMNRemote" - ARMProxy cldf.ContractType = "ARMProxy" - WETH9 cldf.ContractType = "WETH9" - Router cldf.ContractType = "Router" - TokenAdminRegistry cldf.ContractType = "TokenAdminRegistry" - TokenPoolFactory cldf.ContractType = "TokenPoolFactory" - RegistryModule cldf.ContractType = "RegistryModuleOwnerCustom" - NonceManager cldf.ContractType = "NonceManager" - FeeQuoter cldf.ContractType = "FeeQuoter" - CCIPHome cldf.ContractType = "CCIPHome" - RMNHome cldf.ContractType = "RMNHome" - OnRamp cldf.ContractType = "OnRamp" - OffRamp cldf.ContractType = "OffRamp" - CapabilitiesRegistry cldf.ContractType = "CapabilitiesRegistry" - DonIDClaimer cldf.ContractType = "DonIDClaimer" - PriceFeed cldf.ContractType = "PriceFeed" - - // Test contracts. Note test router maps to a regular router contract. - TestRouter cldf.ContractType = "TestRouter" - Multicall3 cldf.ContractType = "Multicall3" - CCIPReceiver cldf.ContractType = "CCIPReceiver" - LogMessageDataReceiver cldf.ContractType = "LogMessageDataReceiver" - USDCMockTransmitter cldf.ContractType = "USDCMockTransmitter" - - // Pools - BurnMintToken cldf.ContractType = "BurnMintToken" - FactoryBurnMintERC20Token cldf.ContractType = "FactoryBurnMintERC20Token" - ERC20Token cldf.ContractType = "ERC20Token" - ERC677Token cldf.ContractType = "ERC677Token" - BurnMintTokenPool cldf.ContractType = "BurnMintTokenPool" - BurnWithFromMintTokenPool cldf.ContractType = "BurnWithFromMintTokenPool" - BurnFromMintTokenPool cldf.ContractType = "BurnFromMintTokenPool" - LockReleaseTokenPool cldf.ContractType = "LockReleaseTokenPool" - USDCToken cldf.ContractType = "USDCToken" - USDCTokenMessenger cldf.ContractType = "USDCTokenMessenger" - USDCTokenPool cldf.ContractType = "USDCTokenPool" - HybridLockReleaseUSDCTokenPool cldf.ContractType = "HybridLockReleaseUSDCTokenPool" - - // Firedrill - FiredrillEntrypointType cldf.ContractType = "FiredrillEntrypoint" - - // Treasury - FeeAggregator cldf.ContractType = "FeeAggregator" -) - -// CCIPChainState holds a Go binding for all the currently deployed CCIP contracts -// on a chain. If a binding is nil, it means here is no such contract on the chain. -type CCIPChainState struct { - commonstate.MCMSWithTimelockState - commonstate.LinkTokenState - commonstate.StaticLinkTokenState - ABIByAddress map[string]string - OnRamp onramp.OnRampInterface - OffRamp offramp.OffRampInterface - FeeQuoter *fee_quoter.FeeQuoter - RMNProxy *rmn_proxy_contract.RMNProxy - NonceManager *nonce_manager.NonceManager - TokenAdminRegistry *token_admin_registry.TokenAdminRegistry - TokenPoolFactory *token_pool_factory.TokenPoolFactory - RegistryModules1_6 []*registryModuleOwnerCustomv16.RegistryModuleOwnerCustom - // TODO change this to contract object for v1.5 RegistryModules once we have the wrapper available in chainlink-evm - RegistryModules1_5 []*registryModuleOwnerCustomv15.RegistryModuleOwnerCustom - Router *router.Router - Weth9 *weth9.WETH9 - RMNRemote *rmn_remote.RMNRemote - // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) - // and the respective token / token pool contract(s) (only one of which would be active on the registry). - // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. - ERC20Tokens map[TokenSymbol]*erc20.ERC20 - FactoryBurnMintERC20Token *factory_burn_mint_erc20.FactoryBurnMintERC20 - ERC677Tokens map[TokenSymbol]*erc677.ERC677 - BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 - BurnMintTokenPools map[TokenSymbol]map[semver.Version]*burn_mint_token_pool.BurnMintTokenPool - BurnWithFromMintTokenPools map[TokenSymbol]map[semver.Version]*burn_with_from_mint_token_pool.BurnWithFromMintTokenPool - BurnFromMintTokenPools map[TokenSymbol]map[semver.Version]*burn_from_mint_token_pool.BurnFromMintTokenPool - USDCTokenPools map[semver.Version]*usdc_token_pool.USDCTokenPool - LockReleaseTokenPools map[TokenSymbol]map[semver.Version]*lock_release_token_pool.LockReleaseTokenPool - // Map between token Symbol (e.g. LinkSymbol, WethSymbol) - // and the respective aggregator USD feed contract - USDFeeds map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface - - // Note we only expect one of these (on the home chain) - CapabilityRegistry *capabilities_registry.CapabilitiesRegistry - CCIPHome *ccip_home.CCIPHome - RMNHome *rmn_home.RMNHome - DonIDClaimer *don_id_claimer.DonIDClaimer - - // Test contracts - Receiver maybe_revert_message_receiver.MaybeRevertMessageReceiverInterface - LogMessageDataReceiver *log_message_data_receiver.LogMessageDataReceiver - TestRouter *router.Router - MockUSDCTransmitter *mock_usdc_token_transmitter.MockE2EUSDCTransmitter - MockUSDCTokenMessenger *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger - Multicall3 *multicall3.Multicall3 - - // Legacy contracts - EVM2EVMOnRamp map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp // mapping of dest chain selector -> EVM2EVMOnRamp - CommitStore map[uint64]*commit_store.CommitStore // mapping of source chain selector -> CommitStore - EVM2EVMOffRamp map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp // mapping of source chain selector -> EVM2EVMOffRamp - MockRMN *mock_rmn_contract.MockRMNContract - PriceRegistry *price_registry_1_2_0.PriceRegistry - RMN *rmn_contract.RMNContract - - // Treasury contracts - FeeAggregator common.Address -} - -// validateHomeChain validates the home chain contracts and their configurations after complete set up -// It cross-references the config across CCIPHome and OffRamps to ensure they are in sync -// This should be called after the complete deployment is done -func (c CCIPChainState) validateHomeChain(e deployment.Environment, nodes deployment.Nodes, offRampsByChain map[uint64]offramp.OffRampInterface) error { - if c.RMNHome == nil { - return errors.New("no RMNHome contract found in the state for home chain") - } - if c.CCIPHome == nil { - return errors.New("no CCIPHome contract found in the state for home chain") - } - if c.CapabilityRegistry == nil { - return errors.New("no CapabilityRegistry contract found in the state for home chain") - } - // get capReg from CCIPHome - capReg, err := c.CCIPHome.GetCapabilityRegistry(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get capability registry from CCIPHome contract: %w", err) - } - if capReg != c.CapabilityRegistry.Address() { - return fmt.Errorf("capability registry mismatch: expected %s, got %s", capReg.Hex(), c.CapabilityRegistry.Address().Hex()) - } - ccipDons, err := ccip.GetCCIPDonsFromCapRegistry(e.GetContext(), c.CapabilityRegistry) - if err != nil { - return fmt.Errorf("failed to get CCIP Dons from capability registry: %w", err) - } - if len(ccipDons) == 0 { - return errors.New("no CCIP Dons found in capability registry") - } - // validate for all ccipDons - for _, don := range ccipDons { - if err := nodes.P2PIDsPresentInJD(don.NodeP2PIds); err != nil { - return fmt.Errorf("failed to find Capability Registry p2pIDs in JD: %w", err) - } - commitConfig, err := c.CCIPHome.GetAllConfigs(&bind.CallOpts{ - Context: e.GetContext(), - }, don.Id, uint8(cciptypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("failed to get commit config for don %d: %w", don.Id, err) - } - if err := c.validateCCIPHomeVersionedActiveConfig(e, nodes, commitConfig.ActiveConfig, offRampsByChain); err != nil { - return fmt.Errorf("failed to validate active commit config for don %d: %w", don.Id, err) - } - execConfig, err := c.CCIPHome.GetAllConfigs(&bind.CallOpts{ - Context: e.GetContext(), - }, don.Id, uint8(cciptypes.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("failed to get exec config for don %d: %w", don.Id, err) - } - if err := c.validateCCIPHomeVersionedActiveConfig(e, nodes, execConfig.ActiveConfig, offRampsByChain); err != nil { - return fmt.Errorf("failed to validate active exec config for don %d: %w", don.Id, err) - } - } - return nil -} - -// validateCCIPHomeVersionedActiveConfig validates the CCIPHomeVersionedConfig based on corresponding chain selector and its state -// The validation related to correctness of F and node length is omitted here as it is already validated in the contract -func (c CCIPChainState) validateCCIPHomeVersionedActiveConfig(e deployment.Environment, nodes deployment.Nodes, homeCfg ccip_home.CCIPHomeVersionedConfig, offRampsByChain map[uint64]offramp.OffRampInterface) error { - if homeCfg.ConfigDigest == [32]byte{} { - return errors.New("active config digest is empty") - } - chainSel := homeCfg.Config.ChainSelector - if _, exists := e.SolChains[chainSel]; exists { - return nil - } - if _, exists := e.AptosChains[chainSel]; exists { - return nil - } - offRamp, ok := offRampsByChain[chainSel] - if !ok { - return fmt.Errorf("offRamp for chain %d not found in the state", chainSel) - } - // validate ChainConfig in CCIPHome - homeChainConfig, err := c.CCIPHome.GetChainConfig(&bind.CallOpts{ - Context: e.GetContext(), - }, chainSel) - if err != nil { - return fmt.Errorf("failed to get home chain config for chain %d: %w", chainSel, err) - } - // Node details should match with what we fetch from JD for CCIP Home Readers - if err := nodes.P2PIDsPresentInJD(homeChainConfig.Readers); err != nil { - return fmt.Errorf("failed to find homechain readers in JD for chain %d: %w", - chainSel, err) - } - - // Validate CCIPHome OCR3 Related Config - if offRamp.Address() != common.BytesToAddress(homeCfg.Config.OfframpAddress) { - return fmt.Errorf("offRamp address mismatch in active config for ccip home for chain %d: expected %s, got %s", - chainSel, offRamp.Address().Hex(), homeCfg.Config.OfframpAddress) - } - if c.RMNHome.Address() != common.BytesToAddress(homeCfg.Config.RmnHomeAddress) { - return fmt.Errorf("RMNHome address mismatch in active config for ccip home for chain %d: expected %s, got %s", - chainSel, c.RMNHome.Address().Hex(), homeCfg.Config.RmnHomeAddress) - } - p2pIDs := make([][32]byte, 0) - for _, node := range homeCfg.Config.Nodes { - p2pIDs = append(p2pIDs, node.P2pId) - } - if err := nodes.P2PIDsPresentInJD(p2pIDs); err != nil { - return fmt.Errorf("failed to find p2pIDs from CCIPHome config in JD for chain %d: %w", chainSel, err) - } - // cross-check with offRamp whether all in sync - switch homeCfg.Config.PluginType { - case uint8(cciptypes.PluginTypeCCIPCommit): - commitConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: e.GetContext(), - }, uint8(cciptypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("failed to get commit config for chain %d offRamp %s: %w", chainSel, c.OffRamp.Address().Hex(), err) - } - // the config digest should match with CCIP Home ActiveConfig - if commitConfig.ConfigInfo.ConfigDigest != homeCfg.ConfigDigest { - return fmt.Errorf("offRamp %s commit config digest mismatch with CCIPHome for chain %d: expected %x, got %x", - offRamp.Address().Hex(), chainSel, homeCfg.ConfigDigest, commitConfig.ConfigInfo.ConfigDigest) - } - if !commitConfig.ConfigInfo.IsSignatureVerificationEnabled { - return fmt.Errorf("offRamp %s for chain %d commit config signature verification is not enabled", - offRamp.Address().Hex(), chainSel) - } - if err := validateLatestConfigOffRamp(offRamp, commitConfig, homeChainConfig); err != nil { - return fmt.Errorf("offRamp %s for chain %d commit config validation error: %w", - offRamp.Address().Hex(), chainSel, err) - } - case uint8(cciptypes.PluginTypeCCIPExec): - execConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: e.GetContext(), - }, uint8(cciptypes.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("failed to get exec config for chain %d offRamp %s: %w", chainSel, offRamp.Address().Hex(), err) - } - // the config digest should match with CCIP Home ActiveConfig - if execConfig.ConfigInfo.ConfigDigest != homeCfg.ConfigDigest { - return fmt.Errorf("offRamp %s exec config digest mismatch with CCIPHome for chain %d: expected %x, got %x", - offRamp.Address().Hex(), chainSel, homeCfg.ConfigDigest, execConfig.ConfigInfo.ConfigDigest) - } - if execConfig.ConfigInfo.IsSignatureVerificationEnabled { - return fmt.Errorf("offRamp %s for chain %d exec config signature verification is enabled", - offRamp.Address().Hex(), chainSel) - } - if err := validateLatestConfigOffRamp(offRamp, execConfig, homeChainConfig); err != nil { - return fmt.Errorf("offRamp %s for chain %d exec config validation error: %w", - offRamp.Address().Hex(), chainSel, err) - } - default: - return fmt.Errorf("unsupported plugin type %d for chain %d", homeCfg.Config.PluginType, chainSel) - } - return nil -} - -// validateOnRamp validates whether the contract addresses configured in static and dynamic config are in sync with state -func (c CCIPChainState) validateOnRamp( - e deployment.Environment, - selector uint64, - connectedChains []uint64, -) error { - if c.OnRamp == nil { - return errors.New("no OnRamp contract found in the state") - } - staticCfg, err := c.OnRamp.GetStaticConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return err - } - if staticCfg.ChainSelector != selector { - return fmt.Errorf("onRamp %s chainSelector mismatch in static config: expected %d, got %d", - c.OnRamp.Address().Hex(), selector, staticCfg.ChainSelector) - } - // it should be RMNProxy pointing to the RMNRemote - if c.RMNProxy.Address() != staticCfg.RmnRemote { - return fmt.Errorf("onRamp %s RMNRemote mismatch in static config: expected %s, got %s", - c.OnRamp.Address().Hex(), c.RMNRemote.Address().Hex(), staticCfg.RmnRemote) - } - if c.NonceManager.Address() != staticCfg.NonceManager { - return fmt.Errorf("onRamp %s NonceManager mismatch in static config: expected %s, got %s", - c.OnRamp.Address().Hex(), c.NonceManager.Address().Hex(), staticCfg.NonceManager) - } - if c.TokenAdminRegistry.Address() != staticCfg.TokenAdminRegistry { - return fmt.Errorf("onRamp %s TokenAdminRegistry mismatch in static config: expected %s, got %s", - c.OnRamp.Address().Hex(), c.TokenAdminRegistry.Address().Hex(), staticCfg.TokenAdminRegistry) - } - dynamicCfg, err := c.OnRamp.GetDynamicConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get dynamic config for chain %d onRamp %s: %w", selector, c.OnRamp.Address().Hex(), err) - } - if dynamicCfg.FeeQuoter != c.FeeQuoter.Address() { - return fmt.Errorf("onRamp %s feeQuoter mismatch in dynamic config: expected %s, got %s", - c.OnRamp.Address().Hex(), c.FeeQuoter.Address().Hex(), dynamicCfg.FeeQuoter.Hex()) - } - // if the fee aggregator is set, it should match the one in the dynamic config - // otherwise the fee aggregator should be the timelock address - if c.FeeAggregator != (common.Address{}) { - if c.FeeAggregator != dynamicCfg.FeeAggregator { - return fmt.Errorf("onRamp %s feeAggregator mismatch in dynamic config: expected %s, got %s", - c.OnRamp.Address().Hex(), c.FeeAggregator.Hex(), dynamicCfg.FeeAggregator.Hex()) - } - } else { - if dynamicCfg.FeeAggregator != e.Chains[selector].DeployerKey.From { - return fmt.Errorf("onRamp %s feeAggregator mismatch in dynamic config: expected deployer key %s, got %s", - c.OnRamp.Address().Hex(), e.Chains[selector].DeployerKey.From.Hex(), dynamicCfg.FeeAggregator.Hex()) - } - } - - for _, otherChainSel := range connectedChains { - destChainCfg, err := c.OnRamp.GetDestChainConfig(&bind.CallOpts{ - Context: e.GetContext(), - }, otherChainSel) - if err != nil { - return fmt.Errorf("failed to get dest chain config from source chain %d onRamp %s for dest chain %d: %w", - selector, c.OnRamp.Address(), otherChainSel, err) - } - // if not blank, the dest chain config should be enabled - if destChainCfg != (onramp.GetDestChainConfig{}) { - if destChainCfg.Router != c.Router.Address() && destChainCfg.Router != c.TestRouter.Address() { - return fmt.Errorf("onRamp %s router mismatch in dest chain config: expected router %s or test router %s, got %s", - c.OnRamp.Address().Hex(), c.Router.Address().Hex(), c.TestRouter.Address().Hex(), destChainCfg.Router.Hex()) - } - } - } - - return nil -} - -// validateFeeQuoter validates whether the fee quoter contract address configured in static config is in sync with state -func (c CCIPChainState) validateFeeQuoter(e deployment.Environment) error { - if c.FeeQuoter == nil { - return errors.New("no FeeQuoter contract found in the state") - } - staticConfig, err := c.FeeQuoter.GetStaticConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get static config for FeeQuoter %s: %w", c.FeeQuoter.Address().Hex(), err) - } - linktokenAddr, err := c.LinkTokenAddress() - if err != nil { - return fmt.Errorf("failed to get link token address for from state: %w", err) - } - if staticConfig.LinkToken != linktokenAddr { - return fmt.Errorf("feeQuoter %s LinkToken mismatch: expected either linktoken %s or static link token %s, got %s", - c.FeeQuoter.Address().Hex(), c.LinkToken.Address().Hex(), c.StaticLinkToken.Address(), staticConfig.LinkToken.Hex()) - } - return nil -} - -// validateRouter validates the router contract to check if all wired contracts are synced with state -// and returns all connected chains with respect to the router -func (c CCIPChainState) validateRouter(e deployment.Environment, isTestRouter bool) ([]uint64, error) { - if c.Router == nil && c.TestRouter == nil { - return nil, errors.New("no Router or TestRouter contract found in the state") - } - routerC := c.Router - if isTestRouter { - routerC = c.TestRouter - } - armProxy, err := routerC.GetArmProxy(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return nil, fmt.Errorf("failed to get armProxy from router : %w", err) - } - if armProxy != c.RMNProxy.Address() { - return nil, fmt.Errorf("armProxy %s mismatch in router %s: expected %s, got %s", - armProxy.Hex(), routerC.Address().Hex(), c.RMNProxy.Address().Hex(), armProxy) - } - native, err := routerC.GetWrappedNative(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return nil, fmt.Errorf("failed to get wrapped native from router %s: %w", routerC.Address().Hex(), err) - } - if native != c.Weth9.Address() { - return nil, fmt.Errorf("wrapped native %s mismatch in router %s: expected %s, got %s", - native.Hex(), routerC.Address().Hex(), c.Weth9.Address().Hex(), native) - } - allConnectedChains := make([]uint64, 0) - // get offRamps - offRampDetails, err := routerC.GetOffRamps(&bind.CallOpts{ - Context: context.Background(), - }) - if err != nil { - return nil, fmt.Errorf("failed to get offRamps from router %s: %w", routerC.Address().Hex(), err) - } - for _, d := range offRampDetails { - // skip if solana - solana state is maintained in solana - if _, exists := e.SolChains[d.SourceChainSelector]; exists { - continue - } - allConnectedChains = append(allConnectedChains, d.SourceChainSelector) - // check if offRamp is valid - if d.OffRamp != c.OffRamp.Address() { - return nil, fmt.Errorf("offRamp %s mismatch for source %d in router %s: expected %s, got %s", - d.OffRamp.Hex(), d.SourceChainSelector, routerC.Address().Hex(), c.OffRamp.Address().Hex(), d.OffRamp) - } - } - // all lanes are bi-directional, if we have a lane from A to B, we also have a lane from B to A - // source to offRamp should be same as dest to onRamp - for _, dest := range allConnectedChains { - onRamp, err := routerC.GetOnRamp(&bind.CallOpts{ - Context: context.Background(), - }, dest) - if err != nil { - return nil, fmt.Errorf("failed to get onRamp for dest %d from router %s: %w", dest, routerC.Address().Hex(), err) - } - if onRamp != c.OnRamp.Address() { - return nil, fmt.Errorf("onRamp %s mismatch for dest chain %d in router %s: expected %s, got %s", - onRamp.Hex(), dest, routerC.Address().Hex(), c.OnRamp.Address().Hex(), onRamp) - } - } - return allConnectedChains, nil -} - -// validateRMNRemote validates the RMNRemote contract to check if all wired contracts are synced with state -// and returns whether RMN is enabled for the chain on the RMNRemote -// It validates whether RMNRemote is in sync with the RMNHome contract -func (c CCIPChainState) validateRMNRemote( - e deployment.Environment, - selector uint64, - rmnHomeActiveDigest [32]byte, -) (bool, error) { - if c.RMNRemote == nil { - return false, errors.New("no RMNRemote contract found in the state") - } - chainSelector, err := c.RMNRemote.GetLocalChainSelector(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return false, fmt.Errorf("failed to get local chain selector from RMNRemote %s: %w", c.RMNRemote.Address().Hex(), err) - } - if chainSelector != selector { - return false, fmt.Errorf("RMNRemote %s chainSelector mismatch: expected %d, got %d", - c.RMNRemote.Address().Hex(), selector, chainSelector) - } - versionedCfg, err := c.RMNRemote.GetVersionedConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return false, fmt.Errorf("failed to get versioned config from RMNRemote %s: %w", c.RMNRemote.Address().Hex(), err) - } - if versionedCfg.Version == 0 { - return false, errors.New("RMNRemote config is not set") - } - if versionedCfg.Config.RmnHomeContractConfigDigest != rmnHomeActiveDigest { - return false, fmt.Errorf("RMNRemote %s config digest mismatch: expected %x, got %x", - c.RMNRemote.Address().Hex(), rmnHomeActiveDigest, versionedCfg.Config.RmnHomeContractConfigDigest) - } - return versionedCfg.Config.FSign > 0, nil -} - -// validateOffRamp validates the offRamp contract to check if all wired contracts are synced with state -func (c CCIPChainState) validateOffRamp( - e deployment.Environment, - selector uint64, - onRampsBySelector map[uint64]common.Address, - isRMNEnabledBySource map[uint64]bool, -) error { - if c.OffRamp == nil { - return errors.New("no OffRamp contract found in the state") - } - // staticConfig chainSelector matches the selector key for the CCIPChainState - staticConfig, err := c.OffRamp.GetStaticConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get static config for chain %d offRammp %s: %w", selector, c.OffRamp.Address().Hex(), err) - } - // staticConfig chainSelector should match the selector key for the CCIPChainState - if staticConfig.ChainSelector != selector { - return fmt.Errorf("offRamp %s chainSelector mismatch: expected %d, got %d", - c.OffRamp.Address().Hex(), selector, staticConfig.ChainSelector) - } - // RMNProxy address for chain should be the same as the one in the static config for RMNRemote - if c.RMNProxy.Address() != staticConfig.RmnRemote { - return fmt.Errorf("offRamp %s RMNRemote mismatch: expected %s, got %s", - c.OffRamp.Address().Hex(), c.RMNRemote.Address().Hex(), staticConfig.RmnRemote) - } - // NonceManager address for chain should be the same as the one in the static config - if c.NonceManager.Address() != staticConfig.NonceManager { - return fmt.Errorf("offRamp %s NonceManager mismatch: expected %s, got %s", - c.OffRamp.Address().Hex(), c.NonceManager.Address().Hex(), staticConfig.NonceManager) - } - // TokenAdminRegistry address for chain should be the same as the one in the static config - if c.TokenAdminRegistry.Address() != staticConfig.TokenAdminRegistry { - return fmt.Errorf("offRamp %s TokenAdminRegistry mismatch: expected %s, got %s", - c.OffRamp.Address().Hex(), c.TokenAdminRegistry.Address().Hex(), staticConfig.TokenAdminRegistry) - } - dynamicConfig, err := c.OffRamp.GetDynamicConfig(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get dynamic config for chain %d offRamp %s: %w", selector, c.OffRamp.Address().Hex(), err) - } - // FeeQuoter address for chain should be the same as the one in the static config - if dynamicConfig.FeeQuoter != c.FeeQuoter.Address() { - return fmt.Errorf("offRamp %s feeQuoter mismatch: expected %s, got %s", - c.OffRamp.Address().Hex(), c.FeeQuoter.Address().Hex(), dynamicConfig.FeeQuoter.Hex()) - } - if dynamicConfig.PermissionLessExecutionThresholdSeconds != uint32(globals.PermissionLessExecutionThreshold.Seconds()) { - return fmt.Errorf("offRamp %s permissionless execution threshold mismatch: expected %f, got %d", - c.OffRamp.Address().Hex(), globals.PermissionLessExecutionThreshold.Seconds(), dynamicConfig.PermissionLessExecutionThresholdSeconds) - } - for chainSel, srcChainOnRamp := range onRampsBySelector { - config, err := c.OffRamp.GetSourceChainConfig(&bind.CallOpts{ - Context: e.GetContext(), - }, chainSel) - if err != nil { - return fmt.Errorf("failed to get source chain config for chain %d: %w", chainSel, err) - } - if config.IsEnabled { - // For all configured sources, the address of configured onRamp for chain A must be the Address() of the onramp on chain A - if srcChainOnRamp != common.BytesToAddress(config.OnRamp) { - return fmt.Errorf("onRamp address mismatch for source chain %d on OffRamp %s : expected %s, got %x", - chainSel, c.OffRamp.Address().Hex(), srcChainOnRamp.Hex(), config.OnRamp) - } - // The address of router should be accurate - if c.Router.Address() != config.Router && c.TestRouter.Address() != config.Router { - return fmt.Errorf("router address mismatch for source chain %d on OffRamp %s : expected either router %s or test router %s, got %s", - chainSel, c.OffRamp.Address().Hex(), c.Router.Address().Hex(), c.TestRouter.Address().Hex(), config.Router.Hex()) - } - // if RMN is enabled for the source chain, the RMNRemote and RMNHome should be configured to enable RMN - // the reverse is not always true, as RMN verification can be disable at offRamp but enabled in RMNRemote and RMNHome - if !config.IsRMNVerificationDisabled && !isRMNEnabledBySource[chainSel] { - return fmt.Errorf("RMN verification is enabled in offRamp %s for source chain %d, "+ - "but RMN is not enabled in RMNHome and RMNRemote for the chain", - c.OffRamp.Address().Hex(), chainSel) - } - } - } - return nil -} - -func (c CCIPChainState) TokenAddressBySymbol() (map[TokenSymbol]common.Address, error) { - tokenAddresses := make(map[TokenSymbol]common.Address) - if c.FactoryBurnMintERC20Token != nil { - tokenAddresses[FactoryBurnMintERC20Symbol] = c.FactoryBurnMintERC20Token.Address() - } - for symbol, token := range c.ERC20Tokens { - tokenAddresses[symbol] = token.Address() - } - for symbol, token := range c.ERC677Tokens { - tokenAddresses[symbol] = token.Address() - } - for symbol, token := range c.BurnMintTokens677 { - tokenAddresses[symbol] = token.Address() - } - var err error - tokenAddresses[LinkSymbol], err = c.LinkTokenAddress() - if err != nil { - return nil, err - } - if c.Weth9 == nil { - return nil, errors.New("no WETH contract found in the state") - } - tokenAddresses[WethSymbol] = c.Weth9.Address() - return tokenAddresses, nil -} - -// TokenDetailsBySymbol get token mapping from the state. It contains only tokens that we have in address book -func (c CCIPChainState) TokenDetailsBySymbol() (map[TokenSymbol]TokenDetails, error) { - tokenDetails := make(map[TokenSymbol]TokenDetails) - if c.FactoryBurnMintERC20Token != nil { - tokenDetails[FactoryBurnMintERC20Symbol] = c.FactoryBurnMintERC20Token - } - for symbol, token := range c.ERC20Tokens { - tokenDetails[symbol] = token - } - for symbol, token := range c.ERC677Tokens { - tokenDetails[symbol] = token - } - for symbol, token := range c.BurnMintTokens677 { - tokenDetails[symbol] = token - } - if c.LinkToken != nil { - tokenDetails[LinkSymbol] = c.LinkToken - } - if c.StaticLinkToken != nil { - tokenDetails[LinkSymbol] = c.StaticLinkToken - } - - if _, ok := tokenDetails[LinkSymbol]; !ok { - return nil, errors.New("no LINK contract found in the state") - } - - if c.Weth9 == nil { - return nil, errors.New("no WETH contract found in the state") - } - tokenDetails[WethSymbol] = c.Weth9 - return tokenDetails, nil -} - -func (c CCIPChainState) LinkTokenAddress() (common.Address, error) { - if c.LinkToken != nil { - return c.LinkToken.Address(), nil - } - if c.StaticLinkToken != nil { - return c.StaticLinkToken.Address(), nil - } - return common.Address{}, errors.New("no link token found in the state") -} - -func (c CCIPChainState) GenerateView(lggr logger.Logger, chain string) (view.ChainView, error) { - chainView := view.NewChain() - grp := errgroup.Group{} - - if c.Router != nil { - grp.Go(func() error { - routerView, err := v1_2.GenerateRouterView(c.Router, false) - if err != nil { - return errors.Wrapf(err, "failed to generate router view for router %s", c.Router.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.Router[c.Router.Address().Hex()] = routerView - lggr.Infow("generated router view", "router", c.Router.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.TestRouter != nil { - grp.Go(func() error { - testRouterView, err := v1_2.GenerateRouterView(c.TestRouter, true) - if err != nil { - return errors.Wrapf(err, "failed to generate router view for test router %s", c.TestRouter.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.Router[c.TestRouter.Address().Hex()] = testRouterView - lggr.Infow("generated test router view", "testRouter", c.TestRouter.Address().Hex(), "chain", chain) - return nil - }) - } - if c.TokenAdminRegistry != nil { - grp.Go(func() error { - lggr.Infow("generating token admin registry view, this might take a while based on number of tokens", - "tokenAdminRegistry", c.TokenAdminRegistry.Address().Hex(), "chain", chain) - taView, err := viewv1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) - if err != nil { - return errors.Wrapf(err, "failed to generate token admin registry view for token admin registry %s", c.TokenAdminRegistry.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView - lggr.Infow("generated token admin registry view", "tokenAdminRegistry", c.TokenAdminRegistry.Address().Hex(), "chain", chain) - return nil - }) - } - if c.TokenPoolFactory != nil { - grp.Go(func() error { - tpfView, err := viewv1_5_1.GenerateTokenPoolFactoryView(c.TokenPoolFactory) - if err != nil { - return errors.Wrapf(err, "failed to generate token pool factory view for token pool factory %s", c.TokenPoolFactory.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.TokenPoolFactory[c.TokenPoolFactory.Address().Hex()] = tpfView - lggr.Infow("generated token pool factory view", "tokenPoolFactory", c.TokenPoolFactory.Address().Hex(), "chain", chain) - return nil - }) - } - for tokenSymbol, versionToPool := range c.BurnMintTokenPools { - for _, tokenPool := range versionToPool { - grp.Go(func() error { - tokenPoolView, err := viewv1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) - if err != nil { - return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) - } - chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), viewv1_5_1.PoolView{ - TokenPoolView: tokenPoolView, - }) - lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) - return nil - }) - } - } - for tokenSymbol, versionToPool := range c.BurnWithFromMintTokenPools { - for _, tokenPool := range versionToPool { - grp.Go(func() error { - tokenPoolView, err := viewv1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) - if err != nil { - return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) - } - chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), viewv1_5_1.PoolView{ - TokenPoolView: tokenPoolView, - }) - lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) - return nil - }) - } - } - for tokenSymbol, versionToPool := range c.BurnFromMintTokenPools { - for _, tokenPool := range versionToPool { - grp.Go(func() error { - tokenPoolView, err := viewv1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) - if err != nil { - return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) - } - chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), viewv1_5_1.PoolView{ - TokenPoolView: tokenPoolView, - }) - lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) - return nil - }) - } - } - for tokenSymbol, versionToPool := range c.LockReleaseTokenPools { - for _, tokenPool := range versionToPool { - grp.Go(func() error { - tokenPoolView, err := viewv1_5_1.GenerateLockReleaseTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) - if err != nil { - return errors.Wrapf(err, "failed to generate lock release token pool view for %s", tokenPool.Address().String()) - } - chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), tokenPoolView) - lggr.Infow("generated lock release token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) - return nil - }) - } - } - for _, pool := range c.USDCTokenPools { - grp.Go(func() error { - tokenPoolView, err := viewv1_5_1.GenerateUSDCTokenPoolView(pool) - if err != nil { - return errors.Wrapf(err, "failed to generate USDC token pool view for %s", pool.Address().String()) - } - chainView.UpdateTokenPool(string(USDCSymbol), pool.Address().Hex(), tokenPoolView) - lggr.Infow("generated USDC token pool view", "tokenPool", pool.Address().Hex(), "chain", chain) - return nil - }) - } - if c.NonceManager != nil { - grp.Go(func() error { - nmView, err := viewv1_6.GenerateNonceManagerView(c.NonceManager) - if err != nil { - return errors.Wrapf(err, "failed to generate nonce manager view for nonce manager %s", c.NonceManager.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView - lggr.Infow("generated nonce manager view", "nonceManager", c.NonceManager.Address().Hex(), "chain", chain) - return nil - }) - } - if c.RMNRemote != nil { - grp.Go(func() error { - rmnView, err := viewv1_6.GenerateRMNRemoteView(c.RMNRemote) - if err != nil { - return errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.RMNRemote[c.RMNRemote.Address().Hex()] = rmnView - lggr.Infow("generated rmn remote view", "rmnRemote", c.RMNRemote.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.RMNHome != nil { - grp.Go(func() error { - rmnHomeView, err := viewv1_6.GenerateRMNHomeView(c.RMNHome) - if err != nil { - return errors.Wrapf(err, "failed to generate rmn home view for rmn home %s", c.RMNHome.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.RMNHome[c.RMNHome.Address().Hex()] = rmnHomeView - lggr.Infow("generated rmn home view", "rmnHome", c.RMNHome.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { - grp.Go(func() error { - // FeeQuoter knows only about tokens that managed by CCIP (i.e. imported from address book) - tokenDetails, err := c.TokenDetailsBySymbol() - if err != nil { - return err - } - tokens := make([]common.Address, 0, len(tokenDetails)) - for _, tokenDetail := range tokenDetails { - tokens = append(tokens, tokenDetail.Address()) - } - fqView, err := viewv1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TestRouter, tokens) - if err != nil { - return errors.Wrapf(err, "failed to generate fee quoter view for fee quoter %s", c.FeeQuoter.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView - lggr.Infow("generated fee quoter view", "feeQuoter", c.FeeQuoter.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.OnRamp != nil && c.Router != nil && c.TokenAdminRegistry != nil { - grp.Go(func() error { - onRampView, err := viewv1_6.GenerateOnRampView( - c.OnRamp, - c.Router, - c.TestRouter, - c.TokenAdminRegistry, - ) - if err != nil { - return errors.Wrapf(err, "failed to generate on ramp view for on ramp %s", c.OnRamp.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView - lggr.Infow("generated on ramp view", "onRamp", c.OnRamp.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.OffRamp != nil && c.Router != nil { - grp.Go(func() error { - offRampView, err := viewv1_6.GenerateOffRampView( - c.OffRamp, - c.Router, - c.TestRouter, - ) - if err != nil { - return errors.Wrapf(err, "failed to generate off ramp view for off ramp %s", c.OffRamp.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView - lggr.Infow("generated off ramp view", "offRamp", c.OffRamp.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.RMNProxy != nil { - grp.Go(func() error { - rmnProxyView, err := viewv1_0.GenerateRMNProxyView(c.RMNProxy) - if err != nil { - return errors.Wrapf(err, "failed to generate rmn proxy view for rmn proxy %s", c.RMNProxy.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.RMNProxy[c.RMNProxy.Address().Hex()] = rmnProxyView - lggr.Infow("generated rmn proxy view", "rmnProxy", c.RMNProxy.Address().Hex(), "chain", chain) - return nil - }) - } - if c.CCIPHome != nil && c.CapabilityRegistry != nil { - grp.Go(func() error { - chView, err := viewv1_6.GenerateCCIPHomeView(c.CapabilityRegistry, c.CCIPHome) - if err != nil { - return errors.Wrapf(err, "failed to generate CCIP home view for CCIP home %s", c.CCIPHome.Address()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.CCIPHome[c.CCIPHome.Address().Hex()] = chView - lggr.Infow("generated CCIP home view", "CCIPHome", c.CCIPHome.Address().Hex(), "chain", chain) - return nil - }) - } - if c.CapabilityRegistry != nil { - grp.Go(func() error { - capRegView, err := common_v1_0.GenerateCapabilityRegistryView(c.CapabilityRegistry) - if err != nil { - return errors.Wrapf(err, "failed to generate capability registry view for capability registry %s", c.CapabilityRegistry.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView - lggr.Infow("generated capability registry view", "capabilityRegistry", c.CapabilityRegistry.Address().Hex(), "chain", chain) - return nil - }) - } - if c.MCMSWithTimelockState.Timelock != nil { - grp.Go(func() error { - mcmsView, err := c.MCMSWithTimelockState.GenerateMCMSWithTimelockView() - if err != nil { - return errors.Wrapf(err, "failed to generate MCMS with timelock view for MCMS with timelock %s", c.MCMSWithTimelockState.Timelock.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.MCMSWithTimelock = mcmsView - lggr.Infow("generated MCMS with timelock view", "MCMSWithTimelock", c.MCMSWithTimelockState.Timelock.Address().Hex(), "chain", chain) - return nil - }) - } - if c.LinkToken != nil { - grp.Go(func() error { - linkTokenView, err := c.GenerateLinkView() - if err != nil { - return errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.LinkToken = linkTokenView - lggr.Infow("generated link token view", "linkToken", c.LinkToken.Address().Hex(), "chain", chain) - return nil - }) - } - if c.StaticLinkToken != nil { - grp.Go(func() error { - staticLinkTokenView, err := c.GenerateStaticLinkView() - if err != nil { - return err - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.StaticLinkToken = staticLinkTokenView - lggr.Infow("generated static link token view", "staticLinkToken", c.StaticLinkToken.Address().Hex(), "chain", chain) - return nil - }) - } - - // Legacy contracts - // OnRamp, OffRamp, CommitStore legacy contract related state generation is not done right now - // considering the state of these contracts are not referred currently, and it's enormously expensive to generate - // state for multiple lanes per chain - for _, registryModule := range c.RegistryModules1_6 { - grp.Go(func() error { - registryModuleView, err := shared.GetRegistryModuleView(registryModule, c.TokenAdminRegistry.Address()) - if err != nil { - return errors.Wrapf(err, "failed to generate registry module view for registry module %s", registryModule.Address().Hex()) - } - chainView.UpdateRegistryModuleView(registryModule.Address().Hex(), registryModuleView) - lggr.Infow("generated registry module view", "registryModule", registryModule.Address().Hex(), "chain", chain) - return nil - }) - } - - for _, registryModule := range c.RegistryModules1_5 { - grp.Go(func() error { - registryModuleView, err := shared.GetRegistryModuleView(registryModule, c.TokenAdminRegistry.Address()) - if err != nil { - return errors.Wrapf(err, "failed to generate registry module view for registry module %s", registryModule.Address().Hex()) - } - chainView.UpdateRegistryModuleView(registryModule.Address().Hex(), registryModuleView) - lggr.Infow("generated registry module view", "registryModule", registryModule.Address().Hex(), "chain", chain) - return nil - }) - } - - if c.PriceRegistry != nil { - grp.Go(func() error { - priceRegistryView, err := v1_2.GeneratePriceRegistryView(c.PriceRegistry) - if err != nil { - return errors.Wrapf(err, "failed to generate price registry view for price registry %s", c.PriceRegistry.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.PriceRegistry[c.PriceRegistry.Address().String()] = priceRegistryView - lggr.Infow("generated price registry view", "priceRegistry", c.PriceRegistry.Address().String(), "chain", chain) - return nil - }) - } - - if c.RMN != nil { - grp.Go(func() error { - rmnView, err := viewv1_5.GenerateRMNView(c.RMN) - if err != nil { - return errors.Wrapf(err, "failed to generate rmn view for rmn %s", c.RMN.Address().String()) - } - chainView.UpdateMu.Lock() - defer chainView.UpdateMu.Unlock() - chainView.RMN[c.RMN.Address().Hex()] = rmnView - lggr.Infow("generated rmn view", "rmn", c.RMN.Address().Hex(), "chain", chain) - return nil - }) - } - - return chainView, grp.Wait() -} - -func (c CCIPChainState) usdFeedOrDefault(symbol TokenSymbol) common.Address { - if feed, ok := c.USDFeeds[symbol]; ok { - return feed.Address() - } - return common.Address{} -} - -// CCIPOnChainState state always derivable from an address book. -// Offchain state always derivable from a list of nodeIds. -// Note can translate this into Go struct needed for MCMS/Docs/UI. -type CCIPOnChainState struct { - // Populated go bindings for the appropriate version for all contracts. - // We would hold 2 versions of each contract here. Once we upgrade we can phase out the old one. - // When generating bindings, make sure the package name corresponds to the version. - Chains map[uint64]CCIPChainState - SolChains map[uint64]SolCCIPChainState - AptosChains map[uint64]AptosCCIPChainState -} - -// ValidatePostDeploymentState should be called after the deployment and configuration for all contracts -// in environment is complete. -// It validates the state of the contracts and ensures that they are correctly configured and wired with each other. -func (c CCIPOnChainState) ValidatePostDeploymentState(e deployment.Environment) error { - onRampsBySelector := make(map[uint64]common.Address) - offRampsBySelector := make(map[uint64]offramp.OffRampInterface) - for selector, chainState := range c.Chains { - if chainState.OnRamp == nil { - return fmt.Errorf("onramp not found in the state for chain %d", selector) - } - onRampsBySelector[selector] = chainState.OnRamp.Address() - offRampsBySelector[selector] = chainState.OffRamp - } - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return fmt.Errorf("failed to get node info from env: %w", err) - } - homeChain, err := c.HomeChainSelector() - if err != nil { - return fmt.Errorf("failed to get home chain selector: %w", err) - } - homeChainState := c.Chains[homeChain] - if err := homeChainState.validateHomeChain(e, nodes, offRampsBySelector); err != nil { - return fmt.Errorf("failed to validate home chain %d: %w", homeChain, err) - } - rmnHomeActiveDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{ - Context: e.GetContext(), - }) - if err != nil { - return fmt.Errorf("failed to get active digest for RMNHome %s at home chain %d: %w", homeChainState.RMNHome.Address().Hex(), homeChain, err) - } - isRMNEnabledInRMNHomeBySourceChain := make(map[uint64]bool) - rmnHomeConfig, err := homeChainState.RMNHome.GetConfig(&bind.CallOpts{ - Context: e.GetContext(), - }, rmnHomeActiveDigest) - if err != nil { - return fmt.Errorf("failed to get config for RMNHome %s at home chain %d: %w", homeChainState.RMNHome.Address().Hex(), homeChain, err) - } - // if Fobserve is greater than 0, RMN is enabled for the source chain in RMNHome - for _, rmnHomeChain := range rmnHomeConfig.VersionedConfig.DynamicConfig.SourceChains { - isRMNEnabledInRMNHomeBySourceChain[rmnHomeChain.ChainSelector] = rmnHomeChain.FObserve > 0 - } - for selector, chainState := range c.Chains { - isRMNEnabledInRmnRemote, err := chainState.validateRMNRemote(e, selector, rmnHomeActiveDigest) - if err != nil { - return fmt.Errorf("failed to validate RMNRemote %s for chain %d: %w", chainState.RMNRemote.Address().Hex(), selector, err) - } - // check whether RMNRemote and RMNHome are in sync in terms of RMNEnabled - if isRMNEnabledInRmnRemote != isRMNEnabledInRMNHomeBySourceChain[selector] { - return fmt.Errorf("RMNRemote %s rmnEnabled mismatch with RMNHome for chain %d: expected %v, got %v", - chainState.RMNRemote.Address().Hex(), selector, isRMNEnabledInRMNHomeBySourceChain[selector], isRMNEnabledInRmnRemote) - } - otherOnRamps := make(map[uint64]common.Address) - isTestRouter := true - if chainState.Router != nil { - isTestRouter = false - } - connectedChains, err := chainState.validateRouter(e, isTestRouter) - if err != nil { - return fmt.Errorf("failed to validate router %s for chain %d: %w", chainState.Router.Address().Hex(), selector, err) - } - for _, connectedChain := range connectedChains { - if connectedChain == selector { - continue - } - otherOnRamps[connectedChain] = c.Chains[connectedChain].OnRamp.Address() - } - if err := chainState.validateOffRamp(e, selector, otherOnRamps, isRMNEnabledInRMNHomeBySourceChain); err != nil { - return fmt.Errorf("failed to validate offramp %s for chain %d: %w", chainState.OffRamp.Address().Hex(), selector, err) - } - if err := chainState.validateOnRamp(e, selector, connectedChains); err != nil { - return fmt.Errorf("failed to validate onramp %s for chain %d: %w", chainState.OnRamp.Address().Hex(), selector, err) - } - if err := chainState.validateFeeQuoter(e); err != nil { - return fmt.Errorf("failed to validate fee quoter %s for chain %d: %w", chainState.FeeQuoter.Address().Hex(), selector, err) - } - } - return nil -} - -// HomeChainSelector returns the selector of the home chain based on the presence of RMNHome, CapabilityRegistry and CCIPHome contracts. -func (c CCIPOnChainState) HomeChainSelector() (uint64, error) { - for selector, chain := range c.Chains { - if chain.RMNHome != nil && chain.CapabilityRegistry != nil && chain.CCIPHome != nil { - return selector, nil - } - } - return 0, errors.New("no home chain found") -} - -func (c CCIPOnChainState) EVMMCMSStateByChain() map[uint64]commonstate.MCMSWithTimelockState { - mcmsStateByChain := make(map[uint64]commonstate.MCMSWithTimelockState) - for chainSelector, chain := range c.Chains { - mcmsStateByChain[chainSelector] = commonstate.MCMSWithTimelockState{ - CancellerMcm: chain.CancellerMcm, - BypasserMcm: chain.BypasserMcm, - ProposerMcm: chain.ProposerMcm, - Timelock: chain.Timelock, - CallProxy: chain.CallProxy, - } - } - return mcmsStateByChain -} - -func (c CCIPOnChainState) OffRampPermissionLessExecutionThresholdSeconds(ctx context.Context, env deployment.Environment, selector uint64) (uint32, error) { - family, err := chain_selectors.GetSelectorFamily(selector) - if err != nil { - return 0, err - } - switch family { - case chain_selectors.FamilyEVM: - chain, ok := c.Chains[selector] - if !ok { - return 0, fmt.Errorf("chain %d not found in the state", selector) - } - offRamp := chain.OffRamp - if offRamp == nil { - return 0, fmt.Errorf("offramp not found in the state for chain %d", selector) - } - dCfg, err := offRamp.GetDynamicConfig(&bind.CallOpts{ - Context: ctx, - }) - if err != nil { - return dCfg.PermissionLessExecutionThresholdSeconds, fmt.Errorf("fetch dynamic config from offRamp %s for chain %d: %w", offRamp.Address().String(), selector, err) - } - return dCfg.PermissionLessExecutionThresholdSeconds, nil - case chain_selectors.FamilySolana: - chainState, ok := c.SolChains[selector] - if !ok { - return 0, fmt.Errorf("chain %d not found in the state", selector) - } - chain, ok := env.SolChains[selector] - if !ok { - return 0, fmt.Errorf("solana chain %d not found in the environment", selector) - } - if chainState.OffRamp.IsZero() { - return 0, fmt.Errorf("offramp not found in existing state, deploy the offramp first for chain %d", selector) - } - var offRampConfig solOffRamp.Config - offRampConfigPDA, _, _ := solState.FindOfframpConfigPDA(chainState.OffRamp) - err := chain.GetAccountDataBorshInto(context.Background(), offRampConfigPDA, &offRampConfig) - if err != nil { - return 0, fmt.Errorf("offramp config not found in existing state, initialize the offramp first %d", chain.Selector) - } - // #nosec G115 - return uint32(offRampConfig.EnableManualExecutionAfter), nil - case chain_selectors.FamilyAptos: - chainState, ok := c.AptosChains[selector] - if !ok { - return 0, fmt.Errorf("chain %d does not exist in state", selector) - } - chain, ok := env.AptosChains[selector] - if !ok { - return 0, fmt.Errorf("chain %d does not exist in env", selector) - } - if chainState.CCIPAddress == (aptos.AccountAddress{}) { - return 0, fmt.Errorf("ccip not found in existing state, deploy the ccip first for Aptos chain %d", selector) - } - offrampDynamicConfig, err := getOfframpDynamicConfig(chain, chainState.CCIPAddress) - if err != nil { - return 0, fmt.Errorf("failed to get offramp dynamic config for Aptos chain %d: %w", selector, err) - } - return offrampDynamicConfig.PermissionlessExecutionThresholdSeconds, nil - } - return 0, fmt.Errorf("unsupported chain family %s", family) -} - -func (c CCIPOnChainState) Validate() error { - for sel, chain := range c.Chains { - // cannot have static link and link together - if chain.LinkToken != nil && chain.StaticLinkToken != nil { - return fmt.Errorf("cannot have both link and static link token on the same chain %d", sel) - } - } - return nil -} - -func (c CCIPOnChainState) GetAllProposerMCMSForChains(chains []uint64) (map[uint64]*gethwrappers.ManyChainMultiSig, error) { - multiSigs := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for _, chain := range chains { - chainState, ok := c.Chains[chain] - if !ok { - return nil, fmt.Errorf("chain %d not found", chain) - } - if chainState.ProposerMcm == nil { - return nil, fmt.Errorf("proposer mcm not found for chain %d", chain) - } - multiSigs[chain] = chainState.ProposerMcm - } - return multiSigs, nil -} - -func (c CCIPOnChainState) GetAllTimeLocksForChains(chains []uint64) (map[uint64]common.Address, error) { - timelocks := make(map[uint64]common.Address) - for _, chain := range chains { - chainState, ok := c.Chains[chain] - if !ok { - return nil, fmt.Errorf("chain %d not found", chain) - } - if chainState.Timelock == nil { - return nil, fmt.Errorf("timelock not found for chain %d", chain) - } - timelocks[chain] = chainState.Timelock.Address() - } - return timelocks, nil -} - -func (c CCIPOnChainState) SupportedChains() map[uint64]struct{} { - chains := make(map[uint64]struct{}) - for chain := range c.Chains { - chains[chain] = struct{}{} - } - for chain := range c.SolChains { - chains[chain] = struct{}{} - } - for chain := range c.AptosChains { - chains[chain] = struct{}{} - } - return chains -} - -// EnforceMCMSUsageIfProd determines if an MCMS config should be enforced for this particular environment. -// It checks if the CCIPHome and CapabilitiesRegistry contracts are owned by the Timelock because all other contracts should follow this precedent. -// If the home chain contracts are owned by the Timelock and no mcmsConfig is provided, this function will return an error. -func (c CCIPOnChainState) EnforceMCMSUsageIfProd(ctx context.Context, mcmsConfig *proposalutils.TimelockConfig) error { - // Instead of accepting a homeChainSelector, we simply look for the CCIPHome and CapabilitiesRegistry in state. - // This is because the home chain selector is not always available in the input to a changeset. - // Also, if the underlying rules to EnforceMCMSUsageIfProd change (i.e. what determines "prod" changes), - // we can simply update the function body without worrying about the function signature. - var ccipHome *ccip_home.CCIPHome - var capReg *capabilities_registry.CapabilitiesRegistry - var homeChainSelector uint64 - for selector, chain := range c.Chains { - if chain.CCIPHome == nil || chain.CapabilityRegistry == nil { - continue - } - // This condition impacts the ability of this function to determine MCMS enforcement. - // As such, we return an error if we find multiple chains with home chain contracts. - if ccipHome != nil { - return errors.New("multiple chains with CCIPHome and CapabilitiesRegistry contracts found") - } - ccipHome = chain.CCIPHome - capReg = chain.CapabilityRegistry - homeChainSelector = selector - } - // It is not the job of this function to enforce the existence of home chain contracts. - // Some tests don't deploy these contracts, and we don't want to fail them. - // We simply say that MCMS is not enforced in such environments. - if ccipHome == nil { - return nil - } - // If the timelock contract is not found on the home chain, - // we know that MCMS is not enforced. - timelock := c.Chains[homeChainSelector].Timelock - if timelock == nil { - return nil - } - ccipHomeOwner, err := ccipHome.Owner(&bind.CallOpts{Context: ctx}) - if err != nil { - return fmt.Errorf("failed to get CCIP home owner: %w", err) - } - capRegOwner, err := capReg.Owner(&bind.CallOpts{Context: ctx}) - if err != nil { - return fmt.Errorf("failed to get capabilities registry owner: %w", err) - } - if ccipHomeOwner != capRegOwner { - return fmt.Errorf("CCIPHome and CapabilitiesRegistry owners do not match: %s != %s", ccipHomeOwner.String(), capRegOwner.String()) - } - // If CCIPHome & CapabilitiesRegistry are owned by timelock, then MCMS is enforced. - if ccipHomeOwner == timelock.Address() && mcmsConfig == nil { - return errors.New("MCMS is enforced for environment (i.e. CCIPHome & CapReg are owned by timelock), but no MCMS config was provided") - } - - return nil -} - -// ValidateOwnershipOfChain validates the ownership of every CCIP contract on a chain. -// If mcmsConfig is nil, the expected owner of each contract is the chain's deployer key. -// If provided, the expected owner is the Timelock contract. -func (c CCIPOnChainState) ValidateOwnershipOfChain(e deployment.Environment, chainSel uint64, mcmsConfig *proposalutils.TimelockConfig) error { - chain, ok := e.Chains[chainSel] - if !ok { - return fmt.Errorf("chain with selector %d not found in the environment", chainSel) - } - - chainState, ok := c.Chains[chainSel] - if !ok { - return fmt.Errorf("%s not found in the state", chain) - } - if chainState.Timelock == nil { - return fmt.Errorf("timelock not found on %s", chain) - } - - ownedContracts := map[string]commoncs.Ownable{ - "router": chainState.Router, - "feeQuoter": chainState.FeeQuoter, - "offRamp": chainState.OffRamp, - "onRamp": chainState.OnRamp, - "nonceManager": chainState.NonceManager, - "rmnRemote": chainState.RMNRemote, - "rmnProxy": chainState.RMNProxy, - "tokenAdminRegistry": chainState.TokenAdminRegistry, - } - var wg sync.WaitGroup - errs := make(chan error, len(ownedContracts)) - for contractName, contract := range ownedContracts { - wg.Add(1) - go func(name string, c commoncs.Ownable) { - defer wg.Done() - if c == nil { - errs <- fmt.Errorf("missing %s contract on %s", name, chain) - return - } - err := commoncs.ValidateOwnership(e.GetContext(), mcmsConfig != nil, chain.DeployerKey.From, chainState.Timelock.Address(), contract) - if err != nil { - errs <- fmt.Errorf("failed to validate ownership of %s contract on %s: %w", name, chain, err) - } - }(contractName, contract) - } - wg.Wait() - close(errs) - var multiErr error - for err := range errs { - multiErr = std_errors.Join(multiErr, err) - } - if multiErr != nil { - return multiErr - } - - return nil -} - -func (c CCIPOnChainState) View(e *deployment.Environment, chains []uint64) (map[string]view.ChainView, map[string]view.SolChainView, error) { - m := sync.Map{} - sm := sync.Map{} - grp := errgroup.Group{} - for _, chainSelector := range chains { - var name string - chainSelector := chainSelector - grp.Go(func() error { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return err - } - chainInfo, err := deployment.ChainInfo(chainSelector) - if err != nil { - return err - } - name = chainInfo.ChainName - if chainInfo.ChainName == "" { - name = strconv.FormatUint(chainSelector, 10) - } - id, err := chain_selectors.GetChainIDFromSelector(chainSelector) - if err != nil { - return fmt.Errorf("failed to get chain id from selector %d: %w", chainSelector, err) - } - e.Logger.Infow("Generating view for", "chainSelector", chainSelector, "chainName", name, "chainID", id) - switch family { - case chain_selectors.FamilyEVM: - if _, ok := c.Chains[chainSelector]; !ok { - return fmt.Errorf("chain not supported %d", chainSelector) - } - chainState := c.Chains[chainSelector] - chainView, err := chainState.GenerateView(e.Logger, name) - if err != nil { - return err - } - chainView.ChainSelector = chainSelector - chainView.ChainID = id - m.Store(name, chainView) - e.Logger.Infow("Completed view for", "chainSelector", chainSelector, "chainName", name, "chainID", id) - case chain_selectors.FamilySolana: - if _, ok := c.SolChains[chainSelector]; !ok { - return fmt.Errorf("chain not supported %d", chainSelector) - } - chainState := c.SolChains[chainSelector] - chainView, err := chainState.GenerateView(e.SolChains[chainSelector]) - if err != nil { - return err - } - chainView.ChainSelector = chainSelector - chainView.ChainID = id - sm.Store(name, chainView) - default: - return fmt.Errorf("unsupported chain family %s", family) - } - return nil - }) - } - if err := grp.Wait(); err != nil { - return nil, nil, err - } - finalEVMMap := make(map[string]view.ChainView) - m.Range(func(key, value interface{}) bool { - finalEVMMap[key.(string)] = value.(view.ChainView) - return true - }) - finalSolanaMap := make(map[string]view.SolChainView) - sm.Range(func(key, value interface{}) bool { - finalSolanaMap[key.(string)] = value.(view.SolChainView) - return true - }) - return finalEVMMap, finalSolanaMap, grp.Wait() -} - -func (c CCIPOnChainState) GetOffRampAddressBytes(chainSelector uint64) ([]byte, error) { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return nil, err - } - - var offRampAddress []byte - switch family { - case chain_selectors.FamilyEVM: - offRampAddress = c.Chains[chainSelector].OffRamp.Address().Bytes() - case chain_selectors.FamilySolana: - offRampAddress = c.SolChains[chainSelector].OffRamp.Bytes() - case chain_selectors.FamilyAptos: - ccipAddress := c.AptosChains[chainSelector].CCIPAddress - offRampAddress = ccipAddress[:] - default: - return nil, fmt.Errorf("unsupported chain family %s", family) - } - - return offRampAddress, nil -} - -func (c CCIPOnChainState) GetOnRampAddressBytes(chainSelector uint64) ([]byte, error) { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return nil, err - } - - var onRampAddressBytes []byte - switch family { - case chain_selectors.FamilyEVM: - if c.Chains[chainSelector].OnRamp == nil { - return nil, fmt.Errorf("no onramp found in the state for chain %d", chainSelector) - } - onRampAddressBytes = c.Chains[chainSelector].OnRamp.Address().Bytes() - case chain_selectors.FamilySolana: - if c.SolChains[chainSelector].Router.IsZero() { - return nil, fmt.Errorf("no router found in the state for chain %d", chainSelector) - } - onRampAddressBytes = c.SolChains[chainSelector].Router.Bytes() - case chain_selectors.FamilyAptos: - ccipAddress := c.AptosChains[chainSelector].CCIPAddress - if ccipAddress == (aptos.AccountAddress{}) { - return nil, fmt.Errorf("no ccip address found in the state for Aptos chain %d", chainSelector) - } - onRampAddressBytes = ccipAddress[:] - default: - return nil, fmt.Errorf("unsupported chain family %s", family) - } - - return onRampAddressBytes, nil -} - -func (c CCIPOnChainState) ValidateRamp(chainSelector uint64, rampType cldf.ContractType) error { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return err - } - switch family { - case chain_selectors.FamilyEVM: - chainState, exists := c.Chains[chainSelector] - if !exists { - return fmt.Errorf("chain %d does not exist", chainSelector) - } - switch rampType { - case OffRamp: - if chainState.OffRamp == nil { - return fmt.Errorf("offramp contract does not exist on evm chain %d", chainSelector) - } - case OnRamp: - if chainState.OnRamp == nil { - return fmt.Errorf("onramp contract does not exist on evm chain %d", chainSelector) - } - default: - return fmt.Errorf("unknown ramp type %s", rampType) - } - - case chain_selectors.FamilySolana: - chainState, exists := c.SolChains[chainSelector] - if !exists { - return fmt.Errorf("chain %d does not exist", chainSelector) - } - switch rampType { - case OffRamp: - if chainState.OffRamp.IsZero() { - return fmt.Errorf("offramp contract does not exist on solana chain %d", chainSelector) - } - case OnRamp: - if chainState.Router.IsZero() { - return fmt.Errorf("router contract does not exist on solana chain %d", chainSelector) - } - default: - return fmt.Errorf("unknown ramp type %s", rampType) - } - - case chain_selectors.FamilyAptos: - chainState, exists := c.AptosChains[chainSelector] - if !exists { - return fmt.Errorf("chain %d does not exist", chainSelector) - } - if chainState.CCIPAddress == (aptos.AccountAddress{}) { - return fmt.Errorf("ccip package does not exist on aptos chain %d", chainSelector) - } - - default: - return fmt.Errorf("unknown chain family %s", family) - } - return nil -} - -func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) { - solanaState, err := LoadOnchainStateSolana(e) - if err != nil { - return CCIPOnChainState{}, err - } - aptosChains, err := LoadOnchainStateAptos(e) - if err != nil { - return CCIPOnChainState{}, err - } - state := CCIPOnChainState{ - Chains: make(map[uint64]CCIPChainState), - SolChains: solanaState.SolChains, - AptosChains: aptosChains, - } - for chainSelector, chain := range e.Chains { - addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector) - if err != nil { - // Chain not found in address book, initialize empty - if errors.Is(err, cldf.ErrChainNotFound) { - addresses = make(map[string]cldf.TypeAndVersion) - } else { - return state, err - } - } - chainState, err := LoadChainState(e.GetContext(), chain, addresses) - if err != nil { - return state, err - } - state.Chains[chainSelector] = chainState - } - return state, state.Validate() -} - -// LoadChainState Loads all state for a chain into state -func LoadChainState(ctx context.Context, chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (CCIPChainState, error) { - var state CCIPChainState - mcmsWithTimelock, err := commonstate.MaybeLoadMCMSWithTimelockChainState(chain, addresses) - if err != nil { - return state, err - } - state.MCMSWithTimelockState = *mcmsWithTimelock - - linkState, err := commonstate.MaybeLoadLinkTokenChainState(chain, addresses) - if err != nil { - return state, err - } - state.LinkTokenState = *linkState - staticLinkState, err := commonstate.MaybeLoadStaticLinkTokenState(chain, addresses) - if err != nil { - return state, err - } - state.StaticLinkTokenState = *staticLinkState - state.ABIByAddress = make(map[string]string) - for address, tvStr := range addresses { - switch tvStr.String() { - case cldf.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(): - state.ABIByAddress[address] = gethwrappers.RBACTimelockABI - case cldf.NewTypeAndVersion(commontypes.CallProxy, deployment.Version1_0_0).String(): - state.ABIByAddress[address] = gethwrappers.CallProxyABI - case cldf.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), - cldf.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), - cldf.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(): - state.ABIByAddress[address] = gethwrappers.ManyChainMultiSigABI - case cldf.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(): - state.ABIByAddress[address] = link_token.LinkTokenABI - case cldf.NewTypeAndVersion(commontypes.StaticLinkToken, deployment.Version1_0_0).String(): - state.ABIByAddress[address] = link_token_interface.LinkTokenABI - case cldf.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): - cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.CapabilityRegistry = cr - state.ABIByAddress[address] = capabilities_registry.CapabilitiesRegistryABI - case cldf.NewTypeAndVersion(OnRamp, deployment.Version1_6_0).String(): - onRampC, err := onramp.NewOnRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.OnRamp = onRampC - state.ABIByAddress[address] = onramp.OnRampABI - case cldf.NewTypeAndVersion(OffRamp, deployment.Version1_6_0).String(): - offRamp, err := offramp.NewOffRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.OffRamp = offRamp - state.ABIByAddress[address] = offramp.OffRampABI - case cldf.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0).String(): - armProxy, err := rmn_proxy_contract.NewRMNProxy(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RMNProxy = armProxy - state.ABIByAddress[address] = rmn_proxy_contract.RMNProxyABI - case cldf.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0).String(): - rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RMNRemote = rmnRemote - state.ABIByAddress[address] = rmn_remote.RMNRemoteABI - case cldf.NewTypeAndVersion(RMNHome, deployment.Version1_6_0).String(): - rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RMNHome = rmnHome - state.ABIByAddress[address] = rmn_home.RMNHomeABI - case cldf.NewTypeAndVersion(WETH9, deployment.Version1_0_0).String(): - _weth9, err := weth9.NewWETH9(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Weth9 = _weth9 - state.ABIByAddress[address] = weth9.WETH9ABI - case cldf.NewTypeAndVersion(NonceManager, deployment.Version1_6_0).String(): - nm, err := nonce_manager.NewNonceManager(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.NonceManager = nm - state.ABIByAddress[address] = nonce_manager.NonceManagerABI - case cldf.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0).String(): - tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.TokenAdminRegistry = tm - state.ABIByAddress[address] = token_admin_registry.TokenAdminRegistryABI - case cldf.NewTypeAndVersion(TokenPoolFactory, deployment.Version1_5_1).String(): - tpf, err := token_pool_factory.NewTokenPoolFactory(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.TokenPoolFactory = tpf - state.ABIByAddress[address] = token_pool_factory.TokenPoolFactoryABI - case cldf.NewTypeAndVersion(RegistryModule, deployment.Version1_6_0).String(): - rm, err := registryModuleOwnerCustomv16.NewRegistryModuleOwnerCustom(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RegistryModules1_6 = append(state.RegistryModules1_6, rm) - state.ABIByAddress[address] = registryModuleOwnerCustomv16.RegistryModuleOwnerCustomABI - case cldf.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0).String(): - rm, err := registryModuleOwnerCustomv15.NewRegistryModuleOwnerCustom(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RegistryModules1_5 = append(state.RegistryModules1_5, rm) - state.ABIByAddress[address] = registryModuleOwnerCustomv15.RegistryModuleOwnerCustomABI - case cldf.NewTypeAndVersion(Router, deployment.Version1_2_0).String(): - r, err := router.NewRouter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Router = r - state.ABIByAddress[address] = router.RouterABI - case cldf.NewTypeAndVersion(TestRouter, deployment.Version1_2_0).String(): - r, err := router.NewRouter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.TestRouter = r - state.ABIByAddress[address] = router.RouterABI - case cldf.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0).String(): - fq, err := fee_quoter.NewFeeQuoter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.FeeQuoter = fq - state.ABIByAddress[address] = fee_quoter.FeeQuoterABI - case cldf.NewTypeAndVersion(USDCToken, deployment.Version1_0_0).String(): - ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.BurnMintTokens677 = map[TokenSymbol]*burn_mint_erc677.BurnMintERC677{ - USDCSymbol: ut, - } - state.ABIByAddress[address] = burn_mint_erc677.BurnMintERC677ABI - case cldf.NewTypeAndVersion(USDCTokenPool, deployment.Version1_5_1).String(): - utp, err := usdc_token_pool.NewUSDCTokenPool(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.USDCTokenPools == nil { - state.USDCTokenPools = make(map[semver.Version]*usdc_token_pool.USDCTokenPool) - } - state.USDCTokenPools[deployment.Version1_5_1] = utp - case cldf.NewTypeAndVersion(HybridLockReleaseUSDCTokenPool, deployment.Version1_5_1).String(): - utp, err := usdc_token_pool.NewUSDCTokenPool(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.USDCTokenPools == nil { - state.USDCTokenPools = make(map[semver.Version]*usdc_token_pool.USDCTokenPool) - } - state.USDCTokenPools[deployment.Version1_5_1] = utp - state.ABIByAddress[address] = usdc_token_pool.USDCTokenPoolABI - case cldf.NewTypeAndVersion(USDCMockTransmitter, deployment.Version1_0_0).String(): - umt, err := mock_usdc_token_transmitter.NewMockE2EUSDCTransmitter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockUSDCTransmitter = umt - state.ABIByAddress[address] = mock_usdc_token_transmitter.MockE2EUSDCTransmitterABI - case cldf.NewTypeAndVersion(USDCTokenMessenger, deployment.Version1_0_0).String(): - utm, err := mock_usdc_token_messenger.NewMockE2EUSDCTokenMessenger(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockUSDCTokenMessenger = utm - state.ABIByAddress[address] = mock_usdc_token_messenger.MockE2EUSDCTokenMessengerABI - case cldf.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0).String(): - ccipHome, err := ccip_home.NewCCIPHome(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.CCIPHome = ccipHome - state.ABIByAddress[address] = ccip_home.CCIPHomeABI - case cldf.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0).String(): - mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Receiver = mr - state.ABIByAddress[address] = maybe_revert_message_receiver.MaybeRevertMessageReceiverABI - case cldf.NewTypeAndVersion(LogMessageDataReceiver, deployment.Version1_0_0).String(): - mr, err := log_message_data_receiver.NewLogMessageDataReceiver(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.LogMessageDataReceiver = mr - state.ABIByAddress[address] = log_message_data_receiver.LogMessageDataReceiverABI - case cldf.NewTypeAndVersion(Multicall3, deployment.Version1_0_0).String(): - mc, err := multicall3.NewMulticall3(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Multicall3 = mc - state.ABIByAddress[address] = multicall3.Multicall3ABI - case cldf.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0).String(): - feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.USDFeeds == nil { - state.USDFeeds = make(map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface) - } - desc, err := feed.Description(&bind.CallOpts{}) - if err != nil { - return state, err - } - key, ok := DescriptionToTokenSymbol[desc] - if !ok { - return state, fmt.Errorf("unknown feed description %s", desc) - } - state.USDFeeds[key] = feed - state.ABIByAddress[address] = aggregator_v3_interface.AggregatorV3InterfaceABI - case cldf.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := NewTokenPoolWithMetadata(ctx, burn_mint_token_pool.NewBurnMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnMintTokenPools = helpers.AddValueToNestedMap(state.BurnMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_mint_token_pool.BurnMintTokenPoolABI - case cldf.NewTypeAndVersion(BurnWithFromMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := NewTokenPoolWithMetadata(ctx, burn_with_from_mint_token_pool.NewBurnWithFromMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnWithFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnWithFromMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_with_from_mint_token_pool.BurnWithFromMintTokenPoolABI - case cldf.NewTypeAndVersion(BurnFromMintTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := NewTokenPoolWithMetadata(ctx, burn_from_mint_token_pool.NewBurnFromMintTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.BurnFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnFromMintTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = burn_from_mint_token_pool.BurnFromMintTokenPoolABI - case cldf.NewTypeAndVersion(LockReleaseTokenPool, deployment.Version1_5_1).String(): - ethAddress := common.HexToAddress(address) - pool, metadata, err := NewTokenPoolWithMetadata(ctx, lock_release_token_pool.NewLockReleaseTokenPool, ethAddress, chain.Client) - if err != nil { - return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) - } - state.LockReleaseTokenPools = helpers.AddValueToNestedMap(state.LockReleaseTokenPools, metadata.Symbol, metadata.Version, pool) - state.ABIByAddress[address] = lock_release_token_pool.LockReleaseTokenPoolABI - case cldf.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0).String(): - tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.BurnMintTokens677 == nil { - state.BurnMintTokens677 = make(map[TokenSymbol]*burn_mint_erc677.BurnMintERC677) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.BurnMintTokens677[TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = burn_mint_erc677.BurnMintERC677ABI - case cldf.NewTypeAndVersion(ERC20Token, deployment.Version1_0_0).String(): - tok, err := erc20.NewERC20(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.ERC20Tokens == nil { - state.ERC20Tokens = make(map[TokenSymbol]*erc20.ERC20) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.ERC20Tokens[TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = erc20.ERC20ABI - case cldf.NewTypeAndVersion(FactoryBurnMintERC20Token, deployment.Version1_0_0).String(): - tok, err := factory_burn_mint_erc20.NewFactoryBurnMintERC20(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.FactoryBurnMintERC20Token = tok - state.ABIByAddress[address] = factory_burn_mint_erc20.FactoryBurnMintERC20ABI - case cldf.NewTypeAndVersion(ERC677Token, deployment.Version1_0_0).String(): - tok, err := erc677.NewERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.ERC677Tokens == nil { - state.ERC677Tokens = make(map[TokenSymbol]*erc677.ERC677) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.ERC677Tokens[TokenSymbol(symbol)] = tok - state.ABIByAddress[address] = erc677.ERC677ABI - // legacy addresses below - case cldf.NewTypeAndVersion(OnRamp, deployment.Version1_5_0).String(): - onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := onRampC.GetStaticConfig(nil) - if err != nil { - return state, fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) - } - if state.EVM2EVMOnRamp == nil { - state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) - } - state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC - state.ABIByAddress[address] = evm_2_evm_onramp.EVM2EVMOnRampABI - case cldf.NewTypeAndVersion(OffRamp, deployment.Version1_5_0).String(): - offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := offRamp.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.EVM2EVMOffRamp == nil { - state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) - } - state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp - state.ABIByAddress[address] = evm_2_evm_offramp.EVM2EVMOffRampABI - case cldf.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): - commitStore, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := commitStore.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.CommitStore == nil { - state.CommitStore = make(map[uint64]*commit_store.CommitStore) - } - state.CommitStore[sCfg.SourceChainSelector] = commitStore - state.ABIByAddress[address] = commit_store.CommitStoreABI - case cldf.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0).String(): - pr, err := price_registry_1_2_0.NewPriceRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.PriceRegistry = pr - state.ABIByAddress[address] = price_registry_1_2_0.PriceRegistryABI - case cldf.NewTypeAndVersion(RMN, deployment.Version1_5_0).String(): - rmnC, err := rmn_contract.NewRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RMN = rmnC - state.ABIByAddress[address] = rmn_contract.RMNContractABI - case cldf.NewTypeAndVersion(MockRMN, deployment.Version1_0_0).String(): - mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockRMN = mockRMN - state.ABIByAddress[address] = mock_rmn_contract.MockRMNContractABI - case cldf.NewTypeAndVersion(FeeAggregator, deployment.Version1_0_0).String(): - state.FeeAggregator = common.HexToAddress(address) - case cldf.NewTypeAndVersion(FiredrillEntrypointType, deployment.Version1_5_0).String(), - cldf.NewTypeAndVersion(FiredrillEntrypointType, deployment.Version1_6_0).String(): - // Ignore firedrill contracts - // Firedrill contracts are unknown to core and their state is being loaded separately - case cldf.NewTypeAndVersion(DonIDClaimer, deployment.Version1_6_1).String(): - donIDClaimer, err := don_id_claimer.NewDonIDClaimer(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.DonIDClaimer = donIDClaimer - state.ABIByAddress[address] = don_id_claimer.DonIDClaimerABI - default: - // ManyChainMultiSig 1.0.0 can have any of these labels, it can have either 1,2 or 3 of these - - // bypasser, proposer and canceller - // if you try to compare tvStr.String() you will have to compare all combinations of labels - // so we will compare the type and version only - if tvStr.Type == commontypes.ManyChainMultisig && tvStr.Version == deployment.Version1_0_0 { - state.ABIByAddress[address] = gethwrappers.ManyChainMultiSigABI - continue - } - return state, fmt.Errorf("unknown contract %s", tvStr) - } - } - return state, nil -} - -func ValidateChain(env deployment.Environment, state CCIPOnChainState, chainSel uint64, mcmsCfg *proposalutils.TimelockConfig) error { - err := deployment.IsValidChainSelector(chainSel) - if err != nil { - return fmt.Errorf("is not valid chain selector %d: %w", chainSel, err) - } - chain, ok := env.Chains[chainSel] - if !ok { - return fmt.Errorf("chain with selector %d does not exist in environment", chainSel) - } - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("%s does not exist in state", chain) - } - if mcmsCfg != nil { - err = mcmsCfg.Validate(chain, commonstate.MCMSWithTimelockState{ - CancellerMcm: chainState.CancellerMcm, - ProposerMcm: chainState.ProposerMcm, - BypasserMcm: chainState.BypasserMcm, - Timelock: chainState.Timelock, - CallProxy: chainState.CallProxy, - }) - if err != nil { - return err - } - } - return nil -} - -func validateLatestConfigOffRamp(offRamp offramp.OffRampInterface, cfg offramp.MultiOCR3BaseOCRConfig, homeChainConfig ccip_home.CCIPHomeChainConfig) error { - // check if number of signers are unique and greater than 3 - if cfg.ConfigInfo.IsSignatureVerificationEnabled { - if len(cfg.Signers) < 3 { - return fmt.Errorf("offRamp %s config signers count mismatch: expected at least 3, got %d", - offRamp.Address().Hex(), len(cfg.Signers)) - } - if !deployment.IsAddressListUnique(cfg.Signers) { - return fmt.Errorf("offRamp %s config signers list %v is not unique", offRamp.Address().Hex(), cfg.Signers) - } - if deployment.AddressListContainsEmptyAddress(cfg.Signers) { - return fmt.Errorf("offRamp %s config signers list %v contains empty address", offRamp.Address().Hex(), cfg.Signers) - } - } else if len(cfg.Signers) != 0 { - return fmt.Errorf("offRamp %s config signers count mismatch: expected 0, got %d", - offRamp.Address().Hex(), len(cfg.Signers)) - } - if len(cfg.Transmitters) < 3 { - return fmt.Errorf("offRamp %s config transmitters count mismatch: expected at least 3, got %d", - offRamp.Address().Hex(), len(cfg.Transmitters)) - } - if !deployment.IsAddressListUnique(cfg.Transmitters) { - return fmt.Errorf("offRamp %s config transmitters list %v is not unique", offRamp.Address().Hex(), cfg.Transmitters) - } - if deployment.AddressListContainsEmptyAddress(cfg.Transmitters) { - return fmt.Errorf("offRamp %s config transmitters list %v contains empty address", offRamp.Address().Hex(), cfg.Transmitters) - } - - // FRoleDON >= fChain is a requirement - if cfg.ConfigInfo.F < homeChainConfig.FChain { - return fmt.Errorf("offRamp %s config fChain mismatch: expected at least %d, got %d", - offRamp.Address().Hex(), homeChainConfig.FChain, cfg.ConfigInfo.F) - } - - // transmitters.length should be validated such that it meets the 3 * fChain + 1 requirement - minTransmitterReq := 3*int(homeChainConfig.FChain) + 1 - if len(cfg.Transmitters) < minTransmitterReq { - return fmt.Errorf("offRamp %s config transmitters count mismatch: expected at least %d, got %d", - offRamp.Address().Hex(), minTransmitterReq, len(cfg.Transmitters)) - } - return nil -} diff --git a/deployment/ccip/changeset/testhelpers/feestest/helpers.go b/deployment/ccip/changeset/testhelpers/feestest/helpers.go index 3a3e4d42cc7..769245c4265 100644 --- a/deployment/ccip/changeset/testhelpers/feestest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/feestest/helpers.go @@ -14,15 +14,18 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/weth9" "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) // NewFeeTokenTestCase creates a new FeeTokenTestCase to test fee token usage scenarios. func NewFeeTokenTestCase( t *testing.T, - env deployment.Environment, + env cldf.Environment, src, dst uint64, feeToken common.Address, tokenAmounts []router.ClientEVMTokenAmount, @@ -50,7 +53,7 @@ func NewFeeTokenTestCase( type FeeTokenTestCase struct { t *testing.T src, dst uint64 - env deployment.Environment + env cldf.Environment srcToken, dstToken *burn_mint_erc677.BurnMintERC677 tokenAmounts []router.ClientEVMTokenAmount feeToken common.Address @@ -70,7 +73,7 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { srcChain := tc.env.Chains[tc.src] dstChain := tc.env.Chains[tc.dst] - state, err := changeset.LoadOnchainState(tc.env) + state, err := stateview.LoadOnchainState(tc.env) require.NoError(tc.t, err) var dstTokBalanceBefore *big.Int @@ -98,7 +101,7 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { srcChain.DeployerKey.Value = assets.Ether(100).ToInt() tx, err := weth9.Deposit(srcChain.DeployerKey) - _, err = deployment.ConfirmIfNoError(srcChain, tx, err) + _, err = cldf.ConfirmIfNoError(srcChain, tx, err) require.NoError(tc.t, err) srcChain.DeployerKey.Value = big.NewInt(0) } @@ -117,7 +120,7 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { // Approve the router to spend fee token tx, err := feeTokenWrapper.Approve(srcChain.DeployerKey, state.Chains[tc.src].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(srcChain, tx, err) + _, err = cldf.ConfirmIfNoError(srcChain, tx, err) require.NoError(tc.t, err) } @@ -204,7 +207,7 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { Context: ctx, }, linkAddress) require.NoError(tc.t, err) - require.Equal(tc.t, changeset.MockLinkPrice, timestampedPrice.Value) + require.Equal(tc.t, shared.MockLinkPrice, timestampedPrice.Value) // Wait for all exec reports to land testhelpers.ConfirmExecWithSeqNrsForAll(tc.t, tc.env, state, expectedSeqNumExec, startBlocks) diff --git a/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go b/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go index 04771f007db..7a5df7621f4 100644 --- a/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go @@ -9,15 +9,17 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) // Expects WithDeployedEnv for ephemeral test environments or WithEnv for long-running test environments like staging. func NewTestSetup( t *testing.T, - onchainState changeset.CCIPOnChainState, + onchainState stateview.CCIPOnChainState, sourceChain, destChain uint64, srctoken common.Address, @@ -53,7 +55,7 @@ func WithDeployedEnv(de testhelpers.DeployedEnv) TestSetupOpts { } } -func WithEnv(env deployment.Environment) TestSetupOpts { +func WithEnv(env cldf.Environment) TestSetupOpts { return func(ts *TestSetup) { ts.Env = env } @@ -61,9 +63,9 @@ func WithEnv(env deployment.Environment) TestSetupOpts { type TestSetup struct { T *testing.T - Env deployment.Environment + Env cldf.Environment DeployedEnv *testhelpers.DeployedEnv - OnchainState changeset.CCIPOnChainState + OnchainState stateview.CCIPOnChainState SrcChain uint64 DestChain uint64 SrcToken common.Address diff --git a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go index c68df18117b..1fbc3aeb32f 100644 --- a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go @@ -18,16 +18,17 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) // Use this when testhelpers.DeployedEnv is available (usually in ephemeral test environments). func NewTestSetupWithDeployedEnv( t *testing.T, depEnv testhelpers.DeployedEnv, - onchainState changeset.CCIPOnChainState, + onchainState stateview.CCIPOnChainState, sourceChain, destChain uint64, sender []byte, @@ -48,8 +49,8 @@ func NewTestSetupWithDeployedEnv( // Use this when testhelpers.DeployedEnv is not available (usually in long-running test environments like staging). func NewTestSetup( t *testing.T, - env deployment.Environment, - onchainState changeset.CCIPOnChainState, + env cldf.Environment, + onchainState stateview.CCIPOnChainState, sourceChain, destChain uint64, sender []byte, @@ -70,9 +71,9 @@ func NewTestSetup( type TestSetup struct { T *testing.T Sender []byte - Env deployment.Environment + Env cldf.Environment DeployedEnv testhelpers.DeployedEnv - OnchainState changeset.CCIPOnChainState + OnchainState stateview.CCIPOnChainState SourceChain uint64 DestChain uint64 TestRouter bool diff --git a/deployment/ccip/changeset/testhelpers/test_assertions.go b/deployment/ccip/changeset/testhelpers/test_assertions.go index 104a675d466..62946979dfe 100644 --- a/deployment/ccip/changeset/testhelpers/test_assertions.go +++ b/deployment/ccip/changeset/testhelpers/test_assertions.go @@ -35,19 +35,19 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" - - "github.com/smartcontractkit/chainlink/deployment" ) func ConfirmGasPriceUpdatedForAll( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, startBlocks map[uint64]*uint64, gasPrice *big.Int, ) { @@ -79,7 +79,7 @@ func ConfirmGasPriceUpdatedForAll( func ConfirmGasPriceUpdated( t *testing.T, - dest deployment.Chain, + dest cldf.Chain, srcFeeQuoter *fee_quoter.FeeQuoter, startBlock uint64, gasPrice *big.Int, @@ -99,8 +99,8 @@ func ConfirmGasPriceUpdated( func ConfirmTokenPriceUpdatedForAll( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, startBlocks map[uint64]*uint64, linkPrice *big.Int, wethPrice *big.Int, @@ -132,7 +132,7 @@ func ConfirmTokenPriceUpdatedForAll( func ConfirmTokenPriceUpdated( t *testing.T, - chain deployment.Chain, + chain cldf.Chain, feeQuoter *fee_quoter.FeeQuoter, startBlock uint64, tokenToInitialPrice map[common.Address]*big.Int, @@ -184,8 +184,8 @@ type SourceDestPair struct { // If startBlocks is nil, it will start watching from the latest block. func ConfirmCommitForAllWithExpectedSeqNums( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, expectedSeqNums map[SourceDestPair]uint64, startBlocks map[uint64]*uint64, ) { @@ -313,8 +313,8 @@ func (c *CommitReportTracker) allCommited(sourceChainSelector uint64) bool { // Waiting is done in parallel per every sourceChain/destChain (lane) passed as argument. func ConfirmMultipleCommits( t *testing.T, - env deployment.Environment, - state changeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, startBlocks map[uint64]*uint64, enforceSingleCommit bool, expectedSeqNums map[SourceDestPair]ccipocr3.SeqNumRange, @@ -384,7 +384,7 @@ func ConfirmMultipleCommits( func ConfirmCommitWithExpectedSeqNumRange( t *testing.T, srcSelector uint64, - dest deployment.Chain, + dest cldf.Chain, offRamp offramp.OffRampInterface, startBlock *uint64, expectedSeqNumRange ccipocr3.SeqNumRange, @@ -569,7 +569,7 @@ func SolEventEmitter[T any]( func ConfirmCommitWithExpectedSeqNumRangeSol( t *testing.T, srcSelector uint64, - dest deployment.SolChain, + dest cldf.SolChain, offrampAddress solana.PublicKey, startSlot uint64, expectedSeqNumRange ccipocr3.SeqNumRange, @@ -690,7 +690,7 @@ func AptosEventEmitter[T any]( func ConfirmCommitWithExpectedSeqNumRangeAptos( t *testing.T, srcSelector uint64, - dest deployment.AptosChain, + dest cldf.AptosChain, offRampAddress aptos.AccountAddress, startVersion *uint64, expectedSeqNumRange ccipocr3.SeqNumRange, @@ -764,8 +764,8 @@ func ConfirmCommitWithExpectedSeqNumRangeAptos( // If startBlocks is nil, it will start watching from the latest block. func ConfirmExecWithSeqNrsForAll( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, expectedSeqNums map[SourceDestPair][]uint64, startBlocks map[uint64]*uint64, ) (executionStates map[SourceDestPair]map[uint64]int) { @@ -855,7 +855,7 @@ func ConfirmExecWithSeqNrsForAll( func ConfirmExecWithSeqNrs( t *testing.T, sourceSelector uint64, - dest deployment.Chain, + dest cldf.Chain, offRamp offramp.OffRampInterface, startBlock *uint64, expectedSeqNrs []uint64, @@ -930,7 +930,7 @@ func ConfirmExecWithSeqNrs( func ConfirmExecWithSeqNrsSol( t *testing.T, srcSelector uint64, - dest deployment.SolChain, + dest cldf.SolChain, offrampAddress solana.PublicKey, startSlot uint64, expectedSeqNrs []uint64, @@ -981,7 +981,7 @@ func ConfirmExecWithSeqNrsSol( func ConfirmExecWithExpectedSeqNrsAptos( t *testing.T, srcSelector uint64, - dest deployment.AptosChain, + dest cldf.AptosChain, offRampAddress aptos.AccountAddress, startVersion *uint64, expectedSeqNrs []uint64, @@ -1035,7 +1035,7 @@ func ConfirmExecWithExpectedSeqNrsAptos( func ConfirmNoExecConsistentlyWithSeqNr( t *testing.T, sourceSelector uint64, - dest deployment.Chain, + dest cldf.Chain, offRamp offramp.OffRampInterface, expectedSeqNr uint64, timeout time.Duration, @@ -1140,7 +1140,7 @@ func AssertTimelockOwnership( t *testing.T, e DeployedEnv, chains []uint64, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, ) { // check that the ownership has been transferred correctly for _, chain := range chains { diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 724e147bf04..bf68227a593 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -26,6 +26,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" @@ -134,8 +136,8 @@ func DefaultTestConfigs() *TestConfigs { NumOfUsersPerChain: 1, Nodes: 4, Bootstraps: 1, - LinkPrice: changeset.MockLinkPrice, - WethPrice: changeset.MockWethPrice, + LinkPrice: shared.MockLinkPrice, + WethPrice: shared.MockWethPrice, CreateJobAndContracts: true, BlockTime: 2 * time.Second, } @@ -293,7 +295,7 @@ type TestEnvironment interface { } type DeployedEnv struct { - Env deployment.Environment + Env cldf.Environment HomeChainSel uint64 FeedChainSel uint64 ReplayBlocks map[uint64]uint64 @@ -303,7 +305,7 @@ type DeployedEnv struct { func (d *DeployedEnv) TimelockContracts(t *testing.T) map[uint64]*proposalutils.TimelockExecutionContracts { timelocks := make(map[uint64]*proposalutils.TimelockExecutionContracts) - state, err := changeset.LoadOnchainState(d.Env) + state, err := stateview.LoadOnchainState(d.Env) require.NoError(t, err) for chain, chainState := range state.Chains { timelocks[chain] = &proposalutils.TimelockExecutionContracts{ @@ -325,9 +327,9 @@ type MemoryEnvironment struct { DeployedEnv nodes map[string]memory.Node TestConfig *TestConfigs - Chains map[uint64]deployment.Chain - SolChains map[uint64]deployment.SolChain - AptosChains map[uint64]deployment.AptosChain + Chains map[uint64]cldf.Chain + SolChains map[uint64]cldf.SolChain + AptosChains map[uint64]cldf.AptosChain } func (m *MemoryEnvironment) TestConfigs() *TestConfigs { @@ -345,7 +347,7 @@ func (m *MemoryEnvironment) UpdateDeployedEnvironment(env DeployedEnv) { func (m *MemoryEnvironment) StartChains(t *testing.T) { ctx := testcontext.Get(t) tc := m.TestConfig - var chains map[uint64]deployment.Chain + var chains map[uint64]cldf.Chain var users map[uint64][]*bind.TransactOpts if len(tc.ChainIDs) > 0 { chains, users = memory.NewMemoryChainsWithChainIDs(t, tc.ChainIDs, tc.NumOfUsersPerChain) @@ -365,7 +367,7 @@ func (m *MemoryEnvironment) StartChains(t *testing.T) { m.Chains = chains m.SolChains = memory.NewMemoryChainsSol(t, tc.SolChains) m.AptosChains = memory.NewMemoryChainsAptos(t, tc.AptosChains) - env := deployment.Environment{ + env := cldf.Environment{ Chains: m.Chains, SolChains: m.SolChains, AptosChains: m.AptosChains, @@ -621,7 +623,7 @@ func NewEnvironmentWithJobsAndContracts(t *testing.T, tEnv TestEnvironment) Depl require.NoError(t, err) // load the state again to get the latest addresses - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) err = state.ValidatePostDeploymentState(e.Env) require.NoError(t, err) @@ -633,7 +635,7 @@ func deployChainContractsToSolChainCS(e DeployedEnv, solChainSelector uint64) ([ if err != nil { return nil, err } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) if err != nil { return nil, err } @@ -753,7 +755,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn require.NoError(t, err) } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) // Assert link present if tc.IsStaticLink { @@ -763,7 +765,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn } require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) - tokenConfig := changeset.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + tokenConfig := shared.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) var tokenDataProviders []pluginconfig.TokenDataObserverConfig if tc.IsUSDC { endpoint := tEnv.MockUSDCAttestationServer(t, tc.IsUSDCAttestationMissing) @@ -844,9 +846,9 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn for _, chain := range solChains { // TODO: this is a workaround for tokenConfig.GetTokenInfo tokenInfo := map[cciptypes.UnknownEncodedAddress]pluginconfig.TokenInfo{} - tokenInfo[cciptypes.UnknownEncodedAddress(state.SolChains[chain].LinkToken.String())] = tokenConfig.TokenSymbolToInfo[changeset.LinkSymbol] + tokenInfo[cciptypes.UnknownEncodedAddress(state.SolChains[chain].LinkToken.String())] = tokenConfig.TokenSymbolToInfo[shared.LinkSymbol] // TODO: point this to proper SOL feed, apparently 0 signified SOL - tokenInfo[cciptypes.UnknownEncodedAddress(solanago.SolMint.String())] = tokenConfig.TokenSymbolToInfo[changeset.WethSymbol] + tokenInfo[cciptypes.UnknownEncodedAddress(solanago.SolMint.String())] = tokenConfig.TokenSymbolToInfo[shared.WethSymbol] ocrOverride := tc.OCRConfigOverride commitOCRConfigs[chain] = v1_6.DeriveOCRParamsForCommit(v1_6.SimulationTest, e.FeedChainSel, tokenInfo, ocrOverride) @@ -868,7 +870,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn // TODO(aptos): update this for token transfers tokenInfo := map[cciptypes.UnknownEncodedAddress]pluginconfig.TokenInfo{} linkTokenAddress := state.AptosChains[chain].LinkTokenAddress - tokenInfo[cciptypes.UnknownEncodedAddress(linkTokenAddress.String())] = tokenConfig.TokenSymbolToInfo[changeset.LinkSymbol] + tokenInfo[cciptypes.UnknownEncodedAddress(linkTokenAddress.String())] = tokenConfig.TokenSymbolToInfo[shared.LinkSymbol] ocrOverride := tc.OCRConfigOverride commitOCRConfigs[chain] = v1_6.DeriveOCRParamsForCommit(v1_6.SimulationTest, e.FeedChainSel, tokenInfo, ocrOverride) @@ -996,7 +998,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) require.NotNil(t, state.Chains[e.HomeChainSel].CapabilityRegistry) require.NotNil(t, state.Chains[e.HomeChainSel].CCIPHome) diff --git a/deployment/ccip/changeset/testhelpers/test_helpers.go b/deployment/ccip/changeset/testhelpers/test_helpers.go index b814e995dd7..20a5f84a2c0 100644 --- a/deployment/ccip/changeset/testhelpers/test_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_helpers.go @@ -29,11 +29,18 @@ import ( solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" + ccipChangeSetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" @@ -56,8 +63,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -180,18 +185,18 @@ func DeployTestContracts(t *testing.T, ab cldf.AddressBook, homeChainSel, feedChainSel uint64, - chains map[uint64]deployment.Chain, + chains map[uint64]cldf.Chain, linkPrice *big.Int, wethPrice *big.Int, ) deployment.CapabilityRegistryConfig { capReg, err := cldf.DeployContract(lggr, chains[homeChainSel], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: crAddr, Contract: cr, Tv: cldf.NewTypeAndVersion(changeset.CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + Address: crAddr, Contract: cr, Tv: cldf.NewTypeAndVersion(shared.CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, } }) require.NoError(t, err) @@ -209,7 +214,7 @@ func DeployTestContracts(t *testing.T, } } -func LatestBlock(ctx context.Context, env deployment.Environment, chainSelector uint64) (uint64, error) { +func LatestBlock(ctx context.Context, env cldf.Environment, chainSelector uint64) (uint64, error) { family, err := chainsel.GetSelectorFamily(chainSelector) if err != nil { return 0, err @@ -236,7 +241,7 @@ func LatestBlock(ctx context.Context, env deployment.Environment, chainSelector } } -func LatestBlocksByChain(ctx context.Context, env deployment.Environment) (map[uint64]uint64, error) { +func LatestBlocksByChain(ctx context.Context, env cldf.Environment) (map[uint64]uint64, error) { latestBlocks := make(map[uint64]uint64) chains := []uint64{} @@ -253,7 +258,7 @@ func LatestBlocksByChain(ctx context.Context, env deployment.Environment) (map[u return latestBlocks, nil } -func allocateCCIPChainSelectors(chains map[uint64]deployment.Chain) (homeChainSel uint64, feeChainSel uint64) { +func allocateCCIPChainSelectors(chains map[uint64]cldf.Chain) (homeChainSel uint64, feeChainSel uint64) { // Lower chainSel is home chain. var chainSels []uint64 // Say first chain is home chain. @@ -292,8 +297,8 @@ func mockAttestationResponse(isFaulty bool) *httptest.Server { } func CCIPSendRequest( - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, cfg *CCIPSendReqConfig, ) (*types.Transaction, uint64, error) { msg := cfg.Message.(router.ClientEVM2AnyMessage) @@ -307,7 +312,7 @@ func CCIPSendRequest( } tx, err := r.CcipSend(cfg.Sender, cfg.DestChain, msg) - blockNum, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[cfg.SourceChain], tx, router.RouterABI, err) + blockNum, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[cfg.SourceChain], tx, router.RouterABI, err) if err != nil { return tx, 0, errors.Wrap(err, "failed to confirm CCIP message") } @@ -319,7 +324,7 @@ func CCIPSendRequest( // and the message will be rejected if the fee is insufficient. // The function will retry based on the config's MaxRetries setting for errors other than insufficient fee. func retryCcipSendUntilNativeFeeIsSufficient( - e deployment.Environment, + e cldf.Environment, r *router.Router, cfg *CCIPSendReqConfig, ) (*types.Transaction, uint64, error) { @@ -334,7 +339,7 @@ func retryCcipSendUntilNativeFeeIsSufficient( for { fee, err := r.GetFee(&bind.CallOpts{Context: context.Background()}, cfg.DestChain, msg) if err != nil { - return nil, 0, fmt.Errorf("failed to get fee: %w", deployment.MaybeDataErr(err)) + return nil, 0, fmt.Errorf("failed to get fee: %w", cldf.MaybeDataErr(err)) } cfg.Sender.Value = fee @@ -356,13 +361,13 @@ func retryCcipSendUntilNativeFeeIsSufficient( // It is configured in the CCIPSendReqConfig. // This retry was originally added to solve transient failure in end to end tests if retryCount >= cfg.MaxRetries { - return nil, 0, fmt.Errorf("failed to confirm CCIP message after %d retries: %w", retryCount, deployment.MaybeDataErr(err)) + return nil, 0, fmt.Errorf("failed to confirm CCIP message after %d retries: %w", retryCount, cldf.MaybeDataErr(err)) } retryCount++ continue } - return nil, 0, fmt.Errorf("failed to confirm CCIP message: %w", deployment.MaybeDataErr(err)) + return nil, 0, fmt.Errorf("failed to confirm CCIP message: %w", cldf.MaybeDataErr(err)) } return tx, blockNum, nil @@ -395,8 +400,8 @@ func CCIPSendCalldata( func TestSendRequest( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, src, dest uint64, testRouter bool, msg any, @@ -472,8 +477,8 @@ func WithDestChain(destChain uint64) SendReqOpts { // SendRequest similar to TestSendRequest but returns an error. func SendRequest( - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, opts ...SendReqOpts, ) (*onramp.OnRampCCIPMessageSent, error) { cfg := &CCIPSendReqConfig{} @@ -498,8 +503,8 @@ func SendRequest( } func SendRequestEVM( - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, cfg *CCIPSendReqConfig, ) (*onramp.OnRampCCIPMessageSent, error) { // Set default sender if not provided @@ -542,8 +547,8 @@ func SendRequestEVM( } func SendRequestSol( - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, cfg *CCIPSendReqConfig, ) (*onramp.OnRampCCIPMessageSent, error) { // TODO: chain independent return value ctx := e.GetContext() @@ -671,7 +676,7 @@ func SendRequestSol( for _, tokenAmount := range message.TokenAmounts { tokenPubKey := tokenAmount.Token - tokenPoolPubKey, err := MatchTokenToTokenPool(ctx, client, tokenPubKey, []solana.PublicKey{s.LockReleaseTokenPools[changeset.CLLMetadata], s.BurnMintTokenPools[changeset.CLLMetadata]}) + tokenPoolPubKey, err := MatchTokenToTokenPool(ctx, client, tokenPubKey, []solana.PublicKey{s.LockReleaseTokenPools[shared.CLLMetadata], s.BurnMintTokenPools[shared.CLLMetadata]}) if err != nil { return nil, err } @@ -1205,7 +1210,7 @@ func RemoveLane(t *testing.T, e *DeployedEnv, src, dest uint64, isTestRouter boo require.NoError(t, err) } -func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, state changeset.CCIPOnChainState, from, to uint64, isTestRouter bool) { +func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, state stateview.CCIPOnChainState, from, to uint64, isTestRouter bool) { gasPrices := map[uint64]*big.Int{ to: DefaultGasPrice, } @@ -1232,7 +1237,7 @@ func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, st // AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain // is connected to every other chain except itself. -func AddLanesForAll(t *testing.T, e *DeployedEnv, state changeset.CCIPOnChainState) { +func AddLanesForAll(t *testing.T, e *DeployedEnv, state stateview.CCIPOnChainState) { chains := []uint64{} allEvmChainSelectors := maps.Keys(e.Env.Chains) allSolChainSelectors := maps.Keys(e.Env.SolChains) @@ -1256,17 +1261,17 @@ func ToPackedFee(execFee, daFee *big.Int) *big.Int { func DeployFeeds( lggr logger.Logger, ab cldf.AddressBook, - chain deployment.Chain, + chain cldf.Chain, linkPrice *big.Int, wethPrice *big.Int, ) (map[string]common.Address, error) { - linkTV := cldf.NewTypeAndVersion(changeset.PriceFeed, deployment.Version1_0_0) - mockLinkFeed := func(chain deployment.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + linkTV := cldf.NewTypeAndVersion(shared.PriceFeed, deployment.Version1_0_0) + mockLinkFeed := func(chain cldf.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { linkFeed, tx, _, err1 := mock_v3_aggregator_contract.DeployMockV3Aggregator( chain.DeployerKey, chain.Client, - changeset.LinkDecimals, // decimals - linkPrice, // initialAnswer + shared.LinkDecimals, // decimals + linkPrice, // initialAnswer ) aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(linkFeed, chain.Client) @@ -1275,7 +1280,7 @@ func DeployFeeds( } } - mockWethFeed := func(chain deployment.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + mockWethFeed := func(chain cldf.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { wethFeed, tx, _, err1 := mock_ethusd_aggregator_wrapper.DeployMockETHUSDAggregator( chain.DeployerKey, chain.Client, @@ -1288,12 +1293,12 @@ func DeployFeeds( } } - linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, changeset.LinkSymbol) + linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, shared.LinkSymbol) if err != nil { return nil, err } - wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, changeset.WethSymbol) + wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, shared.WethSymbol) if err != nil { return nil, err } @@ -1309,9 +1314,9 @@ func DeployFeeds( func deploySingleFeed( lggr logger.Logger, ab cldf.AddressBook, - chain deployment.Chain, - deployFunc func(deployment.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], - symbol changeset.TokenSymbol, + chain cldf.Chain, + deployFunc func(cldf.Chain) cldf.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], + symbol shared.TokenSymbol, ) (common.Address, string, error) { // tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) mockTokenFeed, err := cldf.DeployContract(lggr, chain, ab, deployFunc) @@ -1328,7 +1333,7 @@ func deploySingleFeed( return common.Address{}, "", err } - if desc != changeset.MockSymbolToDescription[symbol] { + if desc != shared.MockSymbolToDescription[symbol] { lggr.Errorw("Unexpected description for token", "symbol", symbol, "desc", desc) return common.Address{}, "", fmt.Errorf("unexpected description: %s", desc) } @@ -1338,10 +1343,10 @@ func deploySingleFeed( func DeployTransferableToken( lggr logger.Logger, - chains map[uint64]deployment.Chain, + chains map[uint64]cldf.Chain, src, dst uint64, srcActor, dstActor *bind.TransactOpts, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, addresses cldf.AddressBook, token string, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { @@ -1383,7 +1388,7 @@ func DeployTransferableToken( // assuming one out of the src and dst is solana and the other is evm func DeployTransferableTokenSolana( lggr logger.Logger, - e deployment.Environment, + e cldf.Environment, evmChainSel, solChainSel uint64, evmDeployer *bind.TransactOpts, evmTokenName string, @@ -1403,7 +1408,7 @@ func DeployTransferableTokenSolana( if selectorFamily != chainsel.FamilySolana { return nil, nil, solana.PublicKey{}, fmt.Errorf("solChainSel %d is not a solana chain", solChainSel) } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return nil, nil, solana.PublicKey{}, err } @@ -1426,7 +1431,7 @@ func DeployTransferableTokenSolana( cldf.CreateLegacyChangeSet(ccipChangeSetSolana.DeploySolanaToken), ccipChangeSetSolana.DeploySolanaTokenConfig{ ChainSelector: solChainSel, - TokenProgramName: changeset.SPL2022Tokens, + TokenProgramName: shared.SPL2022Tokens, TokenDecimals: 9, ATAList: []string{solDeployerKey.String()}, MintAmountToAddress: map[string]uint64{ @@ -1439,7 +1444,7 @@ func DeployTransferableTokenSolana( return nil, nil, solana.PublicKey{}, err } - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) if err != nil { return nil, nil, solana.PublicKey{}, err } @@ -1462,7 +1467,7 @@ func DeployTransferableTokenSolana( } // configure evm - poolConfigPDA, err := soltokens.TokenPoolConfigAddress(solTokenAddress, state.SolChains[solChainSel].BurnMintTokenPools[changeset.CLLMetadata]) + poolConfigPDA, err := soltokens.TokenPoolConfigAddress(solTokenAddress, state.SolChains[solChainSel].BurnMintTokenPools[shared.CLLMetadata]) if err != nil { return nil, nil, solana.PublicKey{}, err } @@ -1486,9 +1491,9 @@ func DeployTransferableTokenSolana( SolPoolType: &bnm, EVMRemoteConfigs: map[uint64]ccipChangeSetSolana.EVMRemoteConfig{ evmChainSel: { - TokenSymbol: changeset.TokenSymbol(evmTokenName), - PoolType: changeset.BurnMintTokenPool, - PoolVersion: changeset.CurrentTokenPoolVersion, + TokenSymbol: shared.TokenSymbol(evmTokenName), + PoolType: shared.BurnMintTokenPool, + PoolVersion: shared.CurrentTokenPoolVersion, RateLimiterConfig: ccipChangeSetSolana.RateLimiterConfig{ Inbound: solTestTokenPool.RateLimitConfig{}, Outbound: solTestTokenPool.RateLimitConfig{}, @@ -1547,10 +1552,10 @@ func DeployTransferableTokenSolana( func deployTokenPoolsInParallel( lggr logger.Logger, - chains map[uint64]deployment.Chain, + chains map[uint64]cldf.Chain, src, dst uint64, srcActor, dstActor *bind.TransactOpts, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, addresses cldf.AddressBook, token string, ) ( @@ -1598,7 +1603,7 @@ func deployTokenPoolsInParallel( return srcToken, srcPool, dstToken, dstPool, nil } -func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, actor *bind.TransactOpts, address common.Address) error { +func grantMintBurnPermissions(lggr logger.Logger, chain cldf.Chain, token *burn_mint_erc677.BurnMintERC677, actor *bind.TransactOpts, address common.Address) error { lggr.Infow("Granting burn/mint permissions", "token", token.Address(), "address", address) tx, err := token.GrantMintAndBurnRoles(actor, address) if err != nil { @@ -1609,7 +1614,7 @@ func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token } func setUSDCTokenPoolCounterPart( - chain deployment.Chain, + chain cldf.Chain, tokenPool *usdc_token_pool.USDCTokenPool, destChainSelector uint64, actor *bind.TransactOpts, @@ -1649,7 +1654,7 @@ func setUSDCTokenPoolCounterPart( } func setTokenPoolCounterPart( - chain deployment.Chain, + chain cldf.Chain, tokenPool *burn_mint_token_pool.BurnMintTokenPool, actor *bind.TransactOpts, destChainSelector uint64, @@ -1686,8 +1691,8 @@ func setTokenPoolCounterPart( } func attachTokenToTheRegistry( - chain deployment.Chain, - state changeset.CCIPChainState, + chain cldf.Chain, + state evm.CCIPChainState, owner *bind.TransactOpts, token common.Address, tokenPool common.Address, @@ -1734,7 +1739,7 @@ func attachTokenToTheRegistry( func deployTransferTokenOneEnd( lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, deployer *bind.TransactOpts, addressBook cldf.AddressBook, tokenSymbol string, @@ -1745,10 +1750,10 @@ func deployTransferTokenOneEnd( return nil, nil, err } for address, v := range chainAddresses { - if cldf.NewTypeAndVersion(changeset.ARMProxy, deployment.Version1_0_0).Equal(v) { + if cldf.NewTypeAndVersion(shared.ARMProxy, deployment.Version1_0_0).Equal(v) { rmnAddress = address } - if cldf.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0).Equal(v) { + if cldf.NewTypeAndVersion(shared.Router, deployment.Version1_2_0).Equal(v) { routerAddress = address } if rmnAddress != "" && routerAddress != "" { @@ -1759,7 +1764,7 @@ func deployTransferTokenOneEnd( tokenDecimals := uint8(18) tokenContract, err := cldf.DeployContract(lggr, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( deployer, chain.Client, @@ -1769,7 +1774,7 @@ func deployTransferTokenOneEnd( big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), ) return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - Address: tokenAddress, Contract: token, Tx: tx, Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), Err: err2, + Address: tokenAddress, Contract: token, Tx: tx, Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Err: err2, } }) if err != nil { @@ -1787,7 +1792,7 @@ func deployTransferTokenOneEnd( } tokenPool, err := cldf.DeployContract(lggr, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { tokenPoolAddress, tx, tokenPoolContract, err2 := burn_mint_token_pool.DeployBurnMintTokenPool( deployer, chain.Client, @@ -1798,7 +1803,7 @@ func deployTransferTokenOneEnd( common.HexToAddress(routerAddress), ) return cldf.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool]{ - Address: tokenPoolAddress, Contract: tokenPoolContract, Tx: tx, Tv: cldf.NewTypeAndVersion(changeset.BurnMintTokenPool, deployment.Version1_5_1), Err: err2, + Address: tokenPoolAddress, Contract: tokenPoolContract, Tx: tx, Tv: cldf.NewTypeAndVersion(shared.BurnMintTokenPool, deployment.Version1_5_1), Err: err2, } }) if err != nil { @@ -1824,7 +1829,7 @@ func NewMintTokenWithCustomSender(auth *bind.TransactOpts, sender *bind.Transact } // ApproveToken approves the router to spend the given amount of tokens -func ApproveToken(env deployment.Environment, src uint64, tokenAddress common.Address, routerAddress common.Address, amount *big.Int) error { +func ApproveToken(env cldf.Environment, src uint64, tokenAddress common.Address, routerAddress common.Address, amount *big.Int) error { token, err := erc20.NewERC20(tokenAddress, env.Chains[src].Client) if err != nil { return err @@ -1846,8 +1851,8 @@ func ApproveToken(env deployment.Environment, src uint64, tokenAddress common.Ad // MintAndAllow mints tokens for deployers and allow router to spend them func MintAndAllow( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, tokenMap map[uint64][]MintTokenInfo, ) { configurePoolGrp := errgroup.Group{} @@ -1889,8 +1894,8 @@ func MintAndAllow( func Transfer( ctx context.Context, t *testing.T, - env deployment.Environment, - state changeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, sourceChain, destChain uint64, tokens any, receiver []byte, @@ -1971,8 +1976,8 @@ type TestTransferRequest struct { func TransferMultiple( ctx context.Context, t *testing.T, - env deployment.Environment, - state changeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, requests []TestTransferRequest, ) ( map[uint64]*uint64, @@ -2104,7 +2109,7 @@ type TokenReceiverIdentifier struct { func WaitForTokenBalances( ctx context.Context, t *testing.T, - env deployment.Environment, + env cldf.Environment, expectedBalances map[uint64][]ExpectedTokenBalance, ) { errGrp := &errgroup.Group{} @@ -2149,7 +2154,7 @@ func WaitForTheTokenBalance( t *testing.T, token common.Address, receiver common.Address, - chain deployment.Chain, + chain cldf.Chain, expected *big.Int, ) { tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) @@ -2175,7 +2180,7 @@ func WaitForTheTokenBalanceSol( t *testing.T, token solana.PublicKey, receiver solana.PublicKey, - chain deployment.SolChain, + chain cldf.SolChain, expected uint64, ) { require.Eventually(t, func() bool { @@ -2204,33 +2209,33 @@ func DefaultRouterMessage(receiverAddress common.Address) router.ClientEVM2AnyMe } // TODO: this should be linked to the solChain function -func SavePreloadedSolAddresses(e deployment.Environment, solChainSelector uint64) error { - tv := cldf.NewTypeAndVersion(changeset.Router, deployment.Version1_0_0) +func SavePreloadedSolAddresses(e cldf.Environment, solChainSelector uint64) error { + tv := cldf.NewTypeAndVersion(shared.Router, deployment.Version1_0_0) err := e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["ccip_router"], tv) if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.Receiver, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.Receiver, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["test_ccip_receiver"], tv) if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.FeeQuoter, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.FeeQuoter, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["fee_quoter"], tv) if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.OffRamp, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.OffRamp, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["ccip_offramp"], tv) if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.BurnMintTokenPool, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.BurnMintTokenPool, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["burnmint_token_pool"], tv) if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.LockReleaseTokenPool, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.LockReleaseTokenPool, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["lockrelease_token_pool"], tv) if err != nil { return err @@ -2250,7 +2255,7 @@ func SavePreloadedSolAddresses(e deployment.Environment, solChainSelector uint64 if err != nil { return err } - tv = cldf.NewTypeAndVersion(changeset.RMNRemote, deployment.Version1_0_0) + tv = cldf.NewTypeAndVersion(shared.RMNRemote, deployment.Version1_0_0) err = e.ExistingAddresses.Save(solChainSelector, memory.SolanaProgramIDs["rmn_remote"], tv) if err != nil { return err @@ -2258,8 +2263,8 @@ func SavePreloadedSolAddresses(e deployment.Environment, solChainSelector uint64 return nil } -func ValidateSolanaState(t *testing.T, e deployment.Environment, solChainSelectors []uint64) { - state, err := changeset.LoadOnchainStateSolana(e) +func ValidateSolanaState(t *testing.T, e cldf.Environment, solChainSelectors []uint64) { + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err, "Failed to load Solana state") for _, sel := range solChainSelectors { @@ -2294,7 +2299,7 @@ func ValidateSolanaState(t *testing.T, e deployment.Environment, solChainSelecto err = e.SolChains[sel].GetAccountDataBorshInto(testcontext.Get(t), chainState.RMNRemoteConfigPDA, &rmnRemoteConfigAccount) require.NoError(t, err, "Failed to deserialize rmn remote config for chain %d", sel) - addressLookupTable, err := changeset.FetchOfframpLookupTable(e.GetContext(), e.SolChains[sel], chainState.OffRamp) + addressLookupTable, err := solanastateview.FetchOfframpLookupTable(e.GetContext(), e.SolChains[sel], chainState.OffRamp) require.NoError(t, err, "Failed to get offramp lookup table for chain %d", sel) addresses, err := solCommonUtil.GetAddressLookupTable( @@ -2306,15 +2311,15 @@ func ValidateSolanaState(t *testing.T, e deployment.Environment, solChainSelecto } } -func DeploySolanaCcipReceiver(t *testing.T, e deployment.Environment) { - state, err := changeset.LoadOnchainStateSolana(e) +func DeploySolanaCcipReceiver(t *testing.T, e cldf.Environment) { + state, err := stateview.LoadOnchainStateSolana(e) require.NoError(t, err) for solSelector, chainState := range state.SolChains { solTestReceiver.SetProgramID(chainState.Receiver) externalExecutionConfigPDA, _, _ := solana.FindProgramAddress([][]byte{[]byte("external_execution_config")}, chainState.Receiver) instruction, ixErr := solTestReceiver.NewInitializeInstruction( chainState.Router, - changeset.FindReceiverTargetAccount(chainState.Receiver), + solanastateview.FindReceiverTargetAccount(chainState.Receiver), externalExecutionConfigPDA, e.SolChains[solSelector].DeployerKey.PublicKey(), solana.SystemProgramID, @@ -2327,7 +2332,7 @@ func DeploySolanaCcipReceiver(t *testing.T, e deployment.Environment) { func TransferOwnershipSolana( t *testing.T, - e *deployment.Environment, + e *cldf.Environment, solChain uint64, needTimelockDeployed bool, contractsToTransfer ccipChangeSetSolana.CCIPContractsToTransfer, @@ -2382,7 +2387,7 @@ func TransferOwnershipSolana( func GenTestTransferOwnershipConfig( e DeployedEnv, chains []uint64, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, ) commoncs.TransferToMCMSWithTimelockConfig { var ( timelocksPerChain = make(map[uint64]common.Address) @@ -2422,7 +2427,7 @@ func GenTestTransferOwnershipConfig( func DeployCCIPContractsTest(t *testing.T, solChains int) { e, _ := NewMemoryEnvironment(t, WithSolChains(solChains)) // Deploy all the CCIP contracts. - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := append(e.Env.AllChainSelectors(), e.Env.AllChainSelectorsSolana()...) snap, solana, err := state.View(&e.Env, allChains) @@ -2444,7 +2449,7 @@ func DeployCCIPContractsTest(t *testing.T, solChains int) { func TransferToTimelock( t *testing.T, tenv DeployedEnv, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, chains []uint64, ) { timelockContracts := make(map[uint64]*proposalutils.TimelockExecutionContracts, len(chains)+1) @@ -2471,14 +2476,14 @@ func TransferToTimelock( AssertTimelockOwnership(t, tenv, chains, state) } -func DeployAptosCCIPReceiver(t *testing.T, e deployment.Environment) { - state, err := changeset.LoadOnchainStateAptos(e) +func DeployAptosCCIPReceiver(t *testing.T, e cldf.Environment) { + state, err := aptosstate.LoadOnchainStateAptos(e) require.NoError(t, err) for selector, onchainState := range state { addr, tx, _, err := ccip_dummy_receiver.DeployToObject(e.AptosChains[selector].DeployerSigner, e.AptosChains[selector].Client, onchainState.CCIPAddress, onchainState.MCMSAddress) require.NoError(t, err) t.Logf("(Aptos) CCIPDummyReceiver(ccip: %s, mcms: %s) deployed to %s in tx %s", onchainState.CCIPAddress.StringLong(), onchainState.MCMSAddress.StringLong(), addr.StringLong(), tx.Hash) require.NoError(t, e.AptosChains[selector].Confirm(tx.Hash)) - e.ExistingAddresses.Save(selector, addr.StringLong(), cldf.NewTypeAndVersion(changeset.AptosReceiverType, deployment.Version1_0_0)) + e.ExistingAddresses.Save(selector, addr.StringLong(), cldf.NewTypeAndVersion(shared.AptosReceiverType, deployment.Version1_0_0)) } } diff --git a/deployment/ccip/changeset/testhelpers/test_token_helpers.go b/deployment/ccip/changeset/testhelpers/test_token_helpers.go index df60a910511..c22f85c53b1 100644 --- a/deployment/ccip/changeset/testhelpers/test_token_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_token_helpers.go @@ -20,6 +20,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" @@ -29,8 +31,8 @@ import ( ) const ( - LocalTokenDecimals = 18 - TestTokenSymbol changeset.TokenSymbol = "TEST" + LocalTokenDecimals = 18 + TestTokenSymbol shared.TokenSymbol = "TEST" ) // CreateSymmetricRateLimits is a utility to quickly create a rate limiter config with equal inbound and outbound values. @@ -54,7 +56,7 @@ func SetupTwoChainEnvironmentWithTokens( t *testing.T, lggr logger.Logger, transferToTimelock bool, -) (env deployment.Environment, sel1 uint64, sel2 uint64, ercmap map[uint64]*cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677], contractmap map[uint64]*proposalutils.TimelockExecutionContracts) { +) (env cldf.Environment, sel1 uint64, sel2 uint64, ercmap map[uint64]*cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677], contractmap map[uint64]*proposalutils.TimelockExecutionContracts) { e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ Chains: 2, }) @@ -77,7 +79,7 @@ func SetupTwoChainEnvironmentWithTokens( tokens := make(map[uint64]*cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]) for _, selector := range selectors { token, err := cldf.DeployContract(e.Logger, e.Chains[selector], addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( e.Chains[selector].DeployerKey, e.Chains[selector].Client, @@ -89,7 +91,7 @@ func SetupTwoChainEnvironmentWithTokens( return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -112,7 +114,7 @@ func SetupTwoChainEnvironmentWithTokens( ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) // We only need the token admin registry to be owned by the timelock in these tests @@ -150,7 +152,7 @@ func SetupTwoChainEnvironmentWithTokens( } // getPoolsOwnedByDeployer returns any pools that need to be transferred to timelock. -func getPoolsOwnedByDeployer[T commonchangeset.Ownable](t *testing.T, contracts map[semver.Version]T, chain deployment.Chain) []common.Address { +func getPoolsOwnedByDeployer[T commonchangeset.Ownable](t *testing.T, contracts map[semver.Version]T, chain cldf.Chain) []common.Address { var addresses []common.Address for _, contract := range contracts { owner, err := contract.Owner(nil) @@ -165,10 +167,10 @@ func getPoolsOwnedByDeployer[T commonchangeset.Ownable](t *testing.T, contracts // DeployTestTokenPools deploys token pools tied for the TEST token across multiple chains. func DeployTestTokenPools( t *testing.T, - e deployment.Environment, + e cldf.Environment, newPools map[uint64]v1_5_1.DeployTokenPoolInput, transferToTimelock bool, -) deployment.Environment { +) cldf.Environment { selectors := e.AllChainSelectors() e, err := commonchangeset.Apply(t, e, nil, @@ -182,7 +184,7 @@ func DeployTestTokenPools( ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) if transferToTimelock { @@ -199,13 +201,13 @@ func DeployTestTokenPools( for _, selector := range selectors { if newPool, ok := newPools[selector]; ok { switch newPool.Type { - case changeset.BurnFromMintTokenPool: + case shared.BurnFromMintTokenPool: timelockOwnedContractsByChain[selector] = getPoolsOwnedByDeployer(t, state.Chains[selector].BurnFromMintTokenPools[TestTokenSymbol], e.Chains[selector]) - case changeset.BurnWithFromMintTokenPool: + case shared.BurnWithFromMintTokenPool: timelockOwnedContractsByChain[selector] = getPoolsOwnedByDeployer(t, state.Chains[selector].BurnWithFromMintTokenPools[TestTokenSymbol], e.Chains[selector]) - case changeset.BurnMintTokenPool: + case shared.BurnMintTokenPool: timelockOwnedContractsByChain[selector] = getPoolsOwnedByDeployer(t, state.Chains[selector].BurnMintTokenPools[TestTokenSymbol], e.Chains[selector]) - case changeset.LockReleaseTokenPool: + case shared.LockReleaseTokenPool: timelockOwnedContractsByChain[selector] = getPoolsOwnedByDeployer(t, state.Chains[selector].LockReleaseTokenPools[TestTokenSymbol], e.Chains[selector]) } } diff --git a/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go b/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go index 193df2ed054..941a3d43435 100644 --- a/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_usdc_helpers.go @@ -14,27 +14,30 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" ) func ConfigureUSDCTokenPools( lggr logger.Logger, - chains map[uint64]deployment.Chain, + chains map[uint64]cldf.Chain, src, dst uint64, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, ) (*burn_mint_erc677.BurnMintERC677, *burn_mint_erc677.BurnMintERC677, error) { - srcToken := state.Chains[src].BurnMintTokens677[changeset.USDCSymbol] - dstToken := state.Chains[dst].BurnMintTokens677[changeset.USDCSymbol] + srcToken := state.Chains[src].BurnMintTokens677[shared.USDCSymbol] + dstToken := state.Chains[dst].BurnMintTokens677[shared.USDCSymbol] srcPool := state.Chains[src].USDCTokenPools[deployment.Version1_5_1] dstPool := state.Chains[dst].USDCTokenPools[deployment.Version1_5_1] args := []struct { - sourceChain deployment.Chain + sourceChain cldf.Chain dstChainSel uint64 - state changeset.CCIPChainState + state evm.CCIPChainState srcToken *burn_mint_erc677.BurnMintERC677 srcPool *usdc_token_pool.USDCTokenPool dstToken *burn_mint_erc677.BurnMintERC677 @@ -72,9 +75,9 @@ func ConfigureUSDCTokenPools( func configureSingleChain( lggr logger.Logger, - sourceChain deployment.Chain, + sourceChain cldf.Chain, dstChainSel uint64, - state changeset.CCIPChainState, + state evm.CCIPChainState, srcToken *burn_mint_erc677.BurnMintERC677, srcPool *usdc_token_pool.USDCTokenPool, dstToken *burn_mint_erc677.BurnMintERC677, @@ -107,9 +110,9 @@ func configureSingleChain( func UpdateFeeQuoterForUSDC( t *testing.T, - e deployment.Environment, + e cldf.Environment, lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, dstChain uint64, ) error { config := fee_quoter.FeeQuoterTokenTransferFeeConfig{ @@ -129,8 +132,8 @@ func UpdateFeeQuoterForUSDC( TokenTransferFeeConfigArgs: []v1_6.TokenTransferFeeConfigArg{ { DestChain: dstChain, - TokenTransferFeeConfigPerToken: map[changeset.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ - changeset.USDCSymbol: config, + TokenTransferFeeConfigPerToken: map[shared.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ + shared.USDCSymbol: config, }, }, }, diff --git a/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go b/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go index f122c47cc9d..8852935956c 100644 --- a/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go +++ b/deployment/ccip/changeset/testhelpers/v1_5/test_helpers.go @@ -18,6 +18,8 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" config2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" price_registry_1_2_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/price_registry" @@ -25,15 +27,13 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" v1_5changeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" plugintesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" ) -func AddLanes(t *testing.T, e deployment.Environment, state changeset.CCIPOnChainState, pairs []testhelpers.SourceDestPair) deployment.Environment { +func AddLanes(t *testing.T, e cldf.Environment, state stateview.CCIPOnChainState, pairs []testhelpers.SourceDestPair) cldf.Environment { addLanesCfg, commitOCR2Configs, execOCR2Configs, jobspecs := LaneConfigsForChains(t, e, state, pairs) var err error e, err = commonchangeset.Apply(t, e, nil, @@ -54,7 +54,7 @@ func AddLanes(t *testing.T, e deployment.Environment, state changeset.CCIPOnChai return e } -func LaneConfigsForChains(t *testing.T, env deployment.Environment, state changeset.CCIPOnChainState, pairs []testhelpers.SourceDestPair) ( +func LaneConfigsForChains(t *testing.T, env cldf.Environment, state stateview.CCIPOnChainState, pairs []testhelpers.SourceDestPair) ( []v1_5changeset.DeployLaneConfig, []v1_5changeset.CommitOCR2ConfigParams, []v1_5changeset.ExecuteOCR2ConfigParams, @@ -212,7 +212,7 @@ func LaneConfigsForChains(t *testing.T, env deployment.Environment, state change } // CreatePriceGetterConfig returns price getter config as json string. -func CreatePriceGetterConfig(t *testing.T, state changeset.CCIPOnChainState, source, dest uint64) string { +func CreatePriceGetterConfig(t *testing.T, state stateview.CCIPOnChainState, source, dest uint64) string { sourceRouter := state.Chains[source].Router destRouter := state.Chains[dest].Router destLinkAddr, err := state.Chains[dest].LinkTokenAddress() @@ -275,8 +275,8 @@ func DefaultOCRParams() confighelper.PublicConfig { func SendRequest( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, opts ...testhelpers.SendReqOpts, ) (*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested, error) { cfg := &testhelpers.CCIPSendReqConfig{} @@ -319,8 +319,8 @@ func SendRequest( func WaitForCommit( t *testing.T, - src deployment.Chain, - dest deployment.Chain, + src cldf.Chain, + dest cldf.Chain, commitStore *commit_store.CommitStore, seqNr uint64, ) { @@ -347,8 +347,8 @@ func WaitForCommit( func WaitForNoCommit( t *testing.T, - src deployment.Chain, - dest deployment.Chain, + src cldf.Chain, + dest cldf.Chain, commitStore *commit_store.CommitStore, seqNr uint64, ) { @@ -375,8 +375,8 @@ func WaitForNoCommit( func WaitForExecute( t *testing.T, - src deployment.Chain, - dest deployment.Chain, + src cldf.Chain, + dest cldf.Chain, offRamp *evm_2_evm_offramp.EVM2EVMOffRamp, seqNrs []uint64, blockNum uint64, diff --git a/deployment/ccip/changeset/v1_5/cs_jobspec.go b/deployment/ccip/changeset/v1_5/cs_jobspec.go index 50aa1cbba83..79cd15bcb66 100644 --- a/deployment/ccip/changeset/v1_5/cs_jobspec.go +++ b/deployment/ccip/changeset/v1_5/cs_jobspec.go @@ -7,8 +7,9 @@ import ( jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" ) @@ -40,10 +41,10 @@ type JobSpecInput struct { } func (j JobSpecInput) Validate() error { - if err := deployment.IsValidChainSelector(j.SourceChainSelector); err != nil { + if err := cldf.IsValidChainSelector(j.SourceChainSelector); err != nil { return fmt.Errorf("SourceChainSelector is invalid: %w", err) } - if err := deployment.IsValidChainSelector(j.DestinationChainSelector); err != nil { + if err := cldf.IsValidChainSelector(j.DestinationChainSelector); err != nil { return fmt.Errorf("DestinationChainSelector is invalid: %w", err) } if j.TokenPricesUSDPipeline == "" && j.PriceGetterConfigJson == "" { @@ -60,11 +61,11 @@ func (j JobSpecInput) Validate() error { return nil } -func JobSpecsForLanesChangeset(env deployment.Environment, c JobSpecsForLanesConfig) (cldf.ChangesetOutput, error) { +func JobSpecsForLanesChangeset(env cldf.Environment, c JobSpecsForLanesConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid JobSpecsForLanesConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, err } @@ -102,8 +103,8 @@ func JobSpecsForLanesChangeset(env deployment.Environment, c JobSpecsForLanesCon } func jobSpecsForLane( - env deployment.Environment, - state changeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, lanesCfg JobSpecsForLanesConfig, ) (map[string][]string, error) { nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) diff --git a/deployment/ccip/changeset/v1_5/cs_lane_contracts.go b/deployment/ccip/changeset/v1_5/cs_lane_contracts.go index 6d1239b94f3..49517158da4 100644 --- a/deployment/ccip/changeset/v1_5/cs_lane_contracts.go +++ b/deployment/ccip/changeset/v1_5/cs_lane_contracts.go @@ -14,7 +14,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" ) var _ cldf.ChangeSet[DeployLanesConfig] = DeployLanesChangeset @@ -23,7 +25,7 @@ type DeployLanesConfig struct { Configs []DeployLaneConfig } -func (c *DeployLanesConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (c *DeployLanesConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { for _, cfg := range c.Configs { if err := cfg.Validate(e, state); err != nil { return err @@ -52,11 +54,11 @@ type DeployLaneConfig struct { GasPriceUpdates []price_registry_1_2_0.InternalGasPriceUpdate } -func (c *DeployLaneConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { +func (c *DeployLaneConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { + if err := cldf.IsValidChainSelector(c.SourceChainSelector); err != nil { return err } - if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { + if err := cldf.IsValidChainSelector(c.DestinationChainSelector); err != nil { return err } sourceChain, exists := e.Chains[c.SourceChainSelector] @@ -86,7 +88,7 @@ func (c *DeployLaneConfig) Validate(e deployment.Environment, state changeset.CC return nil } -func (c *DeployLaneConfig) populateAddresses(state changeset.CCIPOnChainState) error { +func (c *DeployLaneConfig) populateAddresses(state stateview.CCIPOnChainState) error { sourceChainState := state.Chains[c.SourceChainSelector] srcLink, err := sourceChainState.LinkTokenAddress() if err != nil { @@ -101,8 +103,8 @@ func (c *DeployLaneConfig) populateAddresses(state changeset.CCIPOnChainState) e return nil } -func DeployLanesChangeset(env deployment.Environment, c DeployLanesConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func DeployLanesChangeset(env cldf.Environment, c DeployLanesConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) } @@ -128,7 +130,7 @@ func DeployLanesChangeset(env deployment.Environment, c DeployLanesConfig) (cldf }, nil } -func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab cldf.AddressBook, cfg DeployLaneConfig) error { +func deployLane(e cldf.Environment, state stateview.CCIPOnChainState, ab cldf.AddressBook, cfg DeployLaneConfig) error { // update prices on the source price registry sourceChainState := state.Chains[cfg.SourceChainSelector] destChainState := state.Chains[cfg.DestinationChainSelector] @@ -144,7 +146,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c } _, err = sourceChain.Confirm(tx) if err != nil { - return fmt.Errorf("failed to confirm price update tx for chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to confirm price update tx for chain %s: %w", sourceChain.String(), cldf.MaybeDataErr(err)) } // ================================================================ // │ Deploy Lane │ @@ -153,7 +155,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c onRamp, onRampExists := sourceChainState.EVM2EVMOnRamp[cfg.DestinationChainSelector] if !onRampExists { onRampC, err := cldf.DeployContract(e.Logger, sourceChain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp] { + func(chain cldf.Chain) cldf.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp] { onRampAddress, tx2, onRampC, err2 := evm_2_evm_onramp.DeployEVM2EVMOnRamp( sourceChain.DeployerKey, sourceChain.Client, @@ -166,7 +168,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c ) return cldf.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp]{ Address: onRampAddress, Contract: onRampC, Tx: tx2, - Tv: cldf.NewTypeAndVersion(changeset.OnRamp, deployment.Version1_5_0), Err: err2, + Tv: cldf.NewTypeAndVersion(shared.OnRamp, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -184,7 +186,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c commitStore, commitStoreExists := destChainState.CommitStore[cfg.SourceChainSelector] if !commitStoreExists { commitStoreC, err := cldf.DeployContract(e.Logger, destChain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*commit_store.CommitStore] { + func(chain cldf.Chain) cldf.ContractDeploy[*commit_store.CommitStore] { commitStoreAddress, tx2, commitStoreC, err2 := commit_store.DeployCommitStore( destChain.DeployerKey, destChain.Client, @@ -197,7 +199,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c ) return cldf.ContractDeploy[*commit_store.CommitStore]{ Address: commitStoreAddress, Contract: commitStoreC, Tx: tx2, - Tv: cldf.NewTypeAndVersion(changeset.CommitStore, deployment.Version1_5_0), Err: err2, + Tv: cldf.NewTypeAndVersion(shared.CommitStore, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -215,7 +217,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c offRamp, offRampExists := destChainState.EVM2EVMOffRamp[cfg.SourceChainSelector] if !offRampExists { offRampC, err := cldf.DeployContract(e.Logger, destChain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp] { + func(chain cldf.Chain) cldf.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp] { offRampAddress, tx2, offRampC, err2 := evm_2_evm_offramp.DeployEVM2EVMOffRamp( destChain.DeployerKey, destChain.Client, @@ -232,7 +234,7 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c ) return cldf.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp]{ Address: offRampAddress, Contract: offRampC, Tx: tx2, - Tv: cldf.NewTypeAndVersion(changeset.OffRamp, deployment.Version1_5_0), Err: err2, + Tv: cldf.NewTypeAndVersion(shared.OffRamp, deployment.Version1_5_0), Err: err2, } }) if err != nil { @@ -250,11 +252,11 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c tx, err = sourceChainState.Router.ApplyRampUpdates(sourceChain.DeployerKey, []router.RouterOnRamp{{DestChainSelector: destChain.Selector, OnRamp: onRamp.Address()}}, nil, nil) if err != nil { - return fmt.Errorf("failed to apply router updates for source chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to apply router updates for source chain %s: %w", sourceChain.String(), cldf.MaybeDataErr(err)) } _, err = sourceChain.Confirm(tx) if err != nil { - return fmt.Errorf("failed to confirm router updates tx %s for source chain %s: %w", tx.Hash().String(), sourceChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to confirm router updates tx %s for source chain %s: %w", tx.Hash().String(), sourceChain.String(), cldf.MaybeDataErr(err)) } tx, err = destChainState.Router.ApplyRampUpdates(destChain.DeployerKey, @@ -263,11 +265,11 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c []router.RouterOffRamp{{SourceChainSelector: sourceChain.Selector, OffRamp: offRamp.Address()}}, ) if err != nil { - return fmt.Errorf("failed to apply router updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to apply router updates for destination chain %s: %w", destChain.String(), cldf.MaybeDataErr(err)) } _, err = destChain.Confirm(tx) if err != nil { - return fmt.Errorf("failed to confirm router updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to confirm router updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), cldf.MaybeDataErr(err)) } // price registry updates @@ -277,16 +279,16 @@ func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab c []common.Address{}, ) if err != nil { - return fmt.Errorf("failed to apply price registry updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to apply price registry updates for destination chain %s: %w", destChain.String(), cldf.MaybeDataErr(err)) } _, err = destChain.Confirm(tx) if err != nil { - return fmt.Errorf("failed to confirm price registry updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) + return fmt.Errorf("failed to confirm price registry updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), cldf.MaybeDataErr(err)) } return nil } -func arePrerequisitesMet(chainState changeset.CCIPChainState, chain deployment.Chain) error { +func arePrerequisitesMet(chainState evm.CCIPChainState, chain cldf.Chain) error { if chainState.Router == nil { return fmt.Errorf("router not found for chain %s", chain.String()) } diff --git a/deployment/ccip/changeset/v1_5/cs_ocr2_config.go b/deployment/ccip/changeset/v1_5/cs_ocr2_config.go index 430b93cf1d7..468512f1384 100644 --- a/deployment/ccip/changeset/v1_5/cs_ocr2_config.go +++ b/deployment/ccip/changeset/v1_5/cs_ocr2_config.go @@ -16,7 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" ) @@ -68,11 +68,11 @@ func (c *CommitOCR2ConfigParams) PopulateOffChainAndOnChainCfg(priceReg common.A return nil } -func (c *CommitOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { +func (c *CommitOCR2ConfigParams) Validate(state stateview.CCIPOnChainState) error { + if err := cldf.IsValidChainSelector(c.DestinationChainSelector); err != nil { return fmt.Errorf("invalid DestinationChainSelector: %w", err) } - if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { + if err := cldf.IsValidChainSelector(c.SourceChainSelector); err != nil { return fmt.Errorf("invalid SourceChainSelector: %w", err) } @@ -135,11 +135,11 @@ func (e *ExecuteOCR2ConfigParams) PopulateOffChainAndOnChainCfg(router, priceReg return nil } -func (e *ExecuteOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(e.SourceChainSelector); err != nil { +func (e *ExecuteOCR2ConfigParams) Validate(state stateview.CCIPOnChainState) error { + if err := cldf.IsValidChainSelector(e.SourceChainSelector); err != nil { return fmt.Errorf("invalid SourceChainSelector: %w", err) } - if err := deployment.IsValidChainSelector(e.DestinationChainSelector); err != nil { + if err := cldf.IsValidChainSelector(e.DestinationChainSelector); err != nil { return fmt.Errorf("invalid DestinationChainSelector: %w", err) } chain, exists := state.Chains[e.DestinationChainSelector] @@ -167,7 +167,7 @@ type OCR2Config struct { ExecConfigs []ExecuteOCR2ConfigParams } -func (o OCR2Config) Validate(state changeset.CCIPOnChainState) error { +func (o OCR2Config) Validate(state stateview.CCIPOnChainState) error { for _, c := range o.CommitConfigs { if err := c.Validate(state); err != nil { return err @@ -183,8 +183,8 @@ func (o OCR2Config) Validate(state changeset.CCIPOnChainState) error { // SetOCR2ConfigForTestChangeset sets the OCR2 config on the chain for commit and offramp // This is currently not suitable for prod environments it's only for testing -func SetOCR2ConfigForTestChangeset(env deployment.Environment, c OCR2Config) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func SetOCR2ConfigForTestChangeset(env cldf.Environment, c OCR2Config) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) } @@ -212,7 +212,7 @@ func SetOCR2ConfigForTestChangeset(env deployment.Environment, c OCR2Config) (cl ) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to set OCR2 config for commit store %s on chain %s: %w", - commitStore.Address().String(), chain.String(), deployment.MaybeDataErr(err)) + commitStore.Address().String(), chain.String(), cldf.MaybeDataErr(err)) } _, err = chain.Confirm(tx) if err != nil { @@ -255,7 +255,7 @@ func SetOCR2ConfigForTestChangeset(env deployment.Environment, c OCR2Config) (cl } func deriveOCR2Config( - env deployment.Environment, + env cldf.Environment, chainSel uint64, ocrParams confighelper.PublicConfig, ) (FinalOCR2Config, error) { diff --git a/deployment/ccip/changeset/v1_5/cs_rmn.go b/deployment/ccip/changeset/v1_5/cs_rmn.go index 9fbaaa83b8e..6894fe01e56 100644 --- a/deployment/ccip/changeset/v1_5/cs_rmn.go +++ b/deployment/ccip/changeset/v1_5/cs_rmn.go @@ -16,8 +16,9 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -30,8 +31,8 @@ type PermaBlessConfigPerSourceChain struct { // https://github.com/smartcontractkit/ccip/blob/ccip-develop/contracts/src/v0.8/ccip/RMN.sol#L699C30-L699C54 } -func (p PermaBlessConfigPerSourceChain) Validate(destChain uint64, state changeset.CCIPOnChainState, permaBlessedCommitStores []common.Address) error { - if err := deployment.IsValidChainSelector(p.SourceChainSelector); err != nil { +func (p PermaBlessConfigPerSourceChain) Validate(destChain uint64, state stateview.CCIPOnChainState, permaBlessedCommitStores []common.Address) error { + if err := cldf.IsValidChainSelector(p.SourceChainSelector); err != nil { return fmt.Errorf("invalid SourceChainSelector: %w", err) } _, ok := state.Chains[p.SourceChainSelector] @@ -64,13 +65,13 @@ type PermaBlessCommitStoreConfig struct { MCMSConfig *proposalutils.TimelockConfig } -func (c PermaBlessCommitStoreConfig) Validate(env deployment.Environment) error { - state, err := changeset.LoadOnchainState(env) +func (c PermaBlessCommitStoreConfig) Validate(env cldf.Environment) error { + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for destChain, pCfg := range c.Configs { - if err := deployment.IsValidChainSelector(destChain); err != nil { + if err := cldf.IsValidChainSelector(destChain); err != nil { return fmt.Errorf("invalid DestChainSelector: %w", err) } destState, ok := state.Chains[destChain] @@ -104,12 +105,12 @@ func (c PermaBlessCommitStoreConfig) Validate(env deployment.Environment) error // PermaBlessCommitStoreChangeset permablesses the commit stores on the RMN contract // If commit store addresses are added to the permaBlessed list, those will be considered automatically blessed. // This changeset can add to or remove from the existing permaBlessed list. -func PermaBlessCommitStoreChangeset(env deployment.Environment, c PermaBlessCommitStoreConfig) (cldf.ChangesetOutput, error) { +func PermaBlessCommitStoreChangeset(env cldf.Environment, c PermaBlessCommitStoreConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid PermaBlessCommitStoreConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -134,13 +135,13 @@ func PermaBlessCommitStoreChangeset(env deployment.Environment, c PermaBlessComm txOpts := env.Chains[destChain].DeployerKey if c.MCMSConfig != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := RMN.OwnerRemoveThenAddPermaBlessedCommitStores(txOpts, removes, adds) // note: error check is handled below if c.MCMSConfig == nil { - _, err = deployment.ConfirmIfNoErrorWithABI(env.Chains[destChain], tx, rmn_contract.RMNContractABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(env.Chains[destChain], tx, rmn_contract.RMNContractABI, err) if err != nil { return cldf.ChangesetOutput{}, err } @@ -158,7 +159,7 @@ func PermaBlessCommitStoreChangeset(env deployment.Environment, c PermaBlessComm } batchOperation, err := proposalutils.BatchOperationForChain(destChain, RMN.Address().Hex(), tx.Data(), big.NewInt(0), - string(changeset.RMN), []string{}) + string(shared.RMN), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for chain %d: %w", destChain, err) } @@ -169,7 +170,7 @@ func PermaBlessCommitStoreChangeset(env deployment.Environment, c PermaBlessComm return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(env, state, c.MCMSConfig) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(env, state, c.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } diff --git a/deployment/ccip/changeset/v1_5/e2e_test.go b/deployment/ccip/changeset/v1_5/e2e_test.go index 8334a8ad3da..0c261f960d8 100644 --- a/deployment/ccip/changeset/v1_5/e2e_test.go +++ b/deployment/ccip/changeset/v1_5/e2e_test.go @@ -11,10 +11,12 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/v1_5" v1_5changeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" @@ -44,7 +46,7 @@ func TestE2ELegacy(t *testing.T) { }), testhelpers.WithNumOfChains(3), testhelpers.WithChainIDs([]uint64{chainselectors.GETH_TESTNET.EvmChainID})) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) @@ -76,7 +78,7 @@ func TestE2ELegacy(t *testing.T) { ) require.NoError(t, err) // reload state after adding lanes - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) sentEvent, err := v1_5.SendRequest(t, e.Env, state, testhelpers.WithSourceChain(src), diff --git a/deployment/ccip/changeset/token_pools.go b/deployment/ccip/changeset/v1_5_1/commonconfig.go similarity index 63% rename from deployment/ccip/changeset/token_pools.go rename to deployment/ccip/changeset/v1_5_1/commonconfig.go index 64951fa5cfa..3db82906dd5 100644 --- a/deployment/ccip/changeset/token_pools.go +++ b/deployment/ccip/changeset/v1_5_1/commonconfig.go @@ -1,4 +1,4 @@ -package changeset +package v1_5_1 import ( "context" @@ -7,46 +7,106 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-evm/pkg/utils" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/token_pool" - "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc20" + deployment2 "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" + changeset2 "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" ) -var CurrentTokenPoolVersion semver.Version = deployment.Version1_5_1 - -var TokenTypes = map[cldf.ContractType]struct{}{ - BurnMintToken: {}, - ERC20Token: {}, - ERC677Token: {}, +// TokenAdminRegistryChangesetConfig defines a config for all token admin registry actions. +type TokenAdminRegistryChangesetConfig struct { + // MCMS defines the delay to use for Timelock (if absent, the changeset will attempt to use the deployer key). + MCMS *proposalutils.TimelockConfig + // Pools defines the pools corresponding to the tokens we want to accept admin role for. + Pools map[uint64]map[shared.TokenSymbol]TokenPoolInfo + // SkipOwnershipValidation indicates whether or not to skip admin ownership validation of token in the registry. + // it is skipped when propose admin,set admin and set pool operations are done as part of one changeset. + SkipOwnershipValidation bool } -var TokenPoolTypes = map[cldf.ContractType]struct{}{ - BurnMintTokenPool: {}, - BurnWithFromMintTokenPool: {}, - BurnFromMintTokenPool: {}, - LockReleaseTokenPool: {}, - USDCTokenPool: {}, - HybridLockReleaseUSDCTokenPool: {}, -} +// validateTokenAdminRegistryChangeset validates all token admin registry changesets. +func (c TokenAdminRegistryChangesetConfig) Validate( + env cldf.Environment, + mustBeOwner bool, + registryConfigCheck func( + config token_admin_registry.TokenAdminRegistryTokenConfig, + sender common.Address, + externalAdmin common.Address, + symbol shared.TokenSymbol, + chain cldf.Chain, + ) error, +) error { + state, err := stateview.LoadOnchainState(env) + if err != nil { + return fmt.Errorf("failed to load onchain state: %w", err) + } + err = state.EnforceMCMSUsageIfProd(env.GetContext(), c.MCMS) + if err != nil { + return err + } + for chainSelector, symbolToPoolInfo := range c.Pools { + err := stateview.ValidateChain(env, state, chainSelector, c.MCMS) + if err != nil { + return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) + } + chain, ok := env.Chains[chainSelector] + if !ok { + return fmt.Errorf("chain with selector %d does not exist in environment", chainSelector) + } + chainState, ok := state.Chains[chainSelector] + if !ok { + return fmt.Errorf("%s does not exist in state", chain) + } + if tokenAdminRegistry := chainState.TokenAdminRegistry; tokenAdminRegistry == nil { + return fmt.Errorf("missing tokenAdminRegistry on %s", chain) + } + + // Validate that the token admin registry is owned by the address that will be actioning the transactions (i.e. Timelock or deployer key) + // However, most token admin registry actions aren't owner-protected. They just require you to be the admin. + if mustBeOwner { + if err := changeset2.ValidateOwnership(env.GetContext(), c.MCMS != nil, chain.DeployerKey.From, chainState.Timelock.Address(), chainState.TokenAdminRegistry); err != nil { + return fmt.Errorf("token admin registry failed ownership validation on %s: %w", chain, err) + } + } + for symbol, poolInfo := range symbolToPoolInfo { + if err := poolInfo.Validate(); err != nil { + return fmt.Errorf("failed to validate token pool info for %s token on chain %s: %w", symbol, chain, err) + } + + tokenConfigOnRegistry, err := poolInfo.GetConfigOnRegistry(env.GetContext(), symbol, chain, chainState) + if err != nil { + return fmt.Errorf("failed to get state of %s token on chain %s: %w", symbol, chain, err) + } + + fromAddress := chain.DeployerKey.From // "We" are either the deployer key or the timelock + if c.MCMS != nil { + fromAddress = chainState.Timelock.Address() + } -var TokenPoolVersions map[semver.Version]struct{} = map[semver.Version]struct{}{ - deployment.Version1_5_1: struct{}{}, + if !c.SkipOwnershipValidation { + err = registryConfigCheck(tokenConfigOnRegistry, fromAddress, poolInfo.ExternalAdmin, symbol, chain) + if err != nil { + return err + } + } + } + } + + return nil } // TokenPoolInfo defines the type & version of a token pool, along with an optional external administrator. type TokenPoolInfo struct { // Type is the type of the token pool. - Type cldf.ContractType + Type deployment2.ContractType // Version is the version of the token pool. Version semver.Version // ExternalAdmin is the external administrator of the token pool on the registry. @@ -55,12 +115,12 @@ type TokenPoolInfo struct { func (t TokenPoolInfo) Validate() error { // Ensure that the inputted type is known - if _, ok := TokenPoolTypes[t.Type]; !ok { + if _, ok := shared.TokenPoolTypes[t.Type]; !ok { return fmt.Errorf("%s is not a known token pool type", t.Type) } // Ensure that the inputted version is known - if _, ok := TokenPoolVersions[t.Version]; !ok { + if _, ok := shared.TokenPoolVersions[t.Version]; !ok { return fmt.Errorf("%s is not a known token pool version", t.Version) } @@ -70,9 +130,9 @@ func (t TokenPoolInfo) Validate() error { // GetConfigOnRegistry fetches the token's config on the token admin registry. func (t TokenPoolInfo) GetConfigOnRegistry( ctx context.Context, - symbol TokenSymbol, - chain deployment.Chain, - state CCIPChainState, + symbol shared.TokenSymbol, + chain cldf.Chain, + state evm.CCIPChainState, ) (token_admin_registry.TokenAdminRegistryTokenConfig, error) { _, tokenAddress, err := t.GetPoolAndTokenAddress(ctx, symbol, chain, state) if err != nil { @@ -89,9 +149,9 @@ func (t TokenPoolInfo) GetConfigOnRegistry( // GetPoolAndTokenAddress returns pool bindings and the token address. func (t TokenPoolInfo) GetPoolAndTokenAddress( ctx context.Context, - symbol TokenSymbol, - chain deployment.Chain, - state CCIPChainState, + symbol shared.TokenSymbol, + chain cldf.Chain, + state evm.CCIPChainState, ) (*token_pool.TokenPool, common.Address, error) { tokenPoolAddress, ok := GetTokenPoolAddressFromSymbolTypeAndVersion(state, chain, symbol, t.Type, t.Version) if !ok { @@ -108,97 +168,44 @@ func (t TokenPoolInfo) GetPoolAndTokenAddress( return tokenPool, tokenAddress, nil } -// tokenPool defines behavior common to all token pools. -type tokenPool interface { - GetToken(opts *bind.CallOpts) (common.Address, error) - TypeAndVersion(*bind.CallOpts) (string, error) -} - -// tokenPoolMetadata defines the token pool version version and symbol of the corresponding token. -type tokenPoolMetadata struct { - Version semver.Version - Symbol TokenSymbol -} - -// NewTokenPoolWithMetadata returns a token pool along with its metadata. -func NewTokenPoolWithMetadata[P tokenPool]( - ctx context.Context, - newTokenPool func(address common.Address, backend bind.ContractBackend) (P, error), - poolAddress common.Address, - chainClient deployment.OnchainClient, -) (P, tokenPoolMetadata, error) { - pool, err := newTokenPool(poolAddress, chainClient) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to connect address %s with token pool bindings: %w", poolAddress, err) - } - tokenAddress, err := pool.GetToken(&bind.CallOpts{Context: ctx}) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to get token address from pool with address %s: %w", poolAddress, err) - } - typeAndVersionStr, err := pool.TypeAndVersion(&bind.CallOpts{Context: ctx}) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to get type and version from pool with address %s: %w", poolAddress, err) - } - _, versionStr, err := ccipconfig.ParseTypeAndVersion(typeAndVersionStr) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to parse type and version of pool with address %s: %w", poolAddress, err) - } - version, err := semver.NewVersion(versionStr) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed parsing version %s of pool with address %s: %w", versionStr, poolAddress, err) - } - token, err := erc20.NewERC20(tokenAddress, chainClient) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to connect address %s with ERC20 bindings: %w", tokenAddress, err) - } - symbol, err := token.Symbol(&bind.CallOpts{Context: ctx}) - if err != nil { - return pool, tokenPoolMetadata{}, fmt.Errorf("failed to fetch symbol from token with address %s: %w", tokenAddress, err) - } - return pool, tokenPoolMetadata{ - Symbol: TokenSymbol(symbol), - Version: *version, - }, nil -} - // GetTokenPoolAddressFromSymbolTypeAndVersion returns the token pool address in the environment linked to a particular symbol, type, and version func GetTokenPoolAddressFromSymbolTypeAndVersion( - chainState CCIPChainState, - chain deployment.Chain, - symbol TokenSymbol, - poolType cldf.ContractType, + chainState evm.CCIPChainState, + chain cldf.Chain, + symbol shared.TokenSymbol, + poolType deployment2.ContractType, version semver.Version, ) (common.Address, bool) { switch poolType { - case BurnMintTokenPool: + case shared.BurnMintTokenPool: if tokenPools, ok := chainState.BurnMintTokenPools[symbol]; ok { if tokenPool, ok := tokenPools[version]; ok { return tokenPool.Address(), true } } - case BurnFromMintTokenPool: + case shared.BurnFromMintTokenPool: if tokenPools, ok := chainState.BurnFromMintTokenPools[symbol]; ok { if tokenPool, ok := tokenPools[version]; ok { return tokenPool.Address(), true } } - case BurnWithFromMintTokenPool: + case shared.BurnWithFromMintTokenPool: if tokenPools, ok := chainState.BurnWithFromMintTokenPools[symbol]; ok { if tokenPool, ok := tokenPools[version]; ok { return tokenPool.Address(), true } } - case LockReleaseTokenPool: + case shared.LockReleaseTokenPool: if tokenPools, ok := chainState.LockReleaseTokenPools[symbol]; ok { if tokenPool, ok := tokenPools[version]; ok { return tokenPool.Address(), true } } - case USDCTokenPool: + case shared.USDCTokenPool: if tokenPool, ok := chainState.USDCTokenPools[version]; ok { return tokenPool.Address(), true } - case HybridLockReleaseUSDCTokenPool: + case shared.HybridLockReleaseUSDCTokenPool: if tokenPool, ok := chainState.USDCTokenPools[version]; ok { return tokenPool.Address(), true } @@ -206,85 +213,3 @@ func GetTokenPoolAddressFromSymbolTypeAndVersion( return utils.ZeroAddress, false } - -// TokenAdminRegistryChangesetConfig defines a config for all token admin registry actions. -type TokenAdminRegistryChangesetConfig struct { - // MCMS defines the delay to use for Timelock (if absent, the changeset will attempt to use the deployer key). - MCMS *proposalutils.TimelockConfig - // Pools defines the pools corresponding to the tokens we want to accept admin role for. - Pools map[uint64]map[TokenSymbol]TokenPoolInfo - // SkipOwnershipValidation indicates whether or not to skip admin ownership validation of token in the registry. - // it is skipped when propose admin,set admin and set pool operations are done as part of one changeset. - SkipOwnershipValidation bool -} - -// validateTokenAdminRegistryChangeset validates all token admin registry changesets. -func (c TokenAdminRegistryChangesetConfig) Validate( - env deployment.Environment, - mustBeOwner bool, - registryConfigCheck func( - config token_admin_registry.TokenAdminRegistryTokenConfig, - sender common.Address, - externalAdmin common.Address, - symbol TokenSymbol, - chain deployment.Chain, - ) error, -) error { - state, err := LoadOnchainState(env) - if err != nil { - return fmt.Errorf("failed to load onchain state: %w", err) - } - err = state.EnforceMCMSUsageIfProd(env.GetContext(), c.MCMS) - if err != nil { - return err - } - for chainSelector, symbolToPoolInfo := range c.Pools { - err := ValidateChain(env, state, chainSelector, c.MCMS) - if err != nil { - return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) - } - chain, ok := env.Chains[chainSelector] - if !ok { - return fmt.Errorf("chain with selector %d does not exist in environment", chainSelector) - } - chainState, ok := state.Chains[chainSelector] - if !ok { - return fmt.Errorf("%s does not exist in state", chain) - } - if tokenAdminRegistry := chainState.TokenAdminRegistry; tokenAdminRegistry == nil { - return fmt.Errorf("missing tokenAdminRegistry on %s", chain) - } - - // Validate that the token admin registry is owned by the address that will be actioning the transactions (i.e. Timelock or deployer key) - // However, most token admin registry actions aren't owner-protected. They just require you to be the admin. - if mustBeOwner { - if err := commoncs.ValidateOwnership(env.GetContext(), c.MCMS != nil, chain.DeployerKey.From, chainState.Timelock.Address(), chainState.TokenAdminRegistry); err != nil { - return fmt.Errorf("token admin registry failed ownership validation on %s: %w", chain, err) - } - } - for symbol, poolInfo := range symbolToPoolInfo { - if err := poolInfo.Validate(); err != nil { - return fmt.Errorf("failed to validate token pool info for %s token on chain %s: %w", symbol, chain, err) - } - - tokenConfigOnRegistry, err := poolInfo.GetConfigOnRegistry(env.GetContext(), symbol, chain, chainState) - if err != nil { - return fmt.Errorf("failed to get state of %s token on chain %s: %w", symbol, chain, err) - } - - fromAddress := chain.DeployerKey.From // "We" are either the deployer key or the timelock - if c.MCMS != nil { - fromAddress = chainState.Timelock.Address() - } - - if !c.SkipOwnershipValidation { - err = registryConfigCheck(tokenConfigOnRegistry, fromAddress, poolInfo.ExternalAdmin, symbol, chain) - if err != nil { - return err - } - } - } - } - - return nil -} diff --git a/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role.go b/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role.go index 4fa8d8d97a1..cef9a230e18 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role.go +++ b/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role.go @@ -9,18 +9,19 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) -var _ cldf.ChangeSet[changeset.TokenAdminRegistryChangesetConfig] = AcceptAdminRoleChangeset +var _ cldf.ChangeSet[TokenAdminRegistryChangesetConfig] = AcceptAdminRoleChangeset func validateAcceptAdminRole( config token_admin_registry.TokenAdminRegistryTokenConfig, sender common.Address, externalAdmin common.Address, - symbol changeset.TokenSymbol, - chain deployment.Chain, + symbol shared.TokenSymbol, + chain cldf.Chain, ) error { // We must be the pending administrator if config.PendingAdministrator != sender { @@ -30,16 +31,16 @@ func validateAcceptAdminRole( } // AcceptAdminRoleChangeset accepts admin rights for tokens on the token admin registry. -func AcceptAdminRoleChangeset(env deployment.Environment, c changeset.TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { +func AcceptAdminRoleChangeset(env cldf.Environment, c TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env, false, validateAcceptAdminRole); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid TokenAdminRegistryChangesetConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("accept admin role for tokens on token admin registries") + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("accept admin role for tokens on token admin registries") for chainSelector, tokenSymbolToPoolInfo := range c.Pools { chain := env.Chains[chainSelector] diff --git a/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role_test.go b/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role_test.go index 7e3b603bb94..582b5528580 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_accept_admin_role_test.go @@ -7,10 +7,12 @@ import ( "github.com/stretchr/testify/require" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -23,7 +25,7 @@ func TestAcceptAdminRoleChangeset_Validations(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -34,34 +36,34 @@ func TestAcceptAdminRoleChangeset_Validations(t *testing.T) { } tests := []struct { - Config changeset.TokenAdminRegistryChangesetConfig + Config v1_5_1.TokenAdminRegistryChangesetConfig ErrStr string Msg string }{ { Msg: "Chain selector is invalid", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ - 0: map[changeset.TokenSymbol]changeset.TokenPoolInfo{}, + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ + 0: map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{}, }, }, ErrStr: "failed to validate chain selector 0", }, { Msg: "Chain selector doesn't exist in environment", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ - 5009297550715157269: map[changeset.TokenSymbol]changeset.TokenPoolInfo{}, + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ + 5009297550715157269: map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{}, }, }, ErrStr: "does not exist in environment", }, { Msg: "Invalid pool type", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ - selectorA: map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ + selectorA: map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ testhelpers.TestTokenSymbol: { Type: "InvalidType", Version: deployment.Version1_5_1, @@ -73,12 +75,12 @@ func TestAcceptAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool version", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ - selectorA: map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ + selectorA: map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_0_0, }, }, @@ -88,12 +90,12 @@ func TestAcceptAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Not pending admin", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -129,18 +131,18 @@ func TestAcceptAdminRoleChangeset_Execution(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) registryOnA := state.Chains[selectorA].TokenAdminRegistry @@ -149,18 +151,18 @@ func TestAcceptAdminRoleChangeset_Execution(t *testing.T) { e, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -169,18 +171,18 @@ func TestAcceptAdminRoleChangeset_Execution(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, diff --git a/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e.go b/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e.go index 0e818948336..553bc5b051e 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e.go +++ b/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e.go @@ -19,8 +19,10 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc677" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -64,7 +66,7 @@ type E2ETokenAndPoolConfig struct { RateLimiterConfig RateLimiterPerChain // OverrideTokenSymbol is the token symbol to use to override against main symbol (ex: override to clCCIP-LnM when the main token symbol is CCIP-LnM) // WARNING: This should only be used in exceptional cases where the token symbol on a particular chain differs from the main tokenSymbol - OverrideTokenSymbol changeset.TokenSymbol + OverrideTokenSymbol shared.TokenSymbol } type AddTokenE2EConfig struct { @@ -75,13 +77,13 @@ type AddTokenE2EConfig struct { // User do not need to populate these fields. deployPool DeployTokenPoolContractsConfig configurePools ConfigureTokenPoolContractsConfig - configureTokenAdminReg changeset.TokenAdminRegistryChangesetConfig + configureTokenAdminReg TokenAdminRegistryChangesetConfig } // newConfigurePoolAndTokenAdminRegConfig populated internal fields in AddTokenE2EConfig. // It creates the configuration for deploying and configuring token pools and token admin registry. // It then validates the configuration. -func (c *AddTokenE2EConfig) newConfigurePoolAndTokenAdminRegConfig(e deployment.Environment, symbol changeset.TokenSymbol, timelockCfg *proposalutils.TimelockConfig) error { +func (c *AddTokenE2EConfig) newConfigurePoolAndTokenAdminRegConfig(e cldf.Environment, symbol shared.TokenSymbol, timelockCfg *proposalutils.TimelockConfig) error { c.deployPool = DeployTokenPoolContractsConfig{ TokenSymbol: symbol, NewPools: make(map[uint64]DeployTokenPoolInput), @@ -92,9 +94,9 @@ func (c *AddTokenE2EConfig) newConfigurePoolAndTokenAdminRegConfig(e deployment. MCMS: nil, // as token pools are deployed as part of the changeset, the pools will still be owned by the deployer key PoolUpdates: make(map[uint64]TokenPoolConfig), } - c.configureTokenAdminReg = changeset.TokenAdminRegistryChangesetConfig{ + c.configureTokenAdminReg = TokenAdminRegistryChangesetConfig{ MCMS: timelockCfg, - Pools: make(map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo), + Pools: make(map[uint64]map[shared.TokenSymbol]TokenPoolInfo), } for chain, poolCfg := range c.PoolConfig { c.deployPool.NewPools[chain] = *poolCfg.DeployPoolConfig @@ -107,9 +109,9 @@ func (c *AddTokenE2EConfig) newConfigurePoolAndTokenAdminRegConfig(e deployment. // Populate the TokenAdminRegistryChangesetConfig for each chain. if _, ok := c.configureTokenAdminReg.Pools[chain]; !ok { - c.configureTokenAdminReg.Pools[chain] = make(map[changeset.TokenSymbol]changeset.TokenPoolInfo) + c.configureTokenAdminReg.Pools[chain] = make(map[shared.TokenSymbol]TokenPoolInfo) } - c.configureTokenAdminReg.Pools[chain][symbol] = changeset.TokenPoolInfo{ + c.configureTokenAdminReg.Pools[chain][symbol] = TokenPoolInfo{ Version: poolCfg.PoolVersion, ExternalAdmin: poolCfg.ExternalAdmin, Type: poolCfg.DeployPoolConfig.Type, @@ -149,7 +151,7 @@ func (c *AddTokenE2EConfig) newDeployTokenPoolConfigAfterTokenDeployment(tokenAd type DeployTokenConfig struct { TokenName string - TokenSymbol changeset.TokenSymbol + TokenSymbol shared.TokenSymbol TokenDecimals uint8 // needed for BurnMintToken only MaxSupply *big.Int // needed for BurnMintToken only Type cldf.ContractType @@ -163,37 +165,37 @@ func (c *DeployTokenConfig) Validate() error { if c.TokenName == "" { return errors.New("token name must be defined") } - if c.TokenDecimals == 0 && c.Type == changeset.BurnMintToken { + if c.TokenDecimals == 0 && c.Type == shared.BurnMintToken { return errors.New("token decimals must be defined for BurnMintToken type") } - if c.MaxSupply == nil && c.Type == changeset.BurnMintToken { + if c.MaxSupply == nil && c.Type == shared.BurnMintToken { return errors.New("max supply must be defined for BurnMintToken type") } - if _, ok := changeset.TokenPoolTypes[c.PoolType]; !ok { + if _, ok := shared.TokenPoolTypes[c.PoolType]; !ok { return fmt.Errorf("token pool type not supported %s", c.PoolType) } - if _, ok := changeset.TokenTypes[c.Type]; !ok { + if _, ok := shared.TokenTypes[c.Type]; !ok { return fmt.Errorf("token type not supported %s", c.Type) } return nil } type AddTokensE2EConfig struct { - Tokens map[changeset.TokenSymbol]AddTokenE2EConfig + Tokens map[shared.TokenSymbol]AddTokenE2EConfig MCMS *proposalutils.TimelockConfig } -func addTokenE2EPreconditionValidation(e deployment.Environment, config AddTokensE2EConfig) error { +func addTokenE2EPreconditionValidation(e cldf.Environment, config AddTokensE2EConfig) error { if len(config.Tokens) == 0 { return nil } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for token, cfg := range config.Tokens { for chain, poolCfg := range cfg.PoolConfig { - if err := changeset.ValidateChain(e, state, chain, config.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chain, config.MCMS); err != nil { return fmt.Errorf("failed to validate chain %d: %w", chain, err) } if (poolCfg.DeployPoolConfig != nil) == (poolCfg.TokenDeploymentConfig != nil) { @@ -226,7 +228,7 @@ func addTokenE2EPreconditionValidation(e deployment.Environment, config AddToken return nil } -func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cldf.ChangesetOutput, error) { +func addTokenE2ELogic(env cldf.Environment, config AddTokensE2EConfig) (cldf.ChangesetOutput, error) { if len(config.Tokens) == 0 { return cldf.ChangesetOutput{}, nil } @@ -235,7 +237,7 @@ func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cl finalCSOut := &cldf.ChangesetOutput{ AddressBook: cldf.NewMemoryAddressBook(), } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -308,9 +310,9 @@ func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cl // find all tokens for which there is no external admin // for those tokens, accept the admin role and set the pool - updatedConfigureTokenAdminReg := changeset.TokenAdminRegistryChangesetConfig{ + updatedConfigureTokenAdminReg := TokenAdminRegistryChangesetConfig{ MCMS: config.MCMS, - Pools: make(map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo), + Pools: make(map[uint64]map[shared.TokenSymbol]TokenPoolInfo), // SkipOwnershipValidation is set to true as we are accepting admin role and setting token pool as part of one changeset SkipOwnershipValidation: true, } @@ -318,7 +320,7 @@ func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cl for symbol, info := range poolInfo { if info.ExternalAdmin == utils.ZeroAddress { if updatedConfigureTokenAdminReg.Pools[chain] == nil { - updatedConfigureTokenAdminReg.Pools[chain] = make(map[changeset.TokenSymbol]changeset.TokenPoolInfo) + updatedConfigureTokenAdminReg.Pools[chain] = make(map[shared.TokenSymbol]TokenPoolInfo) } updatedConfigureTokenAdminReg.Pools[chain][symbol] = info } @@ -348,7 +350,7 @@ func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cl // if there are multiple proposals, aggregate them so that we don't have to propose them separately if len(finalCSOut.MCMSTimelockProposals) > 1 { aggregatedProposals, err := proposalutils.AggregateProposals( - e, state.EVMMCMSStateByChain(), nil, finalCSOut.MCMSTimelockProposals, nil, + e, state.EVMMCMSStateByChain(), nil, finalCSOut.MCMSTimelockProposals, "Add Tokens E2E", config.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) @@ -358,14 +360,14 @@ func addTokenE2ELogic(env deployment.Environment, config AddTokensE2EConfig) (cl return *finalCSOut, nil } -func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployTokenConfig) (map[uint64]common.Address, cldf.AddressBook, error) { +func deployTokens(e cldf.Environment, tokenDeployCfg map[uint64]DeployTokenConfig) (map[uint64]common.Address, cldf.AddressBook, error) { ab := cldf.NewMemoryAddressBook() tokenAddresses := make(map[uint64]common.Address) // This will hold the token addresses for each chain. for selector, cfg := range tokenDeployCfg { switch cfg.Type { - case changeset.BurnMintToken: + case shared.BurnMintToken: token, err := cldf.DeployContract(e.Logger, e.Chains[selector], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( e.Chains[selector].DeployerKey, e.Chains[selector].Client, @@ -377,7 +379,7 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -403,9 +405,9 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke } tokenAddresses[selector] = token.Address - case changeset.ERC20Token: + case shared.ERC20Token: token, err := cldf.DeployContract(e.Logger, e.Chains[selector], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*erc20.ERC20] { + func(chain cldf.Chain) cldf.ContractDeploy[*erc20.ERC20] { tokenAddress, tx, token, err := erc20.DeployERC20( e.Chains[selector].DeployerKey, e.Chains[selector].Client, @@ -415,7 +417,7 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke return cldf.ContractDeploy[*erc20.ERC20]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.ERC20Token, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.ERC20Token, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -426,9 +428,9 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke return nil, ab, fmt.Errorf("failed to deploy ERC20 token %s on chain %d: %w", cfg.TokenName, selector, err) } tokenAddresses[selector] = token.Address - case changeset.ERC677Token: + case shared.ERC677Token: token, err := cldf.DeployContract(e.Logger, e.Chains[selector], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*erc677.ERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*erc677.ERC677] { tokenAddress, tx, token, err := erc677.DeployERC677( e.Chains[selector].DeployerKey, e.Chains[selector].Client, @@ -438,7 +440,7 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke return cldf.ContractDeploy[*erc677.ERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.ERC677Token, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.ERC677Token, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -459,7 +461,7 @@ func deployTokens(e deployment.Environment, tokenDeployCfg map[uint64]DeployToke // grantAccessToPool grants the token pool contract access to mint and burn tokens. func grantAccessToPool( ctx context.Context, - chain deployment.Chain, + chain cldf.Chain, tpAddress common.Address, tokenAddress common.Address, ) error { @@ -486,7 +488,7 @@ func grantAccessToPool( } // addMinterAndMintToken adds the minter role to the recipient and mints the specified amount of tokens to the recipient's address. -func addMinterAndMintToken(env deployment.Environment, selector uint64, token *burn_mint_erc677.BurnMintERC677, recipient common.Address, amount *big.Int) error { +func addMinterAndMintToken(env cldf.Environment, selector uint64, token *burn_mint_erc677.BurnMintERC677, recipient common.Address, amount *big.Int) error { deployerKey := env.Chains[selector].DeployerKey ctx := env.GetContext() // check if owner is the deployer key diff --git a/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e_test.go b/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e_test.go index c7cb931dba4..366d91236bb 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_add_token_e2e_test.go @@ -19,9 +19,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -74,7 +75,7 @@ func TestAddTokenE2E(t *testing.T) { t.Run(test.name, func(t *testing.T) { ctx := testutils.Context(t) var ( - e deployment.Environment + e cldf.Environment selectorA, selectorB uint64 mcmsConfig *proposalutils.TimelockConfig err error @@ -95,7 +96,7 @@ func TestAddTokenE2E(t *testing.T) { // we deploy the token as part of AddTokenE2E changeset tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithPrerequisiteDeploymentOnly(nil)) e = tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) selectors := e.AllChainSelectors() selectorA = selectors[0] @@ -142,7 +143,7 @@ func TestAddTokenE2E(t *testing.T) { // form the changeset input config for _, chain := range e.AllChainSelectors() { if addTokenE2EConfig.Tokens == nil { - addTokenE2EConfig.Tokens = make(map[changeset.TokenSymbol]v1_5_1.AddTokenE2EConfig) + addTokenE2EConfig.Tokens = make(map[shared.TokenSymbol]v1_5_1.AddTokenE2EConfig) } if _, ok := addTokenE2EConfig.Tokens[testhelpers.TestTokenSymbol]; !ok { addTokenE2EConfig.Tokens[testhelpers.TestTokenSymbol] = v1_5_1.AddTokenE2EConfig{ @@ -167,8 +168,8 @@ func TestAddTokenE2E(t *testing.T) { TokenSymbol: testhelpers.TestTokenSymbol, TokenDecimals: testhelpers.LocalTokenDecimals, MaxSupply: big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), - Type: changeset.BurnMintToken, - PoolType: changeset.BurnMintTokenPool, + Type: shared.BurnMintToken, + PoolType: shared.BurnMintTokenPool, MintTokenForRecipients: map[common.Address]*big.Int{ recipientAddress: topupAmount, }, @@ -176,7 +177,7 @@ func TestAddTokenE2E(t *testing.T) { } else { token := tokens[chain] deployPoolConfig = &v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: token.Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, } @@ -194,7 +195,7 @@ func TestAddTokenE2E(t *testing.T) { commonchangeset.Configure(v1_5_1.AddTokensE2E, addTokenE2EConfig)) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) // populate token details in case of token deployment as part of changeset diff --git a/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools.go b/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools.go index b1dccfe6722..9774a5fd73c 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools.go +++ b/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools.go @@ -14,8 +14,11 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -89,17 +92,17 @@ type SolChainUpdate struct { Metadata string } -func (c SolChainUpdate) GetSolanaTokenAndTokenPool(state changeset.SolCCIPChainState) (token solana.PublicKey, tokenPool solana.PublicKey, err error) { - metadata := changeset.CLLMetadata +func (c SolChainUpdate) GetSolanaTokenAndTokenPool(state solanastateview.CCIPChainState) (token solana.PublicKey, tokenPool solana.PublicKey, err error) { + metadata := shared.CLLMetadata if c.Metadata != "" { metadata = c.Metadata } var tokenPoolProgram solana.PublicKey switch c.Type { - case changeset.BurnMintTokenPool: + case shared.BurnMintTokenPool: tokenPoolProgram = state.BurnMintTokenPools[metadata] - case changeset.LockReleaseTokenPool: + case shared.LockReleaseTokenPool: tokenPoolProgram = state.LockReleaseTokenPools[metadata] default: err = fmt.Errorf("unknown solana token pool type %s", c.Type) @@ -120,7 +123,7 @@ func (c SolChainUpdate) GetSolanaTokenAndTokenPool(state changeset.SolCCIPChainS return } -func (c SolChainUpdate) Validate(state changeset.SolCCIPChainState) error { +func (c SolChainUpdate) Validate(state solanastateview.CCIPChainState) error { if err := validateRateLimiterConfig(c.RateLimiterConfig.Inbound); err != nil { return fmt.Errorf("validation of inbound rate limiter config for solana chain failed: %w", err) } @@ -147,18 +150,18 @@ type TokenPoolConfig struct { Version semver.Version // OverrideTokenSymbol is the token symbol to use to override against main symbol (ex: override to clCCIP-LnM when the main token symbol is CCIP-LnM) // WARNING: This should only be used in exceptional cases where the token symbol on a particular chain differs from the main tokenSymbol - OverrideTokenSymbol changeset.TokenSymbol + OverrideTokenSymbol shared.TokenSymbol } -func (c TokenPoolConfig) Validate(ctx context.Context, chain deployment.Chain, ccipState changeset.CCIPOnChainState, useMcms bool, tokenSymbol changeset.TokenSymbol) error { +func (c TokenPoolConfig) Validate(ctx context.Context, chain cldf.Chain, ccipState stateview.CCIPOnChainState, useMcms bool, tokenSymbol shared.TokenSymbol) error { chainState := ccipState.Chains[chain.Selector] // Ensure that the inputted type is known - if _, ok := changeset.TokenPoolTypes[c.Type]; !ok { + if _, ok := shared.TokenPoolTypes[c.Type]; !ok { return fmt.Errorf("%s is not a known token pool type", c.Type) } // Ensure that the inputted version is known - if _, ok := changeset.TokenPoolVersions[c.Version]; !ok { + if _, ok := shared.TokenPoolVersions[c.Version]; !ok { return fmt.Errorf("%s is not a known token pool version", c.Version) } @@ -167,7 +170,7 @@ func (c TokenPoolConfig) Validate(ctx context.Context, chain deployment.Chain, c } // Ensure that a pool with given symbol, type and version is known to the environment - tokenPoolAddress, ok := changeset.GetTokenPoolAddressFromSymbolTypeAndVersion(chainState, chain, tokenSymbol, c.Type, c.Version) + tokenPoolAddress, ok := GetTokenPoolAddressFromSymbolTypeAndVersion(chainState, chain, tokenSymbol, c.Type, c.Version) if !ok { return fmt.Errorf("token pool does not exist on %s with symbol %s, type %s, and version %s", chain.String(), tokenSymbol, c.Type, c.Version) } @@ -207,19 +210,19 @@ type ConfigureTokenPoolContractsConfig struct { // PoolUpdates defines the changes that we want to make to the token pool on a chain PoolUpdates map[uint64]TokenPoolConfig // Symbol is the symbol of the token of interest. - TokenSymbol changeset.TokenSymbol + TokenSymbol shared.TokenSymbol } -func (c ConfigureTokenPoolContractsConfig) Validate(env deployment.Environment) error { +func (c ConfigureTokenPoolContractsConfig) Validate(env cldf.Environment) error { if c.TokenSymbol == "" { return errors.New("token symbol must be defined") } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for chainSelector, poolUpdate := range c.PoolUpdates { - err := deployment.IsValidChainSelector(chainSelector) + err := cldf.IsValidChainSelector(chainSelector) if err != nil { return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) } @@ -266,16 +269,16 @@ func (c ConfigureTokenPoolContractsConfig) Validate(env deployment.Environment) // ConfigureTokenPoolContractsChangeset configures pools for a given token across multiple chains. // The outputted MCMS proposal will update chain configurations on each pool, encompassing new chain additions and rate limit changes. // Removing chain support is not in scope for this changeset. -func ConfigureTokenPoolContractsChangeset(env deployment.Environment, c ConfigureTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { +func ConfigureTokenPoolContractsChangeset(env cldf.Environment, c ConfigureTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid ConfigureTokenPoolContractsConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext(fmt.Sprintf("configure %s token pools", c.TokenSymbol)) + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext(fmt.Sprintf("configure %s token pools", c.TokenSymbol)) for chainSelector := range c.PoolUpdates { chain := env.Chains[chainSelector] @@ -307,8 +310,8 @@ func ConfigureTokenPoolContractsChangeset(env deployment.Environment, c Configur func configureTokenPool( ctx context.Context, opts *bind.TransactOpts, - chains map[uint64]deployment.Chain, - state changeset.CCIPOnChainState, + chains map[uint64]cldf.Chain, + state stateview.CCIPOnChainState, config ConfigureTokenPoolContractsConfig, chainSelector uint64, ) error { @@ -460,13 +463,13 @@ func configureTokenPool( // getTokenStateFromPool fetches the token config from the registry given the pool address func GetTokenStateFromPoolEVM( ctx context.Context, - symbol changeset.TokenSymbol, + symbol shared.TokenSymbol, poolType cldf.ContractType, version semver.Version, - chain deployment.Chain, - state changeset.CCIPChainState, + chain cldf.Chain, + state evm.CCIPChainState, ) (*token_pool.TokenPool, common.Address, token_admin_registry.TokenAdminRegistryTokenConfig, error) { - tokenPoolAddress, ok := changeset.GetTokenPoolAddressFromSymbolTypeAndVersion(state, chain, symbol, poolType, version) + tokenPoolAddress, ok := GetTokenPoolAddressFromSymbolTypeAndVersion(state, chain, symbol, poolType, version) if !ok { return nil, utils.ZeroAddress, token_admin_registry.TokenAdminRegistryTokenConfig{}, fmt.Errorf("token pool does not exist on %s with symbol %s, type %s, and version %s", chain.String(), symbol, poolType, version) } diff --git a/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools_test.go b/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools_test.go index bab610b3b6a..eb97024e3e3 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_configure_token_pools_test.go @@ -20,10 +20,11 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" changeset_solana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -50,11 +51,11 @@ func createSymmetricRateLimits(rate int64, capacity int64) v1_5_1.RateLimiterCon // validateMemberOfTokenPoolPair performs checks required to validate that a token pool is fully configured for cross-chain transfer. func validateMemberOfTokenPoolPair( t *testing.T, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, tokenPool *token_pool.TokenPool, expectedRemotePools []common.Address, tokens map[uint64]*cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677], - tokenSymbol changeset.TokenSymbol, + tokenSymbol shared.TokenSymbol, chainSelector uint64, rate *big.Int, capacity *big.Int, @@ -107,7 +108,7 @@ func validateMemberOfTokenPoolPair( } } -func validateSolanaConfig(t *testing.T, state changeset.CCIPOnChainState, solChainUpdates map[uint64]v1_5_1.SolChainUpdate, selector uint64, solanaSelector uint64) { +func validateSolanaConfig(t *testing.T, state stateview.CCIPOnChainState, solChainUpdates map[uint64]v1_5_1.SolChainUpdate, selector uint64, solanaSelector uint64) { tokenPool := state.Chains[selector].BurnMintTokenPools[testhelpers.TestTokenSymbol][deployment.Version1_5_1] isSupported, err := tokenPool.IsSupportedChain(nil, solanaSelector) require.NoError(t, err) @@ -196,13 +197,13 @@ func TestValidateTokenPoolConfig(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, true) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) tests := []struct { @@ -219,14 +220,14 @@ func TestValidateTokenPoolConfig(t *testing.T) { { Msg: "Pool version is invalid", TokenPoolConfig: v1_5_1.TokenPoolConfig{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, }, ErrStr: "is not a known token pool version", }, { Msg: "Pool is not owned by required address", TokenPoolConfig: v1_5_1.TokenPoolConfig{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, ErrStr: "failed ownership validation", @@ -251,7 +252,7 @@ func TestValidateConfigureTokenPoolContractsConfig(t *testing.T) { }) tests := []struct { - TokenSymbol changeset.TokenSymbol + TokenSymbol shared.TokenSymbol Input v1_5_1.ConfigureTokenPoolContractsConfig ErrStr string Msg string @@ -423,12 +424,12 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -436,20 +437,20 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AcceptLiquidity: &acceptLiquidity, }, selectorB: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AcceptLiquidity: &acceptLiquidity, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) lockReleaseA, _ := token_pool.NewTokenPool(state.Chains[selectorA].LockReleaseTokenPools[testhelpers.TestTokenSymbol][deployment.Version1_5_1].Address(), e.Chains[selectorA].Client) @@ -487,14 +488,14 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { MCMS: mcmsConfig, PoolUpdates: map[uint64]v1_5_1.TokenPoolConfig{ selectorA: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, ChainUpdates: v1_5_1.RateLimiterPerChain{ selectorB: test.RegistrationPass.SelectorA2B, }, }, selectorB: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, ChainUpdates: v1_5_1.RateLimiterPerChain{ selectorA: test.RegistrationPass.SelectorB2A, @@ -505,18 +506,18 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, @@ -525,18 +526,18 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, @@ -545,18 +546,18 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.SetPoolChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, Version: deployment.Version1_5_1, }, }, @@ -594,13 +595,13 @@ func TestValidateConfigureTokenPoolContracts(t *testing.T) { if test.UpdatePass != nil { // Only configure, do not update registry - aType := changeset.LockReleaseTokenPool + aType := shared.LockReleaseTokenPool if test.UpdatePass.UpdatePoolOnA { - aType = changeset.BurnMintTokenPool + aType = shared.BurnMintTokenPool } - bType := changeset.LockReleaseTokenPool + bType := shared.LockReleaseTokenPool if test.UpdatePass.UpdatePoolOnB { - bType = changeset.BurnMintTokenPool + bType = shared.BurnMintTokenPool } e, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( @@ -693,7 +694,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { /////////////////////////// for _, selector := range evmSelectors { token, err := cldf.DeployContract(e.Logger, e.Chains[selector], addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( e.Chains[selector].DeployerKey, e.Chains[selector].Client, @@ -705,7 +706,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -714,7 +715,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { require.NoError(t, err) e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selector: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: token.Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -730,14 +731,14 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { cldf.CreateLegacyChangeSet(changeset_solana.DeploySolanaToken), changeset_solana.DeploySolanaTokenConfig{ ChainSelector: selector, - TokenProgramName: changeset.SPL2022Tokens, + TokenProgramName: shared.SPL2022Tokens, TokenDecimals: testhelpers.LocalTokenDecimals, TokenSymbol: string(testhelpers.TestTokenSymbol), }, ), ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) tokenAddress := state.SolChains[selector].SPL2022Tokens[0] bnm := solTestTokenPool.BurnAndMint_PoolType @@ -754,7 +755,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { require.NoError(t, err) } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) ///////////////////////////// @@ -764,7 +765,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { solChainUpdates := make(map[uint64]v1_5_1.SolChainUpdate) for _, remoteSelector := range solanaSelectors { solChainUpdates[remoteSelector] = v1_5_1.SolChainUpdate{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: state.SolChains[remoteSelector].SPL2022Tokens[0].String(), RateLimiterConfig: testhelpers.CreateSymmetricRateLimits(0, 0), } @@ -776,7 +777,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { TokenSymbol: testhelpers.TestTokenSymbol, PoolUpdates: map[uint64]v1_5_1.TokenPoolConfig{ selector: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, SolChainUpdates: solChainUpdates, }, @@ -798,7 +799,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { solChainUpdates := make(map[uint64]v1_5_1.SolChainUpdate) for _, remoteSelector := range solanaSelectors { solChainUpdates[remoteSelector] = v1_5_1.SolChainUpdate{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: state.SolChains[remoteSelector].SPL2022Tokens[0].String(), RateLimiterConfig: testhelpers.CreateSymmetricRateLimits(100, 1000), } @@ -811,7 +812,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { TokenSymbol: testhelpers.TestTokenSymbol, PoolUpdates: map[uint64]v1_5_1.TokenPoolConfig{ selector: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, SolChainUpdates: solChainUpdates, }, @@ -837,14 +838,14 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { cldf.CreateLegacyChangeSet(changeset_solana.DeploySolanaToken), changeset_solana.DeploySolanaTokenConfig{ ChainSelector: selector, - TokenProgramName: changeset.SPL2022Tokens, + TokenProgramName: shared.SPL2022Tokens, TokenDecimals: testhelpers.LocalTokenDecimals, TokenSymbol: string(testhelpers.TestTokenSymbol), }, ), ) require.NoError(t, err) - onchainState, err := changeset.LoadOnchainState(e) + onchainState, err := stateview.LoadOnchainState(e) require.NoError(t, err) bnm := solTestTokenPool.BurnAndMint_PoolType for _, tokenAddress := range onchainState.SolChains[selector].SPL2022Tokens { @@ -873,7 +874,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { solChainUpdates := make(map[uint64]v1_5_1.SolChainUpdate) for remoteSelector, remoteTokenAddress := range remoteTokenAddresses { solChainUpdates[remoteSelector] = v1_5_1.SolChainUpdate{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: remoteTokenAddress.String(), RateLimiterConfig: testhelpers.CreateSymmetricRateLimits(0, 0), } @@ -885,7 +886,7 @@ func TestValidateConfigureTokenPoolContractsForSolana(t *testing.T) { TokenSymbol: testhelpers.TestTokenSymbol, PoolUpdates: map[uint64]v1_5_1.TokenPoolConfig{ selector: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, SolChainUpdates: solChainUpdates, }, diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory.go index b6ea3622fc2..a3c4589335e 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory.go @@ -10,7 +10,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) // DeployTokenPoolFactoryChangeset is a changeset that deploys the TokenPoolFactory contract on multiple chains. @@ -27,14 +28,14 @@ type DeployTokenPoolFactoryConfig struct { RegistryModule1_6Addresses map[uint64]common.Address } -func deployTokenPoolFactoryPrecondition(e deployment.Environment, config DeployTokenPoolFactoryConfig) error { - state, err := changeset.LoadOnchainState(e) +func deployTokenPoolFactoryPrecondition(e cldf.Environment, config DeployTokenPoolFactoryConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for _, chainSel := range config.Chains { - err := changeset.ValidateChain(e, state, chainSel, nil) + err := stateview.ValidateChain(e, state, chainSel, nil) if err != nil { return fmt.Errorf("failed to validate chain with selector %d: %w", chainSel, err) } @@ -79,9 +80,9 @@ func deployTokenPoolFactoryPrecondition(e deployment.Environment, config DeployT return nil } -func deployTokenPoolFactoryLogic(e deployment.Environment, config DeployTokenPoolFactoryConfig) (cldf.ChangesetOutput, error) { +func deployTokenPoolFactoryLogic(e cldf.Environment, config DeployTokenPoolFactoryConfig) (cldf.ChangesetOutput, error) { addressBook := cldf.NewMemoryAddressBook() - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -96,7 +97,7 @@ func deployTokenPoolFactoryLogic(e deployment.Environment, config DeployTokenPoo } tokenPoolFactory, err := cldf.DeployContract(e.Logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*token_pool_factory.TokenPoolFactory] { + func(chain cldf.Chain) cldf.ContractDeploy[*token_pool_factory.TokenPoolFactory] { address, tx, tokenPoolFactory, err := token_pool_factory.DeployTokenPoolFactory( chain.DeployerKey, chain.Client, @@ -110,7 +111,7 @@ func deployTokenPoolFactoryLogic(e deployment.Environment, config DeployTokenPoo Address: address, Contract: tokenPoolFactory, Tx: tx, - Tv: cldf.NewTypeAndVersion(changeset.TokenPoolFactory, deployment.Version1_5_1), + Tv: cldf.NewTypeAndVersion(shared.TokenPoolFactory, deployment.Version1_5_1), Err: err, } }, diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory_test.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory_test.go index b20cc99c4fc..23c3a2b247f 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pool_factory_test.go @@ -16,8 +16,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -32,11 +33,11 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { ForgetPrerequisites bool MultipleRegistryModules bool ExpectedErr string - ConfigFn func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig + ConfigFn func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig }{ { Msg: "should deploy token pool factory on all chains", - ConfigFn: func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { + ConfigFn: func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { return v1_5_1.DeployTokenPoolFactoryConfig{ Chains: selectors, } @@ -45,7 +46,7 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { { Msg: "should fail to deploy due to missing prereqs", ForgetPrerequisites: true, - ConfigFn: func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { + ConfigFn: func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { return v1_5_1.DeployTokenPoolFactoryConfig{ Chains: selectors, } @@ -55,7 +56,7 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { { Msg: "should fail to deploy due to multiple registry modules", MultipleRegistryModules: true, - ConfigFn: func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { + ConfigFn: func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { return v1_5_1.DeployTokenPoolFactoryConfig{ Chains: selectors, } @@ -65,7 +66,7 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { { Msg: "should fail when a registry module is specified incorrectly", MultipleRegistryModules: true, - ConfigFn: func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { + ConfigFn: func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { addresses := make(map[uint64]common.Address, len(selectors)) for _, selector := range selectors { addresses[selector] = utils.RandomAddress() @@ -80,7 +81,7 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { { Msg: "should successfully deploy when a registry module is specified", MultipleRegistryModules: true, - ConfigFn: func(selectors []uint64, state changeset.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { + ConfigFn: func(selectors []uint64, state stateview.CCIPOnChainState) v1_5_1.DeployTokenPoolFactoryConfig { addresses := make(map[uint64]common.Address, len(selectors)) for _, selector := range selectors { addresses[selector] = state.Chains[selector].RegistryModules1_6[0].Address() @@ -106,18 +107,18 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { for _, selector := range selectors { // Deploy token admin registry tokenAdminRegistry, err := cldf.DeployContract(e.Logger, e.Chains[selector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( chain.DeployerKey, chain.Client) return cldf.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.TokenAdminRegistry, deployment.Version1_5_0), Err: err2, + Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.TokenAdminRegistry, deployment.Version1_5_0), Err: err2, } }) require.NoError(t, err, "failed to deploy token admin registry") // Deploy RMN proxy rmnProxy, err := cldf.DeployContract(lggr, e.Chains[selector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy] { + func(chain cldf.Chain) cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy] { rmnProxyAddr, tx2, rmnProxy2, err2 := rmn_proxy_contract.DeployRMNProxy( chain.DeployerKey, chain.Client, @@ -126,13 +127,13 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { utils.RandomAddress(), ) return cldf.ContractDeploy[*rmn_proxy_contract.RMNProxy]{ - Address: rmnProxyAddr, Contract: rmnProxy2, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.ARMProxy, deployment.Version1_0_0), Err: err2, + Address: rmnProxyAddr, Contract: rmnProxy2, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.ARMProxy, deployment.Version1_0_0), Err: err2, } }) require.NoError(t, err, "failed to deploy RMN proxy") // Deploy router _, err = cldf.DeployContract(e.Logger, e.Chains[selector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*router.Router] { + func(chain cldf.Chain) cldf.ContractDeploy[*router.Router] { routerAddr, tx2, routerC, err2 := router.DeployRouter( chain.DeployerKey, chain.Client, @@ -142,20 +143,20 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { rmnProxy.Address, ) return cldf.ContractDeploy[*router.Router]{ - Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.Router, deployment.Version1_2_0), Err: err2, + Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.Router, deployment.Version1_2_0), Err: err2, } }) require.NoError(t, err, "failed to deploy router") // Deploy registry module _, err = cldf.DeployContract(e.Logger, e.Chains[selector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { + func(chain cldf.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( chain.DeployerKey, chain.Client, tokenAdminRegistry.Address, ) return cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.RegistryModule, deployment.Version1_6_0), Err: err2, + Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.RegistryModule, deployment.Version1_6_0), Err: err2, } }) require.NoError(t, err, "failed to deploy registry module") @@ -164,24 +165,24 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { if test.MultipleRegistryModules { // Add a new registry module to each chain - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "failed to load onchain state") for _, selector := range selectors { _, err := cldf.DeployContract(e.Logger, e.Chains[selector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { + func(chain cldf.Chain) cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( chain.DeployerKey, chain.Client, state.Chains[selector].TokenAdminRegistry.Address()) return cldf.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.RegistryModule, deployment.Version1_6_0), Err: err2, + Address: regModAddr, Contract: regMod, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.RegistryModule, deployment.Version1_6_0), Err: err2, } }) require.NoError(t, err, "failed to deploy registry module") } } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "failed to load onchain state") e, err = commonchangeset.Apply(t, e, nil, commonchangeset.Configure( @@ -194,7 +195,7 @@ func TestDeployTokenPoolFactoryChangeset(t *testing.T) { } require.NoError(t, err, "failed to apply DeployTokenPoolFactoryChangeset") - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err, "failed to load onchain state") for _, chainSel := range selectors { diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools.go index 3c4ca11d790..1571dc335ca 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools.go @@ -18,8 +18,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_mint_token_pool" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_with_from_mint_token_pool" @@ -45,7 +46,7 @@ type DeployTokenPoolInput struct { AcceptLiquidity *bool } -func (i DeployTokenPoolInput) Validate(ctx context.Context, chain deployment.Chain, state changeset.CCIPChainState, tokenSymbol changeset.TokenSymbol) error { +func (i DeployTokenPoolInput) Validate(ctx context.Context, chain cldf.Chain, state evm.CCIPChainState, tokenSymbol shared.TokenSymbol) error { // Ensure that required fields are populated if i.TokenAddress == utils.ZeroAddress { return errors.New("token address must be defined") @@ -55,7 +56,7 @@ func (i DeployTokenPoolInput) Validate(ctx context.Context, chain deployment.Cha } // Validate that the type is known - if _, ok := changeset.TokenPoolTypes[i.Type]; !ok { + if _, ok := shared.TokenPoolTypes[i.Type]; !ok { return fmt.Errorf("requested token pool type %s is unknown", i.Type) } @@ -82,17 +83,17 @@ func (i DeployTokenPoolInput) Validate(ctx context.Context, chain deployment.Cha } // Validate acceptLiquidity based on requested pool type - if i.Type == changeset.LockReleaseTokenPool && i.AcceptLiquidity == nil { + if i.Type == shared.LockReleaseTokenPool && i.AcceptLiquidity == nil { return errors.New("accept liquidity must be defined for lock release pools") } - if i.Type != changeset.LockReleaseTokenPool && i.AcceptLiquidity != nil { + if i.Type != shared.LockReleaseTokenPool && i.AcceptLiquidity != nil { return errors.New("accept liquidity must be nil for burn mint pools") } // We should check if a token pool with this type, version, and symbol already exists - _, ok := changeset.GetTokenPoolAddressFromSymbolTypeAndVersion(state, chain, tokenSymbol, i.Type, changeset.CurrentTokenPoolVersion) + _, ok := GetTokenPoolAddressFromSymbolTypeAndVersion(state, chain, tokenSymbol, i.Type, shared.CurrentTokenPoolVersion) if ok { - return fmt.Errorf("token pool with type %s and version %s already exists for %s on %s", i.Type, changeset.CurrentTokenPoolVersion, tokenSymbol, chain) + return fmt.Errorf("token pool with type %s and version %s already exists for %s on %s", i.Type, shared.CurrentTokenPoolVersion, tokenSymbol, chain) } return nil @@ -101,25 +102,25 @@ func (i DeployTokenPoolInput) Validate(ctx context.Context, chain deployment.Cha // DeployTokenPoolContractsConfig defines the token pool contracts that need to be deployed on each chain. type DeployTokenPoolContractsConfig struct { // Symbol is the symbol of the token for which we are deploying a pool. - TokenSymbol changeset.TokenSymbol + TokenSymbol shared.TokenSymbol // NewPools defines the per-chain configuration of each new pool NewPools map[uint64]DeployTokenPoolInput // IsTestRouter indicates whether or not the test router should be used. IsTestRouter bool } -func (c DeployTokenPoolContractsConfig) Validate(env deployment.Environment) error { +func (c DeployTokenPoolContractsConfig) Validate(env cldf.Environment) error { // Ensure that required fields are populated - if c.TokenSymbol == changeset.TokenSymbol("") { + if c.TokenSymbol == shared.TokenSymbol("") { return errors.New("token symbol must be defined") } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for chainSelector, poolConfig := range c.NewPools { - err := deployment.IsValidChainSelector(chainSelector) + err := cldf.IsValidChainSelector(chainSelector) if err != nil { return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) } @@ -152,13 +153,13 @@ func (c DeployTokenPoolContractsConfig) Validate(env deployment.Environment) err } // DeployTokenPoolContractsChangeset deploys new pools for a given token across multiple chains. -func DeployTokenPoolContractsChangeset(env deployment.Environment, c DeployTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { +func DeployTokenPoolContractsChangeset(env cldf.Environment, c DeployTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid DeployTokenPoolContractsConfig: %w", err) } newAddresses := cldf.NewMemoryAddressBook() - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -174,7 +175,7 @@ func DeployTokenPoolContractsChangeset(env deployment.Environment, c DeployToken if err != nil { return fmt.Errorf("failed to deploy token pool contract: %w", err) } - if poolConfig.Type == changeset.BurnMintTokenPool { + if poolConfig.Type == shared.BurnMintTokenPool { err := grantAccessToPool(env.GetContext(), chain, contract.Address, poolConfig.TokenAddress) if err != nil { return fmt.Errorf("failed to grant token pool access to token: %s %w", poolConfig.TokenAddress, err) @@ -197,8 +198,8 @@ func DeployTokenPoolContractsChangeset(env deployment.Environment, c DeployToken // deployTokenPool deploys a token pool contract based on a given type & configuration. func deployTokenPool( logger logger.Logger, - chain deployment.Chain, - chainState changeset.CCIPChainState, + chain cldf.Chain, + chainState evm.CCIPChainState, addressBook cldf.AddressBook, poolConfig DeployTokenPoolInput, isTestRouter bool, @@ -210,27 +211,27 @@ func deployTokenPool( rmnProxy := chainState.RMNProxy return cldf.DeployContract(logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*token_pool.TokenPool] { + func(chain cldf.Chain) cldf.ContractDeploy[*token_pool.TokenPool] { var tpAddr common.Address var tx *types.Transaction var err error switch poolConfig.Type { - case changeset.BurnMintTokenPool: + case shared.BurnMintTokenPool: tpAddr, tx, _, err = burn_mint_token_pool.DeployBurnMintTokenPool( chain.DeployerKey, chain.Client, poolConfig.TokenAddress, poolConfig.LocalTokenDecimals, poolConfig.AllowList, rmnProxy.Address(), router.Address(), ) - case changeset.BurnWithFromMintTokenPool: + case shared.BurnWithFromMintTokenPool: tpAddr, tx, _, err = burn_with_from_mint_token_pool.DeployBurnWithFromMintTokenPool( chain.DeployerKey, chain.Client, poolConfig.TokenAddress, poolConfig.LocalTokenDecimals, poolConfig.AllowList, rmnProxy.Address(), router.Address(), ) - case changeset.BurnFromMintTokenPool: + case shared.BurnFromMintTokenPool: tpAddr, tx, _, err = burn_from_mint_token_pool.DeployBurnFromMintTokenPool( chain.DeployerKey, chain.Client, poolConfig.TokenAddress, poolConfig.LocalTokenDecimals, poolConfig.AllowList, rmnProxy.Address(), router.Address(), ) - case changeset.LockReleaseTokenPool: + case shared.LockReleaseTokenPool: tpAddr, tx, _, err = lock_release_token_pool.DeployLockReleaseTokenPool( chain.DeployerKey, chain.Client, poolConfig.TokenAddress, poolConfig.LocalTokenDecimals, poolConfig.AllowList, rmnProxy.Address(), *poolConfig.AcceptLiquidity, router.Address(), @@ -243,7 +244,7 @@ func deployTokenPool( return cldf.ContractDeploy[*token_pool.TokenPool]{ Address: tpAddr, Contract: tp, - Tv: cldf.NewTypeAndVersion(poolConfig.Type, changeset.CurrentTokenPoolVersion), + Tv: cldf.NewTypeAndVersion(poolConfig.Type, shared.CurrentTokenPoolVersion), Tx: tx, Err: err, } diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools_test.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools_test.go index 3aa3a057ec1..5bd6a5b6b42 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_token_pools_test.go @@ -15,9 +15,11 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -34,7 +36,7 @@ func TestValidateDeployTokenPoolContractsConfig(t *testing.T) { tests := []struct { Msg string - TokenSymbol changeset.TokenSymbol + TokenSymbol shared.TokenSymbol Input v1_5_1.DeployTokenPoolContractsConfig ErrStr string }{ @@ -103,7 +105,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -111,7 +113,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { tests := []struct { Msg string - Symbol changeset.TokenSymbol + Symbol shared.TokenSymbol Input v1_5_1.DeployTokenPoolInput ErrStr string }{ @@ -138,7 +140,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { { Msg: "Token address is invalid", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: invalidAddress, }, ErrStr: fmt.Sprintf("failed to fetch symbol from token with address %s", invalidAddress), @@ -147,7 +149,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { Msg: "Token symbol mismatch", Symbol: "WRONG", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, }, ErrStr: fmt.Sprintf("symbol of token with address %s (%s) does not match expected symbol (WRONG)", tokens[selectorA].Address, testhelpers.TestTokenSymbol), @@ -156,7 +158,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { Msg: "Token decimal mismatch", Symbol: testhelpers.TestTokenSymbol, Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: 17, }, @@ -166,7 +168,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { Msg: "Accept liquidity should be defined", Symbol: testhelpers.TestTokenSymbol, Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -176,7 +178,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { Msg: "Accept liquidity should be omitted", Symbol: testhelpers.TestTokenSymbol, Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AcceptLiquidity: &acceptLiquidity, @@ -187,7 +189,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { Msg: "Token pool already exists", Symbol: testhelpers.TestTokenSymbol, Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -197,7 +199,7 @@ func TestValidateDeployTokenPoolInput(t *testing.T) { for _, test := range tests { t.Run(test.Msg, func(t *testing.T) { - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) err = test.Input.Validate(context.Background(), e.Chains[selectorA], state.Chains[selectorA], test.Symbol) @@ -218,16 +220,16 @@ func TestDeployTokenPoolContracts(t *testing.T) { tests := []struct { Msg string Input v1_5_1.DeployTokenPoolInput - GetPool func(changeset.CCIPChainState) Ownable + GetPool func(evm.CCIPChainState) Ownable }{ { Msg: "BurnMint", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AllowList: []common.Address{}, }, - GetPool: func(cs changeset.CCIPChainState) Ownable { + GetPool: func(cs evm.CCIPChainState) Ownable { tokenPools, ok := cs.BurnMintTokenPools[testhelpers.TestTokenSymbol] require.True(t, ok) require.Len(t, tokenPools, 1) @@ -237,11 +239,11 @@ func TestDeployTokenPoolContracts(t *testing.T) { { Msg: "BurnWithFromMint", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnWithFromMintTokenPool, + Type: shared.BurnWithFromMintTokenPool, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AllowList: []common.Address{}, }, - GetPool: func(cs changeset.CCIPChainState) Ownable { + GetPool: func(cs evm.CCIPChainState) Ownable { tokenPools, ok := cs.BurnWithFromMintTokenPools[testhelpers.TestTokenSymbol] require.True(t, ok) require.Len(t, tokenPools, 1) @@ -251,11 +253,11 @@ func TestDeployTokenPoolContracts(t *testing.T) { { Msg: "BurnFromMint", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnFromMintTokenPool, + Type: shared.BurnFromMintTokenPool, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AllowList: []common.Address{}, }, - GetPool: func(cs changeset.CCIPChainState) Ownable { + GetPool: func(cs evm.CCIPChainState) Ownable { tokenPools, ok := cs.BurnFromMintTokenPools[testhelpers.TestTokenSymbol] require.True(t, ok) require.Len(t, tokenPools, 1) @@ -265,12 +267,12 @@ func TestDeployTokenPoolContracts(t *testing.T) { { Msg: "LockRelease", Input: v1_5_1.DeployTokenPoolInput{ - Type: changeset.LockReleaseTokenPool, + Type: shared.LockReleaseTokenPool, LocalTokenDecimals: testhelpers.LocalTokenDecimals, AllowList: []common.Address{}, AcceptLiquidity: &acceptLiquidity, }, - GetPool: func(cs changeset.CCIPChainState) Ownable { + GetPool: func(cs evm.CCIPChainState) Ownable { tokenPools, ok := cs.LockReleaseTokenPools[testhelpers.TestTokenSymbol] require.True(t, ok) require.Len(t, tokenPools, 1) @@ -298,7 +300,7 @@ func TestDeployTokenPoolContracts(t *testing.T) { ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) pool := test.GetPool(state.Chains[selectorA]) diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools.go index 0e0024efe13..6ec099482a8 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools.go @@ -17,7 +17,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" ) var _ cldf.ChangeSet[DeployUSDCTokenPoolContractsConfig] = DeployUSDCTokenPoolContractsChangeset @@ -33,7 +35,7 @@ type DeployUSDCTokenPoolInput struct { AllowList []common.Address } -func (i DeployUSDCTokenPoolInput) Validate(ctx context.Context, chain deployment.Chain, state changeset.CCIPChainState) error { +func (i DeployUSDCTokenPoolInput) Validate(ctx context.Context, chain cldf.Chain, state evm.CCIPChainState) error { // Ensure that required fields are populated if i.TokenAddress == utils.ZeroAddress { return errors.New("token address must be defined") @@ -51,7 +53,7 @@ func (i DeployUSDCTokenPoolInput) Validate(ctx context.Context, chain deployment if err != nil { return fmt.Errorf("failed to fetch symbol from token with address %s: %w", i.TokenAddress, err) } - if symbol != string(changeset.USDCSymbol) { + if symbol != string(shared.USDCSymbol) { return fmt.Errorf("symbol of token with address %s (%s) is not USDC", i.TokenAddress, symbol) } @@ -87,13 +89,13 @@ type DeployUSDCTokenPoolContractsConfig struct { IsTestRouter bool } -func (c DeployUSDCTokenPoolContractsConfig) Validate(env deployment.Environment) error { - state, err := changeset.LoadOnchainState(env) +func (c DeployUSDCTokenPoolContractsConfig) Validate(env cldf.Environment) error { + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for chainSelector, poolConfig := range c.USDCPools { - err := deployment.IsValidChainSelector(chainSelector) + err := cldf.IsValidChainSelector(chainSelector) if err != nil { return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) } @@ -123,13 +125,13 @@ func (c DeployUSDCTokenPoolContractsConfig) Validate(env deployment.Environment) } // DeployUSDCTokenPoolContractsChangeset deploys new USDC pools across multiple chains. -func DeployUSDCTokenPoolContractsChangeset(env deployment.Environment, c DeployUSDCTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { +func DeployUSDCTokenPoolContractsChangeset(env cldf.Environment, c DeployUSDCTokenPoolContractsConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid DeployUSDCTokenPoolContractsConfig: %w", err) } newAddresses := cldf.NewMemoryAddressBook() - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -142,7 +144,7 @@ func DeployUSDCTokenPoolContractsChangeset(env deployment.Environment, c DeployU router = chainState.TestRouter } _, err := cldf.DeployContract(env.Logger, chain, newAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*usdc_token_pool.USDCTokenPool] { + func(chain cldf.Chain) cldf.ContractDeploy[*usdc_token_pool.USDCTokenPool] { poolAddress, tx, usdcTokenPool, err := usdc_token_pool.DeployUSDCTokenPool( chain.DeployerKey, chain.Client, poolConfig.TokenMessenger, poolConfig.TokenAddress, poolConfig.AllowList, chainState.RMNProxy.Address(), router.Address(), @@ -150,7 +152,7 @@ func DeployUSDCTokenPoolContractsChangeset(env deployment.Environment, c DeployU return cldf.ContractDeploy[*usdc_token_pool.USDCTokenPool]{ Address: poolAddress, Contract: usdcTokenPool, - Tv: cldf.NewTypeAndVersion(changeset.USDCTokenPool, deployment.Version1_5_1), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenPool, deployment.Version1_5_1), Tx: tx, Err: err, } diff --git a/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools_test.go b/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools_test.go index 5fead065f69..7a119c8715a 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_deploy_usdc_token_pools_test.go @@ -19,6 +19,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" @@ -29,11 +31,11 @@ import ( func deployUSDCPrerequisites( t *testing.T, logger logger.Logger, - chain deployment.Chain, + chain cldf.Chain, addressBook cldf.AddressBook, ) (*cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677], *cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger]) { usdcToken, err := cldf.DeployContract(logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( chain.DeployerKey, chain.Client, @@ -45,7 +47,7 @@ func deployUSDCPrerequisites( return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.USDCTokenPool, deployment.Version1_5_1), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenPool, deployment.Version1_5_1), Tx: tx, Err: err, } @@ -54,12 +56,12 @@ func deployUSDCPrerequisites( require.NoError(t, err) transmitter, err := cldf.DeployContract(logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { + func(chain cldf.Chain) cldf.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter] { transmitterAddress, tx, transmitter, err := mock_usdc_token_transmitter.DeployMockE2EUSDCTransmitter(chain.DeployerKey, chain.Client, 0, 1, usdcToken.Address) return cldf.ContractDeploy[*mock_usdc_token_transmitter.MockE2EUSDCTransmitter]{ Address: transmitterAddress, Contract: transmitter, - Tv: cldf.NewTypeAndVersion(changeset.USDCMockTransmitter, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.USDCMockTransmitter, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -68,12 +70,12 @@ func deployUSDCPrerequisites( require.NoError(t, err) messenger, err := cldf.DeployContract(logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { + func(chain cldf.Chain) cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { messengerAddress, tx, messenger, err := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger(chain.DeployerKey, chain.Client, 0, transmitter.Address) return cldf.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger]{ Address: messengerAddress, Contract: messenger, - Tv: cldf.NewTypeAndVersion(changeset.USDCTokenMessenger, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenMessenger, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -148,7 +150,7 @@ func TestValidateDeployUSDCTokenPoolInput(t *testing.T) { usdcToken, tokenMessenger := deployUSDCPrerequisites(t, lggr, chain, addressBook) nonUsdcToken, err := cldf.DeployContract(e.Logger, chain, addressBook, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( chain.DeployerKey, chain.Client, @@ -160,7 +162,7 @@ func TestValidateDeployUSDCTokenPoolInput(t *testing.T) { return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.USDCTokenPool, deployment.Version1_5_1), + Tv: cldf.NewTypeAndVersion(shared.USDCTokenPool, deployment.Version1_5_1), Tx: tx, Err: err, } @@ -168,7 +170,7 @@ func TestValidateDeployUSDCTokenPoolInput(t *testing.T) { ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) tests := []struct { @@ -288,7 +290,7 @@ func TestDeployUSDCTokenPoolContracts(t *testing.T) { } else { require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) for _, selector := range selectors { diff --git a/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role.go b/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role.go index 7960c3bc767..514e3c62d42 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role.go +++ b/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role.go @@ -11,21 +11,22 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) // ProposeAdminRoleChangeset is a changeset that proposes admin rights for tokens on the token admin registry. // To be able to propose admin rights, the caller must own the token admin registry and the token must not already have an administrator. // If you want to propose admin role for an external address, you can set the ExternalAdmin field in the TokenPoolInfo within TokenAdminRegistryChangesetConfig. -var _ cldf.ChangeSet[changeset.TokenAdminRegistryChangesetConfig] = ProposeAdminRoleChangeset +var _ cldf.ChangeSet[TokenAdminRegistryChangesetConfig] = ProposeAdminRoleChangeset func validateProposeAdminRole( config token_admin_registry.TokenAdminRegistryTokenConfig, sender common.Address, externalAdmin common.Address, - symbol changeset.TokenSymbol, - chain deployment.Chain, + symbol shared.TokenSymbol, + chain cldf.Chain, ) error { // To propose ourselves as admin of the token, two things must be true. // 1. We own the token admin registry @@ -38,16 +39,16 @@ func validateProposeAdminRole( } // ProposeAdminRoleChangeset proposes admin rights for tokens on the token admin registry. -func ProposeAdminRoleChangeset(env deployment.Environment, c changeset.TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { +func ProposeAdminRoleChangeset(env cldf.Environment, c TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env, true, validateProposeAdminRole); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid TokenAdminRegistryChangesetConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("propose admin role for tokens on token admin registries") + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("propose admin role for tokens on token admin registries") for chainSelector, tokenSymbolToPoolInfo := range c.Pools { chain := env.Chains[chainSelector] diff --git a/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role_test.go b/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role_test.go index 5421fac740d..5934c52280b 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_propose_admin_role_test.go @@ -9,10 +9,12 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -25,7 +27,7 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -39,12 +41,12 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { e, err := commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -53,12 +55,12 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -69,14 +71,14 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { require.NoError(t, err) tests := []struct { - Config changeset.TokenAdminRegistryChangesetConfig + Config v1_5_1.TokenAdminRegistryChangesetConfig ErrStr string Msg string }{ { Msg: "Chain selector is invalid", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 0: {}, }, }, @@ -84,8 +86,8 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Chain selector doesn't exist in environment", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 5009297550715157269: {}, }, }, @@ -93,8 +95,8 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Ownership validation failure", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: {}, }, }, @@ -102,9 +104,9 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool type", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { Type: "InvalidType", @@ -117,12 +119,12 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool version", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_0_0, }, }, @@ -132,12 +134,12 @@ func TestProposeAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Admin already exists", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -173,18 +175,18 @@ func TestProposeAdminRoleChangeset_ExecutionWithoutExternalAdmin(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) registryOnA := state.Chains[selectorA].TokenAdminRegistry @@ -193,18 +195,18 @@ func TestProposeAdminRoleChangeset_ExecutionWithoutExternalAdmin(t *testing.T) { e, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -247,18 +249,18 @@ func TestProposeAdminRoleChangeset_ExecutionWithExternalAdmin(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) registryOnA := state.Chains[selectorA].TokenAdminRegistry @@ -267,19 +269,19 @@ func TestProposeAdminRoleChangeset_ExecutionWithExternalAdmin(t *testing.T) { _, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: externalAdminA, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: externalAdminB, }, diff --git a/deployment/ccip/changeset/v1_5_1/cs_set_pool.go b/deployment/ccip/changeset/v1_5_1/cs_set_pool.go index 42742f85094..ffc7c1e0cb5 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_set_pool.go +++ b/deployment/ccip/changeset/v1_5_1/cs_set_pool.go @@ -9,18 +9,19 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) -var _ cldf.ChangeSet[changeset.TokenAdminRegistryChangesetConfig] = SetPoolChangeset +var _ cldf.ChangeSet[TokenAdminRegistryChangesetConfig] = SetPoolChangeset func validateSetPool( config token_admin_registry.TokenAdminRegistryTokenConfig, sender common.Address, externalAdmin common.Address, - symbol changeset.TokenSymbol, - chain deployment.Chain, + symbol shared.TokenSymbol, + chain cldf.Chain, ) error { // We must be the administrator if config.Administrator != sender { @@ -30,16 +31,16 @@ func validateSetPool( } // SetPoolChangeset sets pools for tokens on the token admin registry. -func SetPoolChangeset(env deployment.Environment, c changeset.TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { +func SetPoolChangeset(env cldf.Environment, c TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env, false, validateSetPool); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid TokenAdminRegistryChangesetConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("set pool for tokens on token admin registries") + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("set pool for tokens on token admin registries") for chainSelector, tokenSymbolToPoolInfo := range c.Pools { chain := env.Chains[chainSelector] diff --git a/deployment/ccip/changeset/v1_5_1/cs_set_pool_test.go b/deployment/ccip/changeset/v1_5_1/cs_set_pool_test.go index 06f37f0a208..a80fbb440a9 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_set_pool_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_set_pool_test.go @@ -7,10 +7,12 @@ import ( "github.com/stretchr/testify/require" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -23,7 +25,7 @@ func TestSetPoolChangeset_Validations(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -34,14 +36,14 @@ func TestSetPoolChangeset_Validations(t *testing.T) { } tests := []struct { - Config changeset.TokenAdminRegistryChangesetConfig + Config v1_5_1.TokenAdminRegistryChangesetConfig ErrStr string Msg string }{ { Msg: "Chain selector is invalid", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 0: {}, }, }, @@ -49,8 +51,8 @@ func TestSetPoolChangeset_Validations(t *testing.T) { }, { Msg: "Chain selector doesn't exist in environment", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 5009297550715157269: {}, }, }, @@ -58,9 +60,9 @@ func TestSetPoolChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool type", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { Type: "InvalidType", @@ -73,12 +75,12 @@ func TestSetPoolChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool version", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_0_0, }, }, @@ -88,12 +90,12 @@ func TestSetPoolChangeset_Validations(t *testing.T) { }, { Msg: "Not admin", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -129,18 +131,18 @@ func TestSetPoolChangeset_Execution(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) registryOnA := state.Chains[selectorA].TokenAdminRegistry @@ -149,18 +151,18 @@ func TestSetPoolChangeset_Execution(t *testing.T) { _, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -169,18 +171,18 @@ func TestSetPoolChangeset_Execution(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -189,18 +191,18 @@ func TestSetPoolChangeset_Execution(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.SetPoolChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, diff --git a/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains.go b/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains.go index 3b61008b084..e9464bf41c2 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains.go +++ b/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains.go @@ -12,8 +12,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -30,7 +30,7 @@ type SyncUSDCDomainsWithChainsConfig struct { MCMS *proposalutils.TimelockConfig } -func (c SyncUSDCDomainsWithChainsConfig) Validate(env deployment.Environment, state changeset.CCIPOnChainState) error { +func (c SyncUSDCDomainsWithChainsConfig) Validate(env cldf.Environment, state stateview.CCIPOnChainState) error { ctx := env.GetContext() if c.ChainSelectorToUSDCDomain == nil { @@ -39,7 +39,7 @@ func (c SyncUSDCDomainsWithChainsConfig) Validate(env deployment.Environment, st // Validate that all USDC configs inputted are for valid chains that define USDC pools. for chainSelector, version := range c.USDCVersionByChain { - err := deployment.IsValidChainSelector(chainSelector) + err := cldf.IsValidChainSelector(chainSelector) if err != nil { return fmt.Errorf("failed to validate chain selector %d: %w", chainSelector, err) } @@ -94,8 +94,8 @@ func (c SyncUSDCDomainsWithChainsConfig) Validate(env deployment.Environment, st // SyncUSDCDomainsWithChainsChangeset syncs domain support on specified USDC token pools with its chain support. // As such, it is expected that ConfigureTokenPoolContractsChangeset is executed before running this changeset. -func SyncUSDCDomainsWithChainsChangeset(env deployment.Environment, c SyncUSDCDomainsWithChainsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func SyncUSDCDomainsWithChainsChangeset(env cldf.Environment, c SyncUSDCDomainsWithChainsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -104,7 +104,7 @@ func SyncUSDCDomainsWithChainsChangeset(env deployment.Environment, c SyncUSDCDo } readOpts := &bind.CallOpts{Context: env.GetContext()} - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("sync domain support with chain support on USDC token pools") + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("sync domain support with chain support on USDC token pools") for chainSelector, version := range c.USDCVersionByChain { chain := env.Chains[chainSelector] diff --git a/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains_test.go b/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains_test.go index 66e65420a93..472f9611a9e 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_sync_usdc_domains_with_chains_test.go @@ -11,10 +11,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -151,14 +153,14 @@ func TestValidateSyncUSDCDomainsWithChainsConfig(t *testing.T) { ChainUpdates: v1_5_1.RateLimiterPerChain{ selectors[1]: testhelpers.CreateSymmetricRateLimits(0, 0), }, - Type: changeset.USDCTokenPool, + Type: shared.USDCTokenPool, Version: deployment.Version1_5_1, }, selectors[1]: { ChainUpdates: v1_5_1.RateLimiterPerChain{ selectors[0]: testhelpers.CreateSymmetricRateLimits(0, 0), }, - Type: changeset.USDCTokenPool, + Type: shared.USDCTokenPool, Version: deployment.Version1_5_1, }, }, @@ -169,7 +171,7 @@ func TestValidateSyncUSDCDomainsWithChainsConfig(t *testing.T) { require.NoError(t, err) } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) err = test.Input(selectors[0]).Validate(e, state) @@ -199,7 +201,7 @@ func TestSyncUSDCDomainsWithChainsChangeset(t *testing.T) { e := deployedEnvironment.Env selectors := e.AllChainSelectors() - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) timelockContracts := make(map[uint64]*proposalutils.TimelockExecutionContracts, len(selectors)) @@ -238,14 +240,14 @@ func TestSyncUSDCDomainsWithChainsChangeset(t *testing.T) { ChainUpdates: v1_5_1.RateLimiterPerChain{ selectors[1]: testhelpers.CreateSymmetricRateLimits(0, 0), }, - Type: changeset.USDCTokenPool, + Type: shared.USDCTokenPool, Version: deployment.Version1_5_1, }, selectors[1]: { ChainUpdates: v1_5_1.RateLimiterPerChain{ selectors[0]: testhelpers.CreateSymmetricRateLimits(0, 0), }, - Type: changeset.USDCTokenPool, + Type: shared.USDCTokenPool, Version: deployment.Version1_5_1, }, }, @@ -273,7 +275,7 @@ func TestSyncUSDCDomainsWithChainsChangeset(t *testing.T) { ) require.NoError(t, err) - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err) for i, selector := range selectors { diff --git a/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role.go b/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role.go index b889b82abc8..1c5ea7d80ae 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role.go +++ b/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role.go @@ -12,18 +12,19 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) -var _ cldf.ChangeSet[changeset.TokenAdminRegistryChangesetConfig] = TransferAdminRoleChangeset +var _ cldf.ChangeSet[TokenAdminRegistryChangesetConfig] = TransferAdminRoleChangeset func validateTransferAdminRole( config token_admin_registry.TokenAdminRegistryTokenConfig, sender common.Address, externalAdmin common.Address, - symbol changeset.TokenSymbol, - chain deployment.Chain, + symbol shared.TokenSymbol, + chain cldf.Chain, ) error { if externalAdmin == utils.ZeroAddress { return errors.New("external admin must be defined") @@ -36,16 +37,16 @@ func validateTransferAdminRole( } // TransferAdminRoleChangeset transfers the admin role for tokens on the token admin registry to 3rd parties. -func TransferAdminRoleChangeset(env deployment.Environment, c changeset.TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { +func TransferAdminRoleChangeset(env cldf.Environment, c TokenAdminRegistryChangesetConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(env, false, validateTransferAdminRole); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid TokenAdminRegistryChangesetConfig: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("transfer admin role for tokens on token admin registries") + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMS).WithDeploymentContext("transfer admin role for tokens on token admin registries") for chainSelector, tokenSymbolToPoolInfo := range c.Pools { chain := env.Chains[chainSelector] diff --git a/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role_test.go b/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role_test.go index 414c7f91ad4..73b10d9a042 100644 --- a/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role_test.go +++ b/deployment/ccip/changeset/v1_5_1/cs_transfer_admin_role_test.go @@ -9,10 +9,12 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -25,7 +27,7 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, @@ -36,14 +38,14 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { } tests := []struct { - Config changeset.TokenAdminRegistryChangesetConfig + Config v1_5_1.TokenAdminRegistryChangesetConfig ErrStr string Msg string }{ { Msg: "Chain selector is invalid", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 0: {}, }, }, @@ -51,8 +53,8 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Chain selector doesn't exist in environment", - Config: changeset.TokenAdminRegistryChangesetConfig{ - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ 5009297550715157269: {}, }, }, @@ -60,9 +62,9 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool type", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { Type: "InvalidType", @@ -75,12 +77,12 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Invalid pool version", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_0_0, }, }, @@ -90,12 +92,12 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "External admin undefined", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -105,12 +107,12 @@ func TestTransferAdminRoleChangeset_Validations(t *testing.T) { }, { Msg: "Not admin", - Config: changeset.TokenAdminRegistryChangesetConfig{ + Config: v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: utils.RandomAddress(), }, @@ -149,18 +151,18 @@ func TestTransferAdminRoleChangeset_Execution(t *testing.T) { e = testhelpers.DeployTestTokenPools(t, e, map[uint64]v1_5_1.DeployTokenPoolInput{ selectorA: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorA].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, selectorB: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, TokenAddress: tokens[selectorB].Address, LocalTokenDecimals: testhelpers.LocalTokenDecimals, }, }, mcmsConfig != nil) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) registryOnA := state.Chains[selectorA].TokenAdminRegistry @@ -169,18 +171,18 @@ func TestTransferAdminRoleChangeset_Execution(t *testing.T) { _, err = commonchangeset.Apply(t, e, timelockContracts, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -189,18 +191,18 @@ func TestTransferAdminRoleChangeset_Execution(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, }, }, @@ -209,19 +211,19 @@ func TestTransferAdminRoleChangeset_Execution(t *testing.T) { ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.TransferAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ MCMS: mcmsConfig, - Pools: map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo{ + Pools: map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ selectorA: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: externalAdminA, }, }, selectorB: { testhelpers.TestTokenSymbol: { - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: externalAdminB, }, diff --git a/deployment/ccip/changeset/v1_6/accept_ownership_test.go b/deployment/ccip/changeset/v1_6/accept_ownership_test.go index 545bed037b4..0fcb7f78613 100644 --- a/deployment/ccip/changeset/v1_6/accept_ownership_test.go +++ b/deployment/ccip/changeset/v1_6/accept_ownership_test.go @@ -7,8 +7,9 @@ import ( "golang.org/x/exp/maps" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -16,7 +17,7 @@ import ( func Test_NewAcceptOwnershipChangeset(t *testing.T) { t.Parallel() e, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := maps.Keys(e.Env.Chains) @@ -36,7 +37,7 @@ func Test_NewAcceptOwnershipChangeset(t *testing.T) { // at this point we have the initial deploys done, now we need to transfer ownership // to the timelock contract - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) // compose the transfer ownership and accept ownership changesets diff --git a/deployment/ccip/changeset/v1_6/config.go b/deployment/ccip/changeset/v1_6/config.go index 09c80c7c773..096427eee9e 100644 --- a/deployment/ccip/changeset/v1_6/config.go +++ b/deployment/ccip/changeset/v1_6/config.go @@ -21,7 +21,7 @@ var ( DefaultOCRParamsForCommitForETH = CCIPOCRParams{ OCRParameters: globals.CommitOCRParamsForEthereum, - CommitOffChainConfig: &globals.DefaultCommitOffChainCfg, + CommitOffChainConfig: &globals.DefaultCommitOffChainCfgForEth, } DefaultOCRParamsForExecForNonETH = CCIPOCRParams{ diff --git a/deployment/ccip/changeset/v1_6/cs_active_candidate_test.go b/deployment/ccip/changeset/v1_6/cs_active_candidate_test.go index ca82b85828d..b9a26fd2bfd 100644 --- a/deployment/ccip/changeset/v1_6/cs_active_candidate_test.go +++ b/deployment/ccip/changeset/v1_6/cs_active_candidate_test.go @@ -12,10 +12,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -35,7 +37,7 @@ func Test_ActiveCandidate(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2), testhelpers.WithNumOfNodes(4)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -194,7 +196,7 @@ func Test_ActiveCandidate(t *testing.T) { // Now we can add a candidate config, send another request, and observe behavior. // The candidate config should not be able to execute messages. - tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + tokenConfig := shared.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) _, err = commonchangeset.Apply(t, tenv.Env, tenv.TimelockContracts(t), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_6.SetCandidateChangeset), diff --git a/deployment/ccip/changeset/v1_6/cs_add_lane_test.go b/deployment/ccip/changeset/v1_6/cs_add_lane_test.go index 2b7da69d33f..67322586cd1 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_lane_test.go +++ b/deployment/ccip/changeset/v1_6/cs_add_lane_test.go @@ -9,15 +9,16 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) func TestAddLanesWithTestRouter(t *testing.T) { t.Parallel() e, _ := testhelpers.NewMemoryEnvironment(t) // Here we have CR + nodes set up, but no CCIP contracts deployed. - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) selectors := e.Env.AllChainSelectors() @@ -50,7 +51,7 @@ func TestAddLanesWithSolana(t *testing.T) { t.Parallel() e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithSolChains(1)) // Here we have CR + nodes set up, but no CCIP contracts deployed. - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) evmSelectors := e.Env.AllChainSelectors() diff --git a/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e.go b/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e.go index 6342a64f5f1..49cce416ca5 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e.go +++ b/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e.go @@ -4,17 +4,17 @@ import ( "errors" "fmt" "math/big" + "slices" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -148,13 +148,13 @@ func (c AddCandidatesForNewChainConfig) updateChainConfig() UpdateChainConfigCon } } -func addCandidatesForNewChainPrecondition(e deployment.Environment, c AddCandidatesForNewChainConfig) error { - state, err := changeset.LoadOnchainState(e) +func addCandidatesForNewChainPrecondition(e cldf.Environment, c AddCandidatesForNewChainConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } - err = changeset.ValidateChain(e, state, c.HomeChainSelector, c.MCMSConfig) + err = stateview.ValidateChain(e, state, c.HomeChainSelector, c.MCMSConfig) if err != nil { return fmt.Errorf("failed to validate home chain: %w", err) } @@ -206,7 +206,7 @@ func addCandidatesForNewChainPrecondition(e deployment.Environment, c AddCandida return nil } -func addCandidatesForNewChainLogic(e deployment.Environment, c AddCandidatesForNewChainConfig) (cldf.ChangesetOutput, error) { +func addCandidatesForNewChainLogic(e cldf.Environment, c AddCandidatesForNewChainConfig) (cldf.ChangesetOutput, error) { newAddresses := cldf.NewMemoryAddressBook() var allProposals []mcmslib.TimelockProposal @@ -255,7 +255,7 @@ func addCandidatesForNewChainLogic(e deployment.Environment, c AddCandidatesForN } // Set the RMN remote on the RMN proxy, using MCMS if RMN proxy is owned by Timelock // RMN proxy will already exist on chains that supported CCIPv1.5.0, in which case RMN proxy will be owned by Timelock - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -310,13 +310,13 @@ func addCandidatesForNewChainLogic(e deployment.Environment, c AddCandidatesForN } // Fetch the next DON ID from the capabilities registry - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } if c.DonIDOffSet != nil { - _, err = deployment.RunChangeset(DonIDClaimerOffSetChangeset, e, DonIDClaimerOffSetConfig{ + _, err = commoncs.RunChangeset(DonIDClaimerOffSetChangeset, e, DonIDClaimerOffSetConfig{ OffSet: *c.DonIDOffSet, }) @@ -389,7 +389,7 @@ func addCandidatesForNewChainLogic(e deployment.Environment, c AddCandidatesForN txOpts := e.Chains[c.HomeChainSelector].DeployerKey tx, err := state.Chains[c.HomeChainSelector].DonIDClaimer.ClaimNextDONId(txOpts) - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[c.HomeChainSelector], tx, don_id_claimer.DonIDClaimerABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[c.HomeChainSelector], tx, don_id_claimer.DonIDClaimerABI, err); err != nil { return cldf.ChangesetOutput{}, err } @@ -408,7 +408,6 @@ func addCandidatesForNewChainLogic(e deployment.Environment, c AddCandidatesForN state.EVMMCMSStateByChain(), nil, allProposals, - nil, fmt.Sprintf("Deploy and set candidates for chain with selector %d", c.NewChain.Selector), c.MCMSConfig, ) @@ -510,8 +509,8 @@ func (c PromoteNewChainForConfig) connectNewChainConfig(testRouter bool) Connect } } -func promoteNewChainForConfigPrecondition(e deployment.Environment, c PromoteNewChainForConfig) error { - state, err := changeset.LoadOnchainState(e) +func promoteNewChainForConfigPrecondition(e cldf.Environment, c PromoteNewChainForConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -541,9 +540,9 @@ func promoteNewChainForConfigPrecondition(e deployment.Environment, c PromoteNew return nil } -func promoteNewChainForConfigLogic(e deployment.Environment, c PromoteNewChainForConfig) (cldf.ChangesetOutput, error) { +func promoteNewChainForConfigLogic(e cldf.Environment, c PromoteNewChainForConfig) (cldf.ChangesetOutput, error) { var allProposals []mcmslib.TimelockProposal - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -588,7 +587,6 @@ func promoteNewChainForConfigLogic(e deployment.Environment, c PromoteNewChainFo state.EVMMCMSStateByChain(), nil, allProposals, - nil, fmt.Sprintf("Promote chain with selector %d for testing", c.NewChain.Selector), c.MCMSConfig, ) @@ -632,7 +630,7 @@ type ConnectNewChainConfig struct { MCMSConfig *proposalutils.TimelockConfig `json:"mcmsConfig,omitempty"` } -func (c ConnectNewChainConfig) validateNewChain(env deployment.Environment, state changeset.CCIPOnChainState) error { +func (c ConnectNewChainConfig) validateNewChain(env cldf.Environment, state stateview.CCIPOnChainState) error { // When running this changeset, there is no case in which the new chain contract should be owned by MCMS, // which is why we do not use MCMSConfig to determine the ownedByMCMS variable. err := c.validateChain(env, state, c.NewChainSelector, false) @@ -643,7 +641,7 @@ func (c ConnectNewChainConfig) validateNewChain(env deployment.Environment, stat return nil } -func (c ConnectNewChainConfig) validateRemoteChains(env deployment.Environment, state changeset.CCIPOnChainState) error { +func (c ConnectNewChainConfig) validateRemoteChains(env cldf.Environment, state stateview.CCIPOnChainState) error { for remoteChainSelector := range c.RemoteChains { // The remote chain may or may not be owned by MCMS, as MCMS is not really used in staging. // Therefore, we use the presence of MCMSConfig to determine the ownedByMCMS variable. @@ -656,8 +654,8 @@ func (c ConnectNewChainConfig) validateRemoteChains(env deployment.Environment, return nil } -func (c ConnectNewChainConfig) validateChain(e deployment.Environment, state changeset.CCIPOnChainState, chainSelector uint64, ownedByMCMS bool) error { - err := changeset.ValidateChain(e, state, chainSelector, c.MCMSConfig) +func (c ConnectNewChainConfig) validateChain(e cldf.Environment, state stateview.CCIPOnChainState, chainSelector uint64, ownedByMCMS bool) error { + err := stateview.ValidateChain(e, state, chainSelector, c.MCMSConfig) if err != nil { return fmt.Errorf("failed to validate chain with selector %d: %w", chainSelector, err) } @@ -699,12 +697,12 @@ func (c ConnectNewChainConfig) validateChain(e deployment.Environment, state cha return nil } -func connectNewChainPrecondition(env deployment.Environment, c ConnectNewChainConfig) error { +func connectNewChainPrecondition(env cldf.Environment, c ConnectNewChainConfig) error { if c.TestRouter == nil { return errors.New("must define whether to use the test router") } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -722,14 +720,14 @@ func connectNewChainPrecondition(env deployment.Environment, c ConnectNewChainCo return nil } -func connectNewChainLogic(env deployment.Environment, c ConnectNewChainConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func connectNewChainLogic(env cldf.Environment, c ConnectNewChainConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } readOpts := &bind.CallOpts{Context: env.GetContext()} - var ownershipTransferProposals []timelock.MCMSWithTimelockProposal + var ownershipTransferProposals []mcmslib.TimelockProposal if !*c.TestRouter && c.MCMSConfig != nil { // If using the production router, transfer ownership of all contracts on the new chain to MCMS. allContracts := []commoncs.Ownable{ @@ -755,7 +753,7 @@ func connectNewChainLogic(env deployment.Environment, c ConnectNewChainConfig) ( addressesToTransfer = append(addressesToTransfer, contract.Address()) } } - out, err := commoncs.TransferToMCMSWithTimelock(env, commoncs.TransferToMCMSWithTimelockConfig{ + out, err := commoncs.TransferToMCMSWithTimelockV2(env, commoncs.TransferToMCMSWithTimelockConfig{ ContractsByChain: map[uint64][]common.Address{ c.NewChainSelector: addressesToTransfer, }, @@ -764,7 +762,7 @@ func connectNewChainLogic(env deployment.Environment, c ConnectNewChainConfig) ( if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to run TransferToMCMSWithTimelock on chain with selector %d: %w", c.NewChainSelector, err) } - ownershipTransferProposals = out.Proposals //nolint:staticcheck //SA1019 ignoring deprecated function for compatibility + ownershipTransferProposals = out.MCMSTimelockProposals // Also, renounce the admin role on the Timelock (if not already done). adminRole, err := state.Chains[c.NewChainSelector].Timelock.ADMINROLE(readOpts) @@ -802,12 +800,13 @@ func connectNewChainLogic(env deployment.Environment, c ConnectNewChainConfig) ( } } + allProposals := slices.Concat(ownershipTransferProposals, allEnablementProposals) + proposal, err := proposalutils.AggregateProposals( env, state.EVMMCMSStateByChain(), nil, - allEnablementProposals, - ownershipTransferProposals, + allProposals, fmt.Sprintf("Connect chain with selector %d to other chains", c.NewChainSelector), c.MCMSConfig, ) @@ -825,7 +824,7 @@ func connectNewChainLogic(env deployment.Environment, c ConnectNewChainConfig) ( // It also sets the onRamp and offRamp on the router for the given remote chains. // This function will add the proposals required to make these changes to the proposalAggregate slice. func connectRampsAndRouters( - e deployment.Environment, + e cldf.Environment, chainSelector uint64, remoteChains map[uint64]ConnectionConfig, mcmsConfig *proposalutils.TimelockConfig, diff --git a/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e_test.go b/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e_test.go index 4c07a618eae..ec06ac371af 100644 --- a/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e_test.go +++ b/deployment/ccip/changeset/v1_6/cs_add_new_chain_e2e_test.go @@ -19,11 +19,11 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" @@ -34,8 +34,8 @@ import ( func checkConnectivity( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, selector uint64, remoteChainSelector uint64, expectedRouter *router.Router, @@ -118,7 +118,7 @@ func TestConnectNewChain(t *testing.T) { }) e := deployedEnvironment.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") selectors := e.AllChainSelectors() @@ -285,7 +285,7 @@ func TestAddAndPromoteCandidatesForNewChain(t *testing.T) { testCfg.ChainIDs = chainIDs }) e := deployedEnvironment.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") // Identify and delete addresses from the new chain @@ -305,7 +305,7 @@ func TestAddAndPromoteCandidatesForNewChain(t *testing.T) { } } e.ExistingAddresses = cldf.NewMemoryAddressBookFromMap(addressesByChain) - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") // Identify and delete the DON ID for the new chain @@ -444,14 +444,14 @@ func TestAddAndPromoteCandidatesForNewChain(t *testing.T) { )) require.NoError(t, err, "must deploy donIDClaimer contract") - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") if test.DonIDOffSet != nil { tx, err := state.Chains[deployedEnvironment.HomeChainSel].DonIDClaimer.ClaimNextDONId(e.Chains[deployedEnvironment.HomeChainSel].DeployerKey) require.NoError(t, err) - _, err = deployment.ConfirmIfNoErrorWithABI(e.Chains[deployedEnvironment.HomeChainSel], tx, don_id_claimer.DonIDClaimerABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(e.Chains[deployedEnvironment.HomeChainSel], tx, don_id_claimer.DonIDClaimerABI, err) require.NoError(t, err) } @@ -471,7 +471,7 @@ func TestAddAndPromoteCandidatesForNewChain(t *testing.T) { ), ) require.NoError(t, err, "must apply AddCandidatesForNewChainChangeset") - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") capReg := state.Chains[deployedEnvironment.HomeChainSel].CapabilityRegistry diff --git a/deployment/ccip/changeset/v1_6/cs_ccip_home.go b/deployment/ccip/changeset/v1_6/cs_ccip_home.go index 8f8838e14d6..e5395d1a6af 100644 --- a/deployment/ccip/changeset/v1_6/cs_ccip_home.go +++ b/deployment/ccip/changeset/v1_6/cs_ccip_home.go @@ -27,12 +27,13 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -52,13 +53,18 @@ var ( DonIDClaimerOffSetChangeset = cldf.CreateChangeSet(donIDClaimerOffSetChangesetLogic, donIDClaimerOffSetChangesetPrecondition) ) -func findTokenInfo(tokens []changeset.TokenDetails, address common.Address) (string, uint8, error) { +func findTokenInfo(tokens []shared.TokenDetails, address common.Address) (string, uint8, error) { for _, token := range tokens { if token.Address() == address { tokenSymbol, err := token.Symbol(nil) if err != nil { return "", 0, fmt.Errorf("fetch token symbol for token %s: %w", address, err) } + // TODO think of better solution + // there are tokens which have diff symbols in testnet and mainnet + if symbol, ok := shared.TokenSymbolSubstitute[tokenSymbol]; ok { + tokenSymbol = symbol + } tokenDecimals, err := token.Decimals(nil) if err != nil { return "", 0, fmt.Errorf("fetch token decimals for token %s: %w", address, err) @@ -69,12 +75,12 @@ func findTokenInfo(tokens []changeset.TokenDetails, address common.Address) (str return "", 0, fmt.Errorf("token %s not found in available tokens", address) } -func validateExecOffchainConfig(e deployment.Environment, c *pluginconfig.ExecuteOffchainConfig, selector uint64, state changeset.CCIPOnChainState) error { +func validateExecOffchainConfig(e cldf.Environment, c *pluginconfig.ExecuteOffchainConfig, selector uint64, state stateview.CCIPOnChainState) error { if err := c.Validate(); err != nil { return fmt.Errorf("invalid execute off-chain config: %w", err) } // get offRamp - if err := state.ValidateRamp(selector, changeset.OffRamp); err != nil { + if err := state.ValidateRamp(selector, shared.OffRamp); err != nil { return fmt.Errorf("validate offRamp: %w", err) } @@ -91,7 +97,7 @@ func validateExecOffchainConfig(e deployment.Environment, c *pluginconfig.Execut return nil } -func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector uint64, feedChainSel uint64, state changeset.CCIPOnChainState) error { +func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector uint64, feedChainSel uint64, state stateview.CCIPOnChainState) error { if err := c.Validate(); err != nil { return fmt.Errorf("invalid commit off-chain config: %w", err) } @@ -113,7 +119,7 @@ func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector aggregatorAddr := common.HexToAddress(string(tokenConfig.AggregatorAddress)) token := common.HexToAddress(tokenUnknownAddr.String()) - tokenInfos := make([]changeset.TokenDetails, 0) + tokenInfos := make([]shared.TokenDetails, 0) onchainState := state.Chains[selector] for _, tk := range onchainState.BurnMintTokens677 { tokenInfos = append(tokenInfos, tk) @@ -124,7 +130,7 @@ func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector for _, tk := range onchainState.ERC677Tokens { tokenInfos = append(tokenInfos, tk) } - var linkTokenInfo changeset.TokenDetails + var linkTokenInfo shared.TokenDetails linkTokenInfo = onchainState.LinkToken if onchainState.LinkToken == nil { linkTokenInfo = onchainState.StaticLinkToken @@ -140,7 +146,7 @@ func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector symbol, token.String(), tokenConfig.Decimals, decimal) } feedChainState := state.Chains[feedChainSel] - aggregatorInState := feedChainState.USDFeeds[changeset.TokenSymbol(symbol)] + aggregatorInState := feedChainState.USDFeeds[shared.TokenSymbol(symbol)] if aggregatorAddr == (common.Address{}) { return fmt.Errorf("token %s -address %s has no aggregator in provided token config", symbol, token.String()) } @@ -156,7 +162,7 @@ func validateCommitOffchainConfig(c *pluginconfig.CommitOffchainConfig, selector return nil } -func validateUSDCConfig(usdcConfig *pluginconfig.USDCCCTPObserverConfig, state changeset.CCIPOnChainState) error { +func validateUSDCConfig(usdcConfig *pluginconfig.USDCCCTPObserverConfig, state stateview.CCIPOnChainState) error { for sel, token := range usdcConfig.Tokens { onchainState, ok := state.Chains[uint64(sel)] if !ok { @@ -198,7 +204,7 @@ func (c CCIPOCRParams) Copy() CCIPOCRParams { return newC } -func (c CCIPOCRParams) Validate(e deployment.Environment, selector uint64, feedChainSel uint64, state changeset.CCIPOnChainState) error { +func (c CCIPOCRParams) Validate(e cldf.Environment, selector uint64, feedChainSel uint64, state stateview.CCIPOnChainState) error { if err := c.OCRParameters.Validate(); err != nil { return fmt.Errorf("invalid OCR parameters: %w", err) } @@ -236,12 +242,12 @@ type PromoteCandidateChangesetConfig struct { MCMS *proposalutils.TimelockConfig `json:"mcms,omitempty"` } -func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map[uint64]uint32, error) { - state, err := changeset.LoadOnchainState(e) +func (p PromoteCandidateChangesetConfig) Validate(e cldf.Environment) (map[uint64]uint32, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return nil, err } - if err := changeset.ValidateChain(e, state, p.HomeChainSelector, p.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, p.HomeChainSelector, p.MCMS); err != nil { return nil, fmt.Errorf("home chain invalid: %w", err) } homeChainState := state.Chains[p.HomeChainSelector] @@ -256,10 +262,10 @@ func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map return nil, errors.New("PluginType must be set to either CCIPCommit or CCIPExec") } for _, chainSelector := range plugin.RemoteChainSelectors { - if err := deployment.IsValidChainSelector(chainSelector); err != nil { + if err := cldf.IsValidChainSelector(chainSelector); err != nil { return nil, fmt.Errorf("don chain selector invalid: %w", err) } - if err := state.ValidateRamp(chainSelector, changeset.OffRamp); err != nil { + if err := state.ValidateRamp(chainSelector, shared.OffRamp); err != nil { return nil, err } @@ -316,14 +322,14 @@ func (p PromoteCandidateChangesetConfig) Validate(e deployment.Environment) (map // PromoteCandidateChangeset is NOT idempotent, once candidate config is promoted to active, if it's called again, // It might promote empty candidate config to active, which is not desired. func PromoteCandidateChangeset( - e deployment.Environment, + e cldf.Environment, cfg PromoteCandidateChangesetConfig, ) (cldf.ChangesetOutput, error) { donIDs, err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("%w: %w", cldf.ErrInvalidConfig, err) } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -335,7 +341,7 @@ func PromoteCandidateChangeset( txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } homeChain := e.Chains[cfg.HomeChainSelector] @@ -371,7 +377,7 @@ func PromoteCandidateChangeset( inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: mcmsTxs}} - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } @@ -407,7 +413,7 @@ func (p SetCandidatePluginInfo) String() string { return fmt.Sprintf("PluginType: %s, Chains: %v", p.PluginType.String(), allchains) } -func (p SetCandidatePluginInfo) Validate(e deployment.Environment, state changeset.CCIPOnChainState, homeChain uint64, feedChain uint64) error { +func (p SetCandidatePluginInfo) Validate(e cldf.Environment, state stateview.CCIPOnChainState, homeChain uint64, feedChain uint64) error { if p.PluginType != types.PluginTypeCCIPCommit && p.PluginType != types.PluginTypeCCIPExec { return errors.New("PluginType must be set to either CCIPCommit or CCIPExec") @@ -416,10 +422,10 @@ func (p SetCandidatePluginInfo) Validate(e deployment.Environment, state changes if _, exists := state.SupportedChains()[chainSelector]; !exists { return fmt.Errorf("chain %d does not exist in state", chainSelector) } - if err := deployment.IsValidChainSelector(chainSelector); err != nil { + if err := cldf.IsValidChainSelector(chainSelector); err != nil { return fmt.Errorf("don chain selector invalid: %w", err) } - if err := state.ValidateRamp(chainSelector, changeset.OffRamp); err != nil { + if err := state.ValidateRamp(chainSelector, shared.OffRamp); err != nil { return err } if p.PluginType == types.PluginTypeCCIPCommit && params.CommitOffChainConfig == nil { @@ -471,11 +477,11 @@ type SetCandidateConfigBase struct { MCMS *proposalutils.TimelockConfig `json:"mcms,omitempty"` } -func (s SetCandidateConfigBase) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(s.HomeChainSelector); err != nil { +func (s SetCandidateConfigBase) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { + if err := cldf.IsValidChainSelector(s.HomeChainSelector); err != nil { return fmt.Errorf("home chain selector invalid: %w", err) } - if err := deployment.IsValidChainSelector(s.FeedChainSelector); err != nil { + if err := cldf.IsValidChainSelector(s.FeedChainSelector); err != nil { return fmt.Errorf("feed chain selector invalid: %w", err) } homeChainState, exists := state.Chains[s.HomeChainSelector] @@ -517,7 +523,7 @@ type AddDonAndSetCandidateChangesetConfig struct { DonIDOverride uint32 `json:"donIdOverride"` } -func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (a AddDonAndSetCandidateChangesetConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { if err := a.SetCandidateConfigBase.Validate(e, state); err != nil { return err } @@ -557,10 +563,10 @@ func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, // AddDonAndSetCandidateChangeset is not idempotent, if AddDON is called more than once for the same chain, // it will throw an error because the DON would already exist for that chain. func AddDonAndSetCandidateChangeset( - e deployment.Environment, + e cldf.Environment, cfg AddDonAndSetCandidateChangesetConfig, ) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -577,7 +583,7 @@ func AddDonAndSetCandidateChangeset( txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } var donMcmsTxs []mcmstypes.Transaction for chainSelector, params := range cfg.PluginInfo.OCRConfigPerRemoteChainSelector { @@ -641,7 +647,7 @@ func AddDonAndSetCandidateChangeset( inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: donMcmsTxs}} - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } @@ -666,7 +672,7 @@ func AddDonAndSetCandidateChangeset( // This proposes to set up OCR3 config for the commit plugin for the DON func newDonWithCandidateOp( txOpts *bind.TransactOpts, - homeChain deployment.Chain, + homeChain cldf.Chain, donID uint32, pluginConfig ccip_home.CCIPHomeOCR3Config, capReg *capabilities_registry.CapabilitiesRegistry, @@ -689,7 +695,7 @@ func newDonWithCandidateOp( nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ { - CapabilityId: ccip.CCIPCapabilityID, + CapabilityId: shared.CCIPCapabilityID, Config: encodedSetCandidateCall, }, }, @@ -700,7 +706,7 @@ func newDonWithCandidateOp( // note: error check is handled below if !mcmsEnabled { - _, err = deployment.ConfirmIfNoErrorWithABI( + _, err = cldf.ConfirmIfNoErrorWithABI( homeChain, addDonTx, ccip_home.CCIPHomeABI, err) if err != nil { return mcmstypes.Transaction{}, fmt.Errorf("error confirming addDon call: %w", err) @@ -711,7 +717,7 @@ func newDonWithCandidateOp( } tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), addDonTx.Data(), - big.NewInt(0), string(changeset.CapabilitiesRegistry), []string{}) + big.NewInt(0), string(shared.CapabilitiesRegistry), []string{}) if err != nil { return mcmstypes.Transaction{}, fmt.Errorf("failed to create AddDON mcms tx (don: %d; ptype: %s): %w", donID, types.PluginType(pluginConfig.PluginType).String(), err) @@ -729,7 +735,7 @@ type SetCandidateChangesetConfig struct { DonIDOverrides map[uint64]uint32 `json:"donIdOverrides"` } -func (s SetCandidateChangesetConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) (map[uint64]uint32, error) { +func (s SetCandidateChangesetConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) (map[uint64]uint32, error) { err := s.SetCandidateConfigBase.Validate(e, state) if err != nil { return nil, err @@ -766,10 +772,10 @@ func (s SetCandidateChangesetConfig) Validate(e deployment.Environment, state ch // SetCandidateChangeset generates a proposal to call setCandidate on the CCIPHome through the capability registry. // A DON must exist in order to use this changeset effectively, i.e AddDonAndSetCandidateChangeset must be called first. func SetCandidateChangeset( - e deployment.Environment, + e cldf.Environment, cfg SetCandidateChangesetConfig, ) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -786,7 +792,7 @@ func SetCandidateChangeset( txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } var setCandidateMcmsTxs []mcmstypes.Transaction pluginInfos := make([]string, 0) @@ -843,7 +849,7 @@ func SetCandidateChangeset( inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: setCandidateMcmsTxs}} - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } @@ -866,9 +872,9 @@ func SetCandidateChangeset( // setCandidateOnExistingDon calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract // This proposes to set up OCR3 config for the provided plugin for the DON func setCandidateOnExistingDon( - e deployment.Environment, + e cldf.Environment, txOpts *bind.TransactOpts, - homeChain deployment.Chain, + homeChain cldf.Chain, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes, @@ -907,7 +913,7 @@ func setCandidateOnExistingDon( nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ { - CapabilityId: ccip.CCIPCapabilityID, + CapabilityId: shared.CCIPCapabilityID, Config: encodedSetCandidateCall, }, }, @@ -917,7 +923,7 @@ func setCandidateOnExistingDon( // note: error check is handled below if !mcmsEnabled { - _, err = deployment.ConfirmIfNoErrorWithABI( + _, err = cldf.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, ccip_home.CCIPHomeABI, err) if err != nil { return nil, fmt.Errorf("error confirming UpdateDON call in set candidate (don: %d; ptype: %s): %w", @@ -928,7 +934,7 @@ func setCandidateOnExistingDon( donID, types.PluginType(pluginConfig.PluginType).String(), err) } - tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), big.NewInt(0), string(changeset.CapabilitiesRegistry), []string{}) + tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), big.NewInt(0), string(shared.CapabilitiesRegistry), []string{}) if err != nil { return nil, fmt.Errorf("failed to create UpdateDON mcms tx in set candidate (don: %d; ptype: %s): %w", donID, types.PluginType(pluginConfig.PluginType).String(), err) @@ -940,7 +946,7 @@ func setCandidateOnExistingDon( // promoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry func promoteCandidateOp( txOpts *bind.TransactOpts, - homeChain deployment.Chain, + homeChain cldf.Chain, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes, @@ -970,7 +976,7 @@ func promoteCandidateOp( nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ { - CapabilityId: ccip.CCIPCapabilityID, + CapabilityId: shared.CCIPCapabilityID, Config: encodedPromotionCall, }, }, @@ -980,7 +986,7 @@ func promoteCandidateOp( // note: error check is handled below if !mcmsEnabled { - _, err = deployment.ConfirmIfNoErrorWithABI( + _, err = cldf.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, ccip_home.CCIPHomeABI, err) if err != nil { return mcmstypes.Transaction{}, fmt.Errorf("error confirming UpdateDON call in promote candidate (don: %d; ptype: %s): %w", @@ -992,7 +998,7 @@ func promoteCandidateOp( } tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), - big.NewInt(0), string(changeset.CapabilitiesRegistry), []string{}) + big.NewInt(0), string(shared.CapabilitiesRegistry), []string{}) if err != nil { return mcmstypes.Transaction{}, fmt.Errorf("failed to create UpdateDON mcms tx in promote candidate (don: %d; ptype: %s): %w", donID, types.PluginType(pluginType).String(), err) @@ -1005,7 +1011,7 @@ func promoteCandidateOp( func promoteCandidateForChainOps( lggr logger.Logger, txOpts *bind.TransactOpts, - homeChain deployment.Chain, + homeChain cldf.Chain, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes, @@ -1054,11 +1060,11 @@ type RevokeCandidateChangesetConfig struct { MCMS *proposalutils.TimelockConfig `json:"mcms,omitempty"` } -func (r RevokeCandidateChangesetConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) (donID uint32, err error) { - if err := deployment.IsValidChainSelector(r.HomeChainSelector); err != nil { +func (r RevokeCandidateChangesetConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) (donID uint32, err error) { + if err := cldf.IsValidChainSelector(r.HomeChainSelector); err != nil { return 0, fmt.Errorf("home chain selector invalid: %w", err) } - if err := deployment.IsValidChainSelector(r.RemoteChainSelector); err != nil { + if err := cldf.IsValidChainSelector(r.RemoteChainSelector); err != nil { return 0, fmt.Errorf("don chain selector invalid: %w", err) } if len(e.NodeIDs) == 0 { @@ -1103,8 +1109,8 @@ func (r RevokeCandidateChangesetConfig) Validate(e deployment.Environment, state return donID, nil } -func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func RevokeCandidateChangeset(e cldf.Environment, cfg RevokeCandidateChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1121,7 +1127,7 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } homeChain := e.Chains[cfg.HomeChainSelector] @@ -1146,7 +1152,7 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} batches := []mcmstypes.BatchOperation{{ChainSelector: mcmstypes.ChainSelector(cfg.HomeChainSelector), Transactions: ops}} - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } @@ -1168,7 +1174,7 @@ func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChang func revokeCandidateOps( txOpts *bind.TransactOpts, - homeChain deployment.Chain, + homeChain cldf.Chain, capReg *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes, @@ -1201,7 +1207,7 @@ func revokeCandidateOps( nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ { - CapabilityId: ccip.CCIPCapabilityID, + CapabilityId: shared.CCIPCapabilityID, Config: encodedRevokeCandidateCall, }, }, @@ -1211,7 +1217,7 @@ func revokeCandidateOps( // note: error check is handled below if !mcmsEnabled { - _, err = deployment.ConfirmIfNoErrorWithABI( + _, err = cldf.ConfirmIfNoErrorWithABI( homeChain, updateDonTx, capabilities_registry.CapabilitiesRegistryABI, err) if err != nil { @@ -1224,7 +1230,7 @@ func revokeCandidateOps( } tx, err := proposalutils.TransactionForChain(homeChain.Selector, capReg.Address().Hex(), updateDonTx.Data(), - big.NewInt(0), string(changeset.CapabilitiesRegistry), []string{}) + big.NewInt(0), string(shared.CapabilitiesRegistry), []string{}) if err != nil { return nil, fmt.Errorf("failed to create UpdateDON mcms tx in revoke candidate (don: %d; ptype: %s): %w", donID, types.PluginType(pluginType).String(), err) @@ -1246,12 +1252,12 @@ type UpdateChainConfigConfig struct { MCMS *proposalutils.TimelockConfig `json:"mcms,omitempty"` } -func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (c UpdateChainConfigConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { + if err := cldf.IsValidChainSelector(c.HomeChainSelector); err != nil { return fmt.Errorf("home chain selector invalid: %w", err) } if len(c.RemoteChainRemoves) == 0 && len(c.RemoteChainAdds) == 0 { @@ -1265,7 +1271,7 @@ func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { return err } for _, remove := range c.RemoteChainRemoves { - if err := deployment.IsValidChainSelector(remove); err != nil { + if err := cldf.IsValidChainSelector(remove); err != nil { return fmt.Errorf("chain remove selector invalid: %w", err) } if _, ok := state.SupportedChains()[remove]; !ok { @@ -1273,7 +1279,7 @@ func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { } } for add, ccfg := range c.RemoteChainAdds { - if err := deployment.IsValidChainSelector(add); err != nil { + if err := cldf.IsValidChainSelector(add); err != nil { return fmt.Errorf("chain remove selector invalid: %w", err) } if _, ok := state.SupportedChains()[add]; !ok { @@ -1292,18 +1298,18 @@ func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { return nil } -func UpdateChainConfigChangeset(e deployment.Environment, cfg UpdateChainConfigConfig) (cldf.ChangesetOutput, error) { +func UpdateChainConfigChangeset(e cldf.Environment, cfg UpdateChainConfigConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("%w: %w", cldf.ErrInvalidConfig, err) } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey txOpts.Context = e.GetContext() if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } var adds []ccip_home.CCIPHomeChainConfigArgs for chain, ccfg := range cfg.RemoteChainAdds { @@ -1335,7 +1341,7 @@ func UpdateChainConfigChangeset(e deployment.Environment, cfg UpdateChainConfigC tx, err := state.Chains[cfg.HomeChainSelector].CCIPHome.ApplyChainConfigUpdates(txOpts, cfg.RemoteChainRemoves, adds) if cfg.MCMS == nil { - _, err = deployment.ConfirmIfNoErrorWithABI(e.Chains[cfg.HomeChainSelector], tx, ccip_home.CCIPHomeABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(e.Chains[cfg.HomeChainSelector], tx, ccip_home.CCIPHomeABI, err) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1346,12 +1352,12 @@ func UpdateChainConfigChangeset(e deployment.Environment, cfg UpdateChainConfigC timelocks := map[uint64]string{cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address().Hex()} inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSelector: mcmsevmsdk.NewInspector(e.Chains[cfg.HomeChainSelector].Client)} batchOp, err := proposalutils.BatchOperationForChain(cfg.HomeChainSelector, state.Chains[cfg.HomeChainSelector].CCIPHome.Address().Hex(), - tx.Data(), big.NewInt(0), string(changeset.CCIPHome), []string{}) + tx.Data(), big.NewInt(0), string(shared.CCIPHome), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation: %w", err) } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to build mcm addresses per chain: %w", err) } @@ -1450,8 +1456,8 @@ func ValidateCCIPHomeConfigSetUp( type DeployDonIDClaimerConfig struct{} -func deployDonIDClaimerChangesetLogic(e deployment.Environment, _ DeployDonIDClaimerConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func deployDonIDClaimerChangesetLogic(e cldf.Environment, _ DeployDonIDClaimerConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return cldf.ChangesetOutput{}, err @@ -1477,7 +1483,7 @@ func deployDonIDClaimerChangesetLogic(e deployment.Environment, _ DeployDonIDCla }, nil } -func deployDonIDClaimerContract(e deployment.Environment, ab cldf.AddressBook, state changeset.CCIPOnChainState, chain deployment.Chain) error { +func deployDonIDClaimerContract(e cldf.Environment, ab cldf.AddressBook, state stateview.CCIPOnChainState, chain cldf.Chain) error { chainState, chainExists := state.Chains[chain.Selector] if !chainExists { return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String()) @@ -1485,14 +1491,14 @@ func deployDonIDClaimerContract(e deployment.Environment, ab cldf.AddressBook, s if state.Chains[chain.Selector].DonIDClaimer == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*don_id_claimer.DonIDClaimer] { + func(chain cldf.Chain) cldf.ContractDeploy[*don_id_claimer.DonIDClaimer] { donIDClaimerAddr, tx2, donIDClaimerC, err2 := don_id_claimer.DeployDonIDClaimer( chain.DeployerKey, chain.Client, chainState.CapabilityRegistry.Address(), ) return cldf.ContractDeploy[*don_id_claimer.DonIDClaimer]{ - Address: donIDClaimerAddr, Contract: donIDClaimerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.DonIDClaimer, deployment.Version1_6_1), Err: err2, + Address: donIDClaimerAddr, Contract: donIDClaimerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.DonIDClaimer, deployment.Version1_6_1), Err: err2, } }) if err != nil { @@ -1506,8 +1512,8 @@ func deployDonIDClaimerContract(e deployment.Environment, ab cldf.AddressBook, s return nil } -func deployDonIDClaimerPrecondition(e deployment.Environment, _ DeployDonIDClaimerConfig) error { - state, err := changeset.LoadOnchainState(e) +func deployDonIDClaimerPrecondition(e cldf.Environment, _ DeployDonIDClaimerConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -1524,8 +1530,8 @@ type DonIDClaimerOffSetConfig struct { OffSet uint32 `json:"offset"` } -func donIDClaimerOffSetChangesetLogic(e deployment.Environment, cfg DonIDClaimerOffSetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func donIDClaimerOffSetChangesetLogic(e cldf.Environment, cfg DonIDClaimerOffSetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return cldf.ChangesetOutput{}, err @@ -1543,15 +1549,15 @@ func donIDClaimerOffSetChangesetLogic(e deployment.Environment, cfg DonIDClaimer txOpts.Context = e.GetContext() tx, err := donIDClaimer.SyncNextDONIdWithOffset(txOpts, cfg.OffSet) - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[homeChainSel], tx, don_id_claimer.DonIDClaimerABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[homeChainSel], tx, don_id_claimer.DonIDClaimerABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error apply offset to donIDClaimer for chain %d: %w", homeChainSel, err) } return cldf.ChangesetOutput{}, err } -func donIDClaimerOffSetChangesetPrecondition(e deployment.Environment, c DonIDClaimerOffSetConfig) error { - state, err := changeset.LoadOnchainState(e) +func donIDClaimerOffSetChangesetPrecondition(e cldf.Environment, c DonIDClaimerOffSetConfig) error { + state, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return err @@ -1588,8 +1594,8 @@ func donIDClaimerOffSetChangesetPrecondition(e deployment.Environment, c DonIDCl return nil } -func donIDClaimerValidationHelper(state changeset.CCIPOnChainState, homeChainSelector uint64) error { - if err := deployment.IsValidChainSelector(homeChainSelector); err != nil { +func donIDClaimerValidationHelper(state stateview.CCIPOnChainState, homeChainSelector uint64) error { + if err := cldf.IsValidChainSelector(homeChainSelector); err != nil { return fmt.Errorf("home chain selector invalid: %w", err) } diff --git a/deployment/ccip/changeset/v1_6/cs_ccip_home_test.go b/deployment/ccip/changeset/v1_6/cs_ccip_home_test.go index 43f0c62e574..9a16b5be6c5 100644 --- a/deployment/ccip/changeset/v1_6/cs_ccip_home_test.go +++ b/deployment/ccip/changeset/v1_6/cs_ccip_home_test.go @@ -17,11 +17,12 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -67,7 +68,7 @@ func TestInvalidOCR3Params(t *testing.T) { ) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) @@ -114,7 +115,7 @@ func Test_PromoteCandidate(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2), testhelpers.WithNumOfNodes(4)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -212,7 +213,7 @@ func Test_SetCandidate(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2), testhelpers.WithNumOfNodes(4)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -250,7 +251,7 @@ func Test_SetCandidate(t *testing.T) { } } - tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + tokenConfig := shared.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) _, err = commonchangeset.Apply(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ @@ -352,7 +353,7 @@ func Test_RevokeCandidate(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2), testhelpers.WithNumOfNodes(4)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) // Deploy to all chains. @@ -389,7 +390,7 @@ func Test_RevokeCandidate(t *testing.T) { MinDelay: 0, } } - tokenConfig := changeset.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) + tokenConfig := shared.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) _, err = commonchangeset.Apply(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ tenv.HomeChainSel: { @@ -503,7 +504,7 @@ func Test_UpdateChainConfigs(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) diff --git a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go index 3ec84127124..00369601b5b 100644 --- a/deployment/ccip/changeset/v1_6/cs_chain_contracts.go +++ b/deployment/ccip/changeset/v1_6/cs_chain_contracts.go @@ -23,14 +23,15 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/nonce_manager" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" @@ -93,8 +94,8 @@ type PreviousRampCfg struct { AllowEmptyOffRamp bool // If true, the prevOffRamp address can be 0x0. } -func (cfg UpdateNonceManagerConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateNonceManagerConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } @@ -145,11 +146,11 @@ func (cfg UpdateNonceManagerConfig) Validate(e deployment.Environment) error { return nil } -func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManagerConfig) (cldf.ChangesetOutput, error) { +func UpdateNonceManagersChangeset(e cldf.Environment, cfg UpdateNonceManagerConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := changeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -161,7 +162,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } nm := s.Chains[chainSel].NonceManager var authTx, prevRampsTx *types.Transaction @@ -171,7 +172,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag RemovedCallers: updates.RemovedAuthCallers, }) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], authTx, nonce_manager.NonceManagerABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], authTx, nonce_manager.NonceManagerABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating authorized callers for chain %s: %w", e.Chains[chainSel].String(), err) } @@ -202,7 +203,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag } prevRampsTx, err = nm.ApplyPreviousRampsUpdates(txOpts, previousRampsArgs) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], prevRampsTx, nonce_manager.NonceManagerABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], prevRampsTx, nonce_manager.NonceManagerABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating previous ramps for chain %s: %w", e.Chains[chainSel].String(), err) } } else { @@ -215,7 +216,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag mcmsTransactions := make([]mcmstypes.Transaction, 0) if authTx != nil { mcmsTx, err := proposalutils.TransactionForChain(chainSel, nm.Address().Hex(), authTx.Data(), big.NewInt(0), - string(changeset.NonceManager), []string{}) + string(shared.NonceManager), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction for chain %d: %w", chainSel, err) } @@ -224,7 +225,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag } if prevRampsTx != nil { mcmsTx, err := proposalutils.TransactionForChain(chainSel, nm.Address().Hex(), prevRampsTx.Data(), big.NewInt(0), - string(changeset.NonceManager), []string{}) + string(shared.NonceManager), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create transaction for chain %d: %w", chainSel, err) } @@ -250,7 +251,7 @@ func UpdateNonceManagersChangeset(e deployment.Environment, cfg UpdateNonceManag if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -289,14 +290,14 @@ type UpdateOnRampDestsConfig struct { SkipOwnershipCheck bool } -func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateOnRampDestsConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } supportedChains := state.SupportedChains() for chainSel, updates := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } chainState, ok := state.Chains[chainSel] @@ -337,11 +338,11 @@ func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error { // UpdateOnRampsDestsChangeset updates the onramp destinations for each onramp // in the chains specified. Multichain support is important - consider when we add a new chain // and need to update the onramp destinations for all chains to support the new chain. -func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDestsConfig) (cldf.ChangesetOutput, error) { +func UpdateOnRampsDestsChangeset(e cldf.Environment, cfg UpdateOnRampDestsConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := changeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -354,7 +355,7 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } onRamp := s.Chains[chainSel].OnRamp var args []onramp.OnRampDestChainConfigArgs @@ -376,7 +377,7 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests } tx, err := onRamp.ApplyDestChainConfigUpdates(txOpts, args) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating onramp destinations for chain %s: %w", e.Chains[chainSel].String(), err) } } else { @@ -385,7 +386,7 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OnRamp), []string{}) + big.NewInt(0), string(shared.OnRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -401,7 +402,7 @@ func UpdateOnRampsDestsChangeset(e deployment.Environment, cfg UpdateOnRampDests if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -435,9 +436,9 @@ type UpdateOnRampDynamicConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateOnRampDynamicConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (cfg UpdateOnRampDynamicConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { for chainSel, config := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, state.Chains[chainSel].Timelock.Address(), state.Chains[chainSel].OnRamp); err != nil { @@ -453,8 +454,8 @@ func (cfg UpdateOnRampDynamicConfig) Validate(e deployment.Environment, state ch return nil } -func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRampDynamicConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func UpdateOnRampDynamicConfigChangeset(e cldf.Environment, cfg UpdateOnRampDynamicConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -469,7 +470,7 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa for chainSel, update := range cfg.UpdatesByChain { txOps := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOps = deployment.SimTransactOpts() + txOps = cldf.SimTransactOpts() } onRamp := state.Chains[chainSel].OnRamp dynamicConfig, err := onRamp.GetDynamicConfig(nil) @@ -492,7 +493,7 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa }) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating onramp dynamic config for chain %s: %w", e.Chains[chainSel].String(), err) } } else { @@ -501,7 +502,7 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OnRamp), []string{}) + big.NewInt(0), string(shared.OnRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -517,7 +518,7 @@ func UpdateOnRampDynamicConfigChangeset(e deployment.Environment, cfg UpdateOnRa if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -546,13 +547,13 @@ type UpdateOnRampAllowListConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateOnRampAllowListConfig) Validate(env deployment.Environment) error { - state, err := changeset.LoadOnchainState(env) +func (cfg UpdateOnRampAllowListConfig) Validate(env cldf.Environment) error { + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } for srcSel, updates := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(env, state, srcSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(env, state, srcSel, cfg.MCMS); err != nil { return err } onRamp := state.Chains[srcSel].OnRamp @@ -580,7 +581,7 @@ func (cfg UpdateOnRampAllowListConfig) Validate(env deployment.Environment) erro } } for destSel, update := range updates { - if err := changeset.ValidateChain(env, state, srcSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(env, state, srcSel, cfg.MCMS); err != nil { return err } if len(update.AddedAllowlistedSenders) > 0 && !update.AllowListEnabled { @@ -596,11 +597,11 @@ func (cfg UpdateOnRampAllowListConfig) Validate(env deployment.Environment) erro return nil } -func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAllowListConfig) (cldf.ChangesetOutput, error) { +func UpdateOnRampAllowListChangeset(e cldf.Environment, cfg UpdateOnRampAllowListConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - onchain, err := changeset.LoadOnchainState(e) + onchain, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -612,7 +613,7 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl for srcSel, updates := range cfg.UpdatesByChain { txOps := e.Chains[srcSel].DeployerKey if cfg.MCMS != nil { - txOps = deployment.SimTransactOpts() + txOps = cldf.SimTransactOpts() } onRamp := onchain.Chains[srcSel].OnRamp args := make([]onramp.OnRampAllowlistConfigArgs, len(updates)) @@ -651,7 +652,7 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl } tx, err := onRamp.ApplyAllowlistUpdates(txOps, args) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[srcSel], tx, onramp.OnRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[srcSel], tx, onramp.OnRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating allowlist for chain %d: %w", srcSel, err) } } else { @@ -660,7 +661,7 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl } batchOperation, err := proposalutils.BatchOperationForChain(srcSel, onRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OnRamp), []string{}) + big.NewInt(0), string(shared.OnRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -676,7 +677,7 @@ func UpdateOnRampAllowListChangeset(e deployment.Environment, cfg UpdateOnRampAl if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, onchain, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, onchain, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -701,9 +702,9 @@ type WithdrawOnRampFeeTokensConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg WithdrawOnRampFeeTokensConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (cfg WithdrawOnRampFeeTokensConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { for chainSel, feeTokens := range cfg.FeeTokensByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, state.Chains[chainSel].Timelock.Address(), state.Chains[chainSel].OnRamp); err != nil { @@ -736,8 +737,8 @@ func (cfg WithdrawOnRampFeeTokensConfig) Validate(e deployment.Environment, stat return nil } -func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRampFeeTokensConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func WithdrawOnRampFeeTokensChangeset(e cldf.Environment, cfg WithdrawOnRampFeeTokensConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -754,7 +755,7 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa onRamp := state.Chains[chainSel].OnRamp tx, err := onRamp.WithdrawFeeTokens(txOps, feeTokens) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, onramp.OnRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error withdrawing fee tokens for chain %s: %w", e.Chains[chainSel].String(), err) } } else { @@ -763,7 +764,7 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, onRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OnRamp), []string{}) + big.NewInt(0), string(shared.OnRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -779,7 +780,7 @@ func WithdrawOnRampFeeTokensChangeset(e deployment.Environment, cfg WithdrawOnRa if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -809,13 +810,13 @@ type FeeQuoterPriceUpdatePerSource struct { GasPrices map[uint64]*big.Int // dest chain -> gas price } -func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateFeeQuoterPricesConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } for chainSel, initialPrice := range cfg.PricesByChain { - if err := deployment.IsValidChainSelector(chainSel); err != nil { + if err := cldf.IsValidChainSelector(chainSel); err != nil { return fmt.Errorf("invalid chain selector: %w", err) } chainState, ok := state.Chains[chainSel] @@ -869,7 +870,7 @@ func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error if chainSel == dest { return errors.New("source and dest chain cannot be the same") } - if err := deployment.IsValidChainSelector(dest); err != nil { + if err := cldf.IsValidChainSelector(dest); err != nil { return fmt.Errorf("invalid dest chain selector: %w", err) } if price == nil { @@ -884,11 +885,11 @@ func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error return nil } -func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuoterPricesConfig) (cldf.ChangesetOutput, error) { +func UpdateFeeQuoterPricesChangeset(e cldf.Environment, cfg UpdateFeeQuoterPricesConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := changeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -900,7 +901,7 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote for chainSel, initialPrice := range cfg.PricesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := s.Chains[chainSel].FeeQuoter var tokenPricesArgs []fee_quoter.InternalTokenPriceUpdate @@ -922,7 +923,7 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote GasPriceUpdates: gasPricesArgs, }) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error confirming transaction for chain %s: %w", e.Chains[chainSel].String(), err) } } else { @@ -931,7 +932,7 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, fq.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.FeeQuoter), []string{}) + big.NewInt(0), string(shared.FeeQuoter), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -947,7 +948,7 @@ func UpdateFeeQuoterPricesChangeset(e deployment.Environment, cfg UpdateFeeQuote if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -975,8 +976,8 @@ type UpdateFeeQuoterDestsConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateFeeQuoterDestsConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateFeeQuoterDestsConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } @@ -1016,11 +1017,11 @@ func (cfg UpdateFeeQuoterDestsConfig) Validate(e deployment.Environment) error { return nil } -func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoterDestsConfig) (cldf.ChangesetOutput, error) { +func UpdateFeeQuoterDestsChangeset(e cldf.Environment, cfg UpdateFeeQuoterDestsConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - s, err := changeset.LoadOnchainState(e) + s, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1033,7 +1034,7 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := s.Chains[chainSel].FeeQuoter var args []fee_quoter.FeeQuoterDestChainConfigArgs @@ -1045,7 +1046,7 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter } tx, err := fq.ApplyDestChainConfigUpdates(txOpts, args) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, err } } else { @@ -1053,7 +1054,7 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter return cldf.ChangesetOutput{}, err } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, fq.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.FeeQuoter), []string{}) + big.NewInt(0), string(shared.FeeQuoter), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1069,7 +1070,7 @@ func UpdateFeeQuoterDestsChangeset(e deployment.Environment, cfg UpdateFeeQuoter if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, s, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1107,7 +1108,7 @@ type UpdateOffRampSourcesConfig struct { SkipOwnershipCheck bool } -func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (cfg UpdateOffRampSourcesConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { supportedChains := state.SupportedChains() for chainSel, updates := range cfg.UpdatesByChain { chainState, ok := state.Chains[chainSel] @@ -1139,7 +1140,7 @@ func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment, state c return fmt.Errorf("cannot update offramp source to the same chain %d", source) } - if err := state.ValidateRamp(source, changeset.OnRamp); err != nil { + if err := state.ValidateRamp(source, shared.OnRamp); err != nil { return err } } @@ -1148,8 +1149,8 @@ func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment, state c } // UpdateOffRampSourcesChangeset updates the offramp sources for each offramp. -func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSourcesConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func UpdateOffRampSourcesChangeset(e cldf.Environment, cfg UpdateOffRampSourcesConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1165,7 +1166,7 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } offRamp := state.Chains[chainSel].OffRamp var args []offramp.OffRampSourceChainConfigArgs @@ -1191,7 +1192,7 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo tx, err := offRamp.ApplySourceChainConfigUpdates(txOpts, args) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, offramp.OffRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, offramp.OffRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying source chain config updates for chain %d: %w", chainSel, err) } } else { @@ -1200,7 +1201,7 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, offRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OffRamp), []string{}) + big.NewInt(0), string(shared.OffRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1216,7 +1217,7 @@ func UpdateOffRampSourcesChangeset(e deployment.Environment, cfg UpdateOffRampSo if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1253,7 +1254,7 @@ type UpdateRouterRampsConfig struct { SkipOwnershipCheck bool } -func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (cfg UpdateRouterRampsConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { if !cfg.TestRouter { // If not using the test router, we need to enforce MCMS usage if the state calls for it. err := state.EnforceMCMSUsageIfProd(e.GetContext(), cfg.MCMS) @@ -1263,7 +1264,7 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state chan } supportedChains := state.SupportedChains() for chainSel, update := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } chainState, ok := state.Chains[chainSel] @@ -1313,7 +1314,7 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state chan if source == chainSel { return fmt.Errorf("cannot update offramp source to the same chain %d", source) } - if err := state.ValidateRamp(source, changeset.OnRamp); err != nil { + if err := state.ValidateRamp(source, shared.OnRamp); err != nil { return err } } @@ -1325,7 +1326,7 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state chan if destination == chainSel { return fmt.Errorf("cannot update onRamp dest to the same chain %d", destination) } - if err := state.ValidateRamp(destination, changeset.OffRamp); err != nil { + if err := state.ValidateRamp(destination, shared.OffRamp); err != nil { return err } } @@ -1340,8 +1341,8 @@ func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment, state chan // - New chain support. When adding a new chain, you can enable the new destination // on all chains to support the new chain through the test router first. Once tested, // Enable the new destination on the real router. -func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func UpdateRouterRampsChangeset(e cldf.Environment, cfg UpdateRouterRampsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1357,7 +1358,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC txOpts := e.Chains[chainSel].DeployerKey txOpts.Context = e.GetContext() if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } routerC := state.Chains[chainSel].Router if cfg.TestRouter { @@ -1399,7 +1400,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC } tx, err := routerC.ApplyRampUpdates(txOpts, onRampUpdates, removes, adds) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, router.RouterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, router.RouterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying ramp updates for chain %d: %w", chainSel, err) } } else { @@ -1408,7 +1409,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, routerC.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.Router), []string{}) + big.NewInt(0), string(shared.Router), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1424,7 +1425,7 @@ func UpdateRouterRampsChangeset(e deployment.Environment, cfg UpdateRouterRampsC if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1451,8 +1452,8 @@ type SetOCR3OffRampConfig struct { MCMS *proposalutils.TimelockConfig } -func (c SetOCR3OffRampConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { - if err := changeset.ValidateChain(e, state, c.HomeChainSel, c.MCMS); err != nil { +func (c SetOCR3OffRampConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { + if err := stateview.ValidateChain(e, state, c.HomeChainSel, c.MCMS); err != nil { return err } if c.CCIPHomeConfigType != globals.ConfigTypeActive && @@ -1467,7 +1468,7 @@ func (c SetOCR3OffRampConfig) Validate(e deployment.Environment, state changeset return nil } -func (c SetOCR3OffRampConfig) validateRemoteChain(e *deployment.Environment, state *changeset.CCIPOnChainState, chainSelector uint64) error { +func (c SetOCR3OffRampConfig) validateRemoteChain(e *cldf.Environment, state *stateview.CCIPOnChainState, chainSelector uint64) error { family, err := chain_selectors.GetSelectorFamily(chainSelector) if err != nil { return err @@ -1501,8 +1502,8 @@ func (c SetOCR3OffRampConfig) validateRemoteChain(e *deployment.Environment, sta // run after the candidate is confirmed to be working correctly. // Multichain is especially helpful for NOP rotations where we have // to touch all the chain to change signers. -func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func SetOCR3OffRampChangeset(e cldf.Environment, cfg SetOCR3OffRampConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1537,12 +1538,12 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) } txOpts := e.Chains[remote].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } offRamp := state.Chains[remote].OffRamp tx, err := offRamp.SetOCR3Configs(txOpts, args) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[remote], tx, offramp.OffRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[remote], tx, offramp.OffRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error setting OCR3 config for chain %d: %w", remote, err) } e.Logger.Infow("Set OCR3 config on offramp", "chain", remote, @@ -1554,7 +1555,7 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) } batchOperation, err := proposalutils.BatchOperationForChain(remote, offRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OffRamp), []string{}) + big.NewInt(0), string(shared.OffRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1570,7 +1571,7 @@ func SetOCR3OffRampChangeset(e deployment.Environment, cfg SetOCR3OffRampConfig) if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1596,13 +1597,13 @@ type UpdateDynamicConfigOffRampConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg UpdateDynamicConfigOffRampConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateDynamicConfigOffRampConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } for chainSel, params := range cfg.Updates { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return fmt.Errorf("chain %d: %w", chainSel, err) } if state.Chains[chainSel].OffRamp == nil { @@ -1632,11 +1633,11 @@ func (cfg UpdateDynamicConfigOffRampConfig) Validate(e deployment.Environment) e return nil } -func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDynamicConfigOffRampConfig) (cldf.ChangesetOutput, error) { +func UpdateDynamicConfigOffRampChangeset(e cldf.Environment, cfg UpdateDynamicConfigOffRampConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1649,7 +1650,7 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn chain := e.Chains[chainSel] txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } offRamp := state.Chains[chainSel].OffRamp dCfg := offramp.OffRampDynamicConfig{ @@ -1659,7 +1660,7 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn } tx, err := offRamp.SetDynamicConfig(txOpts, dCfg) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, offramp.OffRampABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, offramp.OffRampABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error updating offramp dynamic config for chain %d: %w", chainSel, err) } e.Logger.Infow("Updated offramp dynamic config", "chain", chain.String(), "config", dCfg) @@ -1669,7 +1670,7 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn } batchOperation, err := proposalutils.BatchOperationForChain(chainSel, offRamp.Address().Hex(), tx.Data(), - big.NewInt(0), string(changeset.OffRamp), []string{}) + big.NewInt(0), string(shared.OffRamp), []string{}) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1685,7 +1686,7 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1708,7 +1709,7 @@ func UpdateDynamicConfigOffRampChangeset(e deployment.Environment, cfg UpdateDyn func isOCR3ConfigSetOnOffRamp( lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, offRamp offramp.OffRampInterface, offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs, ) (bool, error) { @@ -1805,17 +1806,17 @@ type ApplyFeeTokensUpdatesConfig struct { } type ApplyFeeTokensUpdatesConfigPerChain struct { - TokensToRemove []changeset.TokenSymbol - TokensToAdd []changeset.TokenSymbol + TokensToRemove []shared.TokenSymbol + TokensToAdd []shared.TokenSymbol } -func (cfg ApplyFeeTokensUpdatesConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg ApplyFeeTokensUpdatesConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } for chainSel, updates := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMSConfig); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMSConfig); err != nil { return err } chainState := state.Chains[chainSel] @@ -1852,11 +1853,11 @@ func (cfg ApplyFeeTokensUpdatesConfig) Validate(e deployment.Environment) error // ApplyFeeTokensUpdatesFeeQuoterChangeset applies the token updates to the fee quoter to add or remove fee tokens. // If MCMSConfig is provided, it will create a proposal to apply the changes assuming the fee quoter is owned by the timelock. // If MCMSConfig is nil, it will apply the changes directly using the deployer key for each chain. -func ApplyFeeTokensUpdatesFeeQuoterChangeset(e deployment.Environment, cfg ApplyFeeTokensUpdatesConfig) (cldf.ChangesetOutput, error) { +func ApplyFeeTokensUpdatesFeeQuoterChangeset(e cldf.Environment, cfg ApplyFeeTokensUpdatesConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1866,7 +1867,7 @@ func ApplyFeeTokensUpdatesFeeQuoterChangeset(e deployment.Environment, cfg Apply for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMSConfig != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := state.Chains[chainSel].FeeQuoter tokenAddresses, err := state.Chains[chainSel].TokenAddressBySymbol() @@ -1882,7 +1883,7 @@ func ApplyFeeTokensUpdatesFeeQuoterChangeset(e deployment.Environment, cfg Apply } tx, err := fq.ApplyFeeTokensUpdates(txOpts, tokensToRemove, tokensToAdd) if cfg.MCMSConfig == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying token updates for chain %d: %w", chainSel, err) } } else { @@ -1890,7 +1891,7 @@ func ApplyFeeTokensUpdatesFeeQuoterChangeset(e deployment.Environment, cfg Apply return cldf.ChangesetOutput{}, err } op, err := proposalutils.BatchOperationForChain( - chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), changeset.FeeQuoter.String(), nil) + chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), shared.FeeQuoter.String(), nil) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error creating batch operation for chain %d: %w", chainSel, err) } @@ -1906,7 +1907,7 @@ func ApplyFeeTokensUpdatesFeeQuoterChangeset(e deployment.Environment, cfg Apply if cfg.MCMSConfig == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMSConfig) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -1934,12 +1935,12 @@ type UpdateTokenPriceFeedsConfig struct { } type UpdateTokenPriceFeedsConfigPerChain struct { - SourceToken changeset.TokenSymbol + SourceToken shared.TokenSymbol IsEnabled bool } -func (cfg UpdateTokenPriceFeedsConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg UpdateTokenPriceFeedsConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } @@ -1948,7 +1949,7 @@ func (cfg UpdateTokenPriceFeedsConfig) Validate(e deployment.Environment) error return fmt.Errorf("feed chain %d not found in state", cfg.FeedChainSelector) } for chainSel, updates := range cfg.Updates { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } chainState := state.Chains[chainSel] @@ -1987,12 +1988,12 @@ func (cfg UpdateTokenPriceFeedsConfig) Validate(e deployment.Environment) error // Before applying the changeset, ensure that the environment state/addressbook is up to date with latest token and price feed addresses. // If MCMS is provided, it will create a proposal to apply the changes assuming the fee quoter is owned by the timelock. // If MCMS is nil, it will apply the changes directly using the deployer key for each chain. -func UpdateTokenPriceFeedsFeeQuoterChangeset(e deployment.Environment, cfg UpdateTokenPriceFeedsConfig) (cldf.ChangesetOutput, error) { +func UpdateTokenPriceFeedsFeeQuoterChangeset(e cldf.Environment, cfg UpdateTokenPriceFeedsConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -2002,7 +2003,7 @@ func UpdateTokenPriceFeedsFeeQuoterChangeset(e deployment.Environment, cfg Updat for chainSel, updates := range cfg.Updates { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := state.Chains[chainSel].FeeQuoter tokenAddresses, err := state.Chains[chainSel].TokenAddressBySymbol() @@ -2037,7 +2038,7 @@ func UpdateTokenPriceFeedsFeeQuoterChangeset(e deployment.Environment, cfg Updat } tx, err := fq.UpdateTokenPriceFeeds(txOpts, priceFeedUpdates) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying token price feed update for chain %d: %w", chainSel, err) } } else { @@ -2045,7 +2046,7 @@ func UpdateTokenPriceFeedsFeeQuoterChangeset(e deployment.Environment, cfg Updat return cldf.ChangesetOutput{}, err } op, err := proposalutils.BatchOperationForChain( - chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), changeset.FeeQuoter.String(), nil) + chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), shared.FeeQuoter.String(), nil) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error creating batch operation for chain %d: %w", chainSel, err) } @@ -2061,7 +2062,7 @@ func UpdateTokenPriceFeedsFeeQuoterChangeset(e deployment.Environment, cfg Updat if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -2087,13 +2088,13 @@ type PremiumMultiplierWeiPerEthUpdatesConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg PremiumMultiplierWeiPerEthUpdatesConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg PremiumMultiplierWeiPerEthUpdatesConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } for chainSel, updates := range cfg.Updates { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } chainState := state.Chains[chainSel] @@ -2126,18 +2127,18 @@ func (cfg PremiumMultiplierWeiPerEthUpdatesConfig) Validate(e deployment.Environ } type PremiumMultiplierWeiPerEthUpdatesConfigPerChain struct { - Token changeset.TokenSymbol + Token shared.TokenSymbol PremiumMultiplierWeiPerEth uint64 } // ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset applies the premium multiplier updates for mentioned tokens to the fee quoter. // If MCMS is provided, it will create a proposal to apply the changes assuming the fee quoter is owned by the timelock. // If MCMS is nil, it will apply the changes directly using the deployer key for each chain. -func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e deployment.Environment, cfg PremiumMultiplierWeiPerEthUpdatesConfig) (cldf.ChangesetOutput, error) { +func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e cldf.Environment, cfg PremiumMultiplierWeiPerEthUpdatesConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -2147,7 +2148,7 @@ func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e deployment.Envir for chainSel, updates := range cfg.Updates { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := state.Chains[chainSel].FeeQuoter tokenAddresses, err := state.Chains[chainSel].TokenAddressBySymbol() @@ -2163,7 +2164,7 @@ func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e deployment.Envir } tx, err := fq.ApplyPremiumMultiplierWeiPerEthUpdates(txOpts, premiumMultiplierUpdates) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying premium multiplier updates for chain %d: %w", chainSel, err) } } else { @@ -2171,7 +2172,7 @@ func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e deployment.Envir return cldf.ChangesetOutput{}, err } op, err := proposalutils.BatchOperationForChain( - chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), changeset.FeeQuoter.String(), nil) + chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), shared.FeeQuoter.String(), nil) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error creating batch operation for chain %d: %w", chainSel, err) } @@ -2187,7 +2188,7 @@ func ApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(e deployment.Envir if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } @@ -2213,13 +2214,13 @@ type ApplyTokenTransferFeeConfigUpdatesConfig struct { MCMS *proposalutils.TimelockConfig } -func (cfg ApplyTokenTransferFeeConfigUpdatesConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (cfg ApplyTokenTransferFeeConfigUpdatesConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return err } for chainSel, updates := range cfg.UpdatesByChain { - if err := changeset.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { + if err := stateview.ValidateChain(e, state, chainSel, cfg.MCMS); err != nil { return err } chainState := state.Chains[chainSel] @@ -2245,7 +2246,7 @@ func (cfg ApplyTokenTransferFeeConfigUpdatesConfig) Validate(e deployment.Enviro return fmt.Errorf("dest bytes overhead must be at least %d for token %s in chain %d", globals.CCIPLockOrBurnV1RetBytes, token, chainSel) } } - if err := changeset.ValidateChain(e, state, update.DestChain, nil); err != nil { + if err := stateview.ValidateChain(e, state, update.DestChain, nil); err != nil { return fmt.Errorf("dest chain %d: %w", update.DestChain, err) } } @@ -2256,7 +2257,7 @@ func (cfg ApplyTokenTransferFeeConfigUpdatesConfig) Validate(e deployment.Enviro if _, ok := tokenAddresses[remove.Token]; !ok { return fmt.Errorf("token %s not found in state for chain %d", remove.Token, chainSel) } - if err := changeset.ValidateChain(e, state, remove.DestChain, nil); err != nil { + if err := stateview.ValidateChain(e, state, remove.DestChain, nil); err != nil { return fmt.Errorf("dest chain %d: %w", remove.DestChain, err) } _, err := chainState.FeeQuoter.GetTokenTransferFeeConfig(&bind.CallOpts{ @@ -2287,12 +2288,12 @@ type ApplyTokenTransferFeeConfigUpdatesConfigPerChain struct { type TokenTransferFeeConfigArg struct { DestChain uint64 - TokenTransferFeeConfigPerToken map[changeset.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig + TokenTransferFeeConfigPerToken map[shared.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig } type TokenTransferFeeConfigRemoveArg struct { DestChain uint64 - Token changeset.TokenSymbol + Token shared.TokenSymbol } // ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset applies the token transfer fee config updates for provided tokens to the fee quoter. @@ -2301,11 +2302,11 @@ type TokenTransferFeeConfigRemoveArg struct { // Use this changeset whenever there is a need to update custom token transfer fee config for a chain, dest chain and token. // If MCMS is provided, it will create a proposal to apply the changes assuming the fee quoter is owned by the timelock. // If MCMS is nil, it will apply the changes directly using the deployer key for each chain. -func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e deployment.Environment, cfg ApplyTokenTransferFeeConfigUpdatesConfig) (cldf.ChangesetOutput, error) { +func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e cldf.Environment, cfg ApplyTokenTransferFeeConfigUpdatesConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -2315,7 +2316,7 @@ func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e deployment.Environme for chainSel, updates := range cfg.UpdatesByChain { txOpts := e.Chains[chainSel].DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } fq := state.Chains[chainSel].FeeQuoter tokenAddresses, err := state.Chains[chainSel].TokenAddressBySymbol() @@ -2345,7 +2346,7 @@ func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e deployment.Environme } tx, err := fq.ApplyTokenTransferFeeConfigUpdates(txOpts, tokenTransferFeeConfigs, tokenTransferFeeConfigsRemove) if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(e.Chains[chainSel], tx, fee_quoter.FeeQuoterABI, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error applying token transfer fee config updates for chain %d: %w", chainSel, err) } } else { @@ -2353,7 +2354,7 @@ func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e deployment.Environme return cldf.ChangesetOutput{}, err } op, err := proposalutils.BatchOperationForChain( - chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), changeset.FeeQuoter.String(), nil) + chainSel, fq.Address().String(), tx.Data(), big.NewInt(0), shared.FeeQuoter.String(), nil) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error creating batch operation for chain %d: %w", chainSel, err) } @@ -2369,7 +2370,7 @@ func ApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(e deployment.Environme if cfg.MCMS == nil { return cldf.ChangesetOutput{}, nil } - mcmsContractByChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractByChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error getting mcms contract by chain: %w", err) } diff --git a/deployment/ccip/changeset/v1_6/cs_chain_contracts_test.go b/deployment/ccip/changeset/v1_6/cs_chain_contracts_test.go index 6e0c8ba5e0f..fe7cb7b9791 100644 --- a/deployment/ccip/changeset/v1_6/cs_chain_contracts_test.go +++ b/deployment/ccip/changeset/v1_6/cs_chain_contracts_test.go @@ -26,6 +26,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/v1_5" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" @@ -57,7 +59,7 @@ func TestUpdateOnRampsDests(t *testing.T) { // Default env just has 2 chains with all contracts // deployed but no lanes. tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -133,7 +135,7 @@ func TestUpdateOnRampDynamicConfig(t *testing.T) { // Default env just has 2 chains with all contracts // deployed but no lanes. tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -201,7 +203,7 @@ func TestUpdateOnRampAllowList(t *testing.T) { // Default env just has 2 chains with all contracts // deployed but no lanes. tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -277,7 +279,7 @@ func TestWithdrawOnRampFeeTokens(t *testing.T) { // Default env just has 2 chains with all contracts // deployed but no lanes. tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -391,7 +393,7 @@ func TestUpdateOffRampsSources(t *testing.T) { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -467,7 +469,7 @@ func TestUpdateFQDests(t *testing.T) { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -556,7 +558,7 @@ func TestUpdateRouterRamps(t *testing.T) { t.Run(tc.name, func(t *testing.T) { ctx := testcontext.Get(t) tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -639,7 +641,7 @@ func TestUpdateDynamicConfigOffRampChangeset(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -699,7 +701,7 @@ func TestUpdateNonceManagersCS(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) allChains := maps.Keys(tenv.Env.Chains) @@ -762,7 +764,7 @@ func TestUpdateNonceManagersCSApplyPreviousRampsUpdates(t *testing.T) { }), testhelpers.WithNumOfChains(3), testhelpers.WithChainIDs([]uint64{chainselectors.GETH_TESTNET.EvmChainID})) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) @@ -959,7 +961,7 @@ func TestApplyFeeTokensUpdatesFeeQuoterChangeset(t *testing.T) { ab := cldf.NewMemoryAddressBook() for _, selector := range allChains { _, err := cldf.DeployContract(tenv.Env.Logger, tenv.Env.Chains[selector], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( tenv.Env.Chains[selector].DeployerKey, tenv.Env.Chains[selector].Client, @@ -971,7 +973,7 @@ func TestApplyFeeTokensUpdatesFeeQuoterChangeset(t *testing.T) { return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -980,7 +982,7 @@ func TestApplyFeeTokensUpdatesFeeQuoterChangeset(t *testing.T) { require.NoError(t, err) } require.NoError(t, tenv.Env.ExistingAddresses.Merge(ab)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) source := allChains[0] dest := allChains[1] @@ -1003,8 +1005,8 @@ func TestApplyFeeTokensUpdatesFeeQuoterChangeset(t *testing.T) { v1_6.ApplyFeeTokensUpdatesConfig{ UpdatesByChain: map[uint64]v1_6.ApplyFeeTokensUpdatesConfigPerChain{ source: { - TokensToAdd: []changeset.TokenSymbol{testhelpers.TestTokenSymbol}, - TokensToRemove: []changeset.TokenSymbol{changeset.LinkSymbol}, + TokensToAdd: []shared.TokenSymbol{testhelpers.TestTokenSymbol}, + TokensToRemove: []shared.TokenSymbol{shared.LinkSymbol}, }, }, MCMSConfig: mcmsConfig, @@ -1018,7 +1020,7 @@ func TestApplyFeeTokensUpdatesFeeQuoterChangeset(t *testing.T) { tokenAddresses, err := state.Chains[source].TokenAddressBySymbol() require.NoError(t, err) require.Contains(t, feeTokens, tokenAddresses[testhelpers.TestTokenSymbol]) - require.NotContains(t, feeTokens, tokenAddresses[changeset.LinkSymbol]) + require.NotContains(t, feeTokens, tokenAddresses[shared.LinkSymbol]) }) } } @@ -1042,7 +1044,7 @@ func TestApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(t *testing.T) allChains := maps.Keys(tenv.Env.Chains) source := allChains[0] dest := allChains[1] - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) if tc.mcmsEnabled { // Transfer ownership to timelock so that we can promote the zero digest later down the line. @@ -1078,7 +1080,7 @@ func TestApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(t *testing.T) ab := cldf.NewMemoryAddressBook() for _, selector := range allChains { _, err := cldf.DeployContract(tenv.Env.Logger, tenv.Env.Chains[selector], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( tenv.Env.Chains[selector].DeployerKey, tenv.Env.Chains[selector].Client, @@ -1090,7 +1092,7 @@ func TestApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(t *testing.T) return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -1099,7 +1101,7 @@ func TestApplyPremiumMultiplierWeiPerEthUpdatesFeeQuoterChangeset(t *testing.T) require.NoError(t, err) } require.NoError(t, tenv.Env.ExistingAddresses.Merge(ab)) - state, err = changeset.LoadOnchainState(tenv.Env) + state, err = stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) // now try to apply the changeset for TEST token _, err = commonchangeset.Apply(t, tenv.Env, tenv.TimelockContracts(t), @@ -1157,7 +1159,7 @@ func TestUpdateTokenPriceFeedsFeeQuoterChangeset(t *testing.T) { // deploy a new token ab := cldf.NewMemoryAddressBook() _, err := cldf.DeployContract(tenv.Env.Logger, tenv.Env.Chains[source], ab, - func(chain deployment.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + func(chain cldf.Chain) cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { tokenAddress, tx, token, err := burn_mint_erc677.DeployBurnMintERC677( tenv.Env.Chains[source].DeployerKey, tenv.Env.Chains[source].Client, @@ -1169,7 +1171,7 @@ func TestUpdateTokenPriceFeedsFeeQuoterChangeset(t *testing.T) { return cldf.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, Contract: token, - Tv: cldf.NewTypeAndVersion(changeset.BurnMintToken, deployment.Version1_0_0), + Tv: cldf.NewTypeAndVersion(shared.BurnMintToken, deployment.Version1_0_0), Tx: tx, Err: err, } @@ -1177,7 +1179,7 @@ func TestUpdateTokenPriceFeedsFeeQuoterChangeset(t *testing.T) { ) require.NoError(t, err) require.NoError(t, tenv.Env.ExistingAddresses.Merge(ab)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) if tc.mcmsEnabled { @@ -1219,13 +1221,13 @@ func TestUpdateTokenPriceFeedsFeeQuoterChangeset(t *testing.T) { Updates: map[uint64][]v1_6.UpdateTokenPriceFeedsConfigPerChain{ source: { { - SourceToken: changeset.LinkSymbol, + SourceToken: shared.LinkSymbol, IsEnabled: true, }, }, dest: { { - SourceToken: changeset.LinkSymbol, + SourceToken: shared.LinkSymbol, IsEnabled: true, }, }, @@ -1239,14 +1241,14 @@ func TestUpdateTokenPriceFeedsFeeQuoterChangeset(t *testing.T) { require.NoError(t, err) tokenDetails, err := state.Chains[source].TokenDetailsBySymbol() require.NoError(t, err) - decimals, err := tokenDetails[changeset.LinkSymbol].Decimals(&bind.CallOpts{Context: testcontext.Get(t)}) + decimals, err := tokenDetails[shared.LinkSymbol].Decimals(&bind.CallOpts{Context: testcontext.Get(t)}) require.NoError(t, err) config, err := state.Chains[source].FeeQuoter.GetTokenPriceFeedConfig(&bind.CallOpts{ Context: testcontext.Get(t), - }, tokenAddress[changeset.LinkSymbol]) + }, tokenAddress[shared.LinkSymbol]) require.NoError(t, err) require.True(t, config.IsEnabled) - require.Equal(t, state.Chains[tenv.FeedChainSel].USDFeeds[changeset.LinkSymbol].Address(), config.DataFeedAddress) + require.Equal(t, state.Chains[tenv.FeedChainSel].USDFeeds[shared.LinkSymbol].Address(), config.DataFeedAddress) require.Equal(t, decimals, config.TokenDecimals) }) } @@ -1271,7 +1273,7 @@ func TestApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(t *testing.T) { allChains := maps.Keys(tenv.Env.Chains) source := allChains[0] dest := allChains[1] - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) if tc.mcmsEnabled { // Transfer ownership to timelock so that we can promote the zero digest later down the line. @@ -1294,7 +1296,7 @@ func TestApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(t *testing.T) { TokenTransferFeeConfigRemoveArgs: []v1_6.TokenTransferFeeConfigRemoveArg{ { DestChain: dest, - Token: changeset.LinkSymbol, + Token: shared.LinkSymbol, }, }, }, @@ -1302,8 +1304,8 @@ func TestApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(t *testing.T) { TokenTransferFeeConfigArgs: []v1_6.TokenTransferFeeConfigArg{ { DestChain: source, - TokenTransferFeeConfigPerToken: map[changeset.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ - changeset.LinkSymbol: { + TokenTransferFeeConfigPerToken: map[shared.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ + shared.LinkSymbol: { MinFeeUSDCents: 1, MaxFeeUSDCents: 1, DeciBps: 1, @@ -1330,7 +1332,7 @@ func TestApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(t *testing.T) { TokenTransferFeeConfigRemoveArgs: []v1_6.TokenTransferFeeConfigRemoveArg{ { DestChain: dest, - Token: changeset.LinkSymbol, + Token: shared.LinkSymbol, }, }, }, @@ -1338,8 +1340,8 @@ func TestApplyTokenTransferFeeConfigUpdatesFeeQuoterChangeset(t *testing.T) { TokenTransferFeeConfigArgs: []v1_6.TokenTransferFeeConfigArg{ { DestChain: source, - TokenTransferFeeConfigPerToken: map[changeset.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ - changeset.LinkSymbol: { + TokenTransferFeeConfigPerToken: map[shared.TokenSymbol]fee_quoter.FeeQuoterTokenTransferFeeConfig{ + shared.LinkSymbol: { MinFeeUSDCents: 1, MaxFeeUSDCents: 2, DeciBps: 1, diff --git a/deployment/ccip/changeset/v1_6/cs_deploy_chain.go b/deployment/ccip/changeset/v1_6/cs_deploy_chain.go index 19d36a08962..d6c5613081f 100644 --- a/deployment/ccip/changeset/v1_6/cs_deploy_chain.go +++ b/deployment/ccip/changeset/v1_6/cs_deploy_chain.go @@ -15,7 +15,8 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" @@ -26,7 +27,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_home" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" ) @@ -41,7 +41,7 @@ var _ cldf.ChangeSet[DeployChainContractsConfig] = DeployChainContractsChangeset // In case of migrating from legacy ccip to 1.6, the previous RMN address should be set while deploying RMNRemote. // if there is no existing RMN address found, RMNRemote will be deployed with 0x0 address for previous RMN address // which will set RMN to 0x0 address immutably in RMNRemote. -func DeployChainContractsChangeset(env deployment.Environment, c DeployChainContractsConfig) (cldf.ChangesetOutput, error) { +func DeployChainContractsChangeset(env cldf.Environment, c DeployChainContractsConfig) (cldf.ChangesetOutput, error) { if err := c.Validate(); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) } @@ -49,7 +49,7 @@ func DeployChainContractsChangeset(env deployment.Environment, c DeployChainCont err := deployChainContractsForChains(env, newAddresses, c.HomeChainSelector, c.ContractParamsPerChain) if err != nil { env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "newAddresses", newAddresses) - return cldf.ChangesetOutput{AddressBook: newAddresses}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{AddressBook: newAddresses}, cldf.MaybeDataErr(err) } return cldf.ChangesetOutput{ AddressBook: newAddresses, @@ -62,11 +62,11 @@ type DeployChainContractsConfig struct { } func (c DeployChainContractsConfig) Validate() error { - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { + if err := cldf.IsValidChainSelector(c.HomeChainSelector); err != nil { return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSelector, err) } for cs, args := range c.ContractParamsPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } if err := args.Validate(); err != nil { @@ -158,8 +158,8 @@ func DefaultOffRampParams() OffRampParams { } } -func ValidateHomeChainState(e deployment.Environment, homeChainSel uint64, existingState changeset.CCIPOnChainState) error { - existingState, err := changeset.LoadOnchainState(e) +func ValidateHomeChainState(e cldf.Environment, homeChainSel uint64, existingState stateview.CCIPOnChainState) error { + existingState, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return err @@ -170,17 +170,17 @@ func ValidateHomeChainState(e deployment.Environment, homeChainSel uint64, exist return errors.New("capability registry not found") } cr, err := capReg.GetHashedCapabilityId( - &bind.CallOpts{}, ccip.CapabilityLabelledName, ccip.CapabilityVersion) + &bind.CallOpts{}, shared.CapabilityLabelledName, shared.CapabilityVersion) if err != nil { e.Logger.Errorw("Failed to get hashed capability id", "err", err) return err } - if cr != ccip.CCIPCapabilityID { + if cr != shared.CCIPCapabilityID { return fmt.Errorf("unexpected mismatch between calculated ccip capability id (%s) and expected ccip capability id constant (%s)", hexutil.Encode(cr[:]), - hexutil.Encode(ccip.CCIPCapabilityID[:])) + hexutil.Encode(shared.CCIPCapabilityID[:])) } - capability, err := capReg.GetCapability(nil, ccip.CCIPCapabilityID) + capability, err := capReg.GetCapability(nil, shared.CCIPCapabilityID) if err != nil { e.Logger.Errorw("Failed to get capability", "err", err) return err @@ -202,11 +202,11 @@ func ValidateHomeChainState(e deployment.Environment, homeChainSel uint64, exist } func deployChainContractsForChains( - e deployment.Environment, + e cldf.Environment, ab cldf.AddressBook, homeChainSel uint64, contractParamsPerChain map[uint64]ChainContractParams) error { - existingState, err := changeset.LoadOnchainState(e) + existingState, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return err @@ -258,9 +258,9 @@ func deployChainContractsForChains( return nil } -func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, ab cldf.AddressBook, rmnHome *rmn_home.RMNHome, contractParams ChainContractParams) error { +func deployChainContractsEVM(e cldf.Environment, chain cldf.Chain, ab cldf.AddressBook, rmnHome *rmn_home.RMNHome, contractParams ChainContractParams) error { // check for existing contracts - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { e.Logger.Errorw("Failed to load existing onchain state", "err", err) return err @@ -310,7 +310,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a if chainState.RMNRemote == nil { // TODO: Correctly configure RMN remote. rmnRemote, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*rmn_remote.RMNRemote] { + func(chain cldf.Chain) cldf.ContractDeploy[*rmn_remote.RMNRemote] { rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( chain.DeployerKey, chain.Client, @@ -318,7 +318,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a rmnLegacyAddr, ) return cldf.ContractDeploy[*rmn_remote.RMNRemote]{ - Address: rmnRemoteAddr, Contract: rmnRemote, Tx: tx, Tv: cldf.NewTypeAndVersion(changeset.RMNRemote, deployment.Version1_6_0), Err: err2, + Address: rmnRemoteAddr, Contract: rmnRemote, Tx: tx, Tv: cldf.NewTypeAndVersion(shared.RMNRemote, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -365,7 +365,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a }, FSign: 0, }) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, rmn_remote.RMNRemoteABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, rmn_remote.RMNRemoteABI, err); err != nil { e.Logger.Errorw("Failed to confirm RMNRemote config", "chain", chain.String(), "err", err) return err } @@ -374,7 +374,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a if chainState.TestRouter == nil { _, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*router.Router] { + func(chain cldf.Chain) cldf.ContractDeploy[*router.Router] { routerAddr, tx2, routerC, err2 := router.DeployRouter( chain.DeployerKey, chain.Client, @@ -382,7 +382,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a RMNProxy.Address(), ) return cldf.ContractDeploy[*router.Router]{ - Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.TestRouter, deployment.Version1_2_0), Err: err2, + Address: routerAddr, Contract: routerC, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.TestRouter, deployment.Version1_2_0), Err: err2, } }) if err != nil { @@ -396,14 +396,14 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a nmContract := chainState.NonceManager if chainState.NonceManager == nil { nonceManager, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*nonce_manager.NonceManager] { + func(chain cldf.Chain) cldf.ContractDeploy[*nonce_manager.NonceManager] { nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( chain.DeployerKey, chain.Client, []common.Address{}, // Need to add onRamp after ) return cldf.ContractDeploy[*nonce_manager.NonceManager]{ - Address: nonceManagerAddr, Contract: nonceManager, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.NonceManager, deployment.Version1_6_0), Err: err2, + Address: nonceManagerAddr, Contract: nonceManager, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.NonceManager, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -417,7 +417,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a feeQuoterContract := chainState.FeeQuoter if chainState.FeeQuoter == nil { feeQuoter, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*fee_quoter.FeeQuoter] { + func(chain cldf.Chain) cldf.ContractDeploy[*fee_quoter.FeeQuoter] { prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( chain.DeployerKey, chain.Client, @@ -443,7 +443,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a contractParams.FeeQuoterParams.DestChainConfigArgs, ) return cldf.ContractDeploy[*fee_quoter.FeeQuoter]{ - Address: prAddr, Contract: pr, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.FeeQuoter, deployment.Version1_6_0), Err: err2, + Address: prAddr, Contract: pr, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.FeeQuoter, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -457,7 +457,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a onRampContract := chainState.OnRamp if onRampContract == nil { onRamp, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*onramp.OnRamp] { + func(chain cldf.Chain) cldf.ContractDeploy[*onramp.OnRamp] { onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( chain.DeployerKey, chain.Client, @@ -474,7 +474,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a []onramp.OnRampDestChainConfigArgs{}, ) return cldf.ContractDeploy[*onramp.OnRamp]{ - Address: onRampAddr, Contract: onRamp, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.OnRamp, deployment.Version1_6_0), Err: err2, + Address: onRampAddr, Contract: onRamp, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.OnRamp, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -488,7 +488,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a offRampContract := chainState.OffRamp if offRampContract == nil { offRamp, err := cldf.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*offramp.OffRamp] { + func(chain cldf.Chain) cldf.ContractDeploy[*offramp.OffRamp] { offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( chain.DeployerKey, chain.Client, @@ -507,7 +507,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a []offramp.OffRampSourceChainConfigArgs{}, ) return cldf.ContractDeploy[*offramp.OffRamp]{ - Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.OffRamp, deployment.Version1_6_0), Err: err2, + Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.OffRamp, deployment.Version1_6_0), Err: err2, } }) if err != nil { @@ -537,7 +537,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a // Should be removed after. AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, }) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, fee_quoter.FeeQuoterABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, fee_quoter.FeeQuoterABI, err); err != nil { e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "chain", chain.String(), "err", err) return err } @@ -560,7 +560,7 @@ func deployChainContractsEVM(e deployment.Environment, chain deployment.Chain, a tx, err := nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, }) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, nonce_manager.NonceManagerABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, nonce_manager.NonceManagerABI, err); err != nil { e.Logger.Errorw("Failed to update nonce manager with ramps", "chain", chain.String(), "err", err) return err } diff --git a/deployment/ccip/changeset/v1_6/cs_deploy_chain_test.go b/deployment/ccip/changeset/v1_6/cs_deploy_chain_test.go index b817fb28c5b..f94ff83b0df 100644 --- a/deployment/ccip/changeset/v1_6/cs_deploy_chain_test.go +++ b/deployment/ccip/changeset/v1_6/cs_deploy_chain_test.go @@ -12,6 +12,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -87,7 +89,7 @@ func TestDeployChainContractsChangeset(t *testing.T) { require.NoError(t, err) // load onchain state - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) // verify all contracts populated @@ -112,7 +114,7 @@ func TestDeployChainContractsChangeset(t *testing.T) { ab := cldf.NewMemoryAddressBook() for _, sel := range evmSelectors { require.NoError(t, ab.Save(sel, state.Chains[sel].FeeQuoter.Address().Hex(), - cldf.NewTypeAndVersion(changeset.FeeQuoter, deployment.Version1_6_0))) + cldf.NewTypeAndVersion(shared.FeeQuoter, deployment.Version1_6_0))) } //nolint:staticcheck //SA1019 ignoring deprecated require.NoError(t, e.ExistingAddresses.Remove(ab)) @@ -128,7 +130,7 @@ func TestDeployChainContractsChangeset(t *testing.T) { )) require.NoError(t, err) // verify all contracts populated - postState, err := changeset.LoadOnchainState(e) + postState, err := stateview.LoadOnchainState(e) require.NoError(t, err) for _, sel := range evmSelectors { require.Equal(t, state.Chains[sel].RMNRemote, postState.Chains[sel].RMNRemote) @@ -151,7 +153,7 @@ func TestDeployStaticLinkToken(t *testing.T) { t.Parallel() e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithStaticLink()) // load onchain state - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) for _, chain := range e.Env.AllChainSelectors() { require.NotNil(t, state.Chains[chain].StaticLinkToken) diff --git a/deployment/ccip/changeset/v1_6/cs_home_chain.go b/deployment/ccip/changeset/v1_6/cs_home_chain.go index c113bfaa696..6ddb09b485c 100644 --- a/deployment/ccip/changeset/v1_6/cs_home_chain.go +++ b/deployment/ccip/changeset/v1_6/cs_home_chain.go @@ -24,8 +24,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -60,7 +62,7 @@ var ( ) // DeployHomeChainChangeset is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. -func DeployHomeChainChangeset(env deployment.Environment, cfg DeployHomeChainConfig) (cldf.ChangesetOutput, error) { +func DeployHomeChainChangeset(env cldf.Environment, cfg DeployHomeChainConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return cldf.ChangesetOutput{}, errors.Wrapf(cldf.ErrInvalidConfig, "%v", err) @@ -120,9 +122,9 @@ func (c DeployHomeChainConfig) Validate() error { // and returns a cldf.ContractDeploy struct with the address and contract instance. func deployCapReg( lggr logger.Logger, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, ab cldf.AddressBook, - chain deployment.Chain, + chain cldf.Chain, ) (*cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { homeChainState, exists := state.Chains[chain.Selector] if exists { @@ -130,18 +132,18 @@ func deployCapReg( if cr != nil { lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) return &cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: cr.Address(), Contract: cr, Tv: cldf.NewTypeAndVersion(changeset.CapabilitiesRegistry, deployment.Version1_0_0), + Address: cr.Address(), Contract: cr, Tv: cldf.NewTypeAndVersion(shared.CapabilitiesRegistry, deployment.Version1_0_0), }, nil } } capReg, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: crAddr, Contract: cr, Tv: cldf.NewTypeAndVersion(changeset.CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + Address: crAddr, Contract: cr, Tv: cldf.NewTypeAndVersion(shared.CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, } }) if err != nil { @@ -153,16 +155,16 @@ func deployCapReg( func deployHomeChain( lggr logger.Logger, - e deployment.Environment, + e cldf.Environment, ab cldf.AddressBook, - chain deployment.Chain, + chain cldf.Chain, rmnHomeStatic rmn_home.RMNHomeStaticConfig, rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, ) (*cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { // load existing state - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return nil, fmt.Errorf("failed to load onchain state: %w", err) } @@ -180,14 +182,14 @@ func deployHomeChain( } else { ccipHome, err := cldf.DeployContract( lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*ccip_home.CCIPHome] { + func(chain cldf.Chain) cldf.ContractDeploy[*ccip_home.CCIPHome] { ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( chain.DeployerKey, chain.Client, capReg.Address, ) return cldf.ContractDeploy[*ccip_home.CCIPHome]{ - Address: ccAddr, Tv: cldf.NewTypeAndVersion(changeset.CCIPHome, deployment.Version1_6_0), Tx: tx, Err: err2, Contract: cc, + Address: ccAddr, Tv: cldf.NewTypeAndVersion(shared.CCIPHome, deployment.Version1_6_0), Tx: tx, Err: err2, Contract: cc, } }) if err != nil { @@ -202,13 +204,13 @@ func deployHomeChain( } else { rmnHomeContract, err := cldf.DeployContract( lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*rmn_home.RMNHome] { + func(chain cldf.Chain) cldf.ContractDeploy[*rmn_home.RMNHome] { rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*rmn_home.RMNHome]{ - Address: rmnAddr, Tv: cldf.NewTypeAndVersion(changeset.RMNHome, deployment.Version1_6_0), Tx: tx, Err: err2, Contract: rmn, + Address: rmnAddr, Tv: cldf.NewTypeAndVersion(shared.RMNHome, deployment.Version1_6_0), Tx: tx, Err: err2, Contract: rmn, } }, ) @@ -248,7 +250,7 @@ func deployHomeChain( if setCandidate { tx, err := rmnHome.SetCandidate( chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, configs.CandidateConfig.ConfigDigest) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, rmn_home.RMNHomeABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, rmn_home.RMNHomeABI, err); err != nil { lggr.Errorw("Failed to set candidate on RMNHome", "err", err) return nil, err } @@ -262,7 +264,7 @@ func deployHomeChain( } tx, err := rmnHome.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, rmn_home.RMNHomeABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, rmn_home.RMNHomeABI, err); err != nil { lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "chain", chain.String(), "err", err) return nil, err } @@ -287,8 +289,8 @@ func deployHomeChain( return nil, fmt.Errorf("failed to get capabilities: %w", err) } capabilityToAdd := capabilities_registry.CapabilitiesRegistryCapability{ - LabelledName: ccip.CapabilityLabelledName, - Version: ccip.CapabilityVersion, + LabelledName: shared.CapabilityLabelledName, + Version: shared.CapabilityVersion, CapabilityType: 2, // consensus. not used (?) ResponseType: 0, // report. not used (?) ConfigurationContract: ccipHomeAddr, @@ -308,7 +310,7 @@ func deployHomeChain( chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ capabilityToAdd, }) - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, capabilities_registry.CapabilitiesRegistryABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, capabilities_registry.CapabilitiesRegistryABI, err); err != nil { lggr.Errorw("Failed to add capabilities", "chain", chain.String(), "err", err) return nil, err } @@ -338,7 +340,7 @@ func deployHomeChain( p2pIDsByNodeOpID := make(map[uint32][][32]byte) if len(nodeOpsToAdd) > 0 { tx, err := capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) - txBlockNum, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, capabilities_registry.CapabilitiesRegistryABI, err) + txBlockNum, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, capabilities_registry.CapabilitiesRegistryABI, err) if err != nil { lggr.Errorw("Failed to add node operators", "chain", chain.String(), "err", err) return nil, err @@ -416,7 +418,7 @@ func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.Capabiliti func addNodes( lggr logger.Logger, capReg *capabilities_registry.CapabilitiesRegistry, - chain deployment.Chain, + chain cldf.Chain, p2pIDsByNodeOpId map[uint32][][32]byte, ) error { var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams @@ -445,7 +447,7 @@ func addNodes( Signer: p2pID, // Not used in tests P2pId: p2pID, EncryptionPublicKey: p2pID, // Not used in tests - HashedCapabilityIds: [][32]byte{ccip.CCIPCapabilityID}, + HashedCapabilityIds: [][32]byte{shared.CCIPCapabilityID}, } if existing, ok := existingNodeParams[p2pID]; ok { if isEqualCapabilitiesRegistryNodeParams(existing, nodeParam) { @@ -465,7 +467,7 @@ func addNodes( tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) if err != nil { lggr.Errorw("Failed to add nodes", "chain", chain.String(), - "err", deployment.DecodedErrFromABIIfDataErr(err, capabilities_registry.CapabilitiesRegistryABI)) + "err", cldf.DecodedErrFromABIIfDataErr(err, capabilities_registry.CapabilitiesRegistryABI)) return err } _, err = chain.Confirm(tx) @@ -478,8 +480,8 @@ type RemoveDONsConfig struct { MCMS *proposalutils.TimelockConfig } -func (c RemoveDONsConfig) Validate(homeChain changeset.CCIPChainState) error { - if err := deployment.IsValidChainSelector(c.HomeChainSel); err != nil { +func (c RemoveDONsConfig) Validate(homeChain evm.CCIPChainState) error { + if err := cldf.IsValidChainSelector(c.HomeChainSel); err != nil { return fmt.Errorf("home chain selector must be set %w", err) } if len(c.DonIDs) == 0 { @@ -500,8 +502,8 @@ func (c RemoveDONsConfig) Validate(homeChain changeset.CCIPChainState) error { // RemoveDONs removes DONs from the CapabilitiesRegistry contract. // TODO: Could likely be moved to common, but needs a common state struct first. -func RemoveDONs(e deployment.Environment, cfg RemoveDONsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func RemoveDONs(e cldf.Environment, cfg RemoveDONsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } @@ -515,7 +517,7 @@ func RemoveDONs(e deployment.Environment, cfg RemoveDONsConfig) (cldf.ChangesetO } txOpts := homeChain.DeployerKey if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := homeChainState.CapabilityRegistry.RemoveDONs(txOpts, cfg.DonIDs) @@ -523,7 +525,7 @@ func RemoveDONs(e deployment.Environment, cfg RemoveDONsConfig) (cldf.ChangesetO return cldf.ChangesetOutput{}, err } if cfg.MCMS == nil { - _, err = deployment.ConfirmIfNoErrorWithABI(homeChain, tx, capabilities_registry.CapabilitiesRegistryABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(homeChain, tx, capabilities_registry.CapabilitiesRegistryABI, err) if err != nil { return cldf.ChangesetOutput{}, err } @@ -533,14 +535,14 @@ func RemoveDONs(e deployment.Environment, cfg RemoveDONsConfig) (cldf.ChangesetO batchOperation, err := proposalutils.BatchOperationForChain(cfg.HomeChainSel, homeChainState.CapabilityRegistry.Address().Hex(), tx.Data(), big.NewInt(0), - string(changeset.CapabilitiesRegistry), []string{}) + string(shared.CapabilitiesRegistry), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for home chain: %w", err) } timelocks := map[uint64]string{cfg.HomeChainSel: homeChainState.Timelock.Address().Hex()} inspectors := map[uint64]mcmssdk.Inspector{cfg.HomeChainSel: mcmsevmsdk.NewInspector(homeChain.Client)} - mcmsContractsByActionPerChain, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) + mcmsContractsByActionPerChain, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMS) if err != nil { return cldf.ChangesetOutput{}, err } @@ -567,12 +569,12 @@ type RemoveNodesConfig struct { MCMSCfg *proposalutils.TimelockConfig } -func removeNodesPrecondition(env deployment.Environment, c RemoveNodesConfig) error { - state, err := changeset.LoadOnchainState(env) +func removeNodesPrecondition(env cldf.Environment, c RemoveNodesConfig) error { + state, err := stateview.LoadOnchainState(env) if err != nil { return err } - if err := changeset.ValidateChain(env, state, c.HomeChainSel, c.MCMSCfg); err != nil { + if err := stateview.ValidateChain(env, state, c.HomeChainSel, c.MCMSCfg); err != nil { return err } if len(c.P2PIDsToRemove) == 0 { @@ -642,8 +644,8 @@ func removeNodesPrecondition(env deployment.Environment, c RemoveNodesConfig) er return nil } -func removeNodesLogic(env deployment.Environment, c RemoveNodesConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func removeNodesLogic(env cldf.Environment, c RemoveNodesConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, err } @@ -651,11 +653,11 @@ func removeNodesLogic(env deployment.Environment, c RemoveNodesConfig) (cldf.Cha homeChain := env.Chains[c.HomeChainSel] txOpts := homeChain.DeployerKey if c.MCMSCfg != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := homeChainState.CapabilityRegistry.RemoveNodes(txOpts, c.P2PIDsToRemove) if c.MCMSCfg == nil { - _, err = deployment.ConfirmIfNoErrorWithABI(homeChain, tx, capabilities_registry.CapabilitiesRegistryABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(homeChain, tx, capabilities_registry.CapabilitiesRegistryABI, err) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to remove nodes from capreg %s: %w", homeChainState.CapabilityRegistry.Address().String(), err) @@ -668,13 +670,13 @@ func removeNodesLogic(env deployment.Environment, c RemoveNodesConfig) (cldf.Cha } batchOperation, err := proposalutils.BatchOperationForChain(c.HomeChainSel, homeChainState.CapabilityRegistry.Address().Hex(), tx.Data(), big.NewInt(0), - string(changeset.CapabilitiesRegistry), []string{}) + string(shared.CapabilitiesRegistry), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for home chain: %w", err) } - timelocks := changeset.BuildTimelockAddressPerChain(env, state) - mcmContract, err := changeset.BuildMcmAddressesPerChainByAction(env, state, c.MCMSCfg) + timelocks := deployergroup.BuildTimelockAddressPerChain(env, state) + mcmContract, err := deployergroup.BuildMcmAddressesPerChainByAction(env, state, c.MCMSCfg) if err != nil { return cldf.ChangesetOutput{}, err } @@ -726,8 +728,8 @@ type AddOrUpdateNopsConfig struct { MCMSConfig *proposalutils.TimelockConfig } -func addUpdateOrRemoveNopsPrecondition(env deployment.Environment, c AddOrUpdateNopsConfig) error { - state, err := changeset.LoadOnchainState(env) +func addUpdateOrRemoveNopsPrecondition(env cldf.Environment, c AddOrUpdateNopsConfig) error { + state, err := stateview.LoadOnchainState(env) if err != nil { return err } @@ -735,7 +737,7 @@ func addUpdateOrRemoveNopsPrecondition(env deployment.Environment, c AddOrUpdate if err != nil { return fmt.Errorf("failed to get home chain selector: %w", err) } - if err := changeset.ValidateChain(env, state, c.homeChainSel, c.MCMSConfig); err != nil { + if err := stateview.ValidateChain(env, state, c.homeChainSel, c.MCMSConfig); err != nil { return err } @@ -767,8 +769,8 @@ func addUpdateOrRemoveNopsPrecondition(env deployment.Environment, c AddOrUpdate return nil } -func updateNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func updateNopsLogic(env cldf.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, err } @@ -820,7 +822,7 @@ func updateNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf. return cldf.ChangesetOutput{}, fmt.Errorf("failed to validate access for node operator %s: %w", nop.Name, err) } } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMSConfig). + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMSConfig). WithDeploymentContext("update nops in cap reg") txOpts, err := deployerGroup.GetDeployer(homeChain.Selector) if err != nil { @@ -839,8 +841,8 @@ func updateNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf. // if the sender is the owner of the CapabilitiesRegistry, if onlyOwner is true func validateAccess( ctx context.Context, - chain deployment.Chain, - chainState changeset.CCIPChainState, + chain cldf.Chain, + chainState evm.CCIPChainState, capReg *capabilities_registry.CapabilitiesRegistry, nop capabilities_registry.CapabilitiesRegistryNodeOperator, isMCMS bool, @@ -901,8 +903,8 @@ func allNodeOperatorsByID(ctx context.Context, capReg *capabilities_registry.Cap return nopIDByName, nil } -func addNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func addNopsLogic(env cldf.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, err } @@ -943,7 +945,7 @@ func addNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf.Cha return cldf.ChangesetOutput{}, nil } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMSConfig). + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMSConfig). WithDeploymentContext("add nops in cap reg") txOpts, err := deployerGroup.GetDeployer(homeChain.Selector) if err != nil { @@ -956,8 +958,8 @@ func addNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf.Cha return deployerGroup.Enact() } -func removeNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) +func removeNopsLogic(env cldf.Environment, c AddOrUpdateNopsConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return cldf.ChangesetOutput{}, err } @@ -1000,7 +1002,7 @@ func removeNopsLogic(env deployment.Environment, c AddOrUpdateNopsConfig) (cldf. env.Logger.Infof("No node operators found to be removed") return cldf.ChangesetOutput{}, nil } - deployerGroup := changeset.NewDeployerGroup(env, state, c.MCMSConfig). + deployerGroup := deployergroup.NewDeployerGroup(env, state, c.MCMSConfig). WithDeploymentContext("remove nops in cap reg") txOpts, err := deployerGroup.GetDeployer(homeChain.Selector) if err != nil { diff --git a/deployment/ccip/changeset/v1_6/cs_home_chain_test.go b/deployment/ccip/changeset/v1_6/cs_home_chain_test.go index 18cc1c19306..5301c85676a 100644 --- a/deployment/ccip/changeset/v1_6/cs_home_chain_test.go +++ b/deployment/ccip/changeset/v1_6/cs_home_chain_test.go @@ -15,10 +15,11 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -52,7 +53,7 @@ func TestDeployHomeChain(t *testing.T) { output, err := v1_6.DeployHomeChainChangeset(e, homeChainCfg) require.NoError(t, err) require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) require.NotNil(t, state.Chains[homeChainSel].CCIPHome) @@ -91,7 +92,7 @@ func TestDeployHomeChainIdempotent(t *testing.T) { output, err := v1_6.DeployHomeChainChangeset(e.Env, homeChainCfg) require.NoError(t, err) require.NoError(t, e.Env.ExistingAddresses.Merge(output.AddressBook)) - _, err = changeset.LoadOnchainState(e.Env) + _, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) } @@ -122,7 +123,7 @@ func TestDeployDonIDClaimerAndOffSet(t *testing.T) { )) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) // capabilityRegistryDonID @@ -138,7 +139,7 @@ func TestDeployDonIDClaimerAndOffSet(t *testing.T) { require.NoError(t, err) - state, err = changeset.LoadOnchainState(e) + state, err = stateview.LoadOnchainState(e) require.NoError(t, err) e, err = commonchangeset.Apply(t, e, nil, @@ -161,7 +162,7 @@ func TestDeployDonIDClaimerAndOffSet(t *testing.T) { func TestRemoveDonsValidate(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t) - s, err := changeset.LoadOnchainState(e.Env) + s, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] var tt = []struct { @@ -216,7 +217,7 @@ func TestRemoveDonsValidate(t *testing.T) { func TestRemoveDons(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t) - s, err := changeset.LoadOnchainState(e.Env) + s, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] @@ -275,7 +276,7 @@ func TestRemoveDons(t *testing.T) { func TestAddDonAfterRemoveDons(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t) - s, err := changeset.LoadOnchainState(e.Env) + s, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectors() homeChain := s.Chains[e.HomeChainSel] @@ -379,9 +380,9 @@ func TestAddUpdateAndRemoveNops(t *testing.T) { }) require.NoError(t, err) - s, err := changeset.LoadOnchainState(e.Env) + s, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] @@ -536,9 +537,9 @@ func TestRemoveNodes(t *testing.T) { }) require.NoError(t, err) - s, err := changeset.LoadOnchainState(e.Env) + s, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) homeChain := s.Chains[e.HomeChainSel] allChains := e.Env.AllChainSelectors() diff --git a/deployment/ccip/changeset/v1_6/cs_jobspec.go b/deployment/ccip/changeset/v1_6/cs_jobspec.go index cc6efbcc9f7..7d25c05fbff 100644 --- a/deployment/ccip/changeset/v1_6/cs_jobspec.go +++ b/deployment/ccip/changeset/v1_6/cs_jobspec.go @@ -12,8 +12,9 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" corejob "github.com/smartcontractkit/chainlink/v2/core/services/job" ) @@ -22,7 +23,7 @@ var _ cldf.ChangeSet[any] = CCIPCapabilityJobspecChangeset // CCIPCapabilityJobspecChangeset returns the job specs for the CCIP capability. // The caller needs to propose these job specs to the offchain system. -func CCIPCapabilityJobspecChangeset(env deployment.Environment, _ any) (cldf.ChangesetOutput, error) { +func CCIPCapabilityJobspecChangeset(env cldf.Environment, _ any) (cldf.ChangesetOutput, error) { nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) if err != nil { return cldf.ChangesetOutput{}, err @@ -64,8 +65,8 @@ func CCIPCapabilityJobspecChangeset(env deployment.Environment, _ any) (cldf.Cha if !node.IsBootstrap { spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ P2PV2Bootstrappers: nodes.BootstrapLocators(), - CapabilityVersion: ccip.CapabilityVersion, - CapabilityLabelledName: ccip.CapabilityLabelledName, + CapabilityVersion: shared.CapabilityVersion, + CapabilityLabelledName: shared.CapabilityLabelledName, OCRKeyBundleIDs: keyBundles, P2PKeyID: node.PeerID.String(), RelayConfigs: nil, @@ -74,8 +75,8 @@ func CCIPCapabilityJobspecChangeset(env deployment.Environment, _ any) (cldf.Cha } else { spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ P2PV2Bootstrappers: []string{}, // Intentionally empty for bootstraps. - CapabilityVersion: ccip.CapabilityVersion, - CapabilityLabelledName: ccip.CapabilityLabelledName, + CapabilityVersion: shared.CapabilityVersion, + CapabilityLabelledName: shared.CapabilityLabelledName, OCRKeyBundleIDs: map[string]string{}, P2PKeyID: node.PeerID.String(), RelayConfigs: nil, @@ -189,7 +190,7 @@ func areCCIPSpecsEqual(existingSpecStr, newSpecStr string) (bool, error) { // acceptedOrPendingAcceptedJobSpecs returns a map of nodeID to job specs that are either accepted or pending review // or proposed -func acceptedOrPendingAcceptedJobSpecs(env deployment.Environment, nodes deployment.Nodes) (map[string][]string, error) { +func acceptedOrPendingAcceptedJobSpecs(env cldf.Environment, nodes deployment.Nodes) (map[string][]string, error) { existingSpecs := make(map[string][]string) for _, node := range nodes { jobs, err := env.Offchain.ListJobs(env.GetContext(), &jobv1.ListJobsRequest{ @@ -231,7 +232,7 @@ func acceptedOrPendingAcceptedJobSpecs(env deployment.Environment, nodes deploym // so we return false TODO implement this check when it is available // there is no downside to proposing the same job spec to a node multiple times // It will only be accepted once by node -func isJobProposed(env deployment.Environment, nodeID string, spec string) bool { +func isJobProposed(env cldf.Environment, nodeID string, spec string) bool { // implement this when it is available return false } diff --git a/deployment/ccip/changeset/v1_6/cs_rmn_curse_uncurse.go b/deployment/ccip/changeset/v1_6/cs_rmn_curse_uncurse.go index ac2dc15e70e..6fe59f8f8c2 100644 --- a/deployment/ccip/changeset/v1_6/cs_rmn_curse_uncurse.go +++ b/deployment/ccip/changeset/v1_6/cs_rmn_curse_uncurse.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" chain_selectors "github.com/smartcontractkit/chain-selectors" solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" @@ -15,9 +16,13 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + solCommonUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/common" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" + solanastateview "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -36,7 +41,7 @@ type RMNCurseAction struct { // CurseAction is a function that returns a list of RMNCurseAction to be applied on a chain // CurseChain, CurseLane, CurseGloballyOnlyOnSource are examples of function implementing CurseAction -type CurseAction func(e deployment.Environment) ([]RMNCurseAction, error) +type CurseAction func(e cldf.Environment) ([]RMNCurseAction, error) type RMNCurseConfig struct { MCMS *proposalutils.TimelockConfig @@ -48,8 +53,11 @@ type RMNCurseConfig struct { Reason string } -func (c RMNCurseConfig) Validate(e deployment.Environment) error { - state, err := changeset.LoadOnchainState(e) +func (c RMNCurseConfig) Validate(e cldf.Environment) error { + state, err := stateview.LoadOnchainState(e) + if err != nil { + return fmt.Errorf("failed to load onchain state: %w", err) + } err = state.EnforceMCMSUsageIfProd(e.GetContext(), c.MCMS) if err != nil { return err @@ -87,7 +95,7 @@ func (c RMNCurseConfig) Validate(e deployment.Environment) error { } for _, action := range result { - if err = deployment.IsValidChainSelector(action.ChainSelector); err != nil { + if err = cldf.IsValidChainSelector(action.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector %d", action.ChainSelector) } @@ -122,7 +130,7 @@ func (c RMNCurseConfig) Validate(e deployment.Environment) error { if !ok { return fmt.Errorf("chain %s not found in onchain state", targetChain.String()) } - if err := changeset.ValidateOwnershipSolana(&e, targetChain, c.MCMS != nil, targetChainState.RMNRemote, changeset.RMNRemote, solana.PublicKey{}); err != nil { + if err := solanastateview.ValidateOwnershipSolana(&e, targetChain, c.MCMS != nil, targetChainState.RMNRemote, shared.RMNRemote, solana.PublicKey{}); err != nil { return fmt.Errorf("chain %s: %w", targetChain.String(), err) } } @@ -139,7 +147,7 @@ func (c RMNCurseConfig) Validate(e deployment.Environment) error { // CurseLaneOnlyOnSource(A, B) will curse A with the curse subject of B func CurseLaneOnlyOnSource(sourceSelector uint64, destinationSelector uint64) CurseAction { // Curse from source to destination - return func(e deployment.Environment) ([]RMNCurseAction, error) { + return func(e cldf.Environment) ([]RMNCurseAction, error) { family, err := chain_selectors.GetSelectorFamily(sourceSelector) if err != nil { return nil, err @@ -158,7 +166,7 @@ func CurseLaneOnlyOnSource(sourceSelector uint64, destinationSelector uint64) Cu // Given 3 chains A, B, C // CurseGloballyOnlyOnChain(A) will curse a with the global curse subject only func CurseGloballyOnlyOnChain(selector uint64) CurseAction { - return func(e deployment.Environment) ([]RMNCurseAction, error) { + return func(e cldf.Environment) ([]RMNCurseAction, error) { return []RMNCurseAction{ { ChainSelector: selector, @@ -174,7 +182,7 @@ func CurseGloballyOnlyOnChain(selector uint64) CurseAction { func CurseLaneBidirectionally(sourceSelector uint64, destinationSelector uint64) CurseAction { // Bidirectional curse between two chains - return func(e deployment.Environment) ([]RMNCurseAction, error) { + return func(e cldf.Environment) ([]RMNCurseAction, error) { curseActions1, err := CurseLaneOnlyOnSource(sourceSelector, destinationSelector)(e) if err != nil { return nil, err @@ -193,7 +201,7 @@ func CurseLaneBidirectionally(sourceSelector uint64, destinationSelector uint64) // Given 3 chains A, B, C // CurseChain(A) will curse A with the global curse subject and curse B and C with the curse subject of A func CurseChain(chainSelector uint64) CurseAction { - return func(e deployment.Environment) ([]RMNCurseAction, error) { + return func(e cldf.Environment) ([]RMNCurseAction, error) { chainSelectors := GetAllCursableChainsSelector(e) // Curse all other chains to prevent onramp from sending message to the cursed chain @@ -224,7 +232,7 @@ func CurseChain(chainSelector uint64) CurseAction { } func CurseGloballyAllChains() CurseAction { - return func(e deployment.Environment) ([]RMNCurseAction, error) { + return func(e cldf.Environment) ([]RMNCurseAction, error) { chainSelectors := GetAllCursableChainsSelector(e) var curseActions []RMNCurseAction for _, chainSelector := range chainSelectors { @@ -238,7 +246,7 @@ func CurseGloballyAllChains() CurseAction { } } -func FilterOutNotConnectedLanes(e deployment.Environment, curseActions []RMNCurseAction) ([]RMNCurseAction, error) { +func FilterOutNotConnectedLanes(e cldf.Environment, curseActions []RMNCurseAction) ([]RMNCurseAction, error) { cursableChains, err := GetCursableChains(e) if err != nil { e.Logger.Errorf("failed to load cursable chains: %v", err) @@ -346,18 +354,18 @@ func groupRMNSubjectBySelector(rmnSubjects []RMNCurseAction, avoidCursingSelf bo // This changeset is following an anti-pattern of supporting multiple chain families. Most changeset should be family specific. // The decision to support multiple chain families here is due to the fact that curse changesets are emergency actions // we want to keep a simple unified interface for all chain families to streamline emergency procedures. -func RMNCurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (cldf.ChangesetOutput, error) { +func RMNCurseChangeset(e cldf.Environment, cfg RMNCurseConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to curse RMNs: " + cfg.Reason) + deployerGroup := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to curse RMNs: " + cfg.Reason) // Generate curse actions var curseActions []RMNCurseAction @@ -436,18 +444,18 @@ func RMNCurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (cldf.Chang // This changeset is following an anti-pattern of supporting multiple chain families. Most changeset should be family specific. // The decision to support multiple chain families here is due to the fact that curse changesets are emergency actions // we want to keep a simple unified interface for all chain families to streamline emergency procedures. -func RMNUncurseChangeset(e deployment.Environment, cfg RMNCurseConfig) (cldf.ChangesetOutput, error) { +func RMNUncurseChangeset(e cldf.Environment, cfg RMNCurseConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to uncurse RMNs: " + cfg.Reason) + deployerGroup := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("proposal to uncurse RMNs: " + cfg.Reason) // Generate curse actions var curseActions []RMNCurseAction @@ -508,14 +516,14 @@ type CursableChain interface { IsConnectedToSourceChain(selector uint64) (bool, error) IsCursable() (bool, error) IsSubjectCursed(subject globals.Subject) (bool, error) - Curse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error - Uncurse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error + Curse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error + Uncurse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error } type SolanaCursableChain struct { selector uint64 - env deployment.Environment - chain changeset.SolCCIPChainState + env cldf.Environment + chain solanastateview.CCIPChainState } func (c SolanaCursableChain) IsSubjectCursed(subject globals.Subject) (bool, error) { @@ -534,7 +542,8 @@ func (c SolanaCursableChain) IsSubjectCursed(subject globals.Subject) (bool, err if err != nil { return false, fmt.Errorf("failed to generate instructions: %w", err) } - if err := chain.Confirm([]solana.Instruction{ix}); err != nil { + _, err = solCommonUtil.SendAndConfirmWithLookupTables(context.Background(), chain.Client, []solana.Instruction{ix}, *chain.DeployerKey, rpc.CommitmentConfirmed, nil) + if err != nil { c.env.Logger.Infof("Curse already exists for chain %d and curse subject %v", c.selector, curseSubject) return true, nil } @@ -542,7 +551,7 @@ func (c SolanaCursableChain) IsSubjectCursed(subject globals.Subject) (bool, err return false, nil } -func (c SolanaCursableChain) Curse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error { +func (c SolanaCursableChain) Curse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error { err := assertEndianness(subjects, chain_selectors.FamilySolana) if err != nil { return fmt.Errorf("failed to assert subject endianness: %w", err) @@ -572,7 +581,7 @@ func (c SolanaCursableChain) Curse(deployerGroup *changeset.DeployerGroup, subje return nil, "", "", fmt.Errorf("failed to generate instructions: %w", err) } - return ix, c.chain.RMNRemote.String(), changeset.RMNRemote, nil + return ix, c.chain.RMNRemote.String(), shared.RMNRemote, nil }) if err != nil { return fmt.Errorf("failed to build curse instruction for subject %x on chain %d: %w", subject, c.selector, err) @@ -581,7 +590,7 @@ func (c SolanaCursableChain) Curse(deployerGroup *changeset.DeployerGroup, subje return nil } -func (c SolanaCursableChain) Uncurse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error { +func (c SolanaCursableChain) Uncurse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error { err := assertEndianness(subjects, chain_selectors.FamilySolana) if err != nil { return fmt.Errorf("failed to assert subject endianness: %w", err) @@ -609,7 +618,7 @@ func (c SolanaCursableChain) Uncurse(deployerGroup *changeset.DeployerGroup, sub if err != nil { return nil, "", "", fmt.Errorf("failed to generate instructions: %w", err) } - return ix, c.chain.RMNRemote.String(), changeset.RMNRemote, nil + return ix, c.chain.RMNRemote.String(), shared.RMNRemote, nil }) if err != nil { return fmt.Errorf("failed to build uncurse instruction for subject %x on chain %d: %w", subject, c.selector, err) @@ -623,7 +632,7 @@ func (c SolanaCursableChain) IsCursable() (bool, error) { } func (c SolanaCursableChain) IsConnectedToSourceChain(selector uint64) (bool, error) { - state, err := changeset.LoadOnchainStateSolana(c.env) + state, err := stateview.LoadOnchainStateSolana(c.env) if err != nil { return false, fmt.Errorf("failed to load onchain state: %w", err) } @@ -647,8 +656,8 @@ func (c SolanaCursableChain) Name() string { type EvmCursableChain struct { selector uint64 - env deployment.Environment - chain changeset.CCIPChainState + env cldf.Environment + chain evm.CCIPChainState } func (c EvmCursableChain) Name() string { @@ -679,7 +688,7 @@ func (c EvmCursableChain) IsCursable() (bool, error) { return c.chain.RMNRemote != nil, nil } -func (c EvmCursableChain) Curse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error { +func (c EvmCursableChain) Curse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error { err := assertEndianness(subjects, chain_selectors.FamilyEVM) if err != nil { return fmt.Errorf("failed to assert subject endianness: %w", err) @@ -697,7 +706,7 @@ func (c EvmCursableChain) Curse(deployerGroup *changeset.DeployerGroup, subjects return nil } -func (c EvmCursableChain) Uncurse(deployerGroup *changeset.DeployerGroup, subjects []globals.Subject) error { +func (c EvmCursableChain) Uncurse(deployerGroup *deployergroup.DeployerGroup, subjects []globals.Subject) error { err := assertEndianness(subjects, chain_selectors.FamilyEVM) if err != nil { return fmt.Errorf("failed to assert subject endianness: %w", err) @@ -715,8 +724,8 @@ func (c EvmCursableChain) Uncurse(deployerGroup *changeset.DeployerGroup, subjec return nil } -func GetCursableChains(env deployment.Environment) (map[uint64]CursableChain, error) { - state, err := changeset.LoadOnchainState(env) +func GetCursableChains(env cldf.Environment) (map[uint64]CursableChain, error) { + state, err := stateview.LoadOnchainState(env) if err != nil { return nil, fmt.Errorf("failed to load onchain state: %w", err) } @@ -751,7 +760,7 @@ func GetCursableChains(env deployment.Environment) (map[uint64]CursableChain, er return activeCursableChains, nil } -func GetAllCursableChainsSelector(env deployment.Environment) []uint64 { +func GetAllCursableChainsSelector(env cldf.Environment) []uint64 { selectors := make([]uint64, 0) selectors = append(selectors, env.AllChainSelectors()...) selectors = append(selectors, env.AllChainSelectorsSolana()...) diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go index b899017cb96..fc96076fa68 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes.go @@ -10,8 +10,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -157,14 +156,14 @@ func (c UpdateBidirectionalLanesConfig) BuildConfigs() UpdateBidirectionalLanesC } } -func updateBidirectionalLanesPrecondition(e deployment.Environment, c UpdateBidirectionalLanesConfig) error { +func updateBidirectionalLanesPrecondition(e cldf.Environment, c UpdateBidirectionalLanesConfig) error { configs := c.BuildConfigs() return UpdateLanesPrecondition(e, configs) } -func UpdateLanesPrecondition(e deployment.Environment, configs UpdateBidirectionalLanesChangesetConfigs) error { - state, err := changeset.LoadOnchainState(e) +func UpdateLanesPrecondition(e cldf.Environment, configs UpdateBidirectionalLanesChangesetConfigs) error { + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -197,7 +196,7 @@ func UpdateLanesPrecondition(e deployment.Environment, configs UpdateBidirection return nil } -func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirectionalLanesConfig) (cldf.ChangesetOutput, error) { +func updateBidirectionalLanesLogic(e cldf.Environment, c UpdateBidirectionalLanesConfig) (cldf.ChangesetOutput, error) { configs := c.BuildConfigs() return UpdateLanesLogic(e, c.MCMSConfig, configs) @@ -206,7 +205,7 @@ func updateBidirectionalLanesLogic(e deployment.Environment, c UpdateBidirection // UpdateLanesLogic is the main logic for updating lanes. Configs provided can be unidirectional // TODO: this should be refactored as a sequence once EVM changesets move to Operations API // TODO: UpdateBidirectionalLanesChangesetConfigs name is misleading, it also accepts unidirectional lane updates -func UpdateLanesLogic(e deployment.Environment, mcmsConfig *proposalutils.TimelockConfig, configs UpdateBidirectionalLanesChangesetConfigs) (cldf.ChangesetOutput, error) { +func UpdateLanesLogic(e cldf.Environment, mcmsConfig *proposalutils.TimelockConfig, configs UpdateBidirectionalLanesChangesetConfigs) (cldf.ChangesetOutput, error) { proposals := make([]mcms.TimelockProposal, 0) out, err := UpdateFeeQuoterDestsChangeset(e, configs.UpdateFeeQuoterDestsConfig) @@ -244,11 +243,11 @@ func UpdateLanesLogic(e deployment.Environment, mcmsConfig *proposalutils.Timelo proposals = append(proposals, out.MCMSTimelockProposals...) e.Logger.Info("Ramps updated on Routers") - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), nil, proposals, nil, "Update multiple bidirectional lanes", mcmsConfig) + proposal, err := proposalutils.AggregateProposals(e, state.EVMMCMSStateByChain(), nil, proposals, "Update multiple bidirectional lanes", mcmsConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to aggregate proposals: %w", err) } diff --git a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go index ec89c03cbb8..9043aa5e105 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go +++ b/deployment/ccip/changeset/v1_6/cs_update_bidirectional_lanes_test.go @@ -13,10 +13,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -74,8 +74,8 @@ func getRemoteChains(chains []v1_6.ChainDefinition, currentIndex int) []v1_6.Cha func checkBidirectionalLaneConnectivity( t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, chainOne v1_6.ChainDefinition, chainTwo v1_6.ChainDefinition, testRouter bool, @@ -311,7 +311,7 @@ func TestUpdateBidirectiConalLanesChangeset(t *testing.T) { }) e := deployedEnvironment.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "must load onchain state") selectors := e.AllChainSelectors() diff --git a/deployment/ccip/changeset/v1_6/cs_update_rmn_config.go b/deployment/ccip/changeset/v1_6/cs_update_rmn_config.go index 7eb1b270f31..4debf20c7d3 100644 --- a/deployment/ccip/changeset/v1_6/cs_update_rmn_config.go +++ b/deployment/ccip/changeset/v1_6/cs_update_rmn_config.go @@ -20,8 +20,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_home" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -41,9 +43,9 @@ type SetRMNRemoteOnRMNProxyConfig struct { MCMSConfig *proposalutils.TimelockConfig } -func (c SetRMNRemoteOnRMNProxyConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { +func (c SetRMNRemoteOnRMNProxyConfig) Validate(e cldf.Environment, state stateview.CCIPOnChainState) error { for _, chain := range c.ChainSelectors { - err := deployment.IsValidChainSelector(chain) + err := cldf.IsValidChainSelector(chain) if err != nil { return err } @@ -66,8 +68,8 @@ func (c SetRMNRemoteOnRMNProxyConfig) Validate(e deployment.Environment, state c return nil } -func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteOnRMNProxyConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func SetRMNRemoteOnRMNProxyChangeset(e cldf.Environment, cfg SetRMNRemoteOnRMNProxyConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -75,7 +77,7 @@ func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteO return cldf.ChangesetOutput{}, err } - timelocks := changeset.BuildTimelockAddressPerChain(e, state) + timelocks := deployergroup.BuildTimelockAddressPerChain(e, state) inspectors := map[uint64]mcmssdk.Inspector{} timelockBatch := []mcmstypes.BatchOperation{} @@ -92,7 +94,7 @@ func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteO txOpts := chain.DeployerKey if cfg.MCMSConfig != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } batchOperation, err := setRMNRemoteOnRMNProxyOp(txOpts, chain, state.Chains[sel], cfg.MCMSConfig != nil) if err != nil { @@ -107,7 +109,7 @@ func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteO if len(timelockBatch) == 0 { return cldf.ChangesetOutput{}, nil } - mcmContract, err := changeset.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMSConfig) + mcmContract, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, cfg.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, err } @@ -131,7 +133,7 @@ func SetRMNRemoteOnRMNProxyChangeset(e deployment.Environment, cfg SetRMNRemoteO } func setRMNRemoteOnRMNProxyOp( - txOpts *bind.TransactOpts, chain deployment.Chain, chainState changeset.CCIPChainState, mcmsEnabled bool, + txOpts *bind.TransactOpts, chain cldf.Chain, chainState evm.CCIPChainState, mcmsEnabled bool, ) (mcmstypes.BatchOperation, error) { rmnProxy := chainState.RMNProxy rmnRemoteAddr := chainState.RMNRemote.Address() @@ -139,16 +141,16 @@ func setRMNRemoteOnRMNProxyOp( // note: error check is handled below if !mcmsEnabled { - _, err = deployment.ConfirmIfNoErrorWithABI(chain, setRMNTx, rmn_proxy_contract.RMNProxyABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(chain, setRMNTx, rmn_proxy_contract.RMNProxyABI, err) if err != nil { - return mcmstypes.BatchOperation{}, fmt.Errorf("failed to confirm tx to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), deployment.MaybeDataErr(err)) + return mcmstypes.BatchOperation{}, fmt.Errorf("failed to confirm tx to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), cldf.MaybeDataErr(err)) } } else if err != nil { return mcmstypes.BatchOperation{}, fmt.Errorf("failed to build call data/transaction to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), err) } batchOperation, err := proposalutils.BatchOperationForChain(chain.Selector, rmnProxy.Address().Hex(), - setRMNTx.Data(), big.NewInt(0), string(changeset.RMN), []string{}) + setRMNTx.Data(), big.NewInt(0), string(shared.RMN), []string{}) if err != nil { return mcmstypes.BatchOperation{}, fmt.Errorf("failed to create batch operation for chain%s: %w", chain.String(), err) } @@ -185,12 +187,12 @@ func (c RMNNopConfig) SetBit(bitmap *big.Int, value bool) { } } -func getDeployer(e deployment.Environment, chain uint64, mcmConfig *proposalutils.TimelockConfig) *bind.TransactOpts { +func getDeployer(e cldf.Environment, chain uint64, mcmConfig *proposalutils.TimelockConfig) *bind.TransactOpts { if mcmConfig == nil { return e.Chains[chain].DeployerKey } - return deployment.SimTransactOpts() + return cldf.SimTransactOpts() } type SetRMNHomeCandidateConfig struct { @@ -201,8 +203,8 @@ type SetRMNHomeCandidateConfig struct { MCMSConfig *proposalutils.TimelockConfig } -func (c SetRMNHomeCandidateConfig) Validate(state changeset.CCIPOnChainState) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) +func (c SetRMNHomeCandidateConfig) Validate(state stateview.CCIPOnChainState) error { + err := cldf.IsValidChainSelector(c.HomeChainSelector) if err != nil { return err } @@ -307,8 +309,8 @@ type PromoteRMNHomeCandidateConfig struct { MCMSConfig *proposalutils.TimelockConfig } -func (c PromoteRMNHomeCandidateConfig) Validate(state changeset.CCIPOnChainState) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) +func (c PromoteRMNHomeCandidateConfig) Validate(state stateview.CCIPOnChainState) error { + err := cldf.IsValidChainSelector(c.HomeChainSelector) if err != nil { return err } @@ -341,8 +343,8 @@ func (c PromoteRMNHomeCandidateConfig) Validate(state changeset.CCIPOnChainState // StaticConfig contains the list of nodes with their peerIDs (found in their rageproxy keystore) and offchain public keys (found in the RMN keystore) // DynamicConfig contains the list of source chains with their chain selectors, f value and the bitmap of the nodes that are oberver for each source chain // The bitmap is a 256 bit array where each bit represents a node. If the bit matching the index of the node in the static config is set it means that the node is an observer -func SetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNHomeCandidateConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func SetRMNHomeCandidateConfigChangeset(e cldf.Environment, config SetRMNHomeCandidateConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -372,20 +374,20 @@ func SetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNH chain := e.Chains[config.HomeChainSelector] _, err := chain.Confirm(setCandidateTx) if err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), cldf.MaybeDataErr(err)) } return cldf.ChangesetOutput{}, nil } operation, err := proposalutils.BatchOperationForChain(homeChain.Selector, rmnHome.Address().Hex(), - setCandidateTx.Data(), big.NewInt(0), string(changeset.RMN), []string{}) + setCandidateTx.Data(), big.NewInt(0), string(shared.RMN), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for chain %s: %w", homeChain.String(), err) } - timelocks := changeset.BuildTimelockAddressPerChain(e, state) - mcmContract, err := changeset.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) + timelocks := deployergroup.BuildTimelockAddressPerChain(e, state) + mcmContract, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, err } @@ -410,8 +412,8 @@ func SetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNH return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } -func PromoteRMNHomeCandidateConfigChangeset(e deployment.Environment, config PromoteRMNHomeCandidateConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func PromoteRMNHomeCandidateConfigChangeset(e cldf.Environment, config PromoteRMNHomeCandidateConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -452,20 +454,20 @@ func PromoteRMNHomeCandidateConfigChangeset(e deployment.Environment, config Pro chain := e.Chains[config.HomeChainSelector] _, err := chain.Confirm(promoteCandidateTx) if err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), cldf.MaybeDataErr(err)) } return cldf.ChangesetOutput{}, nil } operation, err := proposalutils.BatchOperationForChain(homeChain.Selector, rmnHome.Address().Hex(), - promoteCandidateTx.Data(), big.NewInt(0), string(changeset.RMN), []string{}) + promoteCandidateTx.Data(), big.NewInt(0), string(shared.RMN), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for chain %s: %w", homeChain.String(), err) } - timelocks := changeset.BuildTimelockAddressPerChain(e, state) - mcmContract, err := changeset.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) + timelocks := deployergroup.BuildTimelockAddressPerChain(e, state) + mcmContract, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, err } @@ -494,7 +496,7 @@ func PromoteRMNHomeCandidateConfigChangeset(e deployment.Environment, config Pro }, nil } -func BuildRMNRemotePerChain(e deployment.Environment, state changeset.CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { +func BuildRMNRemotePerChain(e cldf.Environment, state stateview.CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { timelocksPerChain := make(map[uint64]*rmn_remote.RMNRemote) for _, chain := range e.Chains { timelocksPerChain[chain.Selector] = state.Chains[chain.Selector].RMNRemote @@ -514,13 +516,13 @@ type SetRMNRemoteConfig struct { } func (c SetRMNRemoteConfig) Validate() error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) + err := cldf.IsValidChainSelector(c.HomeChainSelector) if err != nil { return err } for chain, config := range c.RMNRemoteConfigs { - err := deployment.IsValidChainSelector(chain) + err := cldf.IsValidChainSelector(chain) if err != nil { return err } @@ -546,13 +548,13 @@ type SetRMNHomeDynamicConfigConfig struct { MCMS *proposalutils.TimelockConfig } -func (c SetRMNHomeDynamicConfigConfig) Validate(e deployment.Environment) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) +func (c SetRMNHomeDynamicConfigConfig) Validate(e cldf.Environment) error { + err := cldf.IsValidChainSelector(c.HomeChainSelector) if err != nil { return err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -578,18 +580,18 @@ func (c SetRMNHomeDynamicConfigConfig) Validate(e deployment.Environment) error return nil } -func SetRMNHomeDynamicConfigChangeset(e deployment.Environment, cfg SetRMNHomeDynamicConfigConfig) (cldf.ChangesetOutput, error) { +func SetRMNHomeDynamicConfigChangeset(e cldf.Environment, cfg SetRMNHomeDynamicConfigConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("set RMNHome dynamic config") + deployerGroup := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("set RMNHome dynamic config") chain, exists := e.Chains[cfg.HomeChainSelector] if !exists { @@ -621,13 +623,13 @@ type RevokeCandidateConfig struct { MCMS *proposalutils.TimelockConfig } -func (c RevokeCandidateConfig) Validate(e deployment.Environment) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) +func (c RevokeCandidateConfig) Validate(e cldf.Environment) error { + err := cldf.IsValidChainSelector(c.HomeChainSelector) if err != nil { return err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -649,18 +651,18 @@ func (c RevokeCandidateConfig) Validate(e deployment.Environment) error { return nil } -func RevokeRMNHomeCandidateConfigChangeset(e deployment.Environment, cfg RevokeCandidateConfig) (cldf.ChangesetOutput, error) { +func RevokeRMNHomeCandidateConfigChangeset(e cldf.Environment, cfg RevokeCandidateConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, err } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } - deployerGroup := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("revoke candidate config") + deployerGroup := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("revoke candidate config") chain, exists := e.Chains[cfg.HomeChainSelector] if !exists { @@ -685,8 +687,8 @@ func RevokeRMNHomeCandidateConfigChangeset(e deployment.Environment, cfg RevokeC return deployerGroup.Enact() } -func SetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func SetRMNRemoteConfigChangeset(e cldf.Environment, config SetRMNRemoteConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -756,12 +758,12 @@ func SetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteCo _, err := e.Chains[chain].Confirm(tx) if err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", e.Chains[chain].String(), deployment.MaybeDataErr(err)) + return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", e.Chains[chain].String(), cldf.MaybeDataErr(err)) } } operation, err := proposalutils.BatchOperationForChain(e.Chains[chain].Selector, remote.Address().Hex(), - tx.Data(), big.NewInt(0), string(changeset.RMN), []string{}) + tx.Data(), big.NewInt(0), string(shared.RMN), []string{}) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create batch operation for chain %s: %w", homeChain.String(), err) } @@ -773,8 +775,8 @@ func SetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteCo return cldf.ChangesetOutput{}, nil } - timelocks := changeset.BuildTimelockAddressPerChain(e, state) - mcmContract, err := changeset.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) + timelocks := deployergroup.BuildTimelockAddressPerChain(e, state) + mcmContract, err := deployergroup.BuildMcmAddressesPerChainByAction(e, state, config.MCMSConfig) if err != nil { return cldf.ChangesetOutput{}, err } diff --git a/deployment/ccip/manualexechelpers/exec.go b/deployment/ccip/manualexechelpers/exec.go index f6bb76422db..13dfec29f07 100644 --- a/deployment/ccip/manualexechelpers/exec.go +++ b/deployment/ccip/manualexechelpers/exec.go @@ -12,18 +12,19 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" chainsel "github.com/smartcontractkit/chain-selectors" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + defaults "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/default" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm/manualexeclib" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" ) const ( @@ -116,8 +117,8 @@ func durationToBlocks(srcChainSel uint64, lookbackDuration time.Duration) uint64 func getCommitRootAcceptedEvent( ctx context.Context, lggr logger.Logger, - env deployment.Environment, - state ccipchangeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, srcChainSel uint64, destChainSel uint64, msgSeqNr uint64, @@ -210,8 +211,8 @@ func findCommitRoot( func getCCIPMessageSentEvents( ctx context.Context, lggr logger.Logger, - env deployment.Environment, - state ccipchangeset.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, srcChainSel uint64, destChainSel uint64, merkleRoot offramp.InternalMerkleRoot, @@ -302,8 +303,8 @@ func getCCIPMessageSentEvents( func manuallyExecuteSingle( ctx context.Context, lggr logger.Logger, - state ccipchangeset.CCIPOnChainState, - env deployment.Environment, + state stateview.CCIPOnChainState, + env cldf.Environment, srcChainSel uint64, destChainSel uint64, msgSeqNr uint64, @@ -526,7 +527,7 @@ func manuallyExecuteSingle( }, }, ) - _, err = deployment.ConfirmIfNoErrorWithABI(env.Chains[destChainSel], tx, offramp.OffRampABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(env.Chains[destChainSel], tx, offramp.OffRampABI, err) if err != nil { return fmt.Errorf("failed to execute message: %w", err) } @@ -542,8 +543,8 @@ func manuallyExecuteSingle( func ManuallyExecuteAll( ctx context.Context, lggr logger.Logger, - state ccipchangeset.CCIPOnChainState, - env deployment.Environment, + state stateview.CCIPOnChainState, + env cldf.Environment, srcChainSel uint64, destChainSel uint64, msgSeqNrs []int64, @@ -552,9 +553,7 @@ func ManuallyExecuteAll( stepDuration time.Duration, reExecuteIfFailed bool, ) error { - extraDataCodec := ccipcommon.NewExtraDataCodec(ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{})) - - // for large backfills, these caches can speed things up because we don't need to query + extraDataCodec := defaults.DefaultExtraDataCodec // the chain multiple times for the same root/messages. messageSentCache := NewMessageSentCache() commitRootCache := NewRootCache() @@ -587,7 +586,7 @@ func ManuallyExecuteAll( func CheckAlreadyExecuted( ctx context.Context, lggr logger.Logger, - state ccipchangeset.CCIPOnChainState, + state stateview.CCIPOnChainState, srcChainSel uint64, destChainSel uint64, msgSeqNrs []int64, diff --git a/deployment/ccip/changeset/deployer_group.go b/deployment/ccip/shared/deployergroup/deployer_group.go similarity index 93% rename from deployment/ccip/changeset/deployer_group.go rename to deployment/ccip/shared/deployergroup/deployer_group.go index 143cdbb3bfe..253d513b016 100644 --- a/deployment/ccip/changeset/deployer_group.go +++ b/deployment/ccip/shared/deployergroup/deployer_group.go @@ -1,4 +1,4 @@ -package changeset +package deployergroup import ( "context" @@ -22,14 +22,14 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) type DeployerGroup struct { - e deployment.Environment - state CCIPOnChainState + e cldf.Environment + state stateview.CCIPOnChainState mcmConfig *proposalutils.TimelockConfig deploymentContext *DeploymentContext txDecoder *proposalutils.TxCallDecoder @@ -118,8 +118,8 @@ type DeployerGroupWithContext interface { } type deployerGroupBuilder struct { - e deployment.Environment - state CCIPOnChainState + e cldf.Environment + state stateview.CCIPOnChainState mcmConfig *proposalutils.TimelockConfig txDecoder *proposalutils.TxCallDecoder describeContext *proposalutils.ArgumentContext @@ -148,7 +148,7 @@ func (d *deployerGroupBuilder) WithDeploymentContext(description string) *Deploy // state.Chains[selector].RMNRemote.Curse() // # Execute the transaction or create the proposal // deployerGroup.Enact("Curse RMNRemote") -func NewDeployerGroup(e deployment.Environment, state CCIPOnChainState, mcmConfig *proposalutils.TimelockConfig) DeployerGroupWithContext { +func NewDeployerGroup(e cldf.Environment, state stateview.CCIPOnChainState, mcmConfig *proposalutils.TimelockConfig) DeployerGroupWithContext { addresses, _ := e.ExistingAddresses.Addresses() return &deployerGroupBuilder{ e: e, @@ -173,7 +173,7 @@ func (d *DeployerGroup) WithDeploymentContext(description string) *DeployerGroup func (d *DeployerGroup) GetDeployer(chain uint64) (*bind.TransactOpts, error) { txOpts := d.e.Chains[chain].DeployerKey if d.mcmConfig != nil { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() txOpts = &bind.TransactOpts{ From: d.state.Chains[chain].Timelock.Address(), Signer: txOpts.Signer, @@ -313,7 +313,7 @@ func (d *DeployerGroup) Enact() (cldf.ChangesetOutput, error) { return d.enactDeployer() } -func ValidateMCMS(env deployment.Environment, selector uint64, mcmConfig *proposalutils.TimelockConfig) error { +func ValidateMCMS(env cldf.Environment, selector uint64, mcmConfig *proposalutils.TimelockConfig) error { family, err := chain_selectors.GetSelectorFamily(selector) if err != nil { return fmt.Errorf("failed to get chain selector family: %w", err) @@ -321,7 +321,7 @@ func ValidateMCMS(env deployment.Environment, selector uint64, mcmConfig *propos switch family { case chain_selectors.FamilyEVM: - state, err := LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load onchain state: %w", err) } @@ -449,7 +449,7 @@ func (d *DeployerGroup) enactDeployer() (cldf.ChangesetOutput, error) { return fmt.Errorf("failed to send transaction: %w", err) } // TODO how to pass abi here to decode error reason - _, err = deployment.ConfirmIfNoError(d.e.Chains[selector], evmTx.Tx, err) + _, err = cldf.ConfirmIfNoError(d.e.Chains[selector], evmTx.Tx, err) if err != nil { return fmt.Errorf("waiting for tx to be mined failed: %w", err) } @@ -473,7 +473,7 @@ func (d *DeployerGroup) enactDeployer() (cldf.ChangesetOutput, error) { return cldf.ChangesetOutput{}, nil } -func BuildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*proposalutils.TimelockExecutionContracts { +func BuildTimelockPerChain(e cldf.Environment, state stateview.CCIPOnChainState) map[uint64]*proposalutils.TimelockExecutionContracts { timelocksPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) for _, chain := range e.Chains { timelocksPerChain[chain.Selector] = &proposalutils.TimelockExecutionContracts{ @@ -484,7 +484,7 @@ func BuildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map return timelocksPerChain } -func BuildTimelockAddressPerChain(e deployment.Environment, onchainState CCIPOnChainState) map[uint64]string { +func BuildTimelockAddressPerChain(e cldf.Environment, onchainState stateview.CCIPOnChainState) map[uint64]string { addressPerChain := make(map[uint64]string) for _, chain := range e.Chains { if onchainState.Chains[chain.Selector].Timelock == nil { @@ -504,7 +504,7 @@ func BuildTimelockAddressPerChain(e deployment.Environment, onchainState CCIPOnC return addressPerChain } -func BuildMcmAddressesPerChainByAction(e deployment.Environment, onchainState CCIPOnChainState, mcmCfg *proposalutils.TimelockConfig) (map[uint64]string, error) { +func BuildMcmAddressesPerChainByAction(e cldf.Environment, onchainState stateview.CCIPOnChainState, mcmCfg *proposalutils.TimelockConfig) (map[uint64]string, error) { if mcmCfg == nil { return nil, errors.New("mcm config is nil, cannot get mcms address") } @@ -531,6 +531,6 @@ func BuildMcmAddressesPerChainByAction(e deployment.Environment, onchainState CC return addressPerChain, nil } -func addressForChain(e deployment.Environment, selector uint64) (map[string]cldf.TypeAndVersion, error) { +func addressForChain(e cldf.Environment, selector uint64) (map[string]cldf.TypeAndVersion, error) { return e.ExistingAddresses.AddressesForChain(selector) //nolint:staticcheck // Uncomment above once datastore is updated to contains addresses } diff --git a/deployment/ccip/changeset/deployer_group_test.go b/deployment/ccip/shared/deployergroup/deployer_group_test.go similarity index 83% rename from deployment/ccip/changeset/deployer_group_test.go rename to deployment/ccip/shared/deployergroup/deployer_group_test.go index 45c74cdb621..1b9c32de558 100644 --- a/deployment/ccip/changeset/deployer_group_test.go +++ b/deployment/ccip/shared/deployergroup/deployer_group_test.go @@ -1,4 +1,4 @@ -package changeset_test +package deployergroup_test import ( "fmt" @@ -14,9 +14,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -43,25 +44,25 @@ type dummyEmptyBatchChangesetConfig struct { MCMS *proposalutils.TimelockConfig } -func dummyEmptyBatchChangeset(e deployment.Environment, cfg dummyEmptyBatchChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func dummyEmptyBatchChangeset(e cldf.Environment, cfg dummyEmptyBatchChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } - group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("empty batch") + group := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("empty batch") return group.Enact() } -func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func dummyDeployerGroupGrantMintChangeset(e cldf.Environment, cfg dummyDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } token := state.Chains[cfg.selector].LinkToken - group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role") + group := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role") deployer, err := group.GetDeployer(cfg.selector) if err != nil { return cldf.ChangesetOutput{}, err @@ -75,15 +76,15 @@ func dummyDeployerGroupGrantMintChangeset(e deployment.Environment, cfg dummyDep return group.Enact() } -func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func dummyDeployerGroupMintChangeset(e cldf.Environment, cfg dummyDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } token := state.Chains[cfg.selector].LinkToken - group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("mint tokens") + group := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("mint tokens") deployer, err := group.GetDeployer(cfg.selector) if err != nil { return cldf.ChangesetOutput{}, err @@ -99,13 +100,13 @@ func dummyDeployerGroupMintChangeset(e deployment.Environment, cfg dummyDeployer return group.Enact() } -func dummyDeployerGroupGrantMintMultiChainChangeset(e deployment.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func dummyDeployerGroupGrantMintMultiChainChangeset(e cldf.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } - group := changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role") + group := deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext("grant mint role") for _, mint := range cfg.mints { selector := e.AllChainSelectors()[mint.selectorIndex] token := state.Chains[selector].LinkToken @@ -124,13 +125,13 @@ func dummyDeployerGroupGrantMintMultiChainChangeset(e deployment.Environment, cf return group.Enact() } -func dummyDeployerGroupMintMultiDeploymentContextChangeset(e deployment.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(e) +func dummyDeployerGroupMintMultiDeploymentContextChangeset(e cldf.Environment, cfg dummyMultiChainDeployerGroupChangesetConfig) (cldf.ChangesetOutput, error) { + state, err := stateview.LoadOnchainState(e) if err != nil { return cldf.ChangesetOutput{}, err } - var group *changeset.DeployerGroup + var group *deployergroup.DeployerGroup var deployer *bind.TransactOpts for i, mint := range cfg.mints { @@ -138,7 +139,7 @@ func dummyDeployerGroupMintMultiDeploymentContextChangeset(e deployment.Environm token := state.Chains[selector].LinkToken if group == nil { - group = changeset.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext(fmt.Sprintf("mint tokens %d", i+1)) + group = deployergroup.NewDeployerGroup(e, state, cfg.MCMS).WithDeploymentContext(fmt.Sprintf("mint tokens %d", i+1)) } else { group = group.WithDeploymentContext(fmt.Sprintf("mint tokens %d", i+1)) } @@ -197,7 +198,7 @@ func TestDeployerGroup(t *testing.T) { } else { require.NoError(t, err) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) token := state.Chains[e.HomeChainSel].LinkToken @@ -232,10 +233,10 @@ func TestDeployerGroupMCMS(t *testing.T) { tc.cfg.MCMS = &proposalutils.TimelockConfig{ MinDelay: 0, } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) - timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + timelocksPerChain := deployergroup.BuildTimelockPerChain(e.Env, state) contractsByChain := make(map[uint64][]common.Address) contractsByChain[e.HomeChainSel] = []common.Address{state.Chains[e.HomeChainSel].LinkToken.Address()} @@ -269,7 +270,7 @@ func TestDeployerGroupMCMS(t *testing.T) { ) require.NoError(t, err) - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) token := state.Chains[e.HomeChainSel].LinkToken @@ -309,10 +310,10 @@ func TestDeployerGroupGenerateMultipleProposals(t *testing.T) { }, } e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2)) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) - timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + timelocksPerChain := deployergroup.BuildTimelockPerChain(e.Env, state) contractsByChain := make(map[uint64][]common.Address) for _, chain := range e.Env.AllChainSelectors() { @@ -375,10 +376,10 @@ func TestDeployerGroupMultipleProposalsMCMS(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(2)) - currentState, err := changeset.LoadOnchainState(e.Env) + currentState, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) - timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, currentState) + timelocksPerChain := deployergroup.BuildTimelockPerChain(e.Env, currentState) contractsByChain := make(map[uint64][]common.Address) for _, chain := range e.Env.AllChainSelectors() { @@ -414,7 +415,7 @@ func TestDeployerGroupMultipleProposalsMCMS(t *testing.T) { ) require.NoError(t, err) - currentState, err = changeset.LoadOnchainState(e.Env) + currentState, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) token := currentState.Chains[e.HomeChainSel].LinkToken diff --git a/deployment/ccip/helpers.go b/deployment/ccip/shared/helpers.go similarity index 98% rename from deployment/ccip/helpers.go rename to deployment/ccip/shared/helpers.go index 3d0415d9115..d61f900e335 100644 --- a/deployment/ccip/helpers.go +++ b/deployment/ccip/shared/helpers.go @@ -1,4 +1,4 @@ -package ccip +package shared import ( "context" diff --git a/deployment/ccip/changeset/aptos_state.go b/deployment/ccip/shared/stateview/aptos/state.go similarity index 64% rename from deployment/ccip/changeset/aptos_state.go rename to deployment/ccip/shared/stateview/aptos/state.go index 1e682615e55..ed6d89c3a48 100644 --- a/deployment/ccip/changeset/aptos_state.go +++ b/deployment/ccip/shared/stateview/aptos/state.go @@ -1,27 +1,21 @@ -package changeset +package aptos import ( "errors" "fmt" "github.com/aptos-labs/aptos-go-sdk" - aptosBind "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" module_offramp "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp/offramp" + "github.com/smartcontractkit/chainlink-aptos/bindings/bind" + "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -const ( - AptosMCMSType cldf.ContractType = "AptosManyChainMultisig" - AptosCCIPType cldf.ContractType = "AptosCCIP" - AptosReceiverType cldf.ContractType = "AptosReceiver" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/common/types" ) -type AptosCCIPChainState struct { +type CCIPChainState struct { MCMSAddress aptos.AccountAddress CCIPAddress aptos.AccountAddress LinkTokenAddress aptos.AccountAddress @@ -32,8 +26,8 @@ type AptosCCIPChainState struct { } // LoadOnchainStateAptos loads chain state for Aptos chains from env -func LoadOnchainStateAptos(env deployment.Environment) (map[uint64]AptosCCIPChainState, error) { - aptosChains := make(map[uint64]AptosCCIPChainState) +func LoadOnchainStateAptos(env cldf.Environment) (map[uint64]CCIPChainState, error) { + aptosChains := make(map[uint64]CCIPChainState) for chainSelector := range env.AptosChains { addresses, err := env.ExistingAddresses.AddressesForChain(chainSelector) if err != nil { @@ -52,8 +46,8 @@ func LoadOnchainStateAptos(env deployment.Environment) (map[uint64]AptosCCIPChai return aptosChains, nil } -func loadAptosChainStateFromAddresses(addresses map[string]cldf.TypeAndVersion) (AptosCCIPChainState, error) { - chainState := AptosCCIPChainState{} +func loadAptosChainStateFromAddresses(addresses map[string]cldf.TypeAndVersion) (CCIPChainState, error) { + chainState := CCIPChainState{} for addrStr, typeAndVersion := range addresses { // Parse address address := &aptos.AccountAddress{} @@ -63,20 +57,20 @@ func loadAptosChainStateFromAddresses(addresses map[string]cldf.TypeAndVersion) } // Set address based on type switch typeAndVersion.Type { - case AptosMCMSType: + case shared.AptosMCMSType: chainState.MCMSAddress = *address - case AptosCCIPType: + case shared.AptosCCIPType: chainState.CCIPAddress = *address - case commontypes.LinkToken: + case types.LinkToken: chainState.LinkTokenAddress = *address - case AptosReceiverType: + case shared.AptosReceiverType: chainState.ReceiverAddress = *address } } return chainState, nil } -func getOfframpDynamicConfig(c deployment.AptosChain, ccipAddress aptos.AccountAddress) (module_offramp.DynamicConfig, error) { +func GetOfframpDynamicConfig(c cldf.AptosChain, ccipAddress aptos.AccountAddress) (module_offramp.DynamicConfig, error) { offrampBind := ccip_offramp.Bind(ccipAddress, c.Client) - return offrampBind.Offramp().GetDynamicConfig(&aptosBind.CallOpts{}) + return offrampBind.Offramp().GetDynamicConfig(&bind.CallOpts{}) } diff --git a/deployment/ccip/shared/stateview/evm/state.go b/deployment/ccip/shared/stateview/evm/state.go new file mode 100644 index 00000000000..f220c2f744b --- /dev/null +++ b/deployment/ccip/shared/stateview/evm/state.go @@ -0,0 +1,1050 @@ +package evm + +import ( + "context" + "fmt" + + "github.com/Masterminds/semver/v3" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/don_id_claimer" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/factory_burn_mint_erc20" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/log_message_data_receiver" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_messenger" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_transmitter" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/token_pool_factory" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_0_0/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/price_registry" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/commit_store" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/mock_rmn_contract" + registry_module_owner_custom2 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_from_mint_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_mint_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_with_from_mint_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/lock_release_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/usdc_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/nonce_manager" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_home" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc677" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/multicall3" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/weth9" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/view" + shared2 "github.com/smartcontractkit/chainlink/deployment/ccip/view/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_0" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_2" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5_1" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_6" + "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" + v1_1 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" +) + +// CCIPChainState holds a Go binding for all the currently deployed CCIP contracts +// on a chain. If a binding is nil, it means here is no such contract on the chain. +type CCIPChainState struct { + state.MCMSWithTimelockState + state.LinkTokenState + state.StaticLinkTokenState + ABIByAddress map[string]string + OnRamp onramp.OnRampInterface + OffRamp offramp.OffRampInterface + FeeQuoter *fee_quoter.FeeQuoter + RMNProxy *rmn_proxy_contract.RMNProxy + NonceManager *nonce_manager.NonceManager + TokenAdminRegistry *token_admin_registry.TokenAdminRegistry + TokenPoolFactory *token_pool_factory.TokenPoolFactory + RegistryModules1_6 []*registry_module_owner_custom.RegistryModuleOwnerCustom + // TODO change this to contract object for v1.5 RegistryModules once we have the wrapper available in chainlink-evm + RegistryModules1_5 []*registry_module_owner_custom2.RegistryModuleOwnerCustom + Router *router.Router + Weth9 *weth9.WETH9 + RMNRemote *rmn_remote.RMNRemote + // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) + // and the respective token / token pool contract(s) (only one of which would be active on the registry). + // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. + ERC20Tokens map[shared.TokenSymbol]*erc20.ERC20 + FactoryBurnMintERC20Token *factory_burn_mint_erc20.FactoryBurnMintERC20 + ERC677Tokens map[shared.TokenSymbol]*erc677.ERC677 + BurnMintTokens677 map[shared.TokenSymbol]*burn_mint_erc677.BurnMintERC677 + BurnMintTokenPools map[shared.TokenSymbol]map[semver.Version]*burn_mint_token_pool.BurnMintTokenPool + BurnWithFromMintTokenPools map[shared.TokenSymbol]map[semver.Version]*burn_with_from_mint_token_pool.BurnWithFromMintTokenPool + BurnFromMintTokenPools map[shared.TokenSymbol]map[semver.Version]*burn_from_mint_token_pool.BurnFromMintTokenPool + USDCTokenPools map[semver.Version]*usdc_token_pool.USDCTokenPool + LockReleaseTokenPools map[shared.TokenSymbol]map[semver.Version]*lock_release_token_pool.LockReleaseTokenPool + // Map between token Symbol (e.g. LinkSymbol, WethSymbol) + // and the respective aggregator USD feed contract + USDFeeds map[shared.TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface + + // Note we only expect one of these (on the home chain) + CapabilityRegistry *capabilities_registry.CapabilitiesRegistry + CCIPHome *ccip_home.CCIPHome + RMNHome *rmn_home.RMNHome + DonIDClaimer *don_id_claimer.DonIDClaimer + + // Test contracts + Receiver maybe_revert_message_receiver.MaybeRevertMessageReceiverInterface + LogMessageDataReceiver *log_message_data_receiver.LogMessageDataReceiver + TestRouter *router.Router + MockUSDCTransmitter *mock_usdc_token_transmitter.MockE2EUSDCTransmitter + MockUSDCTokenMessenger *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger + Multicall3 *multicall3.Multicall3 + + // Legacy contracts + EVM2EVMOnRamp map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp // mapping of dest chain selector -> EVM2EVMOnRamp + CommitStore map[uint64]*commit_store.CommitStore // mapping of source chain selector -> CommitStore + EVM2EVMOffRamp map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp // mapping of source chain selector -> EVM2EVMOffRamp + MockRMN *mock_rmn_contract.MockRMNContract + PriceRegistry *price_registry.PriceRegistry + RMN *rmn_contract.RMNContract + + // Treasury contracts + FeeAggregator common.Address +} + +// ValidateHomeChain validates the home chain contracts and their configurations after complete set up +// It cross-references the config across CCIPHome and OffRamps to ensure they are in sync +// This should be called after the complete deployment is done +func (c CCIPChainState) ValidateHomeChain(e cldf.Environment, nodes deployment.Nodes, offRampsByChain map[uint64]offramp.OffRampInterface) error { + if c.RMNHome == nil { + return errors.New("no RMNHome contract found in the state for home chain") + } + if c.CCIPHome == nil { + return errors.New("no CCIPHome contract found in the state for home chain") + } + if c.CapabilityRegistry == nil { + return errors.New("no CapabilityRegistry contract found in the state for home chain") + } + // get capReg from CCIPHome + capReg, err := c.CCIPHome.GetCapabilityRegistry(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get capability registry from CCIPHome contract: %w", err) + } + if capReg != c.CapabilityRegistry.Address() { + return fmt.Errorf("capability registry mismatch: expected %s, got %s", capReg.Hex(), c.CapabilityRegistry.Address().Hex()) + } + ccipDons, err := shared.GetCCIPDonsFromCapRegistry(e.GetContext(), c.CapabilityRegistry) + if err != nil { + return fmt.Errorf("failed to get CCIP Dons from capability registry: %w", err) + } + if len(ccipDons) == 0 { + return errors.New("no CCIP Dons found in capability registry") + } + // validate for all ccipDons + for _, don := range ccipDons { + if err := nodes.P2PIDsPresentInJD(don.NodeP2PIds); err != nil { + return fmt.Errorf("failed to find Capability Registry p2pIDs in JD: %w", err) + } + commitConfig, err := c.CCIPHome.GetAllConfigs(&bind.CallOpts{ + Context: e.GetContext(), + }, don.Id, uint8(types.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("failed to get commit config for don %d: %w", don.Id, err) + } + if err := c.validateCCIPHomeVersionedActiveConfig(e, nodes, commitConfig.ActiveConfig, offRampsByChain); err != nil { + return fmt.Errorf("failed to validate active commit config for don %d: %w", don.Id, err) + } + execConfig, err := c.CCIPHome.GetAllConfigs(&bind.CallOpts{ + Context: e.GetContext(), + }, don.Id, uint8(types.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("failed to get exec config for don %d: %w", don.Id, err) + } + if err := c.validateCCIPHomeVersionedActiveConfig(e, nodes, execConfig.ActiveConfig, offRampsByChain); err != nil { + return fmt.Errorf("failed to validate active exec config for don %d: %w", don.Id, err) + } + } + return nil +} + +// validateCCIPHomeVersionedActiveConfig validates the CCIPHomeVersionedConfig based on corresponding chain selector and its state +// The validation related to correctness of F and node length is omitted here as it is already validated in the contract +func (c CCIPChainState) validateCCIPHomeVersionedActiveConfig(e cldf.Environment, nodes deployment.Nodes, homeCfg ccip_home.CCIPHomeVersionedConfig, offRampsByChain map[uint64]offramp.OffRampInterface) error { + if homeCfg.ConfigDigest == [32]byte{} { + return errors.New("active config digest is empty") + } + chainSel := homeCfg.Config.ChainSelector + if _, exists := e.SolChains[chainSel]; exists { + return nil + } + if _, exists := e.AptosChains[chainSel]; exists { + return nil + } + offRamp, ok := offRampsByChain[chainSel] + if !ok { + return fmt.Errorf("offRamp for chain %d not found in the state", chainSel) + } + // validate ChainConfig in CCIPHome + homeChainConfig, err := c.CCIPHome.GetChainConfig(&bind.CallOpts{ + Context: e.GetContext(), + }, chainSel) + if err != nil { + return fmt.Errorf("failed to get home chain config for chain %d: %w", chainSel, err) + } + // Node details should match with what we fetch from JD for CCIP Home Readers + if err := nodes.P2PIDsPresentInJD(homeChainConfig.Readers); err != nil { + return fmt.Errorf("failed to find homechain readers in JD for chain %d: %w", + chainSel, err) + } + + // Validate CCIPHome OCR3 Related Config + if offRamp.Address() != common.BytesToAddress(homeCfg.Config.OfframpAddress) { + return fmt.Errorf("offRamp address mismatch in active config for ccip home for chain %d: expected %s, got %s", + chainSel, offRamp.Address().Hex(), homeCfg.Config.OfframpAddress) + } + if c.RMNHome.Address() != common.BytesToAddress(homeCfg.Config.RmnHomeAddress) { + return fmt.Errorf("RMNHome address mismatch in active config for ccip home for chain %d: expected %s, got %s", + chainSel, c.RMNHome.Address().Hex(), homeCfg.Config.RmnHomeAddress) + } + p2pIDs := make([][32]byte, 0) + for _, node := range homeCfg.Config.Nodes { + p2pIDs = append(p2pIDs, node.P2pId) + } + if err := nodes.P2PIDsPresentInJD(p2pIDs); err != nil { + return fmt.Errorf("failed to find p2pIDs from CCIPHome config in JD for chain %d: %w", chainSel, err) + } + // cross-check with offRamp whether all in sync + switch homeCfg.Config.PluginType { + case uint8(types.PluginTypeCCIPCommit): + commitConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ + Context: e.GetContext(), + }, uint8(types.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("failed to get commit config for chain %d offRamp %s: %w", chainSel, c.OffRamp.Address().Hex(), err) + } + // the config digest should match with CCIP Home ActiveConfig + if commitConfig.ConfigInfo.ConfigDigest != homeCfg.ConfigDigest { + return fmt.Errorf("offRamp %s commit config digest mismatch with CCIPHome for chain %d: expected %x, got %x", + offRamp.Address().Hex(), chainSel, homeCfg.ConfigDigest, commitConfig.ConfigInfo.ConfigDigest) + } + if !commitConfig.ConfigInfo.IsSignatureVerificationEnabled { + return fmt.Errorf("offRamp %s for chain %d commit config signature verification is not enabled", + offRamp.Address().Hex(), chainSel) + } + if err := validateLatestConfigOffRamp(offRamp, commitConfig, homeChainConfig); err != nil { + return fmt.Errorf("offRamp %s for chain %d commit config validation error: %w", + offRamp.Address().Hex(), chainSel, err) + } + case uint8(types.PluginTypeCCIPExec): + execConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ + Context: e.GetContext(), + }, uint8(types.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("failed to get exec config for chain %d offRamp %s: %w", chainSel, offRamp.Address().Hex(), err) + } + // the config digest should match with CCIP Home ActiveConfig + if execConfig.ConfigInfo.ConfigDigest != homeCfg.ConfigDigest { + return fmt.Errorf("offRamp %s exec config digest mismatch with CCIPHome for chain %d: expected %x, got %x", + offRamp.Address().Hex(), chainSel, homeCfg.ConfigDigest, execConfig.ConfigInfo.ConfigDigest) + } + if execConfig.ConfigInfo.IsSignatureVerificationEnabled { + return fmt.Errorf("offRamp %s for chain %d exec config signature verification is enabled", + offRamp.Address().Hex(), chainSel) + } + if err := validateLatestConfigOffRamp(offRamp, execConfig, homeChainConfig); err != nil { + return fmt.Errorf("offRamp %s for chain %d exec config validation error: %w", + offRamp.Address().Hex(), chainSel, err) + } + default: + return fmt.Errorf("unsupported plugin type %d for chain %d", homeCfg.Config.PluginType, chainSel) + } + return nil +} + +// ValidateOnRamp validates whether the contract addresses configured in static and dynamic config are in sync with state +func (c CCIPChainState) ValidateOnRamp( + e cldf.Environment, + selector uint64, + connectedChains []uint64, +) error { + if c.OnRamp == nil { + return errors.New("no OnRamp contract found in the state") + } + staticCfg, err := c.OnRamp.GetStaticConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return err + } + if staticCfg.ChainSelector != selector { + return fmt.Errorf("onRamp %s chainSelector mismatch in static config: expected %d, got %d", + c.OnRamp.Address().Hex(), selector, staticCfg.ChainSelector) + } + // it should be RMNProxy pointing to the RMNRemote + if c.RMNProxy.Address() != staticCfg.RmnRemote { + return fmt.Errorf("onRamp %s RMNRemote mismatch in static config: expected %s, got %s", + c.OnRamp.Address().Hex(), c.RMNRemote.Address().Hex(), staticCfg.RmnRemote) + } + if c.NonceManager.Address() != staticCfg.NonceManager { + return fmt.Errorf("onRamp %s NonceManager mismatch in static config: expected %s, got %s", + c.OnRamp.Address().Hex(), c.NonceManager.Address().Hex(), staticCfg.NonceManager) + } + if c.TokenAdminRegistry.Address() != staticCfg.TokenAdminRegistry { + return fmt.Errorf("onRamp %s TokenAdminRegistry mismatch in static config: expected %s, got %s", + c.OnRamp.Address().Hex(), c.TokenAdminRegistry.Address().Hex(), staticCfg.TokenAdminRegistry) + } + dynamicCfg, err := c.OnRamp.GetDynamicConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get dynamic config for chain %d onRamp %s: %w", selector, c.OnRamp.Address().Hex(), err) + } + if dynamicCfg.FeeQuoter != c.FeeQuoter.Address() { + return fmt.Errorf("onRamp %s feeQuoter mismatch in dynamic config: expected %s, got %s", + c.OnRamp.Address().Hex(), c.FeeQuoter.Address().Hex(), dynamicCfg.FeeQuoter.Hex()) + } + // if the fee aggregator is set, it should match the one in the dynamic config + // otherwise the fee aggregator should be the timelock address + if c.FeeAggregator != (common.Address{}) { + if c.FeeAggregator != dynamicCfg.FeeAggregator { + return fmt.Errorf("onRamp %s feeAggregator mismatch in dynamic config: expected %s, got %s", + c.OnRamp.Address().Hex(), c.FeeAggregator.Hex(), dynamicCfg.FeeAggregator.Hex()) + } + } else { + if dynamicCfg.FeeAggregator != e.Chains[selector].DeployerKey.From { + return fmt.Errorf("onRamp %s feeAggregator mismatch in dynamic config: expected deployer key %s, got %s", + c.OnRamp.Address().Hex(), e.Chains[selector].DeployerKey.From.Hex(), dynamicCfg.FeeAggregator.Hex()) + } + } + + for _, otherChainSel := range connectedChains { + destChainCfg, err := c.OnRamp.GetDestChainConfig(&bind.CallOpts{ + Context: e.GetContext(), + }, otherChainSel) + if err != nil { + return fmt.Errorf("failed to get dest chain config from source chain %d onRamp %s for dest chain %d: %w", + selector, c.OnRamp.Address(), otherChainSel, err) + } + // if not blank, the dest chain config should be enabled + if destChainCfg != (onramp.GetDestChainConfig{}) { + if destChainCfg.Router != c.Router.Address() && destChainCfg.Router != c.TestRouter.Address() { + return fmt.Errorf("onRamp %s router mismatch in dest chain config: expected router %s or test router %s, got %s", + c.OnRamp.Address().Hex(), c.Router.Address().Hex(), c.TestRouter.Address().Hex(), destChainCfg.Router.Hex()) + } + } + } + + return nil +} + +// ValidateFeeQuoter validates whether the fee quoter contract address configured in static config is in sync with state +func (c CCIPChainState) ValidateFeeQuoter(e cldf.Environment) error { + if c.FeeQuoter == nil { + return errors.New("no FeeQuoter contract found in the state") + } + staticConfig, err := c.FeeQuoter.GetStaticConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get static config for FeeQuoter %s: %w", c.FeeQuoter.Address().Hex(), err) + } + linktokenAddr, err := c.LinkTokenAddress() + if err != nil { + return fmt.Errorf("failed to get link token address for from state: %w", err) + } + if staticConfig.LinkToken != linktokenAddr { + return fmt.Errorf("feeQuoter %s LinkToken mismatch: expected either linktoken %s or static link token %s, got %s", + c.FeeQuoter.Address().Hex(), c.LinkToken.Address().Hex(), c.StaticLinkToken.Address(), staticConfig.LinkToken.Hex()) + } + return nil +} + +// ValidateRouter validates the router contract to check if all wired contracts are synced with state +// and returns all connected chains with respect to the router +func (c CCIPChainState) ValidateRouter(e cldf.Environment, isTestRouter bool) ([]uint64, error) { + if c.Router == nil && c.TestRouter == nil { + return nil, errors.New("no Router or TestRouter contract found in the state") + } + routerC := c.Router + if isTestRouter { + routerC = c.TestRouter + } + armProxy, err := routerC.GetArmProxy(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return nil, fmt.Errorf("failed to get armProxy from router : %w", err) + } + if armProxy != c.RMNProxy.Address() { + return nil, fmt.Errorf("armProxy %s mismatch in router %s: expected %s, got %s", + armProxy.Hex(), routerC.Address().Hex(), c.RMNProxy.Address().Hex(), armProxy) + } + native, err := routerC.GetWrappedNative(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return nil, fmt.Errorf("failed to get wrapped native from router %s: %w", routerC.Address().Hex(), err) + } + if native != c.Weth9.Address() { + return nil, fmt.Errorf("wrapped native %s mismatch in router %s: expected %s, got %s", + native.Hex(), routerC.Address().Hex(), c.Weth9.Address().Hex(), native) + } + allConnectedChains := make([]uint64, 0) + // get offRamps + offRampDetails, err := routerC.GetOffRamps(&bind.CallOpts{ + Context: context.Background(), + }) + if err != nil { + return nil, fmt.Errorf("failed to get offRamps from router %s: %w", routerC.Address().Hex(), err) + } + for _, d := range offRampDetails { + // skip if solana - solana state is maintained in solana + if _, exists := e.SolChains[d.SourceChainSelector]; exists { + continue + } + allConnectedChains = append(allConnectedChains, d.SourceChainSelector) + // check if offRamp is valid + if d.OffRamp != c.OffRamp.Address() { + return nil, fmt.Errorf("offRamp %s mismatch for source %d in router %s: expected %s, got %s", + d.OffRamp.Hex(), d.SourceChainSelector, routerC.Address().Hex(), c.OffRamp.Address().Hex(), d.OffRamp) + } + } + // all lanes are bi-directional, if we have a lane from A to B, we also have a lane from B to A + // source to offRamp should be same as dest to onRamp + for _, dest := range allConnectedChains { + onRamp, err := routerC.GetOnRamp(&bind.CallOpts{ + Context: context.Background(), + }, dest) + if err != nil { + return nil, fmt.Errorf("failed to get onRamp for dest %d from router %s: %w", dest, routerC.Address().Hex(), err) + } + if onRamp != c.OnRamp.Address() { + return nil, fmt.Errorf("onRamp %s mismatch for dest chain %d in router %s: expected %s, got %s", + onRamp.Hex(), dest, routerC.Address().Hex(), c.OnRamp.Address().Hex(), onRamp) + } + } + return allConnectedChains, nil +} + +// ValidateRMNRemote validates the RMNRemote contract to check if all wired contracts are synced with state +// and returns whether RMN is enabled for the chain on the RMNRemote +// It validates whether RMNRemote is in sync with the RMNHome contract +func (c CCIPChainState) ValidateRMNRemote( + e cldf.Environment, + selector uint64, + rmnHomeActiveDigest [32]byte, +) (bool, error) { + if c.RMNRemote == nil { + return false, errors.New("no RMNRemote contract found in the state") + } + chainSelector, err := c.RMNRemote.GetLocalChainSelector(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return false, fmt.Errorf("failed to get local chain selector from RMNRemote %s: %w", c.RMNRemote.Address().Hex(), err) + } + if chainSelector != selector { + return false, fmt.Errorf("RMNRemote %s chainSelector mismatch: expected %d, got %d", + c.RMNRemote.Address().Hex(), selector, chainSelector) + } + versionedCfg, err := c.RMNRemote.GetVersionedConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return false, fmt.Errorf("failed to get versioned config from RMNRemote %s: %w", c.RMNRemote.Address().Hex(), err) + } + if versionedCfg.Version == 0 { + return false, errors.New("RMNRemote config is not set") + } + if versionedCfg.Config.RmnHomeContractConfigDigest != rmnHomeActiveDigest { + return false, fmt.Errorf("RMNRemote %s config digest mismatch: expected %x, got %x", + c.RMNRemote.Address().Hex(), rmnHomeActiveDigest, versionedCfg.Config.RmnHomeContractConfigDigest) + } + return versionedCfg.Config.FSign > 0, nil +} + +// ValidateOffRamp validates the offRamp contract to check if all wired contracts are synced with state +func (c CCIPChainState) ValidateOffRamp( + e cldf.Environment, + selector uint64, + onRampsBySelector map[uint64]common.Address, + isRMNEnabledBySource map[uint64]bool, +) error { + if c.OffRamp == nil { + return errors.New("no OffRamp contract found in the state") + } + // staticConfig chainSelector matches the selector key for the CCIPChainState + staticConfig, err := c.OffRamp.GetStaticConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get static config for chain %d offRammp %s: %w", selector, c.OffRamp.Address().Hex(), err) + } + // staticConfig chainSelector should match the selector key for the CCIPChainState + if staticConfig.ChainSelector != selector { + return fmt.Errorf("offRamp %s chainSelector mismatch: expected %d, got %d", + c.OffRamp.Address().Hex(), selector, staticConfig.ChainSelector) + } + // RMNProxy address for chain should be the same as the one in the static config for RMNRemote + if c.RMNProxy.Address() != staticConfig.RmnRemote { + return fmt.Errorf("offRamp %s RMNRemote mismatch: expected %s, got %s", + c.OffRamp.Address().Hex(), c.RMNRemote.Address().Hex(), staticConfig.RmnRemote) + } + // NonceManager address for chain should be the same as the one in the static config + if c.NonceManager.Address() != staticConfig.NonceManager { + return fmt.Errorf("offRamp %s NonceManager mismatch: expected %s, got %s", + c.OffRamp.Address().Hex(), c.NonceManager.Address().Hex(), staticConfig.NonceManager) + } + // TokenAdminRegistry address for chain should be the same as the one in the static config + if c.TokenAdminRegistry.Address() != staticConfig.TokenAdminRegistry { + return fmt.Errorf("offRamp %s TokenAdminRegistry mismatch: expected %s, got %s", + c.OffRamp.Address().Hex(), c.TokenAdminRegistry.Address().Hex(), staticConfig.TokenAdminRegistry) + } + dynamicConfig, err := c.OffRamp.GetDynamicConfig(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get dynamic config for chain %d offRamp %s: %w", selector, c.OffRamp.Address().Hex(), err) + } + // FeeQuoter address for chain should be the same as the one in the static config + if dynamicConfig.FeeQuoter != c.FeeQuoter.Address() { + return fmt.Errorf("offRamp %s feeQuoter mismatch: expected %s, got %s", + c.OffRamp.Address().Hex(), c.FeeQuoter.Address().Hex(), dynamicConfig.FeeQuoter.Hex()) + } + if dynamicConfig.PermissionLessExecutionThresholdSeconds != uint32(globals.PermissionLessExecutionThreshold.Seconds()) { + return fmt.Errorf("offRamp %s permissionless execution threshold mismatch: expected %f, got %d", + c.OffRamp.Address().Hex(), globals.PermissionLessExecutionThreshold.Seconds(), dynamicConfig.PermissionLessExecutionThresholdSeconds) + } + for chainSel, srcChainOnRamp := range onRampsBySelector { + config, err := c.OffRamp.GetSourceChainConfig(&bind.CallOpts{ + Context: e.GetContext(), + }, chainSel) + if err != nil { + return fmt.Errorf("failed to get source chain config for chain %d: %w", chainSel, err) + } + if config.IsEnabled { + // For all configured sources, the address of configured onRamp for chain A must be the Address() of the onramp on chain A + if srcChainOnRamp != common.BytesToAddress(config.OnRamp) { + return fmt.Errorf("onRamp address mismatch for source chain %d on OffRamp %s : expected %s, got %x", + chainSel, c.OffRamp.Address().Hex(), srcChainOnRamp.Hex(), config.OnRamp) + } + // The address of router should be accurate + if c.Router.Address() != config.Router && c.TestRouter.Address() != config.Router { + return fmt.Errorf("router address mismatch for source chain %d on OffRamp %s : expected either router %s or test router %s, got %s", + chainSel, c.OffRamp.Address().Hex(), c.Router.Address().Hex(), c.TestRouter.Address().Hex(), config.Router.Hex()) + } + // if RMN is enabled for the source chain, the RMNRemote and RMNHome should be configured to enable RMN + // the reverse is not always true, as RMN verification can be disable at offRamp but enabled in RMNRemote and RMNHome + if !config.IsRMNVerificationDisabled && !isRMNEnabledBySource[chainSel] { + return fmt.Errorf("RMN verification is enabled in offRamp %s for source chain %d, "+ + "but RMN is not enabled in RMNHome and RMNRemote for the chain", + c.OffRamp.Address().Hex(), chainSel) + } + } + } + return nil +} + +func (c CCIPChainState) TokenAddressBySymbol() (map[shared.TokenSymbol]common.Address, error) { + tokenAddresses := make(map[shared.TokenSymbol]common.Address) + if c.FactoryBurnMintERC20Token != nil { + tokenAddresses[shared.FactoryBurnMintERC20Symbol] = c.FactoryBurnMintERC20Token.Address() + } + for symbol, token := range c.ERC20Tokens { + tokenAddresses[symbol] = token.Address() + } + for symbol, token := range c.ERC677Tokens { + tokenAddresses[symbol] = token.Address() + } + for symbol, token := range c.BurnMintTokens677 { + tokenAddresses[symbol] = token.Address() + } + var err error + tokenAddresses[shared.LinkSymbol], err = c.LinkTokenAddress() + if err != nil { + return nil, err + } + if c.Weth9 == nil { + return nil, errors.New("no WETH contract found in the state") + } + tokenAddresses[shared.WethSymbol] = c.Weth9.Address() + return tokenAddresses, nil +} + +// TokenDetailsBySymbol get token mapping from the state. It contains only tokens that we have in address book +func (c CCIPChainState) TokenDetailsBySymbol() (map[shared.TokenSymbol]shared.TokenDetails, error) { + tokenDetails := make(map[shared.TokenSymbol]shared.TokenDetails) + if c.FactoryBurnMintERC20Token != nil { + tokenDetails[shared.FactoryBurnMintERC20Symbol] = c.FactoryBurnMintERC20Token + } + for symbol, token := range c.ERC20Tokens { + tokenDetails[symbol] = token + } + for symbol, token := range c.ERC677Tokens { + tokenDetails[symbol] = token + } + for symbol, token := range c.BurnMintTokens677 { + tokenDetails[symbol] = token + } + if c.LinkToken != nil { + tokenDetails[shared.LinkSymbol] = c.LinkToken + } + if c.StaticLinkToken != nil { + tokenDetails[shared.LinkSymbol] = c.StaticLinkToken + } + + if _, ok := tokenDetails[shared.LinkSymbol]; !ok { + return nil, errors.New("no LINK contract found in the state") + } + + if c.Weth9 == nil { + return nil, errors.New("no WETH contract found in the state") + } + tokenDetails[shared.WethSymbol] = c.Weth9 + return tokenDetails, nil +} + +func (c CCIPChainState) LinkTokenAddress() (common.Address, error) { + if c.LinkToken != nil { + return c.LinkToken.Address(), nil + } + if c.StaticLinkToken != nil { + return c.StaticLinkToken.Address(), nil + } + return common.Address{}, errors.New("no link token found in the state") +} + +func (c CCIPChainState) GenerateView(lggr logger.Logger, chain string) (view.ChainView, error) { + chainView := view.NewChain() + grp := errgroup.Group{} + + if c.Router != nil { + grp.Go(func() error { + routerView, err := v1_2.GenerateRouterView(c.Router, false) + if err != nil { + return errors.Wrapf(err, "failed to generate router view for router %s", c.Router.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.Router[c.Router.Address().Hex()] = routerView + lggr.Infow("generated router view", "router", c.Router.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.TestRouter != nil { + grp.Go(func() error { + testRouterView, err := v1_2.GenerateRouterView(c.TestRouter, true) + if err != nil { + return errors.Wrapf(err, "failed to generate router view for test router %s", c.TestRouter.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.Router[c.TestRouter.Address().Hex()] = testRouterView + lggr.Infow("generated test router view", "testRouter", c.TestRouter.Address().Hex(), "chain", chain) + return nil + }) + } + if c.TokenAdminRegistry != nil { + grp.Go(func() error { + lggr.Infow("generating token admin registry view, this might take a while based on number of tokens", + "tokenAdminRegistry", c.TokenAdminRegistry.Address().Hex(), "chain", chain) + taView, err := v1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) + if err != nil { + return errors.Wrapf(err, "failed to generate token admin registry view for token admin registry %s", c.TokenAdminRegistry.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView + lggr.Infow("generated token admin registry view", "tokenAdminRegistry", c.TokenAdminRegistry.Address().Hex(), "chain", chain) + return nil + }) + } + if c.TokenPoolFactory != nil { + grp.Go(func() error { + tpfView, err := v1_5_1.GenerateTokenPoolFactoryView(c.TokenPoolFactory) + if err != nil { + return errors.Wrapf(err, "failed to generate token pool factory view for token pool factory %s", c.TokenPoolFactory.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.TokenPoolFactory[c.TokenPoolFactory.Address().Hex()] = tpfView + lggr.Infow("generated token pool factory view", "tokenPoolFactory", c.TokenPoolFactory.Address().Hex(), "chain", chain) + return nil + }) + } + for tokenSymbol, versionToPool := range c.BurnMintTokenPools { + for _, tokenPool := range versionToPool { + grp.Go(func() error { + tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) + if err != nil { + return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) + } + chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), v1_5_1.PoolView{ + TokenPoolView: tokenPoolView, + }) + lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) + return nil + }) + } + } + for tokenSymbol, versionToPool := range c.BurnWithFromMintTokenPools { + for _, tokenPool := range versionToPool { + grp.Go(func() error { + tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) + if err != nil { + return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) + } + chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), v1_5_1.PoolView{ + TokenPoolView: tokenPoolView, + }) + lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) + return nil + }) + } + } + for tokenSymbol, versionToPool := range c.BurnFromMintTokenPools { + for _, tokenPool := range versionToPool { + grp.Go(func() error { + tokenPoolView, err := v1_5_1.GenerateTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) + if err != nil { + return errors.Wrapf(err, "failed to generate burn mint token pool view for %s", tokenPool.Address().String()) + } + chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), v1_5_1.PoolView{ + TokenPoolView: tokenPoolView, + }) + lggr.Infow("generated burn mint token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) + return nil + }) + } + } + for tokenSymbol, versionToPool := range c.LockReleaseTokenPools { + for _, tokenPool := range versionToPool { + grp.Go(func() error { + tokenPoolView, err := v1_5_1.GenerateLockReleaseTokenPoolView(tokenPool, c.usdFeedOrDefault(tokenSymbol)) + if err != nil { + return errors.Wrapf(err, "failed to generate lock release token pool view for %s", tokenPool.Address().String()) + } + chainView.UpdateTokenPool(tokenSymbol.String(), tokenPool.Address().Hex(), tokenPoolView) + lggr.Infow("generated lock release token pool view", "tokenPool", tokenPool.Address().Hex(), "chain", chain) + return nil + }) + } + } + for _, pool := range c.USDCTokenPools { + grp.Go(func() error { + tokenPoolView, err := v1_5_1.GenerateUSDCTokenPoolView(pool) + if err != nil { + return errors.Wrapf(err, "failed to generate USDC token pool view for %s", pool.Address().String()) + } + chainView.UpdateTokenPool(string(shared.USDCSymbol), pool.Address().Hex(), tokenPoolView) + lggr.Infow("generated USDC token pool view", "tokenPool", pool.Address().Hex(), "chain", chain) + return nil + }) + } + if c.NonceManager != nil { + grp.Go(func() error { + nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager) + if err != nil { + return errors.Wrapf(err, "failed to generate nonce manager view for nonce manager %s", c.NonceManager.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView + lggr.Infow("generated nonce manager view", "nonceManager", c.NonceManager.Address().Hex(), "chain", chain) + return nil + }) + } + if c.RMNRemote != nil { + grp.Go(func() error { + rmnView, err := v1_6.GenerateRMNRemoteView(c.RMNRemote) + if err != nil { + return errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.RMNRemote[c.RMNRemote.Address().Hex()] = rmnView + lggr.Infow("generated rmn remote view", "rmnRemote", c.RMNRemote.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.RMNHome != nil { + grp.Go(func() error { + rmnHomeView, err := v1_6.GenerateRMNHomeView(c.RMNHome) + if err != nil { + return errors.Wrapf(err, "failed to generate rmn home view for rmn home %s", c.RMNHome.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.RMNHome[c.RMNHome.Address().Hex()] = rmnHomeView + lggr.Infow("generated rmn home view", "rmnHome", c.RMNHome.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { + grp.Go(func() error { + // FeeQuoter knows only about tokens that managed by CCIP (i.e. imported from address book) + tokenDetails, err := c.TokenDetailsBySymbol() + if err != nil { + return err + } + tokens := make([]common.Address, 0, len(tokenDetails)) + for _, tokenDetail := range tokenDetails { + tokens = append(tokens, tokenDetail.Address()) + } + fqView, err := v1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TestRouter, tokens) + if err != nil { + return errors.Wrapf(err, "failed to generate fee quoter view for fee quoter %s", c.FeeQuoter.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView + lggr.Infow("generated fee quoter view", "feeQuoter", c.FeeQuoter.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.OnRamp != nil && c.Router != nil && c.TokenAdminRegistry != nil { + grp.Go(func() error { + onRampView, err := v1_6.GenerateOnRampView( + c.OnRamp, + c.Router, + c.TestRouter, + c.TokenAdminRegistry, + ) + if err != nil { + return errors.Wrapf(err, "failed to generate on ramp view for on ramp %s", c.OnRamp.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView + lggr.Infow("generated on ramp view", "onRamp", c.OnRamp.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.OffRamp != nil && c.Router != nil { + grp.Go(func() error { + offRampView, err := v1_6.GenerateOffRampView( + c.OffRamp, + c.Router, + c.TestRouter, + ) + if err != nil { + return errors.Wrapf(err, "failed to generate off ramp view for off ramp %s", c.OffRamp.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView + lggr.Infow("generated off ramp view", "offRamp", c.OffRamp.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.RMNProxy != nil { + grp.Go(func() error { + rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxy) + if err != nil { + return errors.Wrapf(err, "failed to generate rmn proxy view for rmn proxy %s", c.RMNProxy.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.RMNProxy[c.RMNProxy.Address().Hex()] = rmnProxyView + lggr.Infow("generated rmn proxy view", "rmnProxy", c.RMNProxy.Address().Hex(), "chain", chain) + return nil + }) + } + if c.CCIPHome != nil && c.CapabilityRegistry != nil { + grp.Go(func() error { + chView, err := v1_6.GenerateCCIPHomeView(c.CapabilityRegistry, c.CCIPHome) + if err != nil { + return errors.Wrapf(err, "failed to generate CCIP home view for CCIP home %s", c.CCIPHome.Address()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.CCIPHome[c.CCIPHome.Address().Hex()] = chView + lggr.Infow("generated CCIP home view", "CCIPHome", c.CCIPHome.Address().Hex(), "chain", chain) + return nil + }) + } + if c.CapabilityRegistry != nil { + grp.Go(func() error { + capRegView, err := v1_1.GenerateCapabilityRegistryView(c.CapabilityRegistry) + if err != nil { + return errors.Wrapf(err, "failed to generate capability registry view for capability registry %s", c.CapabilityRegistry.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView + lggr.Infow("generated capability registry view", "capabilityRegistry", c.CapabilityRegistry.Address().Hex(), "chain", chain) + return nil + }) + } + if c.MCMSWithTimelockState.Timelock != nil { + grp.Go(func() error { + mcmsView, err := c.MCMSWithTimelockState.GenerateMCMSWithTimelockView() + if err != nil { + return errors.Wrapf(err, "failed to generate MCMS with timelock view for MCMS with timelock %s", c.MCMSWithTimelockState.Timelock.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.MCMSWithTimelock = mcmsView + lggr.Infow("generated MCMS with timelock view", "MCMSWithTimelock", c.MCMSWithTimelockState.Timelock.Address().Hex(), "chain", chain) + return nil + }) + } + if c.LinkToken != nil { + grp.Go(func() error { + linkTokenView, err := c.GenerateLinkView() + if err != nil { + return errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.LinkToken = linkTokenView + lggr.Infow("generated link token view", "linkToken", c.LinkToken.Address().Hex(), "chain", chain) + return nil + }) + } + if c.StaticLinkToken != nil { + grp.Go(func() error { + staticLinkTokenView, err := c.GenerateStaticLinkView() + if err != nil { + return err + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.StaticLinkToken = staticLinkTokenView + lggr.Infow("generated static link token view", "staticLinkToken", c.StaticLinkToken.Address().Hex(), "chain", chain) + return nil + }) + } + + // Legacy contracts + // OnRamp, OffRamp, CommitStore legacy contract related state generation is not done right now + // considering the state of these contracts are not referred currently, and it's enormously expensive to generate + // state for multiple lanes per chain + for _, registryModule := range c.RegistryModules1_6 { + grp.Go(func() error { + registryModuleView, err := shared2.GetRegistryModuleView(registryModule, c.TokenAdminRegistry.Address()) + if err != nil { + return errors.Wrapf(err, "failed to generate registry module view for registry module %s", registryModule.Address().Hex()) + } + chainView.UpdateRegistryModuleView(registryModule.Address().Hex(), registryModuleView) + lggr.Infow("generated registry module view", "registryModule", registryModule.Address().Hex(), "chain", chain) + return nil + }) + } + + for _, registryModule := range c.RegistryModules1_5 { + grp.Go(func() error { + registryModuleView, err := shared2.GetRegistryModuleView(registryModule, c.TokenAdminRegistry.Address()) + if err != nil { + return errors.Wrapf(err, "failed to generate registry module view for registry module %s", registryModule.Address().Hex()) + } + chainView.UpdateRegistryModuleView(registryModule.Address().Hex(), registryModuleView) + lggr.Infow("generated registry module view", "registryModule", registryModule.Address().Hex(), "chain", chain) + return nil + }) + } + + if c.PriceRegistry != nil { + grp.Go(func() error { + priceRegistryView, err := v1_2.GeneratePriceRegistryView(c.PriceRegistry) + if err != nil { + return errors.Wrapf(err, "failed to generate price registry view for price registry %s", c.PriceRegistry.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.PriceRegistry[c.PriceRegistry.Address().String()] = priceRegistryView + lggr.Infow("generated price registry view", "priceRegistry", c.PriceRegistry.Address().String(), "chain", chain) + return nil + }) + } + + if c.RMN != nil { + grp.Go(func() error { + rmnView, err := v1_5.GenerateRMNView(c.RMN) + if err != nil { + return errors.Wrapf(err, "failed to generate rmn view for rmn %s", c.RMN.Address().String()) + } + chainView.UpdateMu.Lock() + defer chainView.UpdateMu.Unlock() + chainView.RMN[c.RMN.Address().Hex()] = rmnView + lggr.Infow("generated rmn view", "rmn", c.RMN.Address().Hex(), "chain", chain) + return nil + }) + } + + return chainView, grp.Wait() +} + +func (c CCIPChainState) usdFeedOrDefault(symbol shared.TokenSymbol) common.Address { + if feed, ok := c.USDFeeds[symbol]; ok { + return feed.Address() + } + return common.Address{} +} + +func validateLatestConfigOffRamp(offRamp offramp.OffRampInterface, cfg offramp.MultiOCR3BaseOCRConfig, homeChainConfig ccip_home.CCIPHomeChainConfig) error { + // check if number of signers are unique and greater than 3 + if cfg.ConfigInfo.IsSignatureVerificationEnabled { + if len(cfg.Signers) < 3 { + return fmt.Errorf("offRamp %s config signers count mismatch: expected at least 3, got %d", + offRamp.Address().Hex(), len(cfg.Signers)) + } + if !deployment.IsAddressListUnique(cfg.Signers) { + return fmt.Errorf("offRamp %s config signers list %v is not unique", offRamp.Address().Hex(), cfg.Signers) + } + if deployment.AddressListContainsEmptyAddress(cfg.Signers) { + return fmt.Errorf("offRamp %s config signers list %v contains empty address", offRamp.Address().Hex(), cfg.Signers) + } + } else if len(cfg.Signers) != 0 { + return fmt.Errorf("offRamp %s config signers count mismatch: expected 0, got %d", + offRamp.Address().Hex(), len(cfg.Signers)) + } + if len(cfg.Transmitters) < 3 { + return fmt.Errorf("offRamp %s config transmitters count mismatch: expected at least 3, got %d", + offRamp.Address().Hex(), len(cfg.Transmitters)) + } + if !deployment.IsAddressListUnique(cfg.Transmitters) { + return fmt.Errorf("offRamp %s config transmitters list %v is not unique", offRamp.Address().Hex(), cfg.Transmitters) + } + if deployment.AddressListContainsEmptyAddress(cfg.Transmitters) { + return fmt.Errorf("offRamp %s config transmitters list %v contains empty address", offRamp.Address().Hex(), cfg.Transmitters) + } + + // FRoleDON >= fChain is a requirement + if cfg.ConfigInfo.F < homeChainConfig.FChain { + return fmt.Errorf("offRamp %s config fChain mismatch: expected at least %d, got %d", + offRamp.Address().Hex(), homeChainConfig.FChain, cfg.ConfigInfo.F) + } + + // transmitters.length should be validated such that it meets the 3 * fChain + 1 requirement + minTransmitterReq := 3*int(homeChainConfig.FChain) + 1 + if len(cfg.Transmitters) < minTransmitterReq { + return fmt.Errorf("offRamp %s config transmitters count mismatch: expected at least %d, got %d", + offRamp.Address().Hex(), minTransmitterReq, len(cfg.Transmitters)) + } + return nil +} diff --git a/deployment/ccip/changeset/solana_state.go b/deployment/ccip/shared/stateview/solana/state.go similarity index 58% rename from deployment/ccip/changeset/solana_state.go rename to deployment/ccip/shared/stateview/solana/state.go index 7358c76f1cf..e3e21780575 100644 --- a/deployment/ccip/changeset/solana_state.go +++ b/deployment/ccip/shared/stateview/solana/state.go @@ -1,4 +1,4 @@ -package changeset +package solana import ( "context" @@ -10,47 +10,26 @@ import ( "github.com/gagliardetto/solana-go" "github.com/rs/zerolog/log" - solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" - solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" - solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/rmn_remote" - solTestTokenPool "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/test_token_pool" - solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" - + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/test_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" "github.com/smartcontractkit/chainlink/deployment/ccip/view" - viewSolana "github.com/smartcontractkit/chainlink/deployment/ccip/view/solana" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + solanaview "github.com/smartcontractkit/chainlink/deployment/ccip/view/solana" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" + "github.com/smartcontractkit/chainlink/deployment/common/types" ) -const ( - TokenPool cldf.ContractType = "TokenPool" - Receiver cldf.ContractType = "Receiver" - SPL2022Tokens cldf.ContractType = "SPL2022Tokens" - SPLTokens cldf.ContractType = "SPLTokens" - WSOL cldf.ContractType = "WSOL" - CCIPCommon cldf.ContractType = "CCIPCommon" - // for PDAs from AddRemoteChainToSolana - RemoteSource cldf.ContractType = "RemoteSource" - RemoteDest cldf.ContractType = "RemoteDest" - - // Tokenpool lookup table - TokenPoolLookupTable cldf.ContractType = "TokenPoolLookupTable" - - // CLL Identifier - CLLMetadata string = "CLL" -) - -// SolCCIPChainState holds public keys for all the currently deployed CCIP programs +// CCIPChainState holds public keys for all the currently deployed CCIP programs // on a chain. If a key has zero value, it means the program does not exist on the chain. -type SolCCIPChainState struct { +type CCIPChainState struct { // tokens LinkToken solana.PublicKey WSOL solana.PublicKey @@ -72,7 +51,7 @@ type SolCCIPChainState struct { RouterConfigPDA solana.PublicKey SourceChainStatePDAs map[uint64]solana.PublicKey // deprecated DestChainStatePDAs map[uint64]solana.PublicKey - TokenPoolLookupTable map[solana.PublicKey]map[solTestTokenPool.PoolType]map[string]solana.PublicKey // token -> token pool type -> metadata identifier -> lookup table + TokenPoolLookupTable map[solana.PublicKey]map[test_token_pool.PoolType]map[string]solana.PublicKey // token -> token pool type -> metadata identifier -> lookup table FeeQuoterConfigPDA solana.PublicKey OffRampConfigPDA solana.PublicKey OffRampStatePDA solana.PublicKey @@ -80,41 +59,136 @@ type SolCCIPChainState struct { RMNRemoteCursesPDA solana.PublicKey } -func FetchOfframpLookupTable(ctx context.Context, chain deployment.SolChain, offRampAddress solana.PublicKey) (solana.PublicKey, error) { - var referenceAddressesAccount solOffRamp.ReferenceAddresses - offRampReferenceAddressesPDA, _, _ := solState.FindOfframpReferenceAddressesPDA(offRampAddress) - err := chain.GetAccountDataBorshInto(ctx, offRampReferenceAddressesPDA, &referenceAddressesAccount) +func (s CCIPChainState) TokenToTokenProgram(tokenAddress solana.PublicKey) (solana.PublicKey, error) { + if tokenAddress.Equals(s.LinkToken) || tokenAddress.Equals(s.WSOL) { + return solana.TokenProgramID, nil + } + for _, spl2022Token := range s.SPL2022Tokens { + if spl2022Token.Equals(tokenAddress) { + return solana.Token2022ProgramID, nil + } + } + for _, splToken := range s.SPLTokens { + if splToken.Equals(tokenAddress) { + return solana.TokenProgramID, nil + } + } + return solana.PublicKey{}, fmt.Errorf("token program not found for token address %s", tokenAddress.String()) +} + +func (s CCIPChainState) GetRouterInfo() (router, routerConfigPDA solana.PublicKey, err error) { + if s.Router.IsZero() { + return solana.PublicKey{}, solana.PublicKey{}, errors.New("router not found in existing state, deploy the router first") + } + routerConfigPDA, _, err = state.FindConfigPDA(s.Router) if err != nil { - return solana.PublicKey{}, fmt.Errorf("failed to get offramp reference addresses: %w", err) + return solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("failed to find config PDA: %w", err) } - return referenceAddressesAccount.OfframpLookupTable, nil + return s.Router, routerConfigPDA, nil } -func LoadOnchainStateSolana(e deployment.Environment) (CCIPOnChainState, error) { - state := CCIPOnChainState{ - SolChains: make(map[uint64]SolCCIPChainState), +func (s CCIPChainState) GenerateView(solChain cldf.SolChain) (view.SolChainView, error) { + chainView := view.NewSolChain() + var remoteChains []uint64 + for selector := range s.DestChainStatePDAs { + remoteChains = append(remoteChains, selector) } - for chainSelector, chain := range e.SolChains { - addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector) - if err != nil { - // Chain not found in address book, initialize empty - if !errors.Is(err, cldf.ErrChainNotFound) { - return state, err + var allTokens []solana.PublicKey + allTokens = append(allTokens, s.LinkToken) + allTokens = append(allTokens, s.WSOL) + allTokens = append(allTokens, s.SPL2022Tokens...) + allTokens = append(allTokens, s.SPLTokens...) + for _, token := range allTokens { + if !token.IsZero() { + program, err := s.TokenToTokenProgram(token) + if err != nil { + return chainView, fmt.Errorf("failed to find token program for token %s: %w", token, err) + } + tokenView, err := solanaview.GenerateTokenView(solChain, token, program.String()) + if err != nil { + return chainView, fmt.Errorf("failed to generate token view for token %s: %w", token, err) + } + if token.Equals(s.LinkToken) { + chainView.LinkToken = tokenView + } else { + chainView.Tokens[token.String()] = tokenView } - addresses = make(map[string]cldf.TypeAndVersion) } - chainState, err := LoadChainStateSolana(chain, addresses) + } + if !s.FeeQuoter.IsZero() { + fqView, err := solanaview.GenerateFeeQuoterView(solChain, s.FeeQuoter, remoteChains, allTokens) + if err != nil { + return chainView, fmt.Errorf("failed to generate fee quoter view %s: %w", s.FeeQuoter, err) + } + chainView.FeeQuoter[s.FeeQuoter.String()] = fqView + } + if !s.Router.IsZero() { + routerView, err := solanaview.GenerateRouterView(solChain, s.Router, remoteChains, allTokens) if err != nil { - return state, err + return chainView, fmt.Errorf("failed to generate router view %s: %w", s.Router, err) } - state.SolChains[chainSelector] = chainState + chainView.Router[s.Router.String()] = routerView } - return state, nil + if !s.OffRamp.IsZero() { + offRampView, err := solanaview.GenerateOffRampView(solChain, s.OffRamp, remoteChains, allTokens) + if err != nil { + return chainView, fmt.Errorf("failed to generate offramp view %s: %w", s.OffRamp, err) + } + chainView.OffRamp[s.OffRamp.String()] = offRampView + } + if !s.RMNRemote.IsZero() { + rmnRemoteView, err := solanaview.GenerateRMNRemoteView(solChain, s.RMNRemote, remoteChains, allTokens) + if err != nil { + return chainView, fmt.Errorf("failed to generate rmn remote view %s: %w", s.RMNRemote, err) + } + chainView.RMNRemote[s.RMNRemote.String()] = rmnRemoteView + } + for metadata, tokenPool := range s.BurnMintTokenPools { + if tokenPool.IsZero() { + continue + } + tokenPoolView, err := solanaview.GenerateTokenPoolView(solChain, tokenPool, remoteChains, allTokens, test_token_pool.BurnAndMint_PoolType.String(), metadata) + if err != nil { + return chainView, fmt.Errorf("failed to generate burn mint token pool view %s: %w", tokenPool, err) + } + chainView.TokenPool[tokenPool.String()] = tokenPoolView + } + for metadata, tokenPool := range s.LockReleaseTokenPools { + if tokenPool.IsZero() { + continue + } + tokenPoolView, err := solanaview.GenerateTokenPoolView(solChain, tokenPool, remoteChains, allTokens, test_token_pool.LockAndRelease_PoolType.String(), metadata) + if err != nil { + return chainView, fmt.Errorf("failed to generate lock release token pool view %s: %w", tokenPool, err) + } + chainView.TokenPool[tokenPool.String()] = tokenPoolView + } + return chainView, nil +} + +func (s CCIPChainState) GetFeeAggregator(chain cldf.SolChain) solana.PublicKey { + var config ccip_router.Config + configPDA, _, _ := state.FindConfigPDA(s.Router) + err := chain.GetAccountDataBorshInto(context.Background(), configPDA, &config) + if err != nil { + return solana.PublicKey{} + } + return config.FeeAggregator +} + +func FetchOfframpLookupTable(ctx context.Context, chain cldf.SolChain, offRampAddress solana.PublicKey) (solana.PublicKey, error) { + var referenceAddressesAccount ccip_offramp.ReferenceAddresses + offRampReferenceAddressesPDA, _, _ := state.FindOfframpReferenceAddressesPDA(offRampAddress) + err := chain.GetAccountDataBorshInto(ctx, offRampReferenceAddressesPDA, &referenceAddressesAccount) + if err != nil { + return solana.PublicKey{}, fmt.Errorf("failed to get offramp reference addresses: %w", err) + } + return referenceAddressesAccount.OfframpLookupTable, nil } // LoadChainStateSolana Loads all state for a SolChain into state -func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.TypeAndVersion) (SolCCIPChainState, error) { - state := SolCCIPChainState{ +func LoadChainStateSolana(chain cldf.SolChain, addresses map[string]cldf.TypeAndVersion) (CCIPChainState, error) { + solState := CCIPChainState{ SourceChainStatePDAs: make(map[uint64]solana.PublicKey), DestChainStatePDAs: make(map[uint64]solana.PublicKey), BurnMintTokenPools: make(map[string]solana.PublicKey), @@ -122,26 +196,26 @@ func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.T SPL2022Tokens: make([]solana.PublicKey, 0), SPLTokens: make([]solana.PublicKey, 0), WSOL: solana.SolMint, - TokenPoolLookupTable: make(map[solana.PublicKey]map[solTestTokenPool.PoolType]map[string]solana.PublicKey), + TokenPoolLookupTable: make(map[solana.PublicKey]map[test_token_pool.PoolType]map[string]solana.PublicKey), } // Most programs upgraded in place, but some are not so we always want to // load the latest version versions := make(map[cldf.ContractType]semver.Version) for address, tvStr := range addresses { switch tvStr.Type { - case commontypes.LinkToken: + case types.LinkToken: pub := solana.MustPublicKeyFromBase58(address) - state.LinkToken = pub - case Router: + solState.LinkToken = pub + case shared.Router: pub := solana.MustPublicKeyFromBase58(address) - state.Router = pub - routerConfigPDA, _, err := solState.FindConfigPDA(state.Router) + solState.Router = pub + routerConfigPDA, _, err := state.FindConfigPDA(solState.Router) if err != nil { - return state, err + return solState, err } - state.RouterConfigPDA = routerConfigPDA - case Receiver: - receiverVersion, ok := versions[OffRamp] + solState.RouterConfigPDA = routerConfigPDA + case shared.Receiver: + receiverVersion, ok := versions[shared.OffRamp] // if we have an receiver version, we need to make sure it's a newer version if ok { // if the version is not newer, skip this address @@ -151,36 +225,36 @@ func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.T } } pub := solana.MustPublicKeyFromBase58(address) - state.Receiver = pub - case SPL2022Tokens: + solState.Receiver = pub + case shared.SPL2022Tokens: pub := solana.MustPublicKeyFromBase58(address) - state.SPL2022Tokens = append(state.SPL2022Tokens, pub) - case SPLTokens: + solState.SPL2022Tokens = append(solState.SPL2022Tokens, pub) + case shared.SPLTokens: pub := solana.MustPublicKeyFromBase58(address) - state.SPLTokens = append(state.SPLTokens, pub) - case RemoteSource: + solState.SPLTokens = append(solState.SPLTokens, pub) + case shared.RemoteSource: pub := solana.MustPublicKeyFromBase58(address) // Labels should only have one entry for selStr := range tvStr.Labels { selector, err := strconv.ParseUint(selStr, 10, 64) if err != nil { - return state, err + return solState, err } - state.SourceChainStatePDAs[selector] = pub + solState.SourceChainStatePDAs[selector] = pub } - case RemoteDest: + case shared.RemoteDest: pub := solana.MustPublicKeyFromBase58(address) // Labels should only have one entry for selStr := range tvStr.Labels { selector, err := strconv.ParseUint(selStr, 10, 64) if err != nil { - return state, err + return solState, err } - state.DestChainStatePDAs[selector] = pub + solState.DestChainStatePDAs[selector] = pub } - case TokenPoolLookupTable: + case shared.TokenPoolLookupTable: lookupTablePubKey := solana.MustPublicKeyFromBase58(address) - var poolType *solTestTokenPool.PoolType + var poolType *test_token_pool.PoolType var tokenPubKey solana.PublicKey var poolMetadata string for label := range tvStr.Labels { @@ -189,11 +263,11 @@ func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.T tokenPubKey = maybeTokenPubKey } else { switch label { - case solTestTokenPool.BurnAndMint_PoolType.String(): - t := solTestTokenPool.BurnAndMint_PoolType + case test_token_pool.BurnAndMint_PoolType.String(): + t := test_token_pool.BurnAndMint_PoolType poolType = &t - case solTestTokenPool.LockAndRelease_PoolType.String(): - t := solTestTokenPool.LockAndRelease_PoolType + case test_token_pool.LockAndRelease_PoolType.String(): + t := test_token_pool.LockAndRelease_PoolType poolType = &t default: poolMetadata = label @@ -201,29 +275,29 @@ func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.T } } if poolMetadata == "" { - poolMetadata = CLLMetadata + poolMetadata = shared.CLLMetadata } if poolType == nil { - t := solTestTokenPool.BurnAndMint_PoolType + t := test_token_pool.BurnAndMint_PoolType poolType = &t } - if state.TokenPoolLookupTable[tokenPubKey] == nil { - state.TokenPoolLookupTable[tokenPubKey] = make(map[solTestTokenPool.PoolType]map[string]solana.PublicKey) + if solState.TokenPoolLookupTable[tokenPubKey] == nil { + solState.TokenPoolLookupTable[tokenPubKey] = make(map[test_token_pool.PoolType]map[string]solana.PublicKey) } - if state.TokenPoolLookupTable[tokenPubKey][*poolType] == nil { - state.TokenPoolLookupTable[tokenPubKey][*poolType] = make(map[string]solana.PublicKey) + if solState.TokenPoolLookupTable[tokenPubKey][*poolType] == nil { + solState.TokenPoolLookupTable[tokenPubKey][*poolType] = make(map[string]solana.PublicKey) } - state.TokenPoolLookupTable[tokenPubKey][*poolType][poolMetadata] = lookupTablePubKey - case FeeQuoter: + solState.TokenPoolLookupTable[tokenPubKey][*poolType][poolMetadata] = lookupTablePubKey + case shared.FeeQuoter: pub := solana.MustPublicKeyFromBase58(address) - state.FeeQuoter = pub - feeQuoterConfigPDA, _, err := solState.FindFqConfigPDA(state.FeeQuoter) + solState.FeeQuoter = pub + feeQuoterConfigPDA, _, err := state.FindFqConfigPDA(solState.FeeQuoter) if err != nil { - return state, err + return solState, err } - state.FeeQuoterConfigPDA = feeQuoterConfigPDA - case OffRamp: - offRampVersion, ok := versions[OffRamp] + solState.FeeQuoterConfigPDA = feeQuoterConfigPDA + case shared.OffRamp: + offRampVersion, ok := versions[shared.OffRamp] // if we have an offramp version, we need to make sure it's a newer version if ok { // if the version is not newer, skip this address @@ -233,71 +307,54 @@ func LoadChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.T } } pub := solana.MustPublicKeyFromBase58(address) - state.OffRamp = pub - offRampConfigPDA, _, err := solState.FindOfframpConfigPDA(state.OffRamp) + solState.OffRamp = pub + offRampConfigPDA, _, err := state.FindOfframpConfigPDA(solState.OffRamp) if err != nil { - return state, err + return solState, err } - state.OffRampConfigPDA = offRampConfigPDA - offRampStatePDA, _, err := solState.FindOfframpStatePDA(state.OffRamp) + solState.OffRampConfigPDA = offRampConfigPDA + offRampStatePDA, _, err := state.FindOfframpStatePDA(solState.OffRamp) if err != nil { - return state, err + return solState, err } - state.OffRampStatePDA = offRampStatePDA - case BurnMintTokenPool: + solState.OffRampStatePDA = offRampStatePDA + case shared.BurnMintTokenPool: pub := solana.MustPublicKeyFromBase58(address) if len(tvStr.Labels) == 0 { - state.BurnMintTokenPools[CLLMetadata] = pub + solState.BurnMintTokenPools[shared.CLLMetadata] = pub } // Labels should only have one entry for metadataStr := range tvStr.Labels { - state.BurnMintTokenPools[metadataStr] = pub + solState.BurnMintTokenPools[metadataStr] = pub } - case LockReleaseTokenPool: + case shared.LockReleaseTokenPool: pub := solana.MustPublicKeyFromBase58(address) if len(tvStr.Labels) == 0 { - state.LockReleaseTokenPools[CLLMetadata] = pub + solState.LockReleaseTokenPools[shared.CLLMetadata] = pub } // Labels should only have one entry for metadataStr := range tvStr.Labels { - state.LockReleaseTokenPools[metadataStr] = pub + solState.LockReleaseTokenPools[metadataStr] = pub } - case RMNRemote: + case shared.RMNRemote: pub := solana.MustPublicKeyFromBase58(address) - state.RMNRemote = pub - rmnRemoteConfigPDA, _, err := solState.FindRMNRemoteConfigPDA(state.RMNRemote) + solState.RMNRemote = pub + rmnRemoteConfigPDA, _, err := state.FindRMNRemoteConfigPDA(solState.RMNRemote) if err != nil { - return state, err + return solState, err } - state.RMNRemoteConfigPDA = rmnRemoteConfigPDA - rmnRemoteCursesPDA, _, err := solState.FindRMNRemoteCursesPDA(state.RMNRemote) + solState.RMNRemoteConfigPDA = rmnRemoteConfigPDA + rmnRemoteCursesPDA, _, err := state.FindRMNRemoteCursesPDA(solState.RMNRemote) if err != nil { - return state, err + return solState, err } - state.RMNRemoteCursesPDA = rmnRemoteCursesPDA + solState.RMNRemoteCursesPDA = rmnRemoteCursesPDA default: continue } versions[tvStr.Type] = tvStr.Version } - return state, nil -} - -func (s SolCCIPChainState) TokenToTokenProgram(tokenAddress solana.PublicKey) (solana.PublicKey, error) { - if tokenAddress.Equals(s.LinkToken) || tokenAddress.Equals(s.WSOL) { - return solana.TokenProgramID, nil - } - for _, spl2022Token := range s.SPL2022Tokens { - if spl2022Token.Equals(tokenAddress) { - return solana.Token2022ProgramID, nil - } - } - for _, splToken := range s.SPLTokens { - if splToken.Equals(tokenAddress) { - return solana.TokenProgramID, nil - } - } - return solana.PublicKey{}, fmt.Errorf("token program not found for token address %s", tokenAddress.String()) + return solState, nil } func FindSolanaAddress(tv cldf.TypeAndVersion, addresses map[string]cldf.TypeAndVersion) solana.PublicKey { @@ -311,8 +368,8 @@ func FindSolanaAddress(tv cldf.TypeAndVersion, addresses map[string]cldf.TypeAnd } func ValidateOwnershipSolana( - e *deployment.Environment, - chain deployment.SolChain, + e *cldf.Environment, + chain cldf.SolChain, mcms bool, programID solana.PublicKey, contractType cldf.ContractType, @@ -322,70 +379,70 @@ func ValidateOwnershipSolana( if err != nil { return fmt.Errorf("failed to get existing addresses: %w", err) } - mcmState, err := state.MaybeLoadMCMSWithTimelockChainStateSolana(chain, addresses) + mcmState, err := commonstate.MaybeLoadMCMSWithTimelockChainStateSolana(chain, addresses) if err != nil { return fmt.Errorf("failed to load MCMS with timelock chain state: %w", err) } - timelockSignerPDA := state.GetTimelockSignerPDA(mcmState.TimelockProgram, mcmState.TimelockSeed) - config, _, err := solState.FindConfigPDA(programID) + timelockSignerPDA := commonstate.GetTimelockSignerPDA(mcmState.TimelockProgram, mcmState.TimelockSeed) + config, _, err := state.FindConfigPDA(programID) if err != nil { return fmt.Errorf("failed to find config PDA: %w", err) } switch contractType { - case Router: - programData := solRouter.Config{} + case shared.Router: + programData := ccip_router.Config{} err = chain.GetAccountDataBorshInto(e.GetContext(), config, &programData) if err != nil { return fmt.Errorf("failed to get account data: %w", err) } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { return fmt.Errorf("failed to validate ownership for router: %w", err) } - case OffRamp: + case shared.OffRamp: programData := ccip_offramp.Config{} err = chain.GetAccountDataBorshInto(e.GetContext(), config, &programData) if err != nil { return fmt.Errorf("failed to get account data: %w", err) } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { return fmt.Errorf("failed to validate ownership for offramp: %w", err) } - case FeeQuoter: + case shared.FeeQuoter: programData := fee_quoter.Config{} err = chain.GetAccountDataBorshInto(e.GetContext(), config, &programData) if err != nil { return fmt.Errorf("failed to get account data: %w", err) } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { return fmt.Errorf("failed to validate ownership for feequoter: %w", err) } - case BurnMintTokenPool: - programData := solTestTokenPool.State{} - poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddress, programID) + case shared.BurnMintTokenPool: + programData := test_token_pool.State{} + poolConfigPDA, _ := tokens.TokenPoolConfigAddress(tokenAddress, programID) err = chain.GetAccountDataBorshInto(e.GetContext(), poolConfigPDA, &programData) if err != nil { return nil } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Config.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Config.Owner); err != nil { return fmt.Errorf("failed to validate ownership for burnmint_token_pool: %w", err) } - case LockReleaseTokenPool: - programData := solTestTokenPool.State{} - poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddress, programID) + case shared.LockReleaseTokenPool: + programData := test_token_pool.State{} + poolConfigPDA, _ := tokens.TokenPoolConfigAddress(tokenAddress, programID) err = chain.GetAccountDataBorshInto(e.GetContext(), poolConfigPDA, &programData) if err != nil { return nil } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Config.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Config.Owner); err != nil { return fmt.Errorf("failed to validate ownership for lockrelease_token_pool: %w", err) } - case RMNRemote: + case shared.RMNRemote: programData := rmn_remote.Config{} err = chain.GetAccountDataBorshInto(e.GetContext(), config, &programData) if err != nil { return fmt.Errorf("failed to get account data: %w", err) } - if err := commoncs.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { + if err := commonchangeset.ValidateOwnershipSolanaCommon(mcms, chain.DeployerKey.PublicKey(), timelockSignerPDA, programData.Owner); err != nil { return fmt.Errorf("failed to validate ownership for rmnremote: %w", err) } default: @@ -395,9 +452,9 @@ func ValidateOwnershipSolana( } func IsSolanaProgramOwnedByTimelock( - e *deployment.Environment, - chain deployment.SolChain, - chainState SolCCIPChainState, + e *cldf.Environment, + chain cldf.SolChain, + chainState CCIPChainState, contractType cldf.ContractType, tokenAddress solana.PublicKey, // for token pools only tokenPoolMetadata string, @@ -406,15 +463,15 @@ func IsSolanaProgramOwnedByTimelock( if err != nil { return false } - mcmState, err := state.MaybeLoadMCMSWithTimelockChainStateSolana(chain, addresses) + mcmState, err := commonstate.MaybeLoadMCMSWithTimelockChainStateSolana(chain, addresses) if err != nil { return false } - timelockSignerPDA := state.GetTimelockSignerPDA(mcmState.TimelockProgram, mcmState.TimelockSeed) + timelockSignerPDA := commonstate.GetTimelockSignerPDA(mcmState.TimelockProgram, mcmState.TimelockSeed) switch contractType { - case Router: - programData := solRouter.Config{} - config, _, err := solState.FindConfigPDA(chainState.Router) + case shared.Router: + programData := ccip_router.Config{} + config, _, err := state.FindConfigPDA(chainState.Router) if err != nil { return false } @@ -423,9 +480,9 @@ func IsSolanaProgramOwnedByTimelock( return false } return programData.Owner.Equals(timelockSignerPDA) - case OffRamp: + case shared.OffRamp: programData := ccip_offramp.Config{} - config, _, err := solState.FindConfigPDA(chainState.OffRamp) + config, _, err := state.FindConfigPDA(chainState.OffRamp) if err != nil { return false } @@ -434,9 +491,9 @@ func IsSolanaProgramOwnedByTimelock( return false } return programData.Owner.Equals(timelockSignerPDA) - case FeeQuoter: + case shared.FeeQuoter: programData := fee_quoter.Config{} - config, _, err := solState.FindConfigPDA(chainState.FeeQuoter) + config, _, err := state.FindConfigPDA(chainState.FeeQuoter) if err != nil { return false } @@ -445,33 +502,33 @@ func IsSolanaProgramOwnedByTimelock( return false } return programData.Owner.Equals(timelockSignerPDA) - case BurnMintTokenPool: - programData := solTestTokenPool.State{} - metadata := CLLMetadata + case shared.BurnMintTokenPool: + programData := test_token_pool.State{} + metadata := shared.CLLMetadata if tokenPoolMetadata != "" { metadata = tokenPoolMetadata } - poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddress, chainState.BurnMintTokenPools[metadata]) + poolConfigPDA, _ := tokens.TokenPoolConfigAddress(tokenAddress, chainState.BurnMintTokenPools[metadata]) err = chain.GetAccountDataBorshInto(e.GetContext(), poolConfigPDA, &programData) if err != nil { return false } return programData.Config.Owner.Equals(timelockSignerPDA) - case LockReleaseTokenPool: - programData := solTestTokenPool.State{} - metadata := CLLMetadata + case shared.LockReleaseTokenPool: + programData := test_token_pool.State{} + metadata := shared.CLLMetadata if tokenPoolMetadata != "" { metadata = tokenPoolMetadata } - poolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddress, chainState.LockReleaseTokenPools[metadata]) + poolConfigPDA, _ := tokens.TokenPoolConfigAddress(tokenAddress, chainState.LockReleaseTokenPools[metadata]) err = chain.GetAccountDataBorshInto(e.GetContext(), poolConfigPDA, &programData) if err != nil { return false } return programData.Config.Owner.Equals(timelockSignerPDA) - case RMNRemote: + case shared.RMNRemote: programData := rmn_remote.Config{} - config, _, err := solState.FindConfigPDA(chainState.RMNRemote) + config, _, err := state.FindConfigPDA(chainState.RMNRemote) if err != nil { return false } @@ -485,107 +542,7 @@ func IsSolanaProgramOwnedByTimelock( } } -func (s SolCCIPChainState) GetRouterInfo() (router, routerConfigPDA solana.PublicKey, err error) { - if s.Router.IsZero() { - return solana.PublicKey{}, solana.PublicKey{}, errors.New("router not found in existing state, deploy the router first") - } - routerConfigPDA, _, err = solState.FindConfigPDA(s.Router) - if err != nil { - return solana.PublicKey{}, solana.PublicKey{}, fmt.Errorf("failed to find config PDA: %w", err) - } - return s.Router, routerConfigPDA, nil -} - func FindReceiverTargetAccount(receiverID solana.PublicKey) solana.PublicKey { receiverTargetAccount, _, _ := solana.FindProgramAddress([][]byte{[]byte("counter")}, receiverID) return receiverTargetAccount } - -func (s SolCCIPChainState) GenerateView(solChain deployment.SolChain) (view.SolChainView, error) { - chainView := view.NewSolChain() - var remoteChains []uint64 - for selector := range s.DestChainStatePDAs { - remoteChains = append(remoteChains, selector) - } - var allTokens []solana.PublicKey - allTokens = append(allTokens, s.LinkToken) - allTokens = append(allTokens, s.WSOL) - allTokens = append(allTokens, s.SPL2022Tokens...) - allTokens = append(allTokens, s.SPLTokens...) - for _, token := range allTokens { - if !token.IsZero() { - program, err := s.TokenToTokenProgram(token) - if err != nil { - return chainView, fmt.Errorf("failed to find token program for token %s: %w", token, err) - } - tokenView, err := viewSolana.GenerateTokenView(solChain, token, program.String()) - if err != nil { - return chainView, fmt.Errorf("failed to generate token view for token %s: %w", token, err) - } - if token.Equals(s.LinkToken) { - chainView.LinkToken = tokenView - } else { - chainView.Tokens[token.String()] = tokenView - } - } - } - if !s.FeeQuoter.IsZero() { - fqView, err := viewSolana.GenerateFeeQuoterView(solChain, s.FeeQuoter, remoteChains, allTokens) - if err != nil { - return chainView, fmt.Errorf("failed to generate fee quoter view %s: %w", s.FeeQuoter, err) - } - chainView.FeeQuoter[s.FeeQuoter.String()] = fqView - } - if !s.Router.IsZero() { - routerView, err := viewSolana.GenerateRouterView(solChain, s.Router, remoteChains, allTokens) - if err != nil { - return chainView, fmt.Errorf("failed to generate router view %s: %w", s.Router, err) - } - chainView.Router[s.Router.String()] = routerView - } - if !s.OffRamp.IsZero() { - offRampView, err := viewSolana.GenerateOffRampView(solChain, s.OffRamp, remoteChains, allTokens) - if err != nil { - return chainView, fmt.Errorf("failed to generate offramp view %s: %w", s.OffRamp, err) - } - chainView.OffRamp[s.OffRamp.String()] = offRampView - } - if !s.RMNRemote.IsZero() { - rmnRemoteView, err := viewSolana.GenerateRMNRemoteView(solChain, s.RMNRemote, remoteChains, allTokens) - if err != nil { - return chainView, fmt.Errorf("failed to generate rmn remote view %s: %w", s.RMNRemote, err) - } - chainView.RMNRemote[s.RMNRemote.String()] = rmnRemoteView - } - for metadata, tokenPool := range s.BurnMintTokenPools { - if tokenPool.IsZero() { - continue - } - tokenPoolView, err := viewSolana.GenerateTokenPoolView(solChain, tokenPool, remoteChains, allTokens, solTestTokenPool.BurnAndMint_PoolType.String(), metadata) - if err != nil { - return chainView, fmt.Errorf("failed to generate burn mint token pool view %s: %w", tokenPool, err) - } - chainView.TokenPool[tokenPool.String()] = tokenPoolView - } - for metadata, tokenPool := range s.LockReleaseTokenPools { - if tokenPool.IsZero() { - continue - } - tokenPoolView, err := viewSolana.GenerateTokenPoolView(solChain, tokenPool, remoteChains, allTokens, solTestTokenPool.LockAndRelease_PoolType.String(), metadata) - if err != nil { - return chainView, fmt.Errorf("failed to generate lock release token pool view %s: %w", tokenPool, err) - } - chainView.TokenPool[tokenPool.String()] = tokenPoolView - } - return chainView, nil -} - -func (s SolCCIPChainState) GetFeeAggregator(chain deployment.SolChain) solana.PublicKey { - var config solRouter.Config - configPDA, _, _ := solState.FindConfigPDA(s.Router) - err := chain.GetAccountDataBorshInto(context.Background(), configPDA, &config) - if err != nil { - return solana.PublicKey{} - } - return config.FeeAggregator -} diff --git a/deployment/ccip/shared/stateview/state.go b/deployment/ccip/shared/stateview/state.go new file mode 100644 index 00000000000..b78e9f2b708 --- /dev/null +++ b/deployment/ccip/shared/stateview/state.go @@ -0,0 +1,1094 @@ +package stateview + +import ( + "context" + std_errors "errors" + "fmt" + "strconv" + "sync" + + "github.com/Masterminds/semver/v3" + "github.com/aptos-labs/aptos-go-sdk" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "golang.org/x/sync/errgroup" + + solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" + solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_from_mint_token_pool" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/link_token" + + ccipshared "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/evm" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/solana" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/commit_store" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" + + commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/factory_burn_mint_erc20" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/log_message_data_receiver" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/token_pool_factory" + price_registry_1_2_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/price_registry" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/rmn_contract" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_mint_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/burn_with_from_mint_token_pool" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/lock_release_token_pool" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc20" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc677" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_messenger" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/mock_usdc_token_transmitter" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/usdc_token_pool" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/view" + commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" + commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + "github.com/smartcontractkit/chainlink/deployment/helpers" + + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/token_admin_registry" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" + + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/don_id_claimer" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/latest/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_0_0/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/mock_rmn_contract" + registryModuleOwnerCustomv15 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/nonce_manager" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" + registryModuleOwnerCustomv16 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_home" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" + capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/multicall3" + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/weth9" +) + +// CCIPOnChainState state always derivable from an address book. +// Offchain state always derivable from a list of nodeIds. +// Note can translate this into Go struct needed for MCMS/Docs/UI. +type CCIPOnChainState struct { + // Populated go bindings for the appropriate version for all contracts. + // We would hold 2 versions of each contract here. Once we upgrade we can phase out the old one. + // When generating bindings, make sure the package name corresponds to the version. + Chains map[uint64]evm.CCIPChainState + SolChains map[uint64]solana.CCIPChainState + AptosChains map[uint64]aptosstate.CCIPChainState +} + +// ValidatePostDeploymentState should be called after the deployment and configuration for all contracts +// in environment is complete. +// It validates the state of the contracts and ensures that they are correctly configured and wired with each other. +func (c CCIPOnChainState) ValidatePostDeploymentState(e cldf.Environment) error { + onRampsBySelector := make(map[uint64]common.Address) + offRampsBySelector := make(map[uint64]offramp.OffRampInterface) + for selector, chainState := range c.Chains { + if chainState.OnRamp == nil { + return fmt.Errorf("onramp not found in the state for chain %d", selector) + } + onRampsBySelector[selector] = chainState.OnRamp.Address() + offRampsBySelector[selector] = chainState.OffRamp + } + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil { + return fmt.Errorf("failed to get node info from env: %w", err) + } + homeChain, err := c.HomeChainSelector() + if err != nil { + return fmt.Errorf("failed to get home chain selector: %w", err) + } + homeChainState := c.Chains[homeChain] + if err := homeChainState.ValidateHomeChain(e, nodes, offRampsBySelector); err != nil { + return fmt.Errorf("failed to validate home chain %d: %w", homeChain, err) + } + rmnHomeActiveDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{ + Context: e.GetContext(), + }) + if err != nil { + return fmt.Errorf("failed to get active digest for RMNHome %s at home chain %d: %w", homeChainState.RMNHome.Address().Hex(), homeChain, err) + } + isRMNEnabledInRMNHomeBySourceChain := make(map[uint64]bool) + rmnHomeConfig, err := homeChainState.RMNHome.GetConfig(&bind.CallOpts{ + Context: e.GetContext(), + }, rmnHomeActiveDigest) + if err != nil { + return fmt.Errorf("failed to get config for RMNHome %s at home chain %d: %w", homeChainState.RMNHome.Address().Hex(), homeChain, err) + } + // if Fobserve is greater than 0, RMN is enabled for the source chain in RMNHome + for _, rmnHomeChain := range rmnHomeConfig.VersionedConfig.DynamicConfig.SourceChains { + isRMNEnabledInRMNHomeBySourceChain[rmnHomeChain.ChainSelector] = rmnHomeChain.FObserve > 0 + } + for selector, chainState := range c.Chains { + isRMNEnabledInRmnRemote, err := chainState.ValidateRMNRemote(e, selector, rmnHomeActiveDigest) + if err != nil { + return fmt.Errorf("failed to validate RMNRemote %s for chain %d: %w", chainState.RMNRemote.Address().Hex(), selector, err) + } + // check whether RMNRemote and RMNHome are in sync in terms of RMNEnabled + if isRMNEnabledInRmnRemote != isRMNEnabledInRMNHomeBySourceChain[selector] { + return fmt.Errorf("RMNRemote %s rmnEnabled mismatch with RMNHome for chain %d: expected %v, got %v", + chainState.RMNRemote.Address().Hex(), selector, isRMNEnabledInRMNHomeBySourceChain[selector], isRMNEnabledInRmnRemote) + } + otherOnRamps := make(map[uint64]common.Address) + isTestRouter := true + if chainState.Router != nil { + isTestRouter = false + } + connectedChains, err := chainState.ValidateRouter(e, isTestRouter) + if err != nil { + return fmt.Errorf("failed to validate router %s for chain %d: %w", chainState.Router.Address().Hex(), selector, err) + } + for _, connectedChain := range connectedChains { + if connectedChain == selector { + continue + } + otherOnRamps[connectedChain] = c.Chains[connectedChain].OnRamp.Address() + } + if err := chainState.ValidateOffRamp(e, selector, otherOnRamps, isRMNEnabledInRMNHomeBySourceChain); err != nil { + return fmt.Errorf("failed to validate offramp %s for chain %d: %w", chainState.OffRamp.Address().Hex(), selector, err) + } + if err := chainState.ValidateOnRamp(e, selector, connectedChains); err != nil { + return fmt.Errorf("failed to validate onramp %s for chain %d: %w", chainState.OnRamp.Address().Hex(), selector, err) + } + if err := chainState.ValidateFeeQuoter(e); err != nil { + return fmt.Errorf("failed to validate fee quoter %s for chain %d: %w", chainState.FeeQuoter.Address().Hex(), selector, err) + } + } + return nil +} + +// HomeChainSelector returns the selector of the home chain based on the presence of RMNHome, CapabilityRegistry and CCIPHome contracts. +func (c CCIPOnChainState) HomeChainSelector() (uint64, error) { + for selector, chain := range c.Chains { + if chain.RMNHome != nil && chain.CapabilityRegistry != nil && chain.CCIPHome != nil { + return selector, nil + } + } + return 0, errors.New("no home chain found") +} + +func (c CCIPOnChainState) EVMMCMSStateByChain() map[uint64]commonstate.MCMSWithTimelockState { + mcmsStateByChain := make(map[uint64]commonstate.MCMSWithTimelockState) + for chainSelector, chain := range c.Chains { + mcmsStateByChain[chainSelector] = commonstate.MCMSWithTimelockState{ + CancellerMcm: chain.CancellerMcm, + BypasserMcm: chain.BypasserMcm, + ProposerMcm: chain.ProposerMcm, + Timelock: chain.Timelock, + CallProxy: chain.CallProxy, + } + } + return mcmsStateByChain +} + +func (c CCIPOnChainState) OffRampPermissionLessExecutionThresholdSeconds(ctx context.Context, env cldf.Environment, selector uint64) (uint32, error) { + family, err := chain_selectors.GetSelectorFamily(selector) + if err != nil { + return 0, err + } + switch family { + case chain_selectors.FamilyEVM: + chain, ok := c.Chains[selector] + if !ok { + return 0, fmt.Errorf("chain %d not found in the state", selector) + } + offRamp := chain.OffRamp + if offRamp == nil { + return 0, fmt.Errorf("offramp not found in the state for chain %d", selector) + } + dCfg, err := offRamp.GetDynamicConfig(&bind.CallOpts{ + Context: ctx, + }) + if err != nil { + return dCfg.PermissionLessExecutionThresholdSeconds, fmt.Errorf("fetch dynamic config from offRamp %s for chain %d: %w", offRamp.Address().String(), selector, err) + } + return dCfg.PermissionLessExecutionThresholdSeconds, nil + case chain_selectors.FamilySolana: + chainState, ok := c.SolChains[selector] + if !ok { + return 0, fmt.Errorf("chain %d not found in the state", selector) + } + chain, ok := env.SolChains[selector] + if !ok { + return 0, fmt.Errorf("solana chain %d not found in the environment", selector) + } + if chainState.OffRamp.IsZero() { + return 0, fmt.Errorf("offramp not found in existing state, deploy the offramp first for chain %d", selector) + } + var offRampConfig solOffRamp.Config + offRampConfigPDA, _, _ := solState.FindOfframpConfigPDA(chainState.OffRamp) + err := chain.GetAccountDataBorshInto(context.Background(), offRampConfigPDA, &offRampConfig) + if err != nil { + return 0, fmt.Errorf("offramp config not found in existing state, initialize the offramp first %d", chain.Selector) + } + // #nosec G115 + return uint32(offRampConfig.EnableManualExecutionAfter), nil + case chain_selectors.FamilyAptos: + chainState, ok := c.AptosChains[selector] + if !ok { + return 0, fmt.Errorf("chain %d does not exist in state", selector) + } + chain, ok := env.AptosChains[selector] + if !ok { + return 0, fmt.Errorf("chain %d does not exist in env", selector) + } + if chainState.CCIPAddress == (aptos.AccountAddress{}) { + return 0, fmt.Errorf("ccip not found in existing state, deploy the ccip first for Aptos chain %d", selector) + } + offrampDynamicConfig, err := aptosstate.GetOfframpDynamicConfig(chain, chainState.CCIPAddress) + if err != nil { + return 0, fmt.Errorf("failed to get offramp dynamic config for Aptos chain %d: %w", selector, err) + } + return offrampDynamicConfig.PermissionlessExecutionThresholdSeconds, nil + } + return 0, fmt.Errorf("unsupported chain family %s", family) +} + +func (c CCIPOnChainState) Validate() error { + for sel, chain := range c.Chains { + // cannot have static link and link together + if chain.LinkToken != nil && chain.StaticLinkToken != nil { + return fmt.Errorf("cannot have both link and static link token on the same chain %d", sel) + } + } + return nil +} + +func (c CCIPOnChainState) GetAllProposerMCMSForChains(chains []uint64) (map[uint64]*gethwrappers.ManyChainMultiSig, error) { + multiSigs := make(map[uint64]*gethwrappers.ManyChainMultiSig) + for _, chain := range chains { + chainState, ok := c.Chains[chain] + if !ok { + return nil, fmt.Errorf("chain %d not found", chain) + } + if chainState.ProposerMcm == nil { + return nil, fmt.Errorf("proposer mcm not found for chain %d", chain) + } + multiSigs[chain] = chainState.ProposerMcm + } + return multiSigs, nil +} + +func (c CCIPOnChainState) GetAllTimeLocksForChains(chains []uint64) (map[uint64]common.Address, error) { + timelocks := make(map[uint64]common.Address) + for _, chain := range chains { + chainState, ok := c.Chains[chain] + if !ok { + return nil, fmt.Errorf("chain %d not found", chain) + } + if chainState.Timelock == nil { + return nil, fmt.Errorf("timelock not found for chain %d", chain) + } + timelocks[chain] = chainState.Timelock.Address() + } + return timelocks, nil +} + +func (c CCIPOnChainState) SupportedChains() map[uint64]struct{} { + chains := make(map[uint64]struct{}) + for chain := range c.Chains { + chains[chain] = struct{}{} + } + for chain := range c.SolChains { + chains[chain] = struct{}{} + } + for chain := range c.AptosChains { + chains[chain] = struct{}{} + } + return chains +} + +// EnforceMCMSUsageIfProd determines if an MCMS config should be enforced for this particular environment. +// It checks if the CCIPHome and CapabilitiesRegistry contracts are owned by the Timelock because all other contracts should follow this precedent. +// If the home chain contracts are owned by the Timelock and no mcmsConfig is provided, this function will return an error. +func (c CCIPOnChainState) EnforceMCMSUsageIfProd(ctx context.Context, mcmsConfig *proposalutils.TimelockConfig) error { + // Instead of accepting a homeChainSelector, we simply look for the CCIPHome and CapabilitiesRegistry in state. + // This is because the home chain selector is not always available in the input to a changeset. + // Also, if the underlying rules to EnforceMCMSUsageIfProd change (i.e. what determines "prod" changes), + // we can simply update the function body without worrying about the function signature. + var ccipHome *ccip_home.CCIPHome + var capReg *capabilities_registry.CapabilitiesRegistry + var homeChainSelector uint64 + for selector, chain := range c.Chains { + if chain.CCIPHome == nil || chain.CapabilityRegistry == nil { + continue + } + // This condition impacts the ability of this function to determine MCMS enforcement. + // As such, we return an error if we find multiple chains with home chain contracts. + if ccipHome != nil { + return errors.New("multiple chains with CCIPHome and CapabilitiesRegistry contracts found") + } + ccipHome = chain.CCIPHome + capReg = chain.CapabilityRegistry + homeChainSelector = selector + } + // It is not the job of this function to enforce the existence of home chain contracts. + // Some tests don't deploy these contracts, and we don't want to fail them. + // We simply say that MCMS is not enforced in such environments. + if ccipHome == nil { + return nil + } + // If the timelock contract is not found on the home chain, + // we know that MCMS is not enforced. + timelock := c.Chains[homeChainSelector].Timelock + if timelock == nil { + return nil + } + ccipHomeOwner, err := ccipHome.Owner(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get CCIP home owner: %w", err) + } + capRegOwner, err := capReg.Owner(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get capabilities registry owner: %w", err) + } + if ccipHomeOwner != capRegOwner { + return fmt.Errorf("CCIPHome and CapabilitiesRegistry owners do not match: %s != %s", ccipHomeOwner.String(), capRegOwner.String()) + } + // If CCIPHome & CapabilitiesRegistry are owned by timelock, then MCMS is enforced. + if ccipHomeOwner == timelock.Address() && mcmsConfig == nil { + return errors.New("MCMS is enforced for environment (i.e. CCIPHome & CapReg are owned by timelock), but no MCMS config was provided") + } + + return nil +} + +// ValidateOwnershipOfChain validates the ownership of every CCIP contract on a chain. +// If mcmsConfig is nil, the expected owner of each contract is the chain's deployer key. +// If provided, the expected owner is the Timelock contract. +func (c CCIPOnChainState) ValidateOwnershipOfChain(e cldf.Environment, chainSel uint64, mcmsConfig *proposalutils.TimelockConfig) error { + chain, ok := e.Chains[chainSel] + if !ok { + return fmt.Errorf("chain with selector %d not found in the environment", chainSel) + } + + chainState, ok := c.Chains[chainSel] + if !ok { + return fmt.Errorf("%s not found in the state", chain) + } + if chainState.Timelock == nil { + return fmt.Errorf("timelock not found on %s", chain) + } + + ownedContracts := map[string]commoncs.Ownable{ + "router": chainState.Router, + "feeQuoter": chainState.FeeQuoter, + "offRamp": chainState.OffRamp, + "onRamp": chainState.OnRamp, + "nonceManager": chainState.NonceManager, + "rmnRemote": chainState.RMNRemote, + "rmnProxy": chainState.RMNProxy, + "tokenAdminRegistry": chainState.TokenAdminRegistry, + } + var wg sync.WaitGroup + errs := make(chan error, len(ownedContracts)) + for contractName, contract := range ownedContracts { + wg.Add(1) + go func(name string, c commoncs.Ownable) { + defer wg.Done() + if c == nil { + errs <- fmt.Errorf("missing %s contract on %s", name, chain) + return + } + err := commoncs.ValidateOwnership(e.GetContext(), mcmsConfig != nil, chain.DeployerKey.From, chainState.Timelock.Address(), contract) + if err != nil { + errs <- fmt.Errorf("failed to validate ownership of %s contract on %s: %w", name, chain, err) + } + }(contractName, contract) + } + wg.Wait() + close(errs) + var multiErr error + for err := range errs { + multiErr = std_errors.Join(multiErr, err) + } + if multiErr != nil { + return multiErr + } + + return nil +} + +func (c CCIPOnChainState) View(e *cldf.Environment, chains []uint64) (map[string]view.ChainView, map[string]view.SolChainView, error) { + m := sync.Map{} + sm := sync.Map{} + grp := errgroup.Group{} + for _, chainSelector := range chains { + var name string + chainSelector := chainSelector + grp.Go(func() error { + family, err := chain_selectors.GetSelectorFamily(chainSelector) + if err != nil { + return err + } + chainInfo, err := cldf.ChainInfo(chainSelector) + if err != nil { + return err + } + name = chainInfo.ChainName + if chainInfo.ChainName == "" { + name = strconv.FormatUint(chainSelector, 10) + } + id, err := chain_selectors.GetChainIDFromSelector(chainSelector) + if err != nil { + return fmt.Errorf("failed to get chain id from selector %d: %w", chainSelector, err) + } + e.Logger.Infow("Generating view for", "chainSelector", chainSelector, "chainName", name, "chainID", id) + switch family { + case chain_selectors.FamilyEVM: + if _, ok := c.Chains[chainSelector]; !ok { + return fmt.Errorf("chain not supported %d", chainSelector) + } + chainState := c.Chains[chainSelector] + chainView, err := chainState.GenerateView(e.Logger, name) + if err != nil { + return err + } + chainView.ChainSelector = chainSelector + chainView.ChainID = id + m.Store(name, chainView) + e.Logger.Infow("Completed view for", "chainSelector", chainSelector, "chainName", name, "chainID", id) + case chain_selectors.FamilySolana: + if _, ok := c.SolChains[chainSelector]; !ok { + return fmt.Errorf("chain not supported %d", chainSelector) + } + chainState := c.SolChains[chainSelector] + chainView, err := chainState.GenerateView(e.SolChains[chainSelector]) + if err != nil { + return err + } + chainView.ChainSelector = chainSelector + chainView.ChainID = id + sm.Store(name, chainView) + default: + return fmt.Errorf("unsupported chain family %s", family) + } + return nil + }) + } + if err := grp.Wait(); err != nil { + return nil, nil, err + } + finalEVMMap := make(map[string]view.ChainView) + m.Range(func(key, value interface{}) bool { + finalEVMMap[key.(string)] = value.(view.ChainView) + return true + }) + finalSolanaMap := make(map[string]view.SolChainView) + sm.Range(func(key, value interface{}) bool { + finalSolanaMap[key.(string)] = value.(view.SolChainView) + return true + }) + return finalEVMMap, finalSolanaMap, grp.Wait() +} + +func (c CCIPOnChainState) GetOffRampAddressBytes(chainSelector uint64) ([]byte, error) { + family, err := chain_selectors.GetSelectorFamily(chainSelector) + if err != nil { + return nil, err + } + + var offRampAddress []byte + switch family { + case chain_selectors.FamilyEVM: + offRampAddress = c.Chains[chainSelector].OffRamp.Address().Bytes() + case chain_selectors.FamilySolana: + offRampAddress = c.SolChains[chainSelector].OffRamp.Bytes() + case chain_selectors.FamilyAptos: + ccipAddress := c.AptosChains[chainSelector].CCIPAddress + offRampAddress = ccipAddress[:] + default: + return nil, fmt.Errorf("unsupported chain family %s", family) + } + + return offRampAddress, nil +} + +func (c CCIPOnChainState) GetOnRampAddressBytes(chainSelector uint64) ([]byte, error) { + family, err := chain_selectors.GetSelectorFamily(chainSelector) + if err != nil { + return nil, err + } + + var onRampAddressBytes []byte + switch family { + case chain_selectors.FamilyEVM: + if c.Chains[chainSelector].OnRamp == nil { + return nil, fmt.Errorf("no onramp found in the state for chain %d", chainSelector) + } + onRampAddressBytes = c.Chains[chainSelector].OnRamp.Address().Bytes() + case chain_selectors.FamilySolana: + if c.SolChains[chainSelector].Router.IsZero() { + return nil, fmt.Errorf("no router found in the state for chain %d", chainSelector) + } + onRampAddressBytes = c.SolChains[chainSelector].Router.Bytes() + case chain_selectors.FamilyAptos: + ccipAddress := c.AptosChains[chainSelector].CCIPAddress + if ccipAddress == (aptos.AccountAddress{}) { + return nil, fmt.Errorf("no ccip address found in the state for Aptos chain %d", chainSelector) + } + onRampAddressBytes = ccipAddress[:] + default: + return nil, fmt.Errorf("unsupported chain family %s", family) + } + + return onRampAddressBytes, nil +} + +func (c CCIPOnChainState) ValidateRamp(chainSelector uint64, rampType cldf.ContractType) error { + family, err := chain_selectors.GetSelectorFamily(chainSelector) + if err != nil { + return err + } + switch family { + case chain_selectors.FamilyEVM: + chainState, exists := c.Chains[chainSelector] + if !exists { + return fmt.Errorf("chain %d does not exist", chainSelector) + } + switch rampType { + case ccipshared.OffRamp: + if chainState.OffRamp == nil { + return fmt.Errorf("offramp contract does not exist on evm chain %d", chainSelector) + } + case ccipshared.OnRamp: + if chainState.OnRamp == nil { + return fmt.Errorf("onramp contract does not exist on evm chain %d", chainSelector) + } + default: + return fmt.Errorf("unknown ramp type %s", rampType) + } + + case chain_selectors.FamilySolana: + chainState, exists := c.SolChains[chainSelector] + if !exists { + return fmt.Errorf("chain %d does not exist", chainSelector) + } + switch rampType { + case ccipshared.OffRamp: + if chainState.OffRamp.IsZero() { + return fmt.Errorf("offramp contract does not exist on solana chain %d", chainSelector) + } + case ccipshared.OnRamp: + if chainState.Router.IsZero() { + return fmt.Errorf("router contract does not exist on solana chain %d", chainSelector) + } + default: + return fmt.Errorf("unknown ramp type %s", rampType) + } + + case chain_selectors.FamilyAptos: + chainState, exists := c.AptosChains[chainSelector] + if !exists { + return fmt.Errorf("chain %d does not exist", chainSelector) + } + if chainState.CCIPAddress == (aptos.AccountAddress{}) { + return fmt.Errorf("ccip package does not exist on aptos chain %d", chainSelector) + } + + default: + return fmt.Errorf("unknown chain family %s", family) + } + return nil +} + +func LoadOnchainState(e cldf.Environment) (CCIPOnChainState, error) { + solanaState, err := LoadOnchainStateSolana(e) + if err != nil { + return CCIPOnChainState{}, err + } + aptosChains, err := aptosstate.LoadOnchainStateAptos(e) + if err != nil { + return CCIPOnChainState{}, err + } + state := CCIPOnChainState{ + Chains: make(map[uint64]evm.CCIPChainState), + SolChains: solanaState.SolChains, + AptosChains: aptosChains, + } + for chainSelector, chain := range e.Chains { + addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector) + if err != nil { + if !errors.Is(err, cldf.ErrChainNotFound) { + return state, err + } + // Chain not found in address book, initialize empty + addresses = make(map[string]cldf.TypeAndVersion) + } + chainState, err := LoadChainState(e.GetContext(), chain, addresses) + if err != nil { + return state, err + } + state.Chains[chainSelector] = chainState + } + return state, state.Validate() +} + +// LoadChainState Loads all state for a chain into state +func LoadChainState(ctx context.Context, chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (evm.CCIPChainState, error) { + var state evm.CCIPChainState + mcmsWithTimelock, err := commonstate.MaybeLoadMCMSWithTimelockChainState(chain, addresses) + if err != nil { + return state, err + } + state.MCMSWithTimelockState = *mcmsWithTimelock + + linkState, err := commonstate.MaybeLoadLinkTokenChainState(chain, addresses) + if err != nil { + return state, err + } + state.LinkTokenState = *linkState + staticLinkState, err := commonstate.MaybeLoadStaticLinkTokenState(chain, addresses) + if err != nil { + return state, err + } + state.StaticLinkTokenState = *staticLinkState + state.ABIByAddress = make(map[string]string) + for address, tvStr := range addresses { + switch tvStr.String() { + case cldf.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(): + state.ABIByAddress[address] = gethwrappers.RBACTimelockABI + case cldf.NewTypeAndVersion(commontypes.CallProxy, deployment.Version1_0_0).String(): + state.ABIByAddress[address] = gethwrappers.CallProxyABI + case cldf.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), + cldf.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), + cldf.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(): + state.ABIByAddress[address] = gethwrappers.ManyChainMultiSigABI + case cldf.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(): + state.ABIByAddress[address] = link_token.LinkTokenABI + case cldf.NewTypeAndVersion(commontypes.StaticLinkToken, deployment.Version1_0_0).String(): + state.ABIByAddress[address] = link_token_interface.LinkTokenABI + case cldf.NewTypeAndVersion(ccipshared.CapabilitiesRegistry, deployment.Version1_0_0).String(): + cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CapabilityRegistry = cr + state.ABIByAddress[address] = capabilities_registry.CapabilitiesRegistryABI + case cldf.NewTypeAndVersion(ccipshared.OnRamp, deployment.Version1_6_0).String(): + onRampC, err := onramp.NewOnRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.OnRamp = onRampC + state.ABIByAddress[address] = onramp.OnRampABI + case cldf.NewTypeAndVersion(ccipshared.OffRamp, deployment.Version1_6_0).String(): + offRamp, err := offramp.NewOffRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.OffRamp = offRamp + state.ABIByAddress[address] = offramp.OffRampABI + case cldf.NewTypeAndVersion(ccipshared.ARMProxy, deployment.Version1_0_0).String(): + armProxy, err := rmn_proxy_contract.NewRMNProxy(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNProxy = armProxy + state.ABIByAddress[address] = rmn_proxy_contract.RMNProxyABI + case cldf.NewTypeAndVersion(ccipshared.RMNRemote, deployment.Version1_6_0).String(): + rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNRemote = rmnRemote + state.ABIByAddress[address] = rmn_remote.RMNRemoteABI + case cldf.NewTypeAndVersion(ccipshared.RMNHome, deployment.Version1_6_0).String(): + rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNHome = rmnHome + state.ABIByAddress[address] = rmn_home.RMNHomeABI + case cldf.NewTypeAndVersion(ccipshared.WETH9, deployment.Version1_0_0).String(): + _weth9, err := weth9.NewWETH9(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Weth9 = _weth9 + state.ABIByAddress[address] = weth9.WETH9ABI + case cldf.NewTypeAndVersion(ccipshared.NonceManager, deployment.Version1_6_0).String(): + nm, err := nonce_manager.NewNonceManager(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.NonceManager = nm + state.ABIByAddress[address] = nonce_manager.NonceManagerABI + case cldf.NewTypeAndVersion(ccipshared.TokenAdminRegistry, deployment.Version1_5_0).String(): + tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.TokenAdminRegistry = tm + state.ABIByAddress[address] = token_admin_registry.TokenAdminRegistryABI + case cldf.NewTypeAndVersion(ccipshared.TokenPoolFactory, deployment.Version1_5_1).String(): + tpf, err := token_pool_factory.NewTokenPoolFactory(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.TokenPoolFactory = tpf + state.ABIByAddress[address] = token_pool_factory.TokenPoolFactoryABI + case cldf.NewTypeAndVersion(ccipshared.RegistryModule, deployment.Version1_6_0).String(): + rm, err := registryModuleOwnerCustomv16.NewRegistryModuleOwnerCustom(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RegistryModules1_6 = append(state.RegistryModules1_6, rm) + state.ABIByAddress[address] = registryModuleOwnerCustomv16.RegistryModuleOwnerCustomABI + case cldf.NewTypeAndVersion(ccipshared.RegistryModule, deployment.Version1_5_0).String(): + rm, err := registryModuleOwnerCustomv15.NewRegistryModuleOwnerCustom(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RegistryModules1_5 = append(state.RegistryModules1_5, rm) + state.ABIByAddress[address] = registryModuleOwnerCustomv15.RegistryModuleOwnerCustomABI + case cldf.NewTypeAndVersion(ccipshared.Router, deployment.Version1_2_0).String(): + r, err := router.NewRouter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Router = r + state.ABIByAddress[address] = router.RouterABI + case cldf.NewTypeAndVersion(ccipshared.TestRouter, deployment.Version1_2_0).String(): + r, err := router.NewRouter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.TestRouter = r + state.ABIByAddress[address] = router.RouterABI + case cldf.NewTypeAndVersion(ccipshared.FeeQuoter, deployment.Version1_6_0).String(): + fq, err := fee_quoter.NewFeeQuoter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.FeeQuoter = fq + state.ABIByAddress[address] = fee_quoter.FeeQuoterABI + case cldf.NewTypeAndVersion(ccipshared.USDCToken, deployment.Version1_0_0).String(): + ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.BurnMintTokens677 = map[ccipshared.TokenSymbol]*burn_mint_erc677.BurnMintERC677{ + ccipshared.USDCSymbol: ut, + } + state.ABIByAddress[address] = burn_mint_erc677.BurnMintERC677ABI + case cldf.NewTypeAndVersion(ccipshared.USDCTokenPool, deployment.Version1_5_1).String(): + utp, err := usdc_token_pool.NewUSDCTokenPool(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.USDCTokenPools == nil { + state.USDCTokenPools = make(map[semver.Version]*usdc_token_pool.USDCTokenPool) + } + state.USDCTokenPools[deployment.Version1_5_1] = utp + case cldf.NewTypeAndVersion(ccipshared.HybridLockReleaseUSDCTokenPool, deployment.Version1_5_1).String(): + utp, err := usdc_token_pool.NewUSDCTokenPool(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.USDCTokenPools == nil { + state.USDCTokenPools = make(map[semver.Version]*usdc_token_pool.USDCTokenPool) + } + state.USDCTokenPools[deployment.Version1_5_1] = utp + state.ABIByAddress[address] = usdc_token_pool.USDCTokenPoolABI + case cldf.NewTypeAndVersion(ccipshared.USDCMockTransmitter, deployment.Version1_0_0).String(): + umt, err := mock_usdc_token_transmitter.NewMockE2EUSDCTransmitter(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.MockUSDCTransmitter = umt + state.ABIByAddress[address] = mock_usdc_token_transmitter.MockE2EUSDCTransmitterABI + case cldf.NewTypeAndVersion(ccipshared.USDCTokenMessenger, deployment.Version1_0_0).String(): + utm, err := mock_usdc_token_messenger.NewMockE2EUSDCTokenMessenger(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.MockUSDCTokenMessenger = utm + state.ABIByAddress[address] = mock_usdc_token_messenger.MockE2EUSDCTokenMessengerABI + case cldf.NewTypeAndVersion(ccipshared.CCIPHome, deployment.Version1_6_0).String(): + ccipHome, err := ccip_home.NewCCIPHome(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CCIPHome = ccipHome + state.ABIByAddress[address] = ccip_home.CCIPHomeABI + case cldf.NewTypeAndVersion(ccipshared.CCIPReceiver, deployment.Version1_0_0).String(): + mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Receiver = mr + state.ABIByAddress[address] = maybe_revert_message_receiver.MaybeRevertMessageReceiverABI + case cldf.NewTypeAndVersion(ccipshared.LogMessageDataReceiver, deployment.Version1_0_0).String(): + mr, err := log_message_data_receiver.NewLogMessageDataReceiver(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.LogMessageDataReceiver = mr + state.ABIByAddress[address] = log_message_data_receiver.LogMessageDataReceiverABI + case cldf.NewTypeAndVersion(ccipshared.Multicall3, deployment.Version1_0_0).String(): + mc, err := multicall3.NewMulticall3(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Multicall3 = mc + state.ABIByAddress[address] = multicall3.Multicall3ABI + case cldf.NewTypeAndVersion(ccipshared.PriceFeed, deployment.Version1_0_0).String(): + feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.USDFeeds == nil { + state.USDFeeds = make(map[ccipshared.TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface) + } + desc, err := feed.Description(&bind.CallOpts{}) + if err != nil { + return state, err + } + key, ok := ccipshared.DescriptionToTokenSymbol[desc] + if !ok { + return state, fmt.Errorf("unknown feed description %s", desc) + } + state.USDFeeds[key] = feed + state.ABIByAddress[address] = aggregator_v3_interface.AggregatorV3InterfaceABI + case cldf.NewTypeAndVersion(ccipshared.BurnMintTokenPool, deployment.Version1_5_1).String(): + ethAddress := common.HexToAddress(address) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_mint_token_pool.NewBurnMintTokenPool, ethAddress, chain.Client) + if err != nil { + return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + state.BurnMintTokenPools = helpers.AddValueToNestedMap(state.BurnMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[address] = burn_mint_token_pool.BurnMintTokenPoolABI + case cldf.NewTypeAndVersion(ccipshared.BurnWithFromMintTokenPool, deployment.Version1_5_1).String(): + ethAddress := common.HexToAddress(address) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_with_from_mint_token_pool.NewBurnWithFromMintTokenPool, ethAddress, chain.Client) + if err != nil { + return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + state.BurnWithFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnWithFromMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[address] = burn_with_from_mint_token_pool.BurnWithFromMintTokenPoolABI + case cldf.NewTypeAndVersion(ccipshared.BurnFromMintTokenPool, deployment.Version1_5_1).String(): + ethAddress := common.HexToAddress(address) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, burn_from_mint_token_pool.NewBurnFromMintTokenPool, ethAddress, chain.Client) + if err != nil { + return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + state.BurnFromMintTokenPools = helpers.AddValueToNestedMap(state.BurnFromMintTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[address] = burn_from_mint_token_pool.BurnFromMintTokenPoolABI + case cldf.NewTypeAndVersion(ccipshared.LockReleaseTokenPool, deployment.Version1_5_1).String(): + ethAddress := common.HexToAddress(address) + pool, metadata, err := ccipshared.NewTokenPoolWithMetadata(ctx, lock_release_token_pool.NewLockReleaseTokenPool, ethAddress, chain.Client) + if err != nil { + return state, fmt.Errorf("failed to connect address %s with token pool bindings and get token symbol: %w", ethAddress, err) + } + state.LockReleaseTokenPools = helpers.AddValueToNestedMap(state.LockReleaseTokenPools, metadata.Symbol, metadata.Version, pool) + state.ABIByAddress[address] = lock_release_token_pool.LockReleaseTokenPoolABI + case cldf.NewTypeAndVersion(ccipshared.BurnMintToken, deployment.Version1_0_0).String(): + tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.BurnMintTokens677 == nil { + state.BurnMintTokens677 = make(map[ccipshared.TokenSymbol]*burn_mint_erc677.BurnMintERC677) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.BurnMintTokens677[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[address] = burn_mint_erc677.BurnMintERC677ABI + case cldf.NewTypeAndVersion(ccipshared.ERC20Token, deployment.Version1_0_0).String(): + tok, err := erc20.NewERC20(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.ERC20Tokens == nil { + state.ERC20Tokens = make(map[ccipshared.TokenSymbol]*erc20.ERC20) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.ERC20Tokens[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[address] = erc20.ERC20ABI + case cldf.NewTypeAndVersion(ccipshared.FactoryBurnMintERC20Token, deployment.Version1_0_0).String(): + tok, err := factory_burn_mint_erc20.NewFactoryBurnMintERC20(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.FactoryBurnMintERC20Token = tok + state.ABIByAddress[address] = factory_burn_mint_erc20.FactoryBurnMintERC20ABI + case cldf.NewTypeAndVersion(ccipshared.ERC677Token, deployment.Version1_0_0).String(): + tok, err := erc677.NewERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + if state.ERC677Tokens == nil { + state.ERC677Tokens = make(map[ccipshared.TokenSymbol]*erc677.ERC677) + } + symbol, err := tok.Symbol(nil) + if err != nil { + return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) + } + state.ERC677Tokens[ccipshared.TokenSymbol(symbol)] = tok + state.ABIByAddress[address] = erc677.ERC677ABI + // legacy addresses below + case cldf.NewTypeAndVersion(ccipshared.OnRamp, deployment.Version1_5_0).String(): + onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := onRampC.GetStaticConfig(nil) + if err != nil { + return state, fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) + } + if state.EVM2EVMOnRamp == nil { + state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) + } + state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC + state.ABIByAddress[address] = evm_2_evm_onramp.EVM2EVMOnRampABI + case cldf.NewTypeAndVersion(ccipshared.OffRamp, deployment.Version1_5_0).String(): + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := offRamp.GetStaticConfig(nil) + if err != nil { + return state, err + } + if state.EVM2EVMOffRamp == nil { + state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) + } + state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp + state.ABIByAddress[address] = evm_2_evm_offramp.EVM2EVMOffRampABI + case cldf.NewTypeAndVersion(ccipshared.CommitStore, deployment.Version1_5_0).String(): + commitStore, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + sCfg, err := commitStore.GetStaticConfig(nil) + if err != nil { + return state, err + } + if state.CommitStore == nil { + state.CommitStore = make(map[uint64]*commit_store.CommitStore) + } + state.CommitStore[sCfg.SourceChainSelector] = commitStore + state.ABIByAddress[address] = commit_store.CommitStoreABI + case cldf.NewTypeAndVersion(ccipshared.PriceRegistry, deployment.Version1_2_0).String(): + pr, err := price_registry_1_2_0.NewPriceRegistry(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.PriceRegistry = pr + state.ABIByAddress[address] = price_registry_1_2_0.PriceRegistryABI + case cldf.NewTypeAndVersion(ccipshared.RMN, deployment.Version1_5_0).String(): + rmnC, err := rmn_contract.NewRMNContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMN = rmnC + state.ABIByAddress[address] = rmn_contract.RMNContractABI + case cldf.NewTypeAndVersion(ccipshared.MockRMN, deployment.Version1_0_0).String(): + mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.MockRMN = mockRMN + state.ABIByAddress[address] = mock_rmn_contract.MockRMNContractABI + case cldf.NewTypeAndVersion(ccipshared.FeeAggregator, deployment.Version1_0_0).String(): + state.FeeAggregator = common.HexToAddress(address) + case cldf.NewTypeAndVersion(ccipshared.FiredrillEntrypointType, deployment.Version1_5_0).String(), + cldf.NewTypeAndVersion(ccipshared.FiredrillEntrypointType, deployment.Version1_6_0).String(): + // Ignore firedrill contracts + // Firedrill contracts are unknown to core and their state is being loaded separately + case cldf.NewTypeAndVersion(ccipshared.DonIDClaimer, deployment.Version1_6_1).String(): + donIDClaimer, err := don_id_claimer.NewDonIDClaimer(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.DonIDClaimer = donIDClaimer + state.ABIByAddress[address] = don_id_claimer.DonIDClaimerABI + default: + // ManyChainMultiSig 1.0.0 can have any of these labels, it can have either 1,2 or 3 of these - + // bypasser, proposer and canceller + // if you try to compare tvStr.String() you will have to compare all combinations of labels + // so we will compare the type and version only + if tvStr.Type == commontypes.ManyChainMultisig && tvStr.Version == deployment.Version1_0_0 { + state.ABIByAddress[address] = gethwrappers.ManyChainMultiSigABI + continue + } + return state, fmt.Errorf("unknown contract %s", tvStr) + } + } + return state, nil +} + +func ValidateChain(env cldf.Environment, state CCIPOnChainState, chainSel uint64, mcmsCfg *proposalutils.TimelockConfig) error { + err := cldf.IsValidChainSelector(chainSel) + if err != nil { + return fmt.Errorf("is not valid chain selector %d: %w", chainSel, err) + } + chain, ok := env.Chains[chainSel] + if !ok { + return fmt.Errorf("chain with selector %d does not exist in environment", chainSel) + } + chainState, ok := state.Chains[chainSel] + if !ok { + return fmt.Errorf("%s does not exist in state", chain) + } + if mcmsCfg != nil { + err = mcmsCfg.Validate(chain, commonstate.MCMSWithTimelockState{ + CancellerMcm: chainState.CancellerMcm, + ProposerMcm: chainState.ProposerMcm, + BypasserMcm: chainState.BypasserMcm, + Timelock: chainState.Timelock, + CallProxy: chainState.CallProxy, + }) + if err != nil { + return err + } + } + return nil +} + +func LoadOnchainStateSolana(e cldf.Environment) (CCIPOnChainState, error) { + state := CCIPOnChainState{ + SolChains: make(map[uint64]solana.CCIPChainState), + } + for chainSelector, chain := range e.SolChains { + addresses, err := e.ExistingAddresses.AddressesForChain(chainSelector) + if err != nil { + // Chain not found in address book, initialize empty + if !std_errors.Is(err, cldf.ErrChainNotFound) { + return state, err + } + addresses = make(map[string]cldf.TypeAndVersion) + } + chainState, err := solana.LoadChainStateSolana(chain, addresses) + if err != nil { + return state, err + } + state.SolChains[chainSelector] = chainState + } + return state, nil +} diff --git a/deployment/ccip/changeset/state_test.go b/deployment/ccip/shared/stateview/state_test.go similarity index 92% rename from deployment/ccip/changeset/state_test.go rename to deployment/ccip/shared/stateview/state_test.go index b7ace8fe936..7f9800ce04f 100644 --- a/deployment/ccip/changeset/state_test.go +++ b/deployment/ccip/shared/stateview/state_test.go @@ -1,4 +1,4 @@ -package changeset_test +package stateview_test import ( "testing" @@ -16,9 +16,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" - + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -28,7 +28,7 @@ import ( func TestSmokeState(t *testing.T) { tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) _, _, err = state.View(&tenv.Env, tenv.Env.AllChainSelectors()) require.NoError(t, err) @@ -45,7 +45,7 @@ func TestMCMSState(t *testing.T) { addr := utils.RandomAddress() require.NoError(t, addressbook.Save(tenv.HomeChainSel, addr.String(), newTv)) require.NoError(t, tenv.Env.ExistingAddresses.Merge(addressbook)) - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) require.Equal(t, addr.String(), state.Chains[tenv.HomeChainSel].BypasserMcm.Address().String()) require.Equal(t, addr.String(), state.Chains[tenv.HomeChainSel].ProposerMcm.Address().String()) @@ -168,14 +168,14 @@ func TestEnforceMCMSUsageIfProd(t *testing.T) { if test.DeployCCIPHome { _, err = cldf.DeployContract(e.Logger, e.Chains[homeChainSelector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*ccip_home.CCIPHome] { + func(chain cldf.Chain) cldf.ContractDeploy[*ccip_home.CCIPHome] { address, tx2, contract, err2 := ccip_home.DeployCCIPHome( chain.DeployerKey, chain.Client, utils.RandomAddress(), // We don't need a real contract address here, just a random one to satisfy the constructor. ) return cldf.ContractDeploy[*ccip_home.CCIPHome]{ - Address: address, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.CCIPHome, deployment.Version1_6_0), Err: err2, + Address: address, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.CCIPHome, deployment.Version1_6_0), Err: err2, } }) require.NoError(t, err, "failed to deploy CCIP home") @@ -183,13 +183,13 @@ func TestEnforceMCMSUsageIfProd(t *testing.T) { if test.DeployCapReg { _, err = cldf.DeployContract(e.Logger, e.Chains[homeChainSelector], e.ExistingAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + func(chain cldf.Chain) cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { address, tx2, contract, err2 := capabilities_registry.DeployCapabilitiesRegistry( chain.DeployerKey, chain.Client, ) return cldf.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: address, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(changeset.CapabilitiesRegistry, deployment.Version1_0_0), Err: err2, + Address: address, Contract: contract, Tx: tx2, Tv: cldf.NewTypeAndVersion(shared.CapabilitiesRegistry, deployment.Version1_0_0), Err: err2, } }) require.NoError(t, err, "failed to deploy capability registry") @@ -202,7 +202,7 @@ func TestEnforceMCMSUsageIfProd(t *testing.T) { }), ) require.NoError(t, err, "failed to deploy MCMS") - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "failed to load onchain state") addrs := make([]common.Address, 0, 2) @@ -236,7 +236,7 @@ func TestEnforceMCMSUsageIfProd(t *testing.T) { } } - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err, "failed to load onchain state") err = state.EnforceMCMSUsageIfProd(e.GetContext(), test.MCMSConfig) diff --git a/deployment/ccip/changeset/view.go b/deployment/ccip/shared/stateview/view.go similarity index 97% rename from deployment/ccip/changeset/view.go rename to deployment/ccip/shared/stateview/view.go index a771548ca9c..f4e37460b03 100644 --- a/deployment/ccip/changeset/view.go +++ b/deployment/ccip/shared/stateview/view.go @@ -1,4 +1,4 @@ -package changeset +package stateview import ( "encoding/json" diff --git a/deployment/ccip/changeset/view_test.go b/deployment/ccip/shared/stateview/view_test.go similarity index 73% rename from deployment/ccip/changeset/view_test.go rename to deployment/ccip/shared/stateview/view_test.go index 53626407a56..c8980aa76cb 100644 --- a/deployment/ccip/changeset/view_test.go +++ b/deployment/ccip/shared/stateview/view_test.go @@ -1,18 +1,18 @@ -package changeset_test +package stateview_test import ( "testing" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" ) func TestSmokeView(t *testing.T) { t.Parallel() tenv, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) - jsonData, err := changeset.ViewCCIP(tenv.Env) + jsonData, err := stateview.ViewCCIP(tenv.Env) require.NoError(t, err) // to ensure the view is valid _, err = jsonData.MarshalJSON() diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/shared/token_info.go similarity index 98% rename from deployment/ccip/changeset/token_info.go rename to deployment/ccip/shared/token_info.go index 53055c15178..3c33240a07c 100644 --- a/deployment/ccip/changeset/token_info.go +++ b/deployment/ccip/shared/token_info.go @@ -1,4 +1,4 @@ -package changeset +package shared import ( "math/big" @@ -74,6 +74,10 @@ var ( WethSymbol: MockWETHAggregatorDescription, } TestDeviationPPB = ccipocr3.NewBigIntFromInt64(1e9) + + TokenSymbolSubstitute = map[string]string{ + "wS": WSSymbol.String(), + } ) // TokenConfig mapping between token Symbol (e.g. LinkSymbol, WethSymbol) diff --git a/deployment/ccip/shared/token_pools.go b/deployment/ccip/shared/token_pools.go new file mode 100644 index 00000000000..2f191a07623 --- /dev/null +++ b/deployment/ccip/shared/token_pools.go @@ -0,0 +1,91 @@ +package shared + +import ( + "context" + "fmt" + + "github.com/Masterminds/semver/v3" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/erc20" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment" + ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" +) + +var CurrentTokenPoolVersion = deployment.Version1_5_1 + +var TokenTypes = map[cldf.ContractType]struct{}{ + BurnMintToken: {}, + ERC20Token: {}, + ERC677Token: {}, +} + +var TokenPoolTypes = map[cldf.ContractType]struct{}{ + BurnMintTokenPool: {}, + BurnWithFromMintTokenPool: {}, + BurnFromMintTokenPool: {}, + LockReleaseTokenPool: {}, + USDCTokenPool: {}, + HybridLockReleaseUSDCTokenPool: {}, +} + +var TokenPoolVersions = map[semver.Version]struct{}{ + deployment.Version1_5_1: {}, +} + +// tokenPool defines behavior common to all token pools. +type tokenPool interface { + GetToken(opts *bind.CallOpts) (common.Address, error) + TypeAndVersion(*bind.CallOpts) (string, error) +} + +// TokenPoolMetadata defines the token pool version version and symbol of the corresponding token. +type TokenPoolMetadata struct { + Version semver.Version + Symbol TokenSymbol +} + +// NewTokenPoolWithMetadata returns a token pool along with its metadata. +func NewTokenPoolWithMetadata[P tokenPool]( + ctx context.Context, + newTokenPool func(address common.Address, backend bind.ContractBackend) (P, error), + poolAddress common.Address, + chainClient cldf.OnchainClient, +) (P, TokenPoolMetadata, error) { + pool, err := newTokenPool(poolAddress, chainClient) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to connect address %s with token pool bindings: %w", poolAddress, err) + } + tokenAddress, err := pool.GetToken(&bind.CallOpts{Context: ctx}) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to get token address from pool with address %s: %w", poolAddress, err) + } + typeAndVersionStr, err := pool.TypeAndVersion(&bind.CallOpts{Context: ctx}) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to get type and version from pool with address %s: %w", poolAddress, err) + } + _, versionStr, err := ccipconfig.ParseTypeAndVersion(typeAndVersionStr) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to parse type and version of pool with address %s: %w", poolAddress, err) + } + version, err := semver.NewVersion(versionStr) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed parsing version %s of pool with address %s: %w", versionStr, poolAddress, err) + } + token, err := erc20.NewERC20(tokenAddress, chainClient) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to connect address %s with ERC20 bindings: %w", tokenAddress, err) + } + symbol, err := token.Symbol(&bind.CallOpts{Context: ctx}) + if err != nil { + return pool, TokenPoolMetadata{}, fmt.Errorf("failed to fetch symbol from token with address %s: %w", tokenAddress, err) + } + return pool, TokenPoolMetadata{ + Symbol: TokenSymbol(symbol), + Version: *version, + }, nil +} diff --git a/deployment/ccip/shared/types.go b/deployment/ccip/shared/types.go new file mode 100644 index 00000000000..e3f2eb43cb6 --- /dev/null +++ b/deployment/ccip/shared/types.go @@ -0,0 +1,75 @@ +package shared + +import ( + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" +) + +var ( + // Legacy + CommitStore deployment.ContractType = "CommitStore" + PriceRegistry deployment.ContractType = "PriceRegistry" + RMN deployment.ContractType = "RMN" + + // Not legacy + MockRMN deployment.ContractType = "MockRMN" + RMNRemote deployment.ContractType = "RMNRemote" + ARMProxy deployment.ContractType = "ARMProxy" + WETH9 deployment.ContractType = "WETH9" + Router deployment.ContractType = "Router" + TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" + TokenPoolFactory deployment.ContractType = "TokenPoolFactory" + RegistryModule deployment.ContractType = "RegistryModuleOwnerCustom" + NonceManager deployment.ContractType = "NonceManager" + FeeQuoter deployment.ContractType = "FeeQuoter" + CCIPHome deployment.ContractType = "CCIPHome" + RMNHome deployment.ContractType = "RMNHome" + OnRamp deployment.ContractType = "OnRamp" + OffRamp deployment.ContractType = "OffRamp" + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" + DonIDClaimer deployment.ContractType = "DonIDClaimer" + PriceFeed deployment.ContractType = "PriceFeed" + + // Test contracts. Note test router maps to a regular router contract. + TestRouter deployment.ContractType = "TestRouter" + Multicall3 deployment.ContractType = "Multicall3" + CCIPReceiver deployment.ContractType = "CCIPReceiver" + LogMessageDataReceiver deployment.ContractType = "LogMessageDataReceiver" + USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter" + + // Pools + BurnMintToken deployment.ContractType = "BurnMintToken" + FactoryBurnMintERC20Token deployment.ContractType = "FactoryBurnMintERC20Token" + ERC20Token deployment.ContractType = "ERC20Token" + ERC677Token deployment.ContractType = "ERC677Token" + BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" + BurnWithFromMintTokenPool deployment.ContractType = "BurnWithFromMintTokenPool" + BurnFromMintTokenPool deployment.ContractType = "BurnFromMintTokenPool" + LockReleaseTokenPool deployment.ContractType = "LockReleaseTokenPool" + USDCToken deployment.ContractType = "USDCToken" + USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" + USDCTokenPool deployment.ContractType = "USDCTokenPool" + HybridLockReleaseUSDCTokenPool deployment.ContractType = "HybridLockReleaseUSDCTokenPool" + + // Firedrill + FiredrillEntrypointType deployment.ContractType = "FiredrillEntrypoint" + + // Treasury + FeeAggregator deployment.ContractType = "FeeAggregator" + + // Solana + Receiver deployment.ContractType = "Receiver" + SPL2022Tokens deployment.ContractType = "SPL2022Tokens" + SPLTokens deployment.ContractType = "SPLTokens" + WSOL deployment.ContractType = "WSOL" + CCIPCommon deployment.ContractType = "CCIPCommon" + RemoteSource deployment.ContractType = "RemoteSource" + RemoteDest deployment.ContractType = "RemoteDest" + TokenPoolLookupTable deployment.ContractType = "TokenPoolLookupTable" + // CLL Identifier + CLLMetadata = "CLL" + + // Aptos + AptosMCMSType deployment.ContractType = "AptosManyChainMultisig" + AptosCCIPType deployment.ContractType = "AptosCCIP" + AptosReceiverType deployment.ContractType = "AptosReceiver" +) diff --git a/deployment/ccip/view/solana/feequoter.go b/deployment/ccip/view/solana/feequoter.go index f126fc13d21..3b7f4ac90fb 100644 --- a/deployment/ccip/view/solana/feequoter.go +++ b/deployment/ccip/view/solana/feequoter.go @@ -8,7 +8,8 @@ import ( solFeeQuoter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) type FeeQuoterView struct { @@ -62,7 +63,7 @@ type FeeQuoterTokenTransferConfig struct { IsEnabled bool `json:"isEnabled,omitempty"` } -func GenerateFeeQuoterView(chain deployment.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (FeeQuoterView, error) { +func GenerateFeeQuoterView(chain cldf.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (FeeQuoterView, error) { fq := FeeQuoterView{} var fqConfig solFeeQuoter.Config feeQuoterConfigPDA, _, _ := solState.FindFqConfigPDA(program) diff --git a/deployment/ccip/view/solana/offramp.go b/deployment/ccip/view/solana/offramp.go index e3d2f00f8a1..6d0233e8f95 100644 --- a/deployment/ccip/view/solana/offramp.go +++ b/deployment/ccip/view/solana/offramp.go @@ -8,7 +8,8 @@ import ( solOffRamp "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_offramp" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/shared" ) @@ -38,7 +39,7 @@ type OffRampSourceChainConfig struct { OnRamp string `json:"onRamp,omitempty"` } -func GenerateOffRampView(chain deployment.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (OffRampView, error) { +func GenerateOffRampView(chain cldf.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (OffRampView, error) { view := OffRampView{} var config solOffRamp.Config configPDA, _, _ := solState.FindOfframpConfigPDA(program) diff --git a/deployment/ccip/view/solana/rmnremote.go b/deployment/ccip/view/solana/rmnremote.go index bc85cfa6f6a..b34304024b6 100644 --- a/deployment/ccip/view/solana/rmnremote.go +++ b/deployment/ccip/view/solana/rmnremote.go @@ -9,7 +9,8 @@ import ( solRmnRemote "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/rmn_remote" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) type RMNRemoteView struct { @@ -20,7 +21,7 @@ type RMNRemoteView struct { CurseSubjects []string `json:"curses,omitempty"` } -func GenerateRMNRemoteView(chain deployment.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (RMNRemoteView, error) { +func GenerateRMNRemoteView(chain cldf.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (RMNRemoteView, error) { view := RMNRemoteView{} var config solRmnRemote.Config configPDA, _, _ := solState.FindRMNRemoteConfigPDA(program) diff --git a/deployment/ccip/view/solana/router.go b/deployment/ccip/view/solana/router.go index 74a40fc1ccd..a28564dafd1 100644 --- a/deployment/ccip/view/solana/router.go +++ b/deployment/ccip/view/solana/router.go @@ -9,7 +9,8 @@ import ( solCommon "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_common" solRouter "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" solState "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/state" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) type RouterView struct { @@ -41,7 +42,7 @@ type RouterTokenAdminRegistry struct { Mint string `json:"mint,omitempty"` } -func GenerateRouterView(chain deployment.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (RouterView, error) { +func GenerateRouterView(chain cldf.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey) (RouterView, error) { view := RouterView{} var config solRouter.Config configPDA, _, _ := solState.FindConfigPDA(program) diff --git a/deployment/ccip/view/solana/token.go b/deployment/ccip/view/solana/token.go index d92b9d7073e..bc43d1b58cb 100644 --- a/deployment/ccip/view/solana/token.go +++ b/deployment/ccip/view/solana/token.go @@ -7,7 +7,7 @@ import ( "github.com/gagliardetto/solana-go" solToken "github.com/gagliardetto/solana-go/programs/token" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) type TokenView struct { @@ -19,7 +19,7 @@ type TokenView struct { FreezeAuthority string `json:"freezeAuthority,omitempty"` } -func GenerateTokenView(chain deployment.SolChain, tokenAddress solana.PublicKey, tokenProgram string) (TokenView, error) { +func GenerateTokenView(chain cldf.SolChain, tokenAddress solana.PublicKey, tokenProgram string) (TokenView, error) { view := TokenView{} view.TokenProgramName = tokenProgram var tokenMint solToken.Mint diff --git a/deployment/ccip/view/solana/tokenpool.go b/deployment/ccip/view/solana/tokenpool.go index c3af785e70b..0bc7e7e0894 100644 --- a/deployment/ccip/view/solana/tokenpool.go +++ b/deployment/ccip/view/solana/tokenpool.go @@ -7,7 +7,8 @@ import ( solTestTokenPool "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/test_token_pool" solTokenUtil "github.com/smartcontractkit/chainlink-ccip/chains/solana/utils/tokens" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/view/shared" ) @@ -53,7 +54,7 @@ type TokenPoolRateLimitTokenBucket struct { Rate uint64 `json:"rate"` } -func GenerateTokenPoolView(chain deployment.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey, poolType string, poolMetadata string) (TokenPoolView, error) { +func GenerateTokenPoolView(chain cldf.SolChain, program solana.PublicKey, remoteChains []uint64, tokens []solana.PublicKey, poolType string, poolMetadata string) (TokenPoolView, error) { view := TokenPoolView{} view.PoolType = poolType view.PoolMetadata = poolMetadata diff --git a/deployment/ccip/view/v1_2/price_registry_test.go b/deployment/ccip/view/v1_2/price_registry_test.go index 2c44db60d3c..7c18a7e2b27 100644 --- a/deployment/ccip/view/v1_2/price_registry_test.go +++ b/deployment/ccip/view/v1_2/price_registry_test.go @@ -10,7 +10,9 @@ import ( "go.uber.org/zap/zapcore" price_registry_1_2_0 "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/price_registry" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -23,7 +25,7 @@ func TestGeneratePriceRegistryView(t *testing.T) { f1, f2 := common.HexToAddress("0x1"), common.HexToAddress("0x2") _, tx, c, err := price_registry_1_2_0.DeployPriceRegistry( chain.DeployerKey, chain.Client, []common.Address{chain.DeployerKey.From}, []common.Address{f1, f2}, uint32(10)) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) v, err := GeneratePriceRegistryView(c) diff --git a/deployment/ccip/view/v1_5/offramp_test.go b/deployment/ccip/view/v1_5/offramp_test.go index 714c96fb3db..ca9b411945e 100644 --- a/deployment/ccip/view/v1_5/offramp_test.go +++ b/deployment/ccip/view/v1_5/offramp_test.go @@ -13,7 +13,9 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/commit_store" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -30,7 +32,7 @@ func TestOffRampView(t *testing.T) { OnRamp: common.HexToAddress("0x4"), RmnProxy: common.HexToAddress("0x1"), }) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) sc := evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ ChainSelector: chainsel.TEST_90000002.Selector, @@ -47,7 +49,7 @@ func TestOffRampView(t *testing.T) { } _, tx, c2, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( chain.DeployerKey, chain.Client, sc, rl) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) v, err := GenerateOffRampView(c2) diff --git a/deployment/ccip/view/v1_5/onramp_test.go b/deployment/ccip/view/v1_5/onramp_test.go index 96738dc32f1..962c77fe454 100644 --- a/deployment/ccip/view/v1_5/onramp_test.go +++ b/deployment/ccip/view/v1_5/onramp_test.go @@ -11,7 +11,9 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -57,7 +59,7 @@ func TestOnRampView(t *testing.T) { []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{}, []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, ) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) v, err := GenerateOnRampView(c) require.NoError(t, err) diff --git a/deployment/ccip/view/v1_6/ccip_home.go b/deployment/ccip/view/v1_6/ccip_home.go index 2f4181f93d9..be2aeb4fdf6 100644 --- a/deployment/ccip/view/v1_6/ccip_home.go +++ b/deployment/ccip/view/v1_6/ccip_home.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" "github.com/smartcontractkit/chainlink/deployment/common/view/types" cciptypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -144,7 +144,7 @@ func GenerateCCIPHomeView(cr *capabilities_registry.CapabilitiesRegistry, ch *cc if crAddr != cr.Address() { return CCIPHomeView{}, fmt.Errorf("capability registry address mismatch for CCIPHome %s: %w", ch.Address(), err) } - dons, err := ccip.GetCCIPDonsFromCapRegistry(context.Background(), cr) + dons, err := shared.GetCCIPDonsFromCapRegistry(context.Background(), cr) if err != nil { return CCIPHomeView{}, fmt.Errorf("failed to get DONs for CCIPHome %s: %w", ch.Address(), err) } diff --git a/deployment/ccip/view/v1_6/ccip_home_test.go b/deployment/ccip/view/v1_6/ccip_home_test.go index 4bfd2742366..a36f31540d0 100644 --- a/deployment/ccip/view/v1_6/ccip_home_test.go +++ b/deployment/ccip/view/v1_6/ccip_home_test.go @@ -10,7 +10,9 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/ccip_home" capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -23,12 +25,12 @@ func TestCCIPHomeView(t *testing.T) { _, tx, cr, err := capabilities_registry.DeployCapabilitiesRegistry( chain.DeployerKey, chain.Client) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) _, tx, ch, err := ccip_home.DeployCCIPHome( chain.DeployerKey, chain.Client, cr.Address()) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) v, err := GenerateCCIPHomeView(cr, ch) diff --git a/deployment/ccip/view/v1_6/rmnremote_test.go b/deployment/ccip/view/v1_6/rmnremote_test.go index 64cb4a8bdaa..131ec2381aa 100644 --- a/deployment/ccip/view/v1_6/rmnremote_test.go +++ b/deployment/ccip/view/v1_6/rmnremote_test.go @@ -10,7 +10,9 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -22,18 +24,18 @@ func Test_RMNRemote_Curse_View(t *testing.T) { }) chain := e.Chains[e.AllChainSelectors()[0]] _, tx, remote, err := rmn_remote.DeployRMNRemote(chain.DeployerKey, chain.Client, e.AllChainSelectors()[0], common.Address{}) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = remote.Curse(chain.DeployerKey, globals.GlobalCurseSubject()) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) family, err := chainsel.GetSelectorFamily(e.AllChainSelectors()[0]) require.NoError(t, err) tx, err = remote.Curse(chain.DeployerKey, globals.FamilyAwareSelectorToSubject(e.AllChainSelectors()[0], family)) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) view, err := GenerateRMNRemoteView(remote) diff --git a/deployment/migrated_environment.go b/deployment/cldf/migrated_environment.go similarity index 98% rename from deployment/migrated_environment.go rename to deployment/cldf/migrated_environment.go index d31ad60a60f..98e17f23910 100644 --- a/deployment/migrated_environment.go +++ b/deployment/cldf/migrated_environment.go @@ -1,4 +1,4 @@ -package deployment +package cldf import ( "github.com/smartcontractkit/chainlink-deployments-framework/deployment" diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go index 7e428e48a47..61756488ba2 100644 --- a/deployment/common/changeset/deploy_link_token.go +++ b/deployment/common/changeset/deploy_link_token.go @@ -26,7 +26,7 @@ import ( var _ cldf.ChangeSet[[]uint64] = DeployLinkToken // DeployLinkToken deploys a link token contract to the chain identified by the ChainSelector. -func DeployLinkToken(e deployment.Environment, chains []uint64) (cldf.ChangesetOutput, error) { +func DeployLinkToken(e cldf.Environment, chains []uint64) (cldf.ChangesetOutput, error) { err := deployment.ValidateSelectorsInEnvironment(e, chains) if err != nil { return cldf.ChangesetOutput{}, err @@ -64,7 +64,7 @@ func DeployLinkToken(e deployment.Environment, chains []uint64) (cldf.ChangesetO } // DeployStaticLinkToken deploys a static link token contract to the chain identified by the ChainSelector. -func DeployStaticLinkToken(e deployment.Environment, chains []uint64) (cldf.ChangesetOutput, error) { +func DeployStaticLinkToken(e cldf.Environment, chains []uint64) (cldf.ChangesetOutput, error) { err := deployment.ValidateSelectorsInEnvironment(e, chains) if err != nil { return cldf.ChangesetOutput{}, err @@ -76,7 +76,7 @@ func DeployStaticLinkToken(e deployment.Environment, chains []uint64) (cldf.Chan return cldf.ChangesetOutput{}, fmt.Errorf("chain not found in environment: %d", chainSel) } _, err := cldf.DeployContract[*link_token_interface.LinkToken](e.Logger, chain, newAddresses, - func(chain deployment.Chain) cldf.ContractDeploy[*link_token_interface.LinkToken] { + func(chain cldf.Chain) cldf.ContractDeploy[*link_token_interface.LinkToken] { linkTokenAddr, tx, linkToken, err2 := link_token_interface.DeployLinkToken( chain.DeployerKey, chain.Client, @@ -99,11 +99,11 @@ func DeployStaticLinkToken(e deployment.Environment, chains []uint64) (cldf.Chan func deployLinkTokenContractEVM( lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, ab cldf.AddressBook, ) (*cldf.ContractDeploy[*link_token.LinkToken], error) { linkToken, err := cldf.DeployContract[*link_token.LinkToken](lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*link_token.LinkToken] { + func(chain cldf.Chain) cldf.ContractDeploy[*link_token.LinkToken] { linkTokenAddr, tx, linkToken, err2 := link_token.DeployLinkToken( chain.DeployerKey, chain.Client, @@ -129,7 +129,7 @@ type DeploySolanaLinkTokenConfig struct { TokenDecimals uint8 } -func DeploySolanaLinkToken(e deployment.Environment, cfg DeploySolanaLinkTokenConfig) (cldf.ChangesetOutput, error) { +func DeploySolanaLinkToken(e cldf.Environment, cfg DeploySolanaLinkTokenConfig) (cldf.ChangesetOutput, error) { chain := e.SolChains[cfg.ChainSelector] mint := cfg.TokenPrivKey instructions, err := solTokenUtil.CreateToken( diff --git a/deployment/common/changeset/deploy_mcms_with_timelock.go b/deployment/common/changeset/deploy_mcms_with_timelock.go index c0f9fa60bf9..747ab6d3bb1 100644 --- a/deployment/common/changeset/deploy_mcms_with_timelock.go +++ b/deployment/common/changeset/deploy_mcms_with_timelock.go @@ -40,7 +40,7 @@ var ( // DeployMCMSWithTimelockV2 deploys and initializes the MCM and Timelock contracts func DeployMCMSWithTimelockV2( - env deployment.Environment, cfgByChain map[uint64]types.MCMSWithTimelockConfigV2, + env cldf.Environment, cfgByChain map[uint64]types.MCMSWithTimelockConfigV2, ) (cldf.ChangesetOutput, error) { newAddresses := cldf.NewMemoryAddressBook() @@ -97,7 +97,7 @@ type GrantRoleInput struct { MCMS *proposalutils.TimelockConfig } -func grantRolePreconditions(e deployment.Environment, cfg GrantRoleInput) error { +func grantRolePreconditions(e cldf.Environment, cfg GrantRoleInput) error { mcmsState, err := state.MaybeLoadMCMSWithTimelockState(e, maps.Keys(cfg.ExistingProposerByChain)) if err != nil { return err @@ -133,7 +133,7 @@ func grantRolePreconditions(e deployment.Environment, cfg GrantRoleInput) error return nil } -func grantRoleLogic(e deployment.Environment, cfg GrantRoleInput) (cldf.ChangesetOutput, error) { +func grantRoleLogic(e cldf.Environment, cfg GrantRoleInput) (cldf.ChangesetOutput, error) { mcmsState, err := state.MaybeLoadMCMSWithTimelockState(e, maps.Keys(cfg.ExistingProposerByChain)) if err != nil { return cldf.ChangesetOutput{}, err diff --git a/deployment/common/changeset/deploy_mcms_with_timelock_test.go b/deployment/common/changeset/deploy_mcms_with_timelock_test.go index 3aa42f905a2..1904b6d838b 100644 --- a/deployment/common/changeset/deploy_mcms_with_timelock_test.go +++ b/deployment/common/changeset/deploy_mcms_with_timelock_test.go @@ -552,7 +552,7 @@ func timelockSignerPDA(programID solana.PublicKey, seed mcmschangesetstate.PDASe } func solanaTimelockConfig( - ctx context.Context, t *testing.T, chain deployment.SolChain, programID solana.PublicKey, seed mcmschangesetstate.PDASeed, + ctx context.Context, t *testing.T, chain cldf.SolChain, programID solana.PublicKey, seed mcmschangesetstate.PDASeed, ) timelockBindings.Config { t.Helper() diff --git a/deployment/common/changeset/example/add_mint_burners_link.go b/deployment/common/changeset/example/add_mint_burners_link.go index 7dbac6ac19b..df04e56091e 100644 --- a/deployment/common/changeset/example/add_mint_burners_link.go +++ b/deployment/common/changeset/example/add_mint_burners_link.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" ) @@ -18,7 +18,7 @@ type AddMintersBurnersLinkConfig struct { var _ cldf.ChangeSet[*AddMintersBurnersLinkConfig] = AddMintersBurnersLink // AddMintersBurnersLink grants the minter / burner role to the provided addresses. -func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkConfig) (cldf.ChangesetOutput, error) { +func AddMintersBurnersLink(e cldf.Environment, cfg *AddMintersBurnersLinkConfig) (cldf.ChangesetOutput, error) { chain := e.Chains[cfg.ChainSelector] addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) if err != nil { @@ -42,7 +42,7 @@ func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkC if err != nil { return cldf.ChangesetOutput{}, err } - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) if err != nil { return cldf.ChangesetOutput{}, err } @@ -60,7 +60,7 @@ func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkC if err != nil { return cldf.ChangesetOutput{}, err } - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) if err != nil { return cldf.ChangesetOutput{}, err } diff --git a/deployment/common/changeset/example/link_transfer.go b/deployment/common/changeset/example/link_transfer.go index 0ff91124c80..5c0147e06cf 100644 --- a/deployment/common/changeset/example/link_transfer.go +++ b/deployment/common/changeset/example/link_transfer.go @@ -21,7 +21,6 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -42,16 +41,16 @@ type LinkTransferConfig struct { var _ cldf.ChangeSet[*LinkTransferConfig] = LinkTransfer -func getDeployer(e deployment.Environment, chain uint64, mcmConfig *proposalutils.TimelockConfig) *bind.TransactOpts { +func getDeployer(e cldf.Environment, chain uint64, mcmConfig *proposalutils.TimelockConfig) *bind.TransactOpts { if mcmConfig == nil { return e.Chains[chain].DeployerKey } - return deployment.SimTransactOpts() + return cldf.SimTransactOpts() } // Validate checks that the LinkTransferConfig is valid. -func (cfg LinkTransferConfig) Validate(e deployment.Environment) error { +func (cfg LinkTransferConfig) Validate(e cldf.Environment) error { ctx := e.GetContext() // Check that Transfers map has at least one chainSel if len(cfg.Transfers) == 0 { @@ -121,7 +120,7 @@ func (cfg LinkTransferConfig) Validate(e deployment.Environment) error { } // initStatePerChain initializes the state for each chain selector on the provided config -func initStatePerChain(cfg *LinkTransferConfig, e deployment.Environment) ( +func initStatePerChain(cfg *LinkTransferConfig, e cldf.Environment) ( linkStatePerChain map[uint64]*changeset.LinkTokenState, mcmsStatePerChain map[uint64]*changeset.MCMSWithTimelockState, err error) { @@ -145,11 +144,11 @@ func initStatePerChain(cfg *LinkTransferConfig, e deployment.Environment) ( // transferOrBuildTx transfers the LINK tokens or builds the tx for the MCMS proposal func transferOrBuildTx( - e deployment.Environment, + e cldf.Environment, linkState *changeset.LinkTokenState, transfer TransferConfig, opts *bind.TransactOpts, - chain deployment.Chain, + chain cldf.Chain, mcmsConfig *proposalutils.TimelockConfig) (*ethTypes.Transaction, error) { tx, err := linkState.LinkToken.Transfer(opts, transfer.To, transfer.Value) if err != nil { @@ -157,7 +156,7 @@ func transferOrBuildTx( } // only wait for tx if we are not using MCMS if mcmsConfig == nil { - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { e.Logger.Errorw("Failed to confirm transfer tx", "chain", chain.String(), "err", err) return nil, err } @@ -166,7 +165,7 @@ func transferOrBuildTx( } // LinkTransfer takes the given link transfers and executes them or creates an MCMS proposal for them. -func LinkTransfer(e deployment.Environment, cfg *LinkTransferConfig) (cldf.ChangesetOutput, error) { +func LinkTransfer(e cldf.Environment, cfg *LinkTransferConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid LinkTransferConfig: %w", err) @@ -240,7 +239,7 @@ func LinkTransfer(e deployment.Environment, cfg *LinkTransferConfig) (cldf.Chang } // LinkTransferV2 is an reimplementation of LinkTransfer that uses the new MCMS SDK. -func LinkTransferV2(e deployment.Environment, cfg *LinkTransferConfig) (cldf.ChangesetOutput, error) { +func LinkTransferV2(e cldf.Environment, cfg *LinkTransferConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate(e) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid LinkTransferConfig: %w", err) diff --git a/deployment/common/changeset/example/link_transfer_test.go b/deployment/common/changeset/example/link_transfer_test.go index 2085f18f10d..5c5e9e7b6a6 100644 --- a/deployment/common/changeset/example/link_transfer_test.go +++ b/deployment/common/changeset/example/link_transfer_test.go @@ -11,6 +11,7 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset/example" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -18,14 +19,13 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" ) // setupLinkTransferContracts deploys all required contracts for the link transfer tests and returns the updated env. -func setupLinkTransferTestEnv(t *testing.T) deployment.Environment { +func setupLinkTransferTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ Nodes: 1, @@ -80,12 +80,12 @@ func TestLinkTransferMCMS(t *testing.T) { // grant minter permissions tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = linkState.LinkToken.Mint(chain.DeployerKey, timelockAddress, big.NewInt(750)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) timelocks := map[uint64]*proposalutils.TimelockExecutionContracts{ @@ -154,12 +154,12 @@ func TestLinkTransfer(t *testing.T) { // grant minter permissions tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = linkState.LinkToken.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(750)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) timelocks := map[uint64]*proposalutils.TimelockExecutionContracts{ @@ -217,11 +217,11 @@ func TestValidate(t *testing.T) { require.NoError(t, err) tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = linkState.LinkToken.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(750)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tests := []struct { @@ -393,12 +393,12 @@ func TestLinkTransferMCMSV2(t *testing.T) { // grant minter permissions tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = linkState.LinkToken.Mint(chain.DeployerKey, timelockAddress, big.NewInt(750)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) timelocks := map[uint64]*proposalutils.TimelockExecutionContracts{ diff --git a/deployment/common/changeset/example/mint_link.go b/deployment/common/changeset/example/mint_link.go index a7631c4f984..fb5cd409be3 100644 --- a/deployment/common/changeset/example/mint_link.go +++ b/deployment/common/changeset/example/mint_link.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" ) @@ -19,7 +19,7 @@ type MintLinkConfig struct { var _ cldf.ChangeSet[*MintLinkConfig] = MintLink // MintLink mints LINK to the provided contract. -func MintLink(e deployment.Environment, cfg *MintLinkConfig) (cldf.ChangesetOutput, error) { +func MintLink(e cldf.Environment, cfg *MintLinkConfig) (cldf.ChangesetOutput, error) { chain := e.Chains[cfg.ChainSelector] addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) if err != nil { @@ -34,7 +34,7 @@ func MintLink(e deployment.Environment, cfg *MintLinkConfig) (cldf.ChangesetOutp if err != nil { return cldf.ChangesetOutput{}, err } - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) if err != nil { return cldf.ChangesetOutput{}, err } diff --git a/deployment/common/changeset/example/operations/deploy_and_mint_example.go b/deployment/common/changeset/example/operations/deploy_and_mint_example.go index a7d92059586..10ea72c325c 100644 --- a/deployment/common/changeset/example/operations/deploy_and_mint_example.go +++ b/deployment/common/changeset/example/operations/deploy_and_mint_example.go @@ -9,8 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - - "github.com/smartcontractkit/chainlink/deployment" ) /** @@ -35,18 +33,18 @@ type SqDeployLinkOutput struct { type EthereumDeps struct { Auth *bind.TransactOpts - Chain deployment.Chain + Chain cldf.Chain AB cldf.AddressBook } type DeployAndMintExampleChangeset struct{} -func (l DeployAndMintExampleChangeset) VerifyPreconditions(e deployment.Environment, config SqDeployLinkInput) error { +func (l DeployAndMintExampleChangeset) VerifyPreconditions(e cldf.Environment, config SqDeployLinkInput) error { // perform any preconditions checks here return nil } -func (l DeployAndMintExampleChangeset) Apply(e deployment.Environment, config SqDeployLinkInput) (cldf.ChangesetOutput, error) { +func (l DeployAndMintExampleChangeset) Apply(e cldf.Environment, config SqDeployLinkInput) (cldf.ChangesetOutput, error) { auth := e.Chains[config.ChainID].DeployerKey ab := cldf.NewMemoryAddressBook() diff --git a/deployment/common/changeset/example/operations/operation.go b/deployment/common/changeset/example/operations/operation.go index a91b1168cc8..fc5fd6c04ae 100644 --- a/deployment/common/changeset/example/operations/operation.go +++ b/deployment/common/changeset/example/operations/operation.go @@ -22,7 +22,7 @@ var DeployLinkOp = operations.NewOperation( "Deploy LINK Contract Operation", func(b operations.Bundle, deps EthereumDeps, input operations.EmptyInput) (common.Address, error) { linkToken, err := cldf.DeployContract[*link_token.LinkToken](b.Logger, deps.Chain, deps.AB, - func(chain deployment.Chain) cldf.ContractDeploy[*link_token.LinkToken] { + func(chain cldf.Chain) cldf.ContractDeploy[*link_token.LinkToken] { linkTokenAddr, tx, linkToken, err2 := link_token.DeployLinkToken( chain.DeployerKey, chain.Client, @@ -57,7 +57,7 @@ var GrantMintOp = operations.NewOperation( return nil, err } tx, err := contract.GrantMintRole(deps.Auth, input.To) - _, err = deployment.ConfirmIfNoError(deps.Chain, tx, err) + _, err = cldf.ConfirmIfNoError(deps.Chain, tx, err) if err != nil { return nil, err } @@ -81,7 +81,7 @@ var MintLinkOp = operations.NewOperation( return nil, err } tx, err := contract.Mint(deps.Auth, input.To, input.Amount) - _, err = deployment.ConfirmIfNoError(deps.Chain, tx, err) + _, err = cldf.ConfirmIfNoError(deps.Chain, tx, err) if err != nil { return nil, err } diff --git a/deployment/common/changeset/example/operations/retry_config_example.go b/deployment/common/changeset/example/operations/retry_config_example.go index aca9b1b8cb9..ea906953dc7 100644 --- a/deployment/common/changeset/example/operations/retry_config_example.go +++ b/deployment/common/changeset/example/operations/retry_config_example.go @@ -7,8 +7,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - - "github.com/smartcontractkit/chainlink/deployment" ) /** @@ -20,12 +18,12 @@ var _ cldf.ChangeSetV2[operations.EmptyInput] = DisableRetryExampleChangeset{} type DisableRetryExampleChangeset struct{} -func (l DisableRetryExampleChangeset) VerifyPreconditions(e deployment.Environment, config operations.EmptyInput) error { +func (l DisableRetryExampleChangeset) VerifyPreconditions(e cldf.Environment, config operations.EmptyInput) error { // perform any preconditions checks here return nil } -func (l DisableRetryExampleChangeset) Apply(e deployment.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { +func (l DisableRetryExampleChangeset) Apply(e cldf.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { ab := cldf.NewMemoryAddressBook() operationInput := SuccessFailOperationInput{ShouldFail: true} @@ -45,12 +43,12 @@ var _ cldf.ChangeSetV2[operations.EmptyInput] = UpdateInputExampleChangeset{} type UpdateInputExampleChangeset struct{} -func (l UpdateInputExampleChangeset) VerifyPreconditions(e deployment.Environment, config operations.EmptyInput) error { +func (l UpdateInputExampleChangeset) VerifyPreconditions(e cldf.Environment, config operations.EmptyInput) error { // perform any preconditions checks here return nil } -func (l UpdateInputExampleChangeset) Apply(e deployment.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { +func (l UpdateInputExampleChangeset) Apply(e cldf.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { ab := cldf.NewMemoryAddressBook() operationInput := SuccessFailOperationInput{ShouldFail: true} diff --git a/deployment/common/changeset/example/operations/terminal_error_example.go b/deployment/common/changeset/example/operations/terminal_error_example.go index d3a9267cb87..3d1e0c226d0 100644 --- a/deployment/common/changeset/example/operations/terminal_error_example.go +++ b/deployment/common/changeset/example/operations/terminal_error_example.go @@ -7,8 +7,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-deployments-framework/operations" - - "github.com/smartcontractkit/chainlink/deployment" ) /** @@ -21,12 +19,12 @@ var _ cldf.ChangeSetV2[operations.EmptyInput] = TerminalErrorExampleChangeset{} type TerminalErrorExampleChangeset struct{} -func (l TerminalErrorExampleChangeset) VerifyPreconditions(e deployment.Environment, config operations.EmptyInput) error { +func (l TerminalErrorExampleChangeset) VerifyPreconditions(e cldf.Environment, config operations.EmptyInput) error { // perform any preconditions checks here return nil } -func (l TerminalErrorExampleChangeset) Apply(e deployment.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { +func (l TerminalErrorExampleChangeset) Apply(e cldf.Environment, config operations.EmptyInput) (cldf.ChangesetOutput, error) { ab := cldf.NewMemoryAddressBook() _, err := operations.ExecuteOperation(e.OperationsBundle, TerminalErrorOperation, nil, operations.EmptyInput{}) diff --git a/deployment/common/changeset/example/solana_transfer_mcm.go b/deployment/common/changeset/example/solana_transfer_mcm.go index 8700836e008..52438466677 100644 --- a/deployment/common/changeset/example/solana_transfer_mcm.go +++ b/deployment/common/changeset/example/solana_transfer_mcm.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/mcms/types" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + solanachangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -34,7 +34,7 @@ type TransferFromTimelockConfig struct { type TransferFromTimelock struct{} // VerifyPreconditions checks if the deployer has enough SOL to fund the MCMS signers on each chain. -func (f TransferFromTimelock) VerifyPreconditions(e deployment.Environment, config TransferFromTimelockConfig) error { +func (f TransferFromTimelock) VerifyPreconditions(e cldf.Environment, config TransferFromTimelockConfig) error { // the number of accounts to fund per chain (bypasser, canceller, proposer, timelock) for chainSelector, amountCfg := range config.AmountsPerChain { solChain, ok := e.SolChains[chainSelector] @@ -72,7 +72,7 @@ func (f TransferFromTimelock) VerifyPreconditions(e deployment.Environment, conf } // Apply funds the MCMS signers on each chain. -func (f TransferFromTimelock) Apply(e deployment.Environment, config TransferFromTimelockConfig) (cldf.ChangesetOutput, error) { +func (f TransferFromTimelock) Apply(e cldf.Environment, config TransferFromTimelockConfig) (cldf.ChangesetOutput, error) { timelocks := map[uint64]string{} proposers := map[uint64]string{} var batches []types.BatchOperation diff --git a/deployment/common/changeset/example/solana_transfer_mcm_test.go b/deployment/common/changeset/example/solana_transfer_mcm_test.go index ed8a12d9630..9477e1284bc 100644 --- a/deployment/common/changeset/example/solana_transfer_mcm_test.go +++ b/deployment/common/changeset/example/solana_transfer_mcm_test.go @@ -28,7 +28,7 @@ import ( ) // setupFundingTestEnv deploys all required contracts for the funding test -func setupFundingTestEnv(t *testing.T) deployment.Environment { +func setupFundingTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ SolChains: 1, @@ -61,7 +61,7 @@ func TestTransferFromTimelockConfig_VerifyPreconditions(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) validEnv := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{SolChains: 1}) - validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} validSolChainSelector := validEnv.AllChainSelectorsSolana()[0] receiverKey := solana.NewWallet().PublicKey() cs := example.TransferFromTimelock{} @@ -80,7 +80,7 @@ func TestTransferFromTimelockConfig_VerifyPreconditions(t *testing.T) { noTimelockEnv := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ SolChains: 1, }) - noTimelockEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + noTimelockEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} err = noTimelockEnv.ExistingAddresses.Save(chainselectors.SOLANA_DEVNET.Selector, "dummy", cldf.TypeAndVersion{ Type: "Sometype", Version: deployment.Version1_0_0, @@ -91,11 +91,11 @@ func TestTransferFromTimelockConfig_VerifyPreconditions(t *testing.T) { invalidSolChainEnv := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ SolChains: 0, }) - invalidSolChainEnv.SolChains[validSolChainSelector] = deployment.SolChain{} + invalidSolChainEnv.SolChains[validSolChainSelector] = cldf.SolChain{} tests := []struct { name string - env deployment.Environment + env cldf.Environment config example.TransferFromTimelockConfig expectedError string }{ diff --git a/deployment/common/changeset/internal/evm/mcms.go b/deployment/common/changeset/internal/evm/mcms.go index c40d5d9ed69..ae574238c0e 100644 --- a/deployment/common/changeset/internal/evm/mcms.go +++ b/deployment/common/changeset/internal/evm/mcms.go @@ -50,7 +50,7 @@ type MCMSWithTimelockEVMDeploy struct { func DeployMCMSWithConfigEVM( contractType cldf.ContractType, lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, ab cldf.AddressBook, mcmConfig mcmsTypes.Config, options ...DeployMCMSOption, @@ -61,7 +61,7 @@ func DeployMCMSWithConfigEVM( return nil, err } mcm, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*bindings.ManyChainMultiSig] { + func(chain cldf.Chain) cldf.ContractDeploy[*bindings.ManyChainMultiSig] { mcmAddr, tx, mcm, err2 := bindings.DeployManyChainMultiSig( chain.DeployerKey, chain.Client, @@ -88,7 +88,7 @@ func DeployMCMSWithConfigEVM( groupParents, false, ) - if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, mcmsTx, err); err != nil { lggr.Errorw("Failed to confirm mcm config", "chain", chain.String(), "err", err) return mcm, err } @@ -103,7 +103,7 @@ func DeployMCMSWithConfigEVM( func DeployMCMSWithTimelockContractsEVM( ctx context.Context, lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, ab cldf.AddressBook, config commontypes.MCMSWithTimelockConfigV2, state *state.MCMSWithTimelockState, @@ -157,7 +157,7 @@ func DeployMCMSWithTimelockContractsEVM( if timelock == nil { timelockC, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*bindings.RBACTimelock] { + func(chain cldf.Chain) cldf.ContractDeploy[*bindings.RBACTimelock] { timelock, tx2, cc, err2 := bindings.DeployRBACTimelock( chain.DeployerKey, chain.Client, @@ -195,7 +195,7 @@ func DeployMCMSWithTimelockContractsEVM( if callProxy == nil { callProxyC, err := cldf.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) cldf.ContractDeploy[*bindings.CallProxy] { + func(chain cldf.Chain) cldf.ContractDeploy[*bindings.CallProxy] { callProxy, tx2, cc, err2 := bindings.DeployCallProxy( chain.DeployerKey, chain.Client, @@ -269,7 +269,7 @@ func getAdminAddresses(ctx context.Context, timelock *bindings.RBACTimelock) ([] func GrantRolesForTimelock( ctx context.Context, lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, timelockContracts *proposalutils.MCMSWithTimelockContracts, skipIfDeployerKeyNotAdmin bool, // If true, skip role grants if the deployer key is not an admin. ) ([]mcmsTypes.Transaction, error) { @@ -389,12 +389,12 @@ func GrantRolesForTimelock( func grantRoleTx( lggr logger.Logger, timelock *bindings.RBACTimelock, - chain deployment.Chain, + chain cldf.Chain, isDeployerKeyAdmin bool, roleID [32]byte, address common.Address, ) (mcmsTypes.Transaction, error) { - txOpts := deployment.SimTransactOpts() + txOpts := cldf.SimTransactOpts() if isDeployerKeyAdmin { txOpts = chain.DeployerKey } @@ -402,7 +402,7 @@ func grantRoleTx( txOpts, roleID, address, ) if isDeployerKeyAdmin { - if _, err2 := deployment.ConfirmIfNoErrorWithABI(chain, grantRoleTx, bindings.RBACTimelockABI, err); err != nil { + if _, err2 := cldf.ConfirmIfNoErrorWithABI(chain, grantRoleTx, bindings.RBACTimelockABI, err); err != nil { lggr.Errorw("Failed to grant timelock role", "chain", chain.String(), "timelock", timelock.Address().Hex(), diff --git a/deployment/common/changeset/jobspec.go b/deployment/common/changeset/jobspec.go index 1423cbec792..1f83ffa255d 100644 --- a/deployment/common/changeset/jobspec.go +++ b/deployment/common/changeset/jobspec.go @@ -8,7 +8,6 @@ import ( jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" ) var ( @@ -23,7 +22,7 @@ var ( DeleteJobChangeset = cldf.CreateChangeSet(deleteJobsLogic, deleteJobsPrecondition) ) -func revokeJobsPrecondition(env deployment.Environment, jobIDs []string) error { +func revokeJobsPrecondition(env cldf.Environment, jobIDs []string) error { proposals, err := env.Offchain.ListProposals(env.GetContext(), &jobv1.ListProposalsRequest{ Filter: &jobv1.ListProposalsRequest_Filter{ JobIds: jobIDs, @@ -40,7 +39,7 @@ func revokeJobsPrecondition(env deployment.Environment, jobIDs []string) error { return nil } -func revokeJobsLogic(env deployment.Environment, jobIDs []string) (cldf.ChangesetOutput, error) { +func revokeJobsLogic(env cldf.Environment, jobIDs []string) (cldf.ChangesetOutput, error) { var successfullyRevoked []string for _, jobID := range jobIDs { res, err := env.Offchain.RevokeJob(env.GetContext(), &jobv1.RevokeJobRequest{ @@ -67,7 +66,7 @@ func revokeJobsLogic(env deployment.Environment, jobIDs []string) (cldf.Changese return cldf.ChangesetOutput{}, nil } -func deleteJobsPrecondition(env deployment.Environment, jobIDs []string) error { +func deleteJobsPrecondition(env cldf.Environment, jobIDs []string) error { jobs, err := env.Offchain.ListJobs(env.GetContext(), &jobv1.ListJobsRequest{ Filter: &jobv1.ListJobsRequest_Filter{ Ids: jobIDs, @@ -91,7 +90,7 @@ func deleteJobsPrecondition(env deployment.Environment, jobIDs []string) error { // DeleteJobChangeset sends the delete job request to nodes for the given jobID. // nops needs to cancel the job once the request is sent by JD. -func deleteJobsLogic(env deployment.Environment, jobIDs []string) (cldf.ChangesetOutput, error) { +func deleteJobsLogic(env cldf.Environment, jobIDs []string) (cldf.ChangesetOutput, error) { jobIDsToDelete, err := jobsToDelete(env, jobIDs) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to get jobIDs to delete: %w", err) @@ -114,7 +113,7 @@ func deleteJobsLogic(env deployment.Environment, jobIDs []string) (cldf.Changese return cldf.ChangesetOutput{}, nil } -func jobsToDelete(env deployment.Environment, jobIDs []string) ([]string, error) { +func jobsToDelete(env cldf.Environment, jobIDs []string) ([]string, error) { jobs, err := env.Offchain.ListProposals(env.GetContext(), &jobv1.ListProposalsRequest{ Filter: &jobv1.ListProposalsRequest_Filter{ JobIds: jobIDs, diff --git a/deployment/common/changeset/mcms_firedrill.go b/deployment/common/changeset/mcms_firedrill.go index 3c1322c823c..bc032ab1216 100644 --- a/deployment/common/changeset/mcms_firedrill.go +++ b/deployment/common/changeset/mcms_firedrill.go @@ -12,7 +12,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -23,7 +22,7 @@ type FireDrillConfig struct { } // buildNoOPEVM builds a dummy tx that transfers 0 to the RBACTimelock -func buildNoOPEVM(e deployment.Environment, selector uint64) (mcmstypes.Transaction, error) { +func buildNoOPEVM(e cldf.Environment, selector uint64) (mcmstypes.Transaction, error) { chain, ok := e.Chains[selector] if !ok { return mcmstypes.Transaction{}, nil @@ -73,7 +72,7 @@ func buildNoOPSolana() (mcmstypes.Transaction, error) { // MCMSSignFireDrillChangeset creates a changeset for a MCMS signing Fire Drill. // It is used to make sure team member can effectively sign proposal and that the execution pipelines are healthy. // The changeset will create a NO-OP transaction for each chain selector in the environment and create a proposal for it. -func MCMSSignFireDrillChangeset(e deployment.Environment, cfg FireDrillConfig) (cldf.ChangesetOutput, error) { +func MCMSSignFireDrillChangeset(e cldf.Environment, cfg FireDrillConfig) (cldf.ChangesetOutput, error) { allSelectors := cfg.Selectors if len(allSelectors) == 0 { solSelectors := e.AllChainSelectorsSolana() diff --git a/deployment/common/changeset/mcms_firedrill_test.go b/deployment/common/changeset/mcms_firedrill_test.go index 3e322034f2a..d4f14f74720 100644 --- a/deployment/common/changeset/mcms_firedrill_test.go +++ b/deployment/common/changeset/mcms_firedrill_test.go @@ -9,7 +9,7 @@ import ( "go.uber.org/zap/zapcore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -19,7 +19,7 @@ import ( ) // setupFiredrillTestEnv deploys all required contracts for the firedrill proposal execution -func setupFiredrillTestEnv(t *testing.T) deployment.Environment { +func setupFiredrillTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ Chains: 2, diff --git a/deployment/migrated_changeset.go b/deployment/common/changeset/run_changeset.go similarity index 97% rename from deployment/migrated_changeset.go rename to deployment/common/changeset/run_changeset.go index 8a6351920e1..77d310cc163 100644 --- a/deployment/migrated_changeset.go +++ b/deployment/common/changeset/run_changeset.go @@ -1,4 +1,4 @@ -package deployment +package changeset import ( "fmt" diff --git a/deployment/common/changeset/save_existing.go b/deployment/common/changeset/save_existing.go index bf08ff0d135..c8908502a8a 100644 --- a/deployment/common/changeset/save_existing.go +++ b/deployment/common/changeset/save_existing.go @@ -8,8 +8,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/mr-tron/base58" chain_selectors "github.com/smartcontractkit/chain-selectors" ) @@ -30,7 +28,7 @@ type ExistingContractsConfig struct { func (cfg ExistingContractsConfig) Validate() error { for _, ec := range cfg.ExistingContracts { - if err := deployment.IsValidChainSelector(ec.ChainSelector); err != nil { + if err := cldf.IsValidChainSelector(ec.ChainSelector); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", ec.ChainSelector, err) } if ec.Address == "" { @@ -69,7 +67,7 @@ func (cfg ExistingContractsConfig) Validate() error { // SaveExistingContractsChangeset saves the existing contracts to the address book. // Caller should update the environment's address book with the returned addresses. -func SaveExistingContractsChangeset(env deployment.Environment, cfg ExistingContractsConfig) (cldf.ChangesetOutput, error) { +func SaveExistingContractsChangeset(env cldf.Environment, cfg ExistingContractsConfig) (cldf.ChangesetOutput, error) { err := cfg.Validate() if err != nil { return cldf.ChangesetOutput{}, errors.Wrapf(cldf.ErrInvalidConfig, "%v", err) diff --git a/deployment/common/changeset/save_existing_test.go b/deployment/common/changeset/save_existing_test.go index 6b2ea5bc93f..09881593dcd 100644 --- a/deployment/common/changeset/save_existing_test.go +++ b/deployment/common/changeset/save_existing_test.go @@ -16,11 +16,11 @@ import ( ) func TestSaveExisting(t *testing.T) { - dummyEnv := deployment.Environment{ + dummyEnv := cldf.Environment{ Name: "dummy", Logger: logger.TestLogger(t), ExistingAddresses: cldf.NewMemoryAddressBook(), - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chainsel.TEST_90000001.Selector: {}, chainsel.TEST_90000002.Selector: {}, }, @@ -58,11 +58,11 @@ func TestSaveExisting(t *testing.T) { } func TestSaveExistingAddressWithLabels(t *testing.T) { - dummyEnv := deployment.Environment{ + dummyEnv := cldf.Environment{ Name: "dummy", Logger: logger.TestLogger(t), ExistingAddresses: cldf.NewMemoryAddressBook(), - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chainsel.TEST_90000001.Selector: {}, chainsel.TEST_90000002.Selector: {}, }, @@ -96,11 +96,11 @@ func TestSaveExistingAddressWithLabels(t *testing.T) { } func TestSaveExistingMCMSAddressWithLabels(t *testing.T) { - dummyEnv := deployment.Environment{ + dummyEnv := cldf.Environment{ Name: "dummy", Logger: logger.TestLogger(t), ExistingAddresses: cldf.NewMemoryAddressBook(), - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chainsel.TEST_90000001.Selector: {}, chainsel.TEST_90000002.Selector: {}, }, diff --git a/deployment/common/changeset/set_config_mcms.go b/deployment/common/changeset/set_config_mcms.go index f483da5bf05..340cd303085 100644 --- a/deployment/common/changeset/set_config_mcms.go +++ b/deployment/common/changeset/set_config_mcms.go @@ -6,96 +6,39 @@ import ( "fmt" "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" solanasdk "github.com/gagliardetto/solana-go" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - mcmslib "github.com/smartcontractkit/mcms" "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" commonState "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) -// Deprecated: use ConfigPerRoleV2 instead -type ConfigPerRole struct { - Proposer config.Config - Canceller config.Config - Bypasser config.Config -} - type ConfigPerRoleV2 struct { Proposer mcmstypes.Config Canceller mcmstypes.Config Bypasser mcmstypes.Config } -type MCMSConfig struct { - ConfigsPerChain map[uint64]ConfigPerRole - ProposalConfig *proposalutils.TimelockConfig -} - type MCMSConfigV2 struct { ConfigsPerChain map[uint64]ConfigPerRoleV2 ProposalConfig *proposalutils.TimelockConfig } -var _ cldf.ChangeSet[MCMSConfig] = SetConfigMCMS var _ cldf.ChangeSet[MCMSConfigV2] = SetConfigMCMSV2 -// Validate checks that the MCMSConfig is valid -func (cfg MCMSConfig) Validate(e deployment.Environment, selectors []uint64) error { - if len(cfg.ConfigsPerChain) == 0 { - return errors.New("no chain configs provided") - } - // configs should have at least one chain - state, err := MaybeLoadMCMSWithTimelockState(e, selectors) - if err != nil { - return err - } - for chainSelector, c := range cfg.ConfigsPerChain { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return err - } - if family != chain_selectors.FamilyEVM { - return fmt.Errorf("chain selector: %d is not an ethereum chain", chainSelector) - } - _, ok := e.Chains[chainSelector] - if !ok { - return fmt.Errorf("chain selector: %d not found in environment", chainSelector) - } - _, ok = state[chainSelector] - if !ok { - return fmt.Errorf("chain selector: %d not found for MCMS state", chainSelector) - } - if err := c.Proposer.Validate(); err != nil { - return err - } - if err := c.Canceller.Validate(); err != nil { - return err - } - if err := c.Bypasser.Validate(); err != nil { - return err - } - } - return nil -} - // Validate checks that the MCMSConfigV2 is valid -func (cfg MCMSConfigV2) Validate(e deployment.Environment, selectors []uint64) error { +func (cfg MCMSConfigV2) Validate(e cldf.Environment, selectors []uint64) error { if len(cfg.ConfigsPerChain) == 0 { return errors.New("no chain configs provided") } @@ -151,32 +94,9 @@ func (cfg MCMSConfigV2) Validate(e deployment.Environment, selectors []uint64) e return nil } -// setConfigOrTxData executes set config tx or gets the tx data for the MCMS proposal -// Deprecated: Use setConfigOrTxDataV2 instead. -func setConfigOrTxData(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg config.Config, contract *gethwrappers.ManyChainMultiSig, useMCMS bool) (*types.Transaction, error) { - groupQuorums, groupParents, signerAddresses, signerGroups := cfg.ExtractSetConfigInputs() - opts := deployment.SimTransactOpts() - if !useMCMS { - opts = chain.DeployerKey - } - opts.Context = ctx - tx, err := contract.SetConfig(opts, signerAddresses, signerGroups, groupQuorums, groupParents, false) - if err != nil { - return nil, err - } - if !useMCMS { - _, err = deployment.ConfirmIfNoErrorWithABI(chain, tx, gethwrappers.ManyChainMultiSigABI, err) - if err != nil { - return nil, err - } - lggr.Infow("SetConfigMCMS tx confirmed", "txHash", tx.Hash().Hex()) - } - return tx, nil -} - // setConfigOrTxDataV2 executes set config tx or gets the tx data for the MCMS proposal -func setConfigOrTxDataV2(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg mcmstypes.Config, contract *gethwrappers.ManyChainMultiSig, useMCMS bool) (*types.Transaction, error) { - opts := deployment.SimTransactOpts() +func setConfigOrTxDataV2(ctx context.Context, lggr logger.Logger, chain cldf.Chain, cfg mcmstypes.Config, contract *gethwrappers.ManyChainMultiSig, useMCMS bool) (*types.Transaction, error) { + opts := cldf.SimTransactOpts() if !useMCMS { opts = chain.DeployerKey } @@ -190,7 +110,7 @@ func setConfigOrTxDataV2(ctx context.Context, lggr logger.Logger, chain deployme transaction := res.RawData.(*types.Transaction) if !useMCMS { - _, err = deployment.ConfirmIfNoErrorWithABI(chain, transaction, gethwrappers.ManyChainMultiSigABI, err) + _, err = cldf.ConfirmIfNoErrorWithABI(chain, transaction, gethwrappers.ManyChainMultiSigABI, err) if err != nil { return nil, err } @@ -205,34 +125,8 @@ type setConfigTxs struct { bypasserTx *types.Transaction } -// setConfigPerRole sets the configuration for each of the MCMS contract roles on the mcmsState. -// Deprecated: Use setConfigPerRoleV2 instead. -func setConfigPerRole(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg ConfigPerRole, mcmsState *MCMSWithTimelockState, useMCMS bool) (setConfigTxs, error) { - // Proposer set config - proposerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Proposer, mcmsState.ProposerMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - // Canceller set config - cancellerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Canceller, mcmsState.CancellerMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - // Bypasser set config - bypasserTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Bypasser, mcmsState.BypasserMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - - return setConfigTxs{ - proposerTx: proposerTx, - cancellerTx: cancellerTx, - bypasserTx: bypasserTx, - }, nil -} - // setConfigPerRoleV2 sets the configuration for each of the MCMS contract roles on the mcmsState. -func setConfigPerRoleV2(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg ConfigPerRoleV2, mcmsState *commonState.MCMSWithTimelockState, useMCMS bool) (setConfigTxs, error) { +func setConfigPerRoleV2(ctx context.Context, lggr logger.Logger, chain cldf.Chain, cfg ConfigPerRoleV2, mcmsState *commonState.MCMSWithTimelockState, useMCMS bool) (setConfigTxs, error) { // Proposer set config proposerTx, err := setConfigOrTxDataV2(ctx, lggr, chain, cfg.Proposer, mcmsState.ProposerMcm, useMCMS) if err != nil { @@ -256,86 +150,8 @@ func setConfigPerRoleV2(ctx context.Context, lggr logger.Logger, chain deploymen }, nil } -func addTxsToProposalBatch(setConfigTxsChain setConfigTxs, chainSelector uint64, state MCMSWithTimelockState) timelock.BatchChainOperation { - result := timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSelector), - Batch: []mcms.Operation{}, - } - result.Batch = append(result.Batch, mcms.Operation{ - To: state.ProposerMcm.Address(), - Data: setConfigTxsChain.proposerTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.ProposerManyChainMultisig), - }) - result.Batch = append(result.Batch, mcms.Operation{ - To: state.CancellerMcm.Address(), - Data: setConfigTxsChain.cancellerTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.CancellerManyChainMultisig), - }) - result.Batch = append(result.Batch, mcms.Operation{ - To: state.BypasserMcm.Address(), - Data: setConfigTxsChain.bypasserTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.BypasserManyChainMultisig), - }) - return result -} - -// SetConfigMCMS sets the configuration of the MCMS contract on the chain identified by the chainSelector. -// Deprecated: Use SetConfigMCMSV2 instead. -func SetConfigMCMS(e deployment.Environment, cfg MCMSConfig) (cldf.ChangesetOutput, error) { - selectors := []uint64{} - lggr := e.Logger - ctx := e.GetContext() - for chainSelector := range cfg.ConfigsPerChain { - selectors = append(selectors, chainSelector) - } - useMCMS := cfg.ProposalConfig != nil - err := cfg.Validate(e, selectors) - if err != nil { - return cldf.ChangesetOutput{}, err - } - - batches := []timelock.BatchChainOperation{} - timelocksPerChain := map[uint64]common.Address{} - proposerMcmsPerChain := map[uint64]*gethwrappers.ManyChainMultiSig{} - - mcmsStatePerChain, err := MaybeLoadMCMSWithTimelockState(e, selectors) - if err != nil { - return cldf.ChangesetOutput{}, err - } - - for chainSelector, c := range cfg.ConfigsPerChain { - chain := e.Chains[chainSelector] - state := mcmsStatePerChain[chainSelector] - timelocksPerChain[chainSelector] = state.Timelock.Address() - proposerMcmsPerChain[chainSelector] = state.ProposerMcm - setConfigTxsChain, err := setConfigPerRole(ctx, lggr, chain, c, state, useMCMS) - if err != nil { - return cldf.ChangesetOutput{}, err - } - if useMCMS { - batch := addTxsToProposalBatch(setConfigTxsChain, chainSelector, *state) - batches = append(batches, batch) - } - } - - if useMCMS { - // Create MCMS with timelock proposal - proposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMcmsPerChain, batches, "Set config proposal", cfg.ProposalConfig.MinDelay) - if err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) - } - lggr.Infow("SetConfigMCMS proposal created", "proposal", proposal) - return cldf.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil - } - - return cldf.ChangesetOutput{}, nil -} - // SetConfigMCMSV2 is a reimplementation of SetConfigMCMS that uses the new MCMS library. -func SetConfigMCMSV2(e deployment.Environment, cfg MCMSConfigV2) (cldf.ChangesetOutput, error) { +func SetConfigMCMSV2(e cldf.Environment, cfg MCMSConfigV2) (cldf.ChangesetOutput, error) { selectors := []uint64{} lggr := e.Logger ctx := e.GetContext() @@ -431,7 +247,7 @@ func addTxsToProposalBatchV2(setConfigTxsChain setConfigTxs, chainSelector uint6 } func setConfigSolana( - e deployment.Environment, chainSelector uint64, cfg ConfigPerRoleV2, + e cldf.Environment, chainSelector uint64, cfg ConfigPerRoleV2, timelockAddressesPerChain, proposerMcmsPerChain map[uint64]string, useMCMS bool, ) ([]mcmstypes.BatchOperation, error) { chain := e.SolChains[chainSelector] @@ -473,7 +289,7 @@ func setConfigSolana( return batches, nil } -func setConfigForRole(e deployment.Environment, chain deployment.SolChain, cfg mcmstypes.Config, mcmAddress string, contractType string, useMCMS bool, timelockSignerPDA solanasdk.PublicKey) (mcmstypes.BatchOperation, error) { +func setConfigForRole(e cldf.Environment, chain cldf.SolChain, cfg mcmstypes.Config, mcmAddress string, contractType string, useMCMS bool, timelockSignerPDA solanasdk.PublicKey) (mcmstypes.BatchOperation, error) { var configurer *solana.Configurer if useMCMS { diff --git a/deployment/common/changeset/set_config_mcms_test.go b/deployment/common/changeset/set_config_mcms_test.go index 6def9ca1ddf..75ec0fdca52 100644 --- a/deployment/common/changeset/set_config_mcms_test.go +++ b/deployment/common/changeset/set_config_mcms_test.go @@ -5,23 +5,18 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" solanasdk "github.com/gagliardetto/solana-go" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/mcms/sdk/evm" "github.com/smartcontractkit/mcms/sdk/solana" mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commonchangesetsolana "github.com/smartcontractkit/chainlink/deployment/common/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" @@ -32,7 +27,7 @@ import ( ) // setupSetConfigTestEnv deploys all required contracts for the setConfig MCMS contract call. -func setupSetConfigTestEnv(t *testing.T) deployment.Environment { +func setupSetConfigTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ Chains: 2, @@ -62,117 +57,6 @@ func setupSetConfigTestEnv(t *testing.T) deployment.Environment { return env } -// TestSetConfigMCMSVariants tests the SetConfigMCMS changeset variants. -func TestSetConfigMCMSVariants(t *testing.T) { - t.Parallel() - // Add the timelock as a signer to check state changes - for _, tc := range []struct { - name string - changeSets func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ConfiguredChangeSet - }{ - { - name: "MCMS disabled", - changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ConfiguredChangeSet { - return []commonchangeset.ConfiguredChangeSet{ - commonchangeset.Configure( - cldf.CreateLegacyChangeSet(commonchangeset.SetConfigMCMS), - commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSel: { - Proposer: cfgProp, - Canceller: cfgCancel, - Bypasser: cfgBypass, - }, - }, - }, - ), - } - }, - }, - { - name: "MCMS enabled", - changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ConfiguredChangeSet { - return []commonchangeset.ConfiguredChangeSet{ - commonchangeset.Configure( - cldf.CreateLegacyChangeSet(commonchangeset.TransferToMCMSWithTimelock), - commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: map[uint64][]common.Address{ - chainSel: {mcmsState.ProposerMcm.Address(), mcmsState.BypasserMcm.Address(), mcmsState.CancellerMcm.Address()}, - }, - }, - ), - commonchangeset.Configure( - cldf.CreateLegacyChangeSet(commonchangeset.SetConfigMCMS), - commonchangeset.MCMSConfig{ - ProposalConfig: &proposalutils.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSel: { - Proposer: cfgProp, - Canceller: cfgCancel, - Bypasser: cfgBypass, - }, - }, - }, - ), - } - }, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := tests.Context(t) - - env := setupSetConfigTestEnv(t) - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - timelockAddress := mcmsState.Timelock.Address() - cfgProposer := proposalutils.SingleGroupMCMS(t) - cfgProposer.Signers = append(cfgProposer.Signers, timelockAddress) - cfgProposer.Quorum = 2 // quorum should change to 2 out of 2 signers - timelockMap := map[uint64]*proposalutils.TimelockExecutionContracts{ - chainSelector: { - Timelock: mcmsState.Timelock, - CallProxy: mcmsState.CallProxy, - }, - } - cfgCanceller := proposalutils.SingleGroupMCMS(t) - cfgBypasser := proposalutils.SingleGroupMCMS(t) - cfgBypasser.Signers = append(cfgBypasser.Signers, timelockAddress) - cfgBypasser.Signers = append(cfgBypasser.Signers, mcmsState.ProposerMcm.Address()) - cfgBypasser.Quorum = 3 // quorum should change to 3 out of 3 signers - - // Set config on all 3 MCMS contracts - changesetsToApply := tc.changeSets(mcmsState, chainSelector, cfgProposer, cfgCanceller, cfgBypasser) - _, err = commonchangeset.ApplyChangesets(t, env, timelockMap, changesetsToApply) - require.NoError(t, err) - - // Check new State - expected := cfgProposer.ToRawConfig() - opts := &bind.CallOpts{Context: ctx} - newConf, err := mcmsState.ProposerMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - - expected = cfgBypasser.ToRawConfig() - newConf, err = mcmsState.BypasserMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - - expected = cfgCanceller.ToRawConfig() - newConf, err = mcmsState.CancellerMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - }) - } -} - func TestSetConfigMCMSV2EVM(t *testing.T) { t.Parallel() // Add the timelock as a signer to check state changes @@ -384,156 +268,6 @@ func TestSetConfigMCMSV2Solana(t *testing.T) { } } -func TestValidate(t *testing.T) { - t.Parallel() - env := setupSetConfigTestEnv(t) - - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - cfg := proposalutils.SingleGroupMCMS(t) - timelockAddress := mcmsState.Timelock.Address() - // Add the timelock as a signer to check state changes - cfg.Signers = append(cfg.Signers, timelockAddress) - cfg.Quorum = 2 // quorum - - cfgInvalid := proposalutils.SingleGroupMCMS(t) - cfgInvalid.Quorum = 0 - require.NoError(t, err) - tests := []struct { - name string - cfg commonchangeset.MCMSConfig - errorMsg string - }{ - { - name: "valid config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &proposalutils.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - }, - { - name: "valid non mcms config", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - }, - { - name: "no chain configurations", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{}, - }, - errorMsg: "no chain configs provided", - }, - { - name: "non evm chain", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chain_selectors.APTOS_MAINNET.Selector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "chain selector: 4741433654826277614 is not an ethereum chain", - }, - { - name: "chain selector not found in environment", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - 123: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "unknown chain selector 123", - }, - { - name: "invalid proposer config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &proposalutils.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfgInvalid, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - { - name: "invalid canceller config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &proposalutils.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfgInvalid, - Bypasser: cfg, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - { - name: "invalid bypasser config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &proposalutils.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfgInvalid, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - selectors := []uint64{chainSelector} - - err := tt.cfg.Validate(env, selectors) - if tt.errorMsg != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tt.errorMsg) - } else { - require.NoError(t, err) - } - }) - } -} - func TestValidateV2(t *testing.T) { tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-439") @@ -690,7 +424,7 @@ func TestValidateV2(t *testing.T) { } func fundSignerPDAs( - t *testing.T, env deployment.Environment, chainSelector uint64, chainState *state.MCMSWithTimelockStateSolana, + t *testing.T, env cldf.Environment, chainSelector uint64, chainState *state.MCMSWithTimelockStateSolana, ) { t.Helper() solChain := env.SolChains[chainSelector] diff --git a/deployment/common/changeset/solana/fund_mcm_pdas.go b/deployment/common/changeset/solana/fund_mcm_pdas.go index b3ab148fcf1..bcc7b8eb7da 100644 --- a/deployment/common/changeset/solana/fund_mcm_pdas.go +++ b/deployment/common/changeset/solana/fund_mcm_pdas.go @@ -8,7 +8,7 @@ import ( "github.com/gagliardetto/solana-go/rpc" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" ) @@ -30,7 +30,7 @@ type FundMCMSignerConfig struct { type FundMCMSignersChangeset struct{} // VerifyPreconditions checks if the deployer has enough SOL to fund the MCMS signers on each chain. -func (f FundMCMSignersChangeset) VerifyPreconditions(e deployment.Environment, config FundMCMSignerConfig) error { +func (f FundMCMSignersChangeset) VerifyPreconditions(e cldf.Environment, config FundMCMSignerConfig) error { // the number of accounts to fund per chain (bypasser, canceller, proposer, timelock) for chainSelector, chainCfg := range config.AmountsPerChain { solChain, ok := e.SolChains[chainSelector] @@ -66,7 +66,7 @@ func (f FundMCMSignersChangeset) VerifyPreconditions(e deployment.Environment, c } // Apply funds the MCMS signers on each chain. -func (f FundMCMSignersChangeset) Apply(e deployment.Environment, config FundMCMSignerConfig) (cldf.ChangesetOutput, error) { +func (f FundMCMSignersChangeset) Apply(e cldf.Environment, config FundMCMSignerConfig) (cldf.ChangesetOutput, error) { for chainSelector, cfgAmounts := range config.AmountsPerChain { solChain := e.SolChains[chainSelector] addreses, err := e.ExistingAddresses.AddressesForChain(chainSelector) diff --git a/deployment/common/changeset/solana/fund_mcm_pdas_test.go b/deployment/common/changeset/solana/fund_mcm_pdas_test.go index 3819f709dee..dd539dd3ca5 100644 --- a/deployment/common/changeset/solana/fund_mcm_pdas_test.go +++ b/deployment/common/changeset/solana/fund_mcm_pdas_test.go @@ -27,7 +27,7 @@ import ( ) // setupFundingTestEnv deploys all required contracts for the funding test -func setupFundingTestEnv(t *testing.T) deployment.Environment { +func setupFundingTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ Nodes: 1, @@ -61,7 +61,7 @@ func TestFundMCMSignersChangeset_VerifyPreconditions(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) validEnv := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{SolChains: 1}) - validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} validSolChainSelector := validEnv.AllChainSelectorsSolana()[0] timelockID := mcmsSolana.ContractAddress( @@ -115,7 +115,7 @@ func TestFundMCMSignersChangeset_VerifyPreconditions(t *testing.T) { SolChains: 1, Nodes: 1, }) - noMCMSEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + noMCMSEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} err = noMCMSEnv.ExistingAddresses.Save(chainselectors.SOLANA_DEVNET.Selector, mcmsProposerIDEmpty, cldf.TypeAndVersion{ Type: types.BypasserManyChainMultisig, Version: deployment.Version1_0_0, @@ -128,11 +128,11 @@ func TestFundMCMSignersChangeset_VerifyPreconditions(t *testing.T) { SolChains: 0, Nodes: 1, }) - invalidSolChainEnv.SolChains[validSolChainSelector] = deployment.SolChain{} + invalidSolChainEnv.SolChains[validSolChainSelector] = cldf.SolChain{} tests := []struct { name string - env deployment.Environment + env cldf.Environment config commonSolana.FundMCMSignerConfig expectedError string }{ diff --git a/deployment/common/changeset/solana/helpers.go b/deployment/common/changeset/solana/helpers.go index e23ac65ac20..7d501ac0711 100644 --- a/deployment/common/changeset/solana/helpers.go +++ b/deployment/common/changeset/solana/helpers.go @@ -6,11 +6,11 @@ import ( "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) // FundFromAddressIxs transfers SOL from the given address to each provided account and waits for confirmations. -func FundFromAddressIxs(solChain deployment.SolChain, from solana.PublicKey, accounts []solana.PublicKey, amount uint64) ([]solana.Instruction, error) { +func FundFromAddressIxs(solChain cldf.SolChain, from solana.PublicKey, accounts []solana.PublicKey, amount uint64) ([]solana.Instruction, error) { var ixs []solana.Instruction for _, account := range accounts { // Create a transfer instruction using the provided builder. @@ -29,7 +29,7 @@ func FundFromAddressIxs(solChain deployment.SolChain, from solana.PublicKey, acc } // FundFromDeployerKey transfers SOL from the deployer to each provided account and waits for confirmations. -func FundFromDeployerKey(solChain deployment.SolChain, accounts []solana.PublicKey, amount uint64) error { +func FundFromDeployerKey(solChain cldf.SolChain, accounts []solana.PublicKey, amount uint64) error { ixs, err := FundFromAddressIxs(solChain, solChain.DeployerKey.PublicKey(), accounts, amount) if err != nil { return fmt.Errorf("failed to create transfer instructions: %w", err) diff --git a/deployment/common/changeset/solana/mcms/access_controller.go b/deployment/common/changeset/solana/mcms/access_controller.go index 52dcd265c18..161662b4c55 100644 --- a/deployment/common/changeset/solana/mcms/access_controller.go +++ b/deployment/common/changeset/solana/mcms/access_controller.go @@ -21,8 +21,8 @@ import ( ) func deployAccessControllerProgram( - e deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, - chain deployment.SolChain, addressBook cldf.AddressBook, + e cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, + chain cldf.SolChain, addressBook cldf.AddressBook, ) error { typeAndVersion := cldf.NewTypeAndVersion(commontypes.AccessControllerProgram, deployment.Version1_0_0) log := logger.With(e.Logger, "chain", chain.String(), "contract", typeAndVersion.String()) @@ -62,8 +62,8 @@ func deployAccessControllerProgram( } func initAccessController( - e deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, contractType cldf.ContractType, - chain deployment.SolChain, addressBook cldf.AddressBook, + e cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, contractType cldf.ContractType, + chain cldf.SolChain, addressBook cldf.AddressBook, ) error { if chainState.AccessControllerProgram.IsZero() { return errors.New("access controller program is not deployed") @@ -121,7 +121,7 @@ func initAccessController( const accessControllerAccountSize = uint64(8 + 32 + 32 + ((32 * 64) + 8)) func initializeAccessController( - e deployment.Environment, chain deployment.SolChain, programID solana.PublicKey, roleAccount solana.PrivateKey, + e cldf.Environment, chain cldf.SolChain, programID solana.PublicKey, roleAccount solana.PrivateKey, ) error { rentExemption, err := chain.Client.GetMinimumBalanceForRentExemption(e.GetContext(), accessControllerAccountSize, rpc.CommitmentConfirmed) @@ -158,7 +158,7 @@ func initializeAccessController( return nil } -func setupRoles(chainState *state.MCMSWithTimelockStateSolana, chain deployment.SolChain) error { +func setupRoles(chainState *state.MCMSWithTimelockStateSolana, chain cldf.SolChain) error { proposerPDA := state.GetMCMSignerPDA(chainState.McmProgram, chainState.ProposerMcmSeed) cancellerPDA := state.GetMCMSignerPDA(chainState.McmProgram, chainState.CancellerMcmSeed) bypasserPDA := state.GetMCMSignerPDA(chainState.McmProgram, chainState.BypasserMcmSeed) @@ -187,7 +187,7 @@ func setupRoles(chainState *state.MCMSWithTimelockStateSolana, chain deployment. } func addAccess( - chain deployment.SolChain, chainState *state.MCMSWithTimelockStateSolana, + chain cldf.SolChain, chainState *state.MCMSWithTimelockStateSolana, role timelockBindings.Role, accounts ...solana.PublicKey, ) error { timelockConfigPDA := state.GetTimelockConfigPDA(chainState.TimelockProgram, chainState.TimelockSeed) diff --git a/deployment/common/changeset/solana/mcms/mcm.go b/deployment/common/changeset/solana/mcms/mcm.go index f4b618f7a7e..94438fd0d6b 100644 --- a/deployment/common/changeset/solana/mcms/mcm.go +++ b/deployment/common/changeset/solana/mcms/mcm.go @@ -24,8 +24,8 @@ import ( ) func deployMCMProgram( - env deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, - chain deployment.SolChain, addressBook cldf.AddressBook, + env cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, + chain cldf.SolChain, addressBook cldf.AddressBook, ) error { typeAndVersion := cldf.NewTypeAndVersion(commontypes.ManyChainMultisigProgram, deployment.Version1_0_0) log := logger.With(env.Logger, "chain", chain.String(), "contract", typeAndVersion.String()) @@ -65,8 +65,8 @@ func deployMCMProgram( } func initMCM( - env deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, contractType cldf.ContractType, - chain deployment.SolChain, addressBook cldf.AddressBook, mcmConfig *mcmsTypes.Config, + env cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, contractType cldf.ContractType, + chain cldf.SolChain, addressBook cldf.AddressBook, mcmConfig *mcmsTypes.Config, ) error { if chainState.McmProgram.IsZero() { return errors.New("mcm program is not deployed") @@ -124,7 +124,7 @@ func initMCM( return nil } -func initializeMCM(e deployment.Environment, chain deployment.SolChain, mcmProgram solana.PublicKey, multisigID state.PDASeed) error { +func initializeMCM(e cldf.Environment, chain cldf.SolChain, mcmProgram solana.PublicKey, multisigID state.PDASeed) error { var mcmConfig mcmBindings.MultisigConfig err := chain.GetAccountDataBorshInto(e.GetContext(), state.GetMCMConfigPDA(mcmProgram, multisigID), &mcmConfig) if err == nil { diff --git a/deployment/common/changeset/solana/mcms/mcms.go b/deployment/common/changeset/solana/mcms/mcms.go index bf8cb6cabcf..6a065607e05 100644 --- a/deployment/common/changeset/solana/mcms/mcms.go +++ b/deployment/common/changeset/solana/mcms/mcms.go @@ -6,7 +6,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -16,8 +15,8 @@ import ( // as well as the timelock program. It's not necessarily the only way to use // the timelock and MCMS, but its reasonable pattern. func DeployMCMSWithTimelockProgramsSolana( - e deployment.Environment, - chain deployment.SolChain, + e cldf.Environment, + chain cldf.SolChain, addressBook cldf.AddressBook, config commontypes.MCMSWithTimelockConfigV2, ) (*state.MCMSWithTimelockStateSolana, error) { diff --git a/deployment/common/changeset/solana/mcms/timelock.go b/deployment/common/changeset/solana/mcms/timelock.go index 1a048608c62..9182f073a03 100644 --- a/deployment/common/changeset/solana/mcms/timelock.go +++ b/deployment/common/changeset/solana/mcms/timelock.go @@ -20,7 +20,7 @@ import ( ) func deployTimelockProgram( - e deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, chain deployment.SolChain, + e cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, chain cldf.SolChain, addressBook cldf.AddressBook, ) error { typeAndVersion := cldf.NewTypeAndVersion(commontypes.RBACTimelockProgram, deployment.Version1_0_0) @@ -61,7 +61,7 @@ func deployTimelockProgram( } func initTimelock( - e deployment.Environment, chainState *state.MCMSWithTimelockStateSolana, chain deployment.SolChain, + e cldf.Environment, chainState *state.MCMSWithTimelockStateSolana, chain cldf.SolChain, addressBook cldf.AddressBook, minDelay *big.Int, ) error { if chainState.TimelockProgram.IsZero() { @@ -114,7 +114,7 @@ func initTimelock( } func initializeTimelock( - e deployment.Environment, chain deployment.SolChain, timelockProgram solana.PublicKey, timelockID state.PDASeed, + e cldf.Environment, chain cldf.SolChain, timelockProgram solana.PublicKey, timelockID state.PDASeed, chainState *state.MCMSWithTimelockStateSolana, minDelay *big.Int, ) error { if minDelay == nil { diff --git a/deployment/common/changeset/solana/transfer_ownership.go b/deployment/common/changeset/solana/transfer_ownership.go index 9d933fdc683..80e131c380d 100644 --- a/deployment/common/changeset/solana/transfer_ownership.go +++ b/deployment/common/changeset/solana/transfer_ownership.go @@ -17,7 +17,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -46,7 +45,7 @@ type OwnableContract struct { type TransferToTimelockSolana struct{} func (t *TransferToTimelockSolana) VerifyPreconditions( - env deployment.Environment, config TransferToTimelockSolanaConfig, + env cldf.Environment, config TransferToTimelockSolanaConfig, ) error { for chainSelector, contracts := range config.ContractsByChain { err := addressBookContains(env.ExistingAddresses, chainSelector, @@ -99,7 +98,7 @@ func (t *TransferToTimelockSolana) VerifyPreconditions( } func (t *TransferToTimelockSolana) Apply( - env deployment.Environment, cfg TransferToTimelockSolanaConfig, + env cldf.Environment, cfg TransferToTimelockSolanaConfig, ) (cldf.ChangesetOutput, error) { mcmsState, err := state.MaybeLoadMCMSWithTimelockStateSolana(env, slices.Collect(maps.Keys(env.SolChains))) if err != nil { @@ -190,7 +189,7 @@ type TransferMCMSToTimelockSolanaConfig struct { type TransferMCMSToTimelockSolana struct{} func (t TransferMCMSToTimelockSolana) VerifyPreconditions( - env deployment.Environment, config TransferMCMSToTimelockSolanaConfig, + env cldf.Environment, config TransferMCMSToTimelockSolanaConfig, ) error { for _, chainSelector := range config.Chains { err := addressBookContains(env.ExistingAddresses, chainSelector, @@ -207,7 +206,7 @@ func (t TransferMCMSToTimelockSolana) VerifyPreconditions( } func (t TransferMCMSToTimelockSolana) Apply( - env deployment.Environment, cfg TransferMCMSToTimelockSolanaConfig, + env cldf.Environment, cfg TransferMCMSToTimelockSolanaConfig, ) (cldf.ChangesetOutput, error) { mcmsState, err := state.MaybeLoadMCMSWithTimelockStateSolana(env, cfg.Chains) if err != nil { diff --git a/deployment/common/changeset/solana/transfer_ownership_test.go b/deployment/common/changeset/solana/transfer_ownership_test.go index 50d8b1b78bd..21a3e1dc49c 100644 --- a/deployment/common/changeset/solana/transfer_ownership_test.go +++ b/deployment/common/changeset/solana/transfer_ownership_test.go @@ -15,7 +15,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" solanachangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset/solana" solanaMCMS "github.com/smartcontractkit/chainlink/deployment/common/changeset/solana/mcms" @@ -58,7 +57,7 @@ func TestTransferToMCMSToTimelockSolana(t *testing.T) { assertOwner(t, env, solanaSelector, chainState, timelockSignerPDA) } -func deployMCMS(t *testing.T, env deployment.Environment, selector uint64) *state.MCMSWithTimelockStateSolana { +func deployMCMS(t *testing.T, env cldf.Environment, selector uint64) *state.MCMSWithTimelockStateSolana { t.Helper() solanaChain := env.SolChains[selector] @@ -79,7 +78,7 @@ func deployMCMS(t *testing.T, env deployment.Environment, selector uint64) *stat } func assertOwner( - t *testing.T, env deployment.Environment, selector uint64, chainState *state.MCMSWithTimelockStateSolana, owner solana.PublicKey, + t *testing.T, env cldf.Environment, selector uint64, chainState *state.MCMSWithTimelockStateSolana, owner solana.PublicKey, ) { assertMCMOwner(t, owner, state.GetMCMConfigPDA(chainState.McmProgram, chainState.ProposerMcmSeed), env, selector) assertMCMOwner(t, owner, state.GetMCMConfigPDA(chainState.McmProgram, chainState.CancellerMcmSeed), env, selector) @@ -92,7 +91,7 @@ func assertOwner( } func assertMCMOwner( - t *testing.T, want solana.PublicKey, configPDA solana.PublicKey, env deployment.Environment, selector uint64, + t *testing.T, want solana.PublicKey, configPDA solana.PublicKey, env cldf.Environment, selector uint64, ) { t.Helper() var config mcmBindings.MultisigConfig @@ -102,7 +101,7 @@ func assertMCMOwner( } func assertTimelockOwner( - t *testing.T, want solana.PublicKey, configPDA solana.PublicKey, env deployment.Environment, selector uint64, + t *testing.T, want solana.PublicKey, configPDA solana.PublicKey, env cldf.Environment, selector uint64, ) { t.Helper() var config timelockBindings.Config @@ -112,7 +111,7 @@ func assertTimelockOwner( } func assertAccessControllerOwner( - t *testing.T, want solana.PublicKey, account solana.PublicKey, env deployment.Environment, selector uint64, + t *testing.T, want solana.PublicKey, account solana.PublicKey, env cldf.Environment, selector uint64, ) { t.Helper() var config accessControllerBindings.AccessController @@ -122,7 +121,7 @@ func assertAccessControllerOwner( } func fundSignerPDAs( - t *testing.T, env deployment.Environment, chainSelector uint64, chainState *state.MCMSWithTimelockStateSolana, + t *testing.T, env cldf.Environment, chainSelector uint64, chainState *state.MCMSWithTimelockStateSolana, ) { t.Helper() solChain := env.SolChains[chainSelector] diff --git a/deployment/common/changeset/solana/update_delay_timelock.go b/deployment/common/changeset/solana/update_delay_timelock.go index 6039f0ffb07..4c471ab9231 100644 --- a/deployment/common/changeset/solana/update_delay_timelock.go +++ b/deployment/common/changeset/solana/update_delay_timelock.go @@ -10,7 +10,6 @@ import ( timelockBindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" ) @@ -22,7 +21,7 @@ type UpdateTimelockDelaySolanaCfg struct { } func (t UpdateTimelockDelaySolana) VerifyPreconditions( - env deployment.Environment, config UpdateTimelockDelaySolanaCfg, + env cldf.Environment, config UpdateTimelockDelaySolanaCfg, ) error { if len(config.DelayPerChain) == 0 { return errors.New("no delay configs provided") @@ -57,7 +56,7 @@ func (t UpdateTimelockDelaySolana) VerifyPreconditions( } func (t UpdateTimelockDelaySolana) Apply( - env deployment.Environment, cfg UpdateTimelockDelaySolanaCfg, + env cldf.Environment, cfg UpdateTimelockDelaySolanaCfg, ) (cldf.ChangesetOutput, error) { for chainSelector, delay := range cfg.DelayPerChain { solChain := env.SolChains[chainSelector] diff --git a/deployment/common/changeset/solana/update_delay_timelock_test.go b/deployment/common/changeset/solana/update_delay_timelock_test.go index c2f1fde0bdb..02f5f296365 100644 --- a/deployment/common/changeset/solana/update_delay_timelock_test.go +++ b/deployment/common/changeset/solana/update_delay_timelock_test.go @@ -9,6 +9,7 @@ import ( "go.uber.org/zap/zapcore" timelockBindings "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/timelock" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" chainselectors "github.com/smartcontractkit/chain-selectors" mcmsSolana "github.com/smartcontractkit/mcms/sdk/solana" @@ -28,7 +29,7 @@ import ( ) // setupUpdateDelayTestEnv deploys all required contracts for set \delay test -func setupUpdateDelayTestEnv(t *testing.T) deployment.Environment { +func setupUpdateDelayTestEnv(t *testing.T) cldf.Environment { lggr := logger.TestLogger(t) cfg := memory.MemoryEnvironmentConfig{ SolChains: 1, @@ -62,7 +63,7 @@ func TestUpdateTimelockDelaySolana_VerifyPreconditions(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) validEnv := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{SolChains: 1}) - validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + validEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} validSolChainSelector := validEnv.AllChainSelectorsSolana()[0] timelockID := mcmsSolana.ContractAddress( @@ -89,7 +90,7 @@ func TestUpdateTimelockDelaySolana_VerifyPreconditions(t *testing.T) { SolChains: 1, Nodes: 1, }) - noTimelockEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = deployment.SolChain{} + noTimelockEnv.SolChains[chainselectors.SOLANA_DEVNET.Selector] = cldf.SolChain{} //nolint:staticcheck // will wait till we can migrate from address book before using data store err = noTimelockEnv.ExistingAddresses.Save(chainselectors.SOLANA_DEVNET.Selector, mcmsProposerIDEmpty, cldf.TypeAndVersion{ @@ -104,11 +105,11 @@ func TestUpdateTimelockDelaySolana_VerifyPreconditions(t *testing.T) { SolChains: 0, Nodes: 1, }) - invalidSolChainEnv.SolChains[validSolChainSelector] = deployment.SolChain{} + invalidSolChainEnv.SolChains[validSolChainSelector] = cldf.SolChain{} tests := []struct { name string - env deployment.Environment + env cldf.Environment config commonSolana.UpdateTimelockDelaySolanaCfg expectedError string }{ @@ -174,6 +175,7 @@ func TestUpdateTimelockDelaySolana_VerifyPreconditions(t *testing.T) { } func TestUpdateTimelockDelaySolana_Apply(t *testing.T) { + tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-762") t.Parallel() env := setupUpdateDelayTestEnv(t) newDelayDuration := 5 * time.Minute diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go index f69cb26d642..94591a5e1f4 100644 --- a/deployment/common/changeset/state.go +++ b/deployment/common/changeset/state.go @@ -66,7 +66,7 @@ func (state MCMSWithTimelockState) GenerateMCMSWithTimelockView() (v1_0.MCMSWith // MaybeLoadMCMSWithTimelockState loads the MCMSWithTimelockState state for each chain in the given environment. // Deprecated: use MaybeLoadMCMSWithTimelockState from deployment/common/changeset/state/evm.go instead // if you are changing this, please make the similar changes in deployment/common/changeset/state -func MaybeLoadMCMSWithTimelockState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { +func MaybeLoadMCMSWithTimelockState(env cldf.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { result := map[uint64]*MCMSWithTimelockState{} for _, chainSelector := range chainSelectors { chain, ok := env.Chains[chainSelector] @@ -97,7 +97,7 @@ func MaybeLoadMCMSWithTimelockState(env deployment.Environment, chainSelectors [ // Deprecated: use MaybeLoadMCMSWithTimelockChainState from deployment/common/changeset/state/evm.go instead // if you are changing this, please make the similar changes in deployment/common/changeset/state func MaybeLoadMCMSWithTimelockChainState( - chain deployment.Chain, + chain cldf.Chain, addresses map[string]cldf.TypeAndVersion, ) (*MCMSWithTimelockState, error) { var ( @@ -203,7 +203,7 @@ func (s LinkTokenState) GenerateLinkView() (v1_0.LinkTokenView, error) { // MaybeLoadLinkTokenState loads the LinkTokenState state for each chain in the given environment. // Deprecated: use MaybeLoadLinkTokenState from deployment/common/changeset/state/evm.go instead // if you are changing this, please make the similar changes in deployment/common/changeset/state -func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*LinkTokenState, error) { +func MaybeLoadLinkTokenState(env cldf.Environment, chainSelectors []uint64) (map[uint64]*LinkTokenState, error) { result := map[uint64]*LinkTokenState{} for _, chainSelector := range chainSelectors { chain, ok := env.Chains[chainSelector] @@ -225,7 +225,7 @@ func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64 // Deprecated: use MaybeLoadLinkTokenChainState from deployment/common/changeset/state/evm.go instead // if you are changing this, please make the similar changes in deployment/common/changeset/state -func MaybeLoadLinkTokenChainState(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*LinkTokenState, error) { +func MaybeLoadLinkTokenChainState(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*LinkTokenState, error) { state := LinkTokenState{} linkToken := cldf.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) @@ -265,7 +265,7 @@ func (s StaticLinkTokenState) GenerateStaticLinkView() (v1_0.StaticLinkTokenView // Deprecated: use MaybeLoadStaticLinkTokenState from deployment/common/changeset/state/evm.go instead // if you are changing this, please make the similar changes in deployment/common/changeset/state -func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*StaticLinkTokenState, error) { +func MaybeLoadStaticLinkTokenState(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*StaticLinkTokenState, error) { state := StaticLinkTokenState{} staticLinkToken := cldf.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0) diff --git a/deployment/common/changeset/state/evm.go b/deployment/common/changeset/state/evm.go index 5045e5a3e10..1d46df86e7a 100644 --- a/deployment/common/changeset/state/evm.go +++ b/deployment/common/changeset/state/evm.go @@ -60,7 +60,7 @@ func (state MCMSWithTimelockState) GenerateMCMSWithTimelockView() (view.MCMSWith } // MaybeLoadMCMSWithTimelockState loads the MCMSWithTimelockState state for each chain in the given environment. -func MaybeLoadMCMSWithTimelockState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { +func MaybeLoadMCMSWithTimelockState(env cldf.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { result := map[uint64]*MCMSWithTimelockState{} for _, chainSelector := range chainSelectors { chain, ok := env.Chains[chainSelector] @@ -81,7 +81,7 @@ func MaybeLoadMCMSWithTimelockState(env deployment.Environment, chainSelectors [ } // MaybeLoadMCMSWithTimelockStateDataStore loads the MCMSWithTimelockState state for each chain in the given environment from the DataStore. -func MaybeLoadMCMSWithTimelockStateDataStore(env deployment.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { +func MaybeLoadMCMSWithTimelockStateDataStore(env cldf.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { result := map[uint64]*MCMSWithTimelockState{} for _, chainSelector := range chainSelectors { chain, ok := env.Chains[chainSelector] @@ -127,7 +127,7 @@ func loadAddressesFromDataStore(ds datastore.DataStore[datastore.DefaultMetadata // - Found but was unable to load a contract // - It only found part of the bundle of contracts // - If found more than one instance of a contract (we expect one bundle in the given addresses) -func MaybeLoadMCMSWithTimelockChainState(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockState, error) { +func MaybeLoadMCMSWithTimelockChainState(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockState, error) { state := MCMSWithTimelockState{} var ( // We expect one of each contract on the chain. @@ -224,7 +224,7 @@ func (s LinkTokenState) GenerateLinkView() (view.LinkTokenView, error) { } // MaybeLoadLinkTokenState loads the LinkTokenState state for each chain in the given environment. -func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*LinkTokenState, error) { +func MaybeLoadLinkTokenState(env cldf.Environment, chainSelectors []uint64) (map[uint64]*LinkTokenState, error) { result := map[uint64]*LinkTokenState{} for _, chainSelector := range chainSelectors { chain, ok := env.Chains[chainSelector] @@ -244,7 +244,7 @@ func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64 return result, nil } -func MaybeLoadLinkTokenChainState(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*LinkTokenState, error) { +func MaybeLoadLinkTokenChainState(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*LinkTokenState, error) { state := LinkTokenState{} linkToken := cldf.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) @@ -280,7 +280,7 @@ func (s StaticLinkTokenState) GenerateStaticLinkView() (view.StaticLinkTokenView return view.GenerateStaticLinkTokenView(s.StaticLinkToken) } -func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*StaticLinkTokenState, error) { +func MaybeLoadStaticLinkTokenState(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*StaticLinkTokenState, error) { state := StaticLinkTokenState{} staticLinkToken := cldf.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0) diff --git a/deployment/common/changeset/state/evm_test.go b/deployment/common/changeset/state/evm_test.go index 62e0b457be3..b2adbfe2788 100644 --- a/deployment/common/changeset/state/evm_test.go +++ b/deployment/common/changeset/state/evm_test.go @@ -14,7 +14,8 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -135,7 +136,7 @@ func toJSON[T any](t *testing.T, value T) string { } func deployMCMEvm( - t *testing.T, chain deployment.Chain, config *mcmstypes.Config, + t *testing.T, chain cldf.Chain, config *mcmstypes.Config, ) *bindings.ManyChainMultiSig { t.Helper() @@ -155,7 +156,7 @@ func deployMCMEvm( } func deployTimelockEvm( - t *testing.T, chain deployment.Chain, minDelay *big.Int, admin common.Address, + t *testing.T, chain cldf.Chain, minDelay *big.Int, admin common.Address, proposers, executors, cancellers, bypassers []common.Address, ) *bindings.RBACTimelock { t.Helper() @@ -169,7 +170,7 @@ func deployTimelockEvm( } func deployCallProxyEvm( - t *testing.T, chain deployment.Chain, target common.Address, + t *testing.T, chain cldf.Chain, target common.Address, ) *bindings.CallProxy { t.Helper() _, tx, contract, err := bindings.DeployCallProxy(chain.DeployerKey, chain.Client, target) diff --git a/deployment/common/changeset/state/solana.go b/deployment/common/changeset/state/solana.go index 67ea6ce5ed1..83ce51f59b4 100644 --- a/deployment/common/changeset/state/solana.go +++ b/deployment/common/changeset/state/solana.go @@ -142,7 +142,7 @@ func (s *MCMSWithTimelockProgramsSolana) RoleAccount(role timelockBindings.Role) } func (s *MCMSWithTimelockProgramsSolana) GenerateView( - ctx context.Context, chain deployment.SolChain, + ctx context.Context, chain cldf.SolChain, ) (view.MCMSWithTimelockViewSolana, error) { if err := s.Validate(); err != nil { return view.MCMSWithTimelockViewSolana{}, fmt.Errorf("unable to validate state: %w", err) @@ -164,7 +164,7 @@ type MCMSWithTimelockStateSolana struct { } // MaybeLoadMCMSWithTimelockState loads the MCMSWithTimelockState state for each chain in the given environment. -func MaybeLoadMCMSWithTimelockStateSolana(env deployment.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockStateSolana, error) { +func MaybeLoadMCMSWithTimelockStateSolana(env cldf.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockStateSolana, error) { result := map[uint64]*MCMSWithTimelockStateSolana{} for _, chainSelector := range chainSelectors { chain, ok := env.SolChains[chainSelector] @@ -196,7 +196,7 @@ func MaybeLoadMCMSWithTimelockStateSolana(env deployment.Environment, chainSelec // - Found but was unable to load a contract // - It only found part of the bundle of contracts // - If found more than one instance of a contract (we expect one bundle in the given addresses) -func MaybeLoadMCMSWithTimelockChainStateSolana(chain deployment.SolChain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockStateSolana, error) { +func MaybeLoadMCMSWithTimelockChainStateSolana(chain cldf.SolChain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockStateSolana, error) { state := MCMSWithTimelockStateSolana{MCMSWithTimelockProgramsSolana: &MCMSWithTimelockProgramsSolana{}} mcmProgram := cldf.NewTypeAndVersion(types.ManyChainMultisigProgram, deployment.Version1_0_0) diff --git a/deployment/common/changeset/state_test.go b/deployment/common/changeset/state_test.go index cd91fe265f9..f9274904c4b 100644 --- a/deployment/common/changeset/state_test.go +++ b/deployment/common/changeset/state_test.go @@ -20,13 +20,13 @@ import ( func TestMaybeLoadMCMSWithTimelockChainState(t *testing.T) { type testCase struct { name string - chain deployment.Chain + chain cldf.Chain addresses map[string]cldf.TypeAndVersion wantState *MCMSWithTimelockState // Expected state wantErr string } - defaultChain := deployment.Chain{ + defaultChain := cldf.Chain{ Selector: chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector, } tests := []testCase{ diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go index 8eefba90b9f..6b7a3a0bc61 100644 --- a/deployment/common/changeset/test_helpers.go +++ b/deployment/common/changeset/test_helpers.go @@ -28,7 +28,7 @@ import ( ) type ConfiguredChangeSet interface { - Apply(e deployment.Environment) (cldf.ChangesetOutput, error) + Apply(e cldf.Environment) (cldf.ChangesetOutput, error) } func Configure[C any]( @@ -46,7 +46,7 @@ type configuredChangeSetImpl[C any] struct { config C } -func (ca configuredChangeSetImpl[C]) Apply(e deployment.Environment) (cldf.ChangesetOutput, error) { +func (ca configuredChangeSetImpl[C]) Apply(e cldf.Environment) (cldf.ChangesetOutput, error) { err := ca.changeset.VerifyPreconditions(e, ca.config) if err != nil { return cldf.ChangesetOutput{}, err @@ -57,12 +57,12 @@ func (ca configuredChangeSetImpl[C]) Apply(e deployment.Environment) (cldf.Chang // Apply applies the changeset applications to the environment and returns the updated environment. This is the // variadic function equivalent of ApplyChangesets, but allowing you to simply pass in one or more changesets as // parameters at the end of the function. e.g. `changeset.Apply(t, e, nil, configuredCS1, configuredCS2)` etc. -func Apply(t *testing.T, e deployment.Environment, timelockContractsPerChain map[uint64]*proposalutils.TimelockExecutionContracts, first ConfiguredChangeSet, rest ...ConfiguredChangeSet) (deployment.Environment, error) { +func Apply(t *testing.T, e cldf.Environment, timelockContractsPerChain map[uint64]*proposalutils.TimelockExecutionContracts, first ConfiguredChangeSet, rest ...ConfiguredChangeSet) (cldf.Environment, error) { return ApplyChangesets(t, e, timelockContractsPerChain, append([]ConfiguredChangeSet{first}, rest...)) } // ApplyChangesets applies the changeset applications to the environment and returns the updated environment. -func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPerChain map[uint64]*proposalutils.TimelockExecutionContracts, changesetApplications []ConfiguredChangeSet) (deployment.Environment, error) { +func ApplyChangesets(t *testing.T, e cldf.Environment, timelockContractsPerChain map[uint64]*proposalutils.TimelockExecutionContracts, changesetApplications []ConfiguredChangeSet) (cldf.Environment, error) { currentEnv := e for i, csa := range changesetApplications { out, err := csa.Apply(currentEnv) @@ -116,7 +116,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe for _, sel := range chains.ToSlice() { timelockContracts, ok := timelockContractsPerChain[sel] if !ok || timelockContracts == nil { - return deployment.Environment{}, fmt.Errorf("timelock contracts not found for chain %d", sel) + return cldf.Environment{}, fmt.Errorf("timelock contracts not found for chain %d", sel) } err := proposalutils.ExecuteProposal(t, e, signed, timelockContracts, sel) //nolint:staticcheck //SA1019 ignoring deprecated function for compatibility; we don't have tools to generate the new field @@ -132,11 +132,11 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe // return the error so devs can ensure expected reversions err = proposalutils.ExecuteMCMSProposalV2(t, e, mcmProp) if err != nil { - return deployment.Environment{}, err + return cldf.Environment{}, err } err = proposalutils.ExecuteMCMSTimelockProposalV2(t, e, &prop) if err != nil { - return deployment.Environment{}, err + return cldf.Environment{}, err } } } @@ -146,11 +146,11 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe // return the error so devs can ensure expected reversions err = proposalutils.ExecuteMCMSProposalV2(t, e, p) if err != nil { - return deployment.Environment{}, err + return cldf.Environment{}, err } } } - currentEnv = deployment.Environment{ + currentEnv = cldf.Environment{ Name: e.Name, Logger: e.Logger, ExistingAddresses: addresses, @@ -169,7 +169,7 @@ func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPe } // ApplyChangesetsV2 applies the changeset applications to the environment and returns the updated environment. -func ApplyChangesetsV2(t *testing.T, e deployment.Environment, changesetApplications []ConfiguredChangeSet) (deployment.Environment, []cldf.ChangesetOutput, error) { +func ApplyChangesetsV2(t *testing.T, e cldf.Environment, changesetApplications []ConfiguredChangeSet) (cldf.Environment, []cldf.ChangesetOutput, error) { currentEnv := e outputs := make([]cldf.ChangesetOutput, 0, len(changesetApplications)) for i, csa := range changesetApplications { @@ -217,7 +217,7 @@ func ApplyChangesetsV2(t *testing.T, e deployment.Environment, changesetApplicat // Updated environment may be required before executing proposals when proposals involve new addresses // Ex. changesets[0] deploys MCMS, changesets[1] generates a proposal with the new MCMS addresses - currentEnv = deployment.Environment{ + currentEnv = cldf.Environment{ Name: e.Name, Logger: e.Logger, ExistingAddresses: addresses, @@ -242,7 +242,7 @@ func ApplyChangesetsV2(t *testing.T, e deployment.Environment, changesetApplicat p := proposalutils.SignMCMSTimelockProposal(t, currentEnv, &prop) err = proposalutils.ExecuteMCMSProposalV2(t, currentEnv, p) if err != nil { - return deployment.Environment{}, nil, err + return cldf.Environment{}, nil, err } if prop.Action != mcmsTypes.TimelockActionSchedule { // We don't need to execute the proposal if it's not a schedule action @@ -251,7 +251,7 @@ func ApplyChangesetsV2(t *testing.T, e deployment.Environment, changesetApplicat } err = proposalutils.ExecuteMCMSTimelockProposalV2(t, currentEnv, &prop) if err != nil { - return deployment.Environment{}, nil, err + return cldf.Environment{}, nil, err } } } @@ -265,7 +265,7 @@ func ApplyChangesetsV2(t *testing.T, e deployment.Environment, changesetApplicat p := proposalutils.SignMCMSProposal(t, currentEnv, &prop) err = proposalutils.ExecuteMCMSProposalV2(t, currentEnv, p) if err != nil { - return deployment.Environment{}, nil, err + return cldf.Environment{}, nil, err } } } @@ -313,7 +313,7 @@ func DeployLinkTokenTest(t *testing.T, solChains int) { } } -func SetPreloadedSolanaAddresses(t *testing.T, env deployment.Environment, selector uint64) { +func SetPreloadedSolanaAddresses(t *testing.T, env cldf.Environment, selector uint64) { typeAndVersion := cldf.NewTypeAndVersion(commontypes.ManyChainMultisigProgram, deployment.Version1_0_0) err := env.ExistingAddresses.Save(selector, memory.SolanaProgramIDs["mcm"], typeAndVersion) require.NoError(t, err) @@ -327,7 +327,7 @@ func SetPreloadedSolanaAddresses(t *testing.T, env deployment.Environment, selec require.NoError(t, err) } -func MustFundAddressWithLink(t *testing.T, e deployment.Environment, chain deployment.Chain, to common.Address, amount int64) { +func MustFundAddressWithLink(t *testing.T, e cldf.Environment, chain cldf.Chain, to common.Address, amount int64) { addresses, err := e.ExistingAddresses.AddressesForChain(chain.Selector) require.NoError(t, err) @@ -339,13 +339,13 @@ func MustFundAddressWithLink(t *testing.T, e deployment.Environment, chain deplo e.Logger.Info("granting minter permissions for chain", chain.DeployerKey) tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // Mint 'To' address some tokens tx, err = linkState.LinkToken.Mint(chain.DeployerKey, to, big.NewInt(amount)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // 'To' address should have the tokens @@ -357,7 +357,7 @@ func MustFundAddressWithLink(t *testing.T, e deployment.Environment, chain deplo } // MaybeGetLinkBalance returns the LINK balance of the given address on the given chain. -func MaybeGetLinkBalance(t *testing.T, e deployment.Environment, chain deployment.Chain, linkAddr common.Address) *big.Int { +func MaybeGetLinkBalance(t *testing.T, e cldf.Environment, chain cldf.Chain, linkAddr common.Address) *big.Int { addresses, err := e.ExistingAddresses.AddressesForChain(chain.Selector) require.NoError(t, err) linkState, err := commonState.MaybeLoadLinkTokenChainState(chain, addresses) diff --git a/deployment/common/changeset/test_helpers_test.go b/deployment/common/changeset/test_helpers_test.go index f537981c181..b2651d1718e 100644 --- a/deployment/common/changeset/test_helpers_test.go +++ b/deployment/common/changeset/test_helpers_test.go @@ -12,8 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -25,11 +23,11 @@ func TestChangeSetLegacyFunction_PassingCase(t *testing.T) { executedValidator := false csv2 := cldf.CreateChangeSet( - func(e deployment.Environment, config uint32) (cldf.ChangesetOutput, error) { + func(e cldf.Environment, config uint32) (cldf.ChangesetOutput, error) { executedCs = true return cldf.ChangesetOutput{AddressBook: cldf.NewMemoryAddressBook()}, nil }, - func(e deployment.Environment, config uint32) error { + func(e cldf.Environment, config uint32) error { executedValidator = true return nil }, @@ -50,11 +48,11 @@ func TestChangeSetLegacyFunction_ErrorCase(t *testing.T) { executedValidator := false csv2 := cldf.CreateChangeSet( - func(e deployment.Environment, config uint32) (cldf.ChangesetOutput, error) { + func(e cldf.Environment, config uint32) (cldf.ChangesetOutput, error) { executedCs = true return cldf.ChangesetOutput{AddressBook: cldf.NewMemoryAddressBook()}, nil }, - func(e deployment.Environment, config uint32) error { + func(e cldf.Environment, config uint32) error { executedValidator = true return errors.New("you shall not pass") }, @@ -67,8 +65,8 @@ func TestChangeSetLegacyFunction_ErrorCase(t *testing.T) { require.Equal(t, "failed to apply changeset at index 0: you shall not pass", err.Error()) } -func NewNoopEnvironment(t *testing.T) deployment.Environment { - return *deployment.NewEnvironment( +func NewNoopEnvironment(t *testing.T) cldf.Environment { + return *cldf.NewEnvironment( "noop", logger.TestLogger(t), cldf.NewMemoryAddressBook(), @@ -76,9 +74,9 @@ func NewNoopEnvironment(t *testing.T) deployment.Environment { datastore.DefaultMetadata, datastore.DefaultMetadata, ]().Seal(), - map[uint64]deployment.Chain{}, - map[uint64]deployment.SolChain{}, - map[uint64]deployment.AptosChain{}, + map[uint64]cldf.Chain{}, + map[uint64]cldf.SolChain{}, + map[uint64]cldf.AptosChain{}, []string{}, nil, func() context.Context { return tests.Context(t) }, @@ -91,7 +89,7 @@ func TestApplyChangesetsHelpers(t *testing.T) { changesets := []ConfiguredChangeSet{ Configure(cldf.CreateChangeSet( - func(e deployment.Environment, config uint32) (cldf.ChangesetOutput, error) { + func(e cldf.Environment, config uint32) (cldf.ChangesetOutput, error) { ds := datastore.NewMemoryDataStore[ datastore.DefaultMetadata, datastore.DefaultMetadata, @@ -125,7 +123,7 @@ func TestApplyChangesetsHelpers(t *testing.T) { DataStore: ds, }, nil }, - func(e deployment.Environment, config uint32) error { + func(e cldf.Environment, config uint32) error { return nil }, ), 1), @@ -134,7 +132,7 @@ func TestApplyChangesetsHelpers(t *testing.T) { csTests := []struct { name string changesets []ConfiguredChangeSet - validate func(t *testing.T, e deployment.Environment) + validate func(t *testing.T, e cldf.Environment) wantError bool changesetApplyFunction string }{ @@ -142,7 +140,7 @@ func TestApplyChangesetsHelpers(t *testing.T) { name: "ApplyChangesets validates datastore is merged after apply", changesets: changesets, changesetApplyFunction: "V2", - validate: func(t *testing.T, e deployment.Environment) { + validate: func(t *testing.T, e cldf.Environment) { // Check address was stored correctly record, err := e.DataStore.Addresses().Get( datastore.NewAddressRefKey( @@ -168,7 +166,7 @@ func TestApplyChangesetsHelpers(t *testing.T) { name: "ApplyChangesetsV2 validates datastore is merged after apply", changesets: changesets, changesetApplyFunction: "V1", - validate: func(t *testing.T, e deployment.Environment) { + validate: func(t *testing.T, e cldf.Environment) { // Check address was stored correctly record, err := e.DataStore.Addresses().Get( datastore.NewAddressRefKey( diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock.go b/deployment/common/changeset/transfer_to_mcms_with_timelock.go index 4981039420a..fb90d1d0fa6 100644 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock.go +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock.go @@ -22,7 +22,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -53,7 +52,7 @@ func LoadOwnableContract(addr common.Address, client bind.ContractBackend) (comm return owner, c, nil } -func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) error { +func (t TransferToMCMSWithTimelockConfig) Validate(e cldf.Environment) error { for chainSelector, contracts := range t.ContractsByChain { for _, contract := range contracts { // Cannot transfer an unknown address. @@ -94,7 +93,7 @@ var _ cldf.ChangeSet[TransferToMCMSWithTimelockConfig] = TransferToMCMSWithTimel // are currently owned by the deployer key. // Deprecated: Use TransferToMCMSWithTimelockV2 instead. func TransferToMCMSWithTimelock( - e deployment.Environment, + e cldf.Environment, cfg TransferToMCMSWithTimelockConfig, ) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { @@ -125,11 +124,11 @@ func TransferToMCMSWithTimelock( continue } tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) - _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[chainSelector], tx, err) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %w", contract, err) } - tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) + tx, err = c.AcceptOwnership(cldf.SimTransactOpts()) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %s: %w", contract, err) } @@ -157,7 +156,7 @@ var _ cldf.ChangeSet[TransferToMCMSWithTimelockConfig] = TransferToMCMSWithTimel // TransferToMCMSWithTimelockV2 is a reimplementation of TransferToMCMSWithTimelock which uses the new MCMS library. func TransferToMCMSWithTimelockV2( - e deployment.Environment, + e cldf.Environment, cfg TransferToMCMSWithTimelockConfig, ) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { @@ -186,11 +185,11 @@ func TransferToMCMSWithTimelockV2( continue } tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) - _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[chainSelector], tx, err) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %w", contract, err) } - tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) + tx, err = c.AcceptOwnership(cldf.SimTransactOpts()) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %s: %w", contract, err) } @@ -227,7 +226,7 @@ type TransferToDeployerConfig struct { // still being a timelock admin and transfers the ownership of a contract // back to the deployer key. It's effectively the rollback function of transferring // to the timelock. -func TransferToDeployer(e deployment.Environment, cfg TransferToDeployerConfig) (cldf.ChangesetOutput, error) { +func TransferToDeployer(e cldf.Environment, cfg TransferToDeployerConfig) (cldf.ChangesetOutput, error) { owner, ownable, err := LoadOwnableContract(cfg.ContractAddress, e.Chains[cfg.ChainSel].Client) if err != nil { return cldf.ChangesetOutput{}, err @@ -236,7 +235,7 @@ func TransferToDeployer(e deployment.Environment, cfg TransferToDeployerConfig) e.Logger.Infof("Contract %s already owned by deployer", cfg.ContractAddress) return cldf.ChangesetOutput{}, nil } - tx, err := ownable.TransferOwnership(deployment.SimTransactOpts(), e.Chains[cfg.ChainSel].DeployerKey.From) + tx, err := ownable.TransferOwnership(cldf.SimTransactOpts(), e.Chains[cfg.ChainSel].DeployerKey.From) if err != nil { return cldf.ChangesetOutput{}, err } @@ -258,7 +257,7 @@ func TransferToDeployer(e deployment.Environment, cfg TransferToDeployerConfig) var salt [32]byte binary.BigEndian.PutUint32(salt[:], uint32(time.Now().Unix())) tx, err = tls.Timelock.ScheduleBatch(e.Chains[cfg.ChainSel].DeployerKey, calls, [32]byte{}, salt, big.NewInt(0)) - if _, err = deployment.ConfirmIfNoErrorWithABI(e.Chains[cfg.ChainSel], tx, owner_helpers.RBACTimelockABI, err); err != nil { + if _, err = cldf.ConfirmIfNoErrorWithABI(e.Chains[cfg.ChainSel], tx, owner_helpers.RBACTimelockABI, err); err != nil { return cldf.ChangesetOutput{}, err } e.Logger.Infof("scheduled transfer ownership batch with tx %s", tx.Hash().Hex()) @@ -272,14 +271,14 @@ func TransferToDeployer(e deployment.Environment, cfg TransferToDeployerConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("error executing batch: %w", err) } - if _, err = deployment.ConfirmIfNoErrorWithABI(e.Chains[cfg.ChainSel], tx, owner_helpers.RBACTimelockABI, err); err != nil { + if _, err = cldf.ConfirmIfNoErrorWithABI(e.Chains[cfg.ChainSel], tx, owner_helpers.RBACTimelockABI, err); err != nil { return cldf.ChangesetOutput{}, err } e.Logger.Infof("executed transfer ownership to deployer key with tx %s", tx.Hash().Hex()) tx, err = ownable.AcceptOwnership(e.Chains[cfg.ChainSel].DeployerKey) - if _, err = deployment.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { + if _, err = cldf.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { return cldf.ChangesetOutput{}, err } e.Logger.Infof("deployer key accepted ownership tx %s", tx.Hash().Hex()) @@ -292,8 +291,8 @@ type RenounceTimelockDeployerConfig struct { ChainSel uint64 } -func (cfg RenounceTimelockDeployerConfig) Validate(e deployment.Environment) error { - if err := deployment.IsValidChainSelector(cfg.ChainSel); err != nil { +func (cfg RenounceTimelockDeployerConfig) Validate(e cldf.Environment) error { + if err := cldf.IsValidChainSelector(cfg.ChainSel); err != nil { return fmt.Errorf("invalid chain selector: %w", err) } @@ -320,7 +319,7 @@ func (cfg RenounceTimelockDeployerConfig) Validate(e deployment.Environment) err } // RenounceTimelockDeployer revokes the deployer key from administering the contract. -func RenounceTimelockDeployer(e deployment.Environment, cfg RenounceTimelockDeployerConfig) (cldf.ChangesetOutput, error) { +func RenounceTimelockDeployer(e cldf.Environment, cfg RenounceTimelockDeployerConfig) (cldf.ChangesetOutput, error) { if err := cfg.Validate(e); err != nil { return cldf.ChangesetOutput{}, err } @@ -340,7 +339,7 @@ func RenounceTimelockDeployer(e deployment.Environment, cfg RenounceTimelockDepl if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to revoke deployer key: %w", err) } - if _, err := deployment.ConfirmIfNoErrorWithABI(chain, tx, owner_helpers.RBACTimelockABI, err); err != nil { + if _, err := cldf.ConfirmIfNoErrorWithABI(chain, tx, owner_helpers.RBACTimelockABI, err); err != nil { return cldf.ChangesetOutput{}, err } e.Logger.Infof("revoked deployer key from owning contract %s", tl.Address().Hex()) diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go index 573bccdd9ce..0674a8c4f5b 100644 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go +++ b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go @@ -9,8 +9,10 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -150,6 +152,7 @@ func TestTransferToMCMSWithTimelockV2(t *testing.T) { } func TestRenounceTimelockDeployerConfigValidate(t *testing.T) { + tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/DX-724") t.Parallel() lggr := logger.TestLogger(t) e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ @@ -176,7 +179,7 @@ func TestRenounceTimelockDeployerConfigValidate(t *testing.T) { for _, test := range []struct { name string config RenounceTimelockDeployerConfig - env deployment.Environment + env cldf.Environment err string }{ { diff --git a/deployment/common/proposalutils/mcms_helpers.go b/deployment/common/proposalutils/mcms_helpers.go index 2683ee6bdb1..6261111747f 100644 --- a/deployment/common/proposalutils/mcms_helpers.go +++ b/deployment/common/proposalutils/mcms_helpers.go @@ -37,7 +37,7 @@ type TimelockExecutionContracts struct { // NewTimelockExecutionContracts creates a new TimelockExecutionContracts struct. // If there are multiple timelocks or call proxy on the chain, an error is returned. // Used by CLD'S cli -func NewTimelockExecutionContracts(env deployment.Environment, chainSelector uint64) (*TimelockExecutionContracts, error) { +func NewTimelockExecutionContracts(env cldf.Environment, chainSelector uint64) (*TimelockExecutionContracts, error) { addrTypeVer, err := env.ExistingAddresses.AddressesForChain(chainSelector) if err != nil { return nil, fmt.Errorf("error getting addresses for chain: %w", err) @@ -115,7 +115,7 @@ func (cfg RunTimelockExecutorConfig) Validate() error { // If the block start is not provided, it assumes that the operations have not been scheduled yet // and executes all the operations for the given chain. // It is an error if there are no operations for the given chain. -func RunTimelockExecutor(env deployment.Environment, cfg RunTimelockExecutorConfig) error { +func RunTimelockExecutor(env cldf.Environment, cfg RunTimelockExecutorConfig) error { // TODO: This sort of helper probably should move to the MCMS lib. // Execute all the transactions in the proposal which are for this chain. if err := cfg.Validate(); err != nil { @@ -231,7 +231,7 @@ func (state MCMSWithTimelockContracts) Validate() error { // - Found but was unable to load a contract // - It only found part of the bundle of contracts // - If found more than one instance of a contract (we expect one bundle in the given addresses) -func MaybeLoadMCMSWithTimelockContracts(chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockContracts, error) { +func MaybeLoadMCMSWithTimelockContracts(chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*MCMSWithTimelockContracts, error) { state := MCMSWithTimelockContracts{} // We expect one of each contract on the chain. timelock := cldf.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) @@ -300,7 +300,7 @@ func McmsTimelockConverterForChain(chain uint64) (mcmssdk.TimelockConverter, err } } -func McmsTimelockConverters(env deployment.Environment) (map[uint64]mcmssdk.TimelockConverter, error) { +func McmsTimelockConverters(env cldf.Environment) (map[uint64]mcmssdk.TimelockConverter, error) { converters := make(map[uint64]mcmssdk.TimelockConverter, len(env.Chains)+len(env.SolChains)) for _, chain := range env.Chains { @@ -322,7 +322,7 @@ func McmsTimelockConverters(env deployment.Environment) (map[uint64]mcmssdk.Time return converters, nil } -func McmsInspectorForChain(env deployment.Environment, chain uint64) (mcmssdk.Inspector, error) { +func McmsInspectorForChain(env cldf.Environment, chain uint64) (mcmssdk.Inspector, error) { chainFamily, err := mcmstypes.GetChainSelectorFamily(mcmstypes.ChainSelector(chain)) if err != nil { return nil, fmt.Errorf("failed to get chain family for chain %d: %w", chain, err) @@ -338,7 +338,7 @@ func McmsInspectorForChain(env deployment.Environment, chain uint64) (mcmssdk.In } } -func McmsInspectors(env deployment.Environment) (map[uint64]mcmssdk.Inspector, error) { +func McmsInspectors(env cldf.Environment) (map[uint64]mcmssdk.Inspector, error) { inspectors := make(map[uint64]mcmssdk.Inspector, len(env.Chains)+len(env.SolChains)) for _, chain := range env.Chains { diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go index 2a1658e56ce..33a94cab98a 100644 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ b/deployment/common/proposalutils/mcms_test_helpers.go @@ -27,6 +27,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -64,7 +66,7 @@ func SingleGroupMCMSV2(t *testing.T) mcmstypes.Config { } // Deprecated: Use SignMCMSTimelockProposal instead. -func SignProposal(t *testing.T, env deployment.Environment, proposal *timelock.MCMSWithTimelockProposal) *mcms.Executor { +func SignProposal(t *testing.T, env cldf.Environment, proposal *timelock.MCMSWithTimelockProposal) *mcms.Executor { executorClients := make(map[mcms.ChainIdentifier]mcms.ContractDeployBackend) for _, chain := range env.Chains { chainselc, exists := chainsel.ChainBySelector(chain.Selector) @@ -87,13 +89,13 @@ func SignProposal(t *testing.T, env deployment.Environment, proposal *timelock.M } // Deprecated: Use ExecuteMCMSTimelockProposalV2 instead. -func ExecuteProposal(t *testing.T, env deployment.Environment, executor *mcms.Executor, +func ExecuteProposal(t *testing.T, env cldf.Environment, executor *mcms.Executor, timelockContracts *TimelockExecutionContracts, sel uint64) error { t.Log("Executing proposal on chain", sel) // Set the root. tx, err2 := executor.SetRootOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, mcms.ChainIdentifier(sel)) if err2 != nil { - require.NoError(t, deployment.MaybeDataErr(err2), "failed to set root") + require.NoError(t, cldf.MaybeDataErr(err2), "failed to set root") } _, err2 = env.Chains[sel].Confirm(tx) @@ -108,7 +110,7 @@ func ExecuteProposal(t *testing.T, env deployment.Environment, executor *mcms.Ex } // SignMCMSTimelockProposal - Signs an MCMS timelock proposal. -func SignMCMSTimelockProposal(t *testing.T, env deployment.Environment, proposal *mcmslib.TimelockProposal) *mcmslib.Proposal { +func SignMCMSTimelockProposal(t *testing.T, env cldf.Environment, proposal *mcmslib.TimelockProposal) *mcmslib.Proposal { converters := make(map[mcmstypes.ChainSelector]mcmssdk.TimelockConverter) inspectorsMap := make(map[mcmstypes.ChainSelector]mcmssdk.Inspector) for _, chain := range env.Chains { @@ -161,7 +163,7 @@ func SignMCMSTimelockProposal(t *testing.T, env deployment.Environment, proposal } // SignMCMSProposal - Signs an MCMS proposal. For timelock proposal, use SignMCMSTimelockProposal instead. -func SignMCMSProposal(t *testing.T, env deployment.Environment, proposal *mcmslib.Proposal) *mcmslib.Proposal { +func SignMCMSProposal(t *testing.T, env cldf.Environment, proposal *mcmslib.Proposal) *mcmslib.Proposal { converters := make(map[mcmstypes.ChainSelector]mcmssdk.TimelockConverter) inspectorsMap := make(map[mcmstypes.ChainSelector]mcmssdk.Inspector) for _, chain := range env.Chains { @@ -200,7 +202,7 @@ func SignMCMSProposal(t *testing.T, env deployment.Environment, proposal *mcmsli } // ExecuteMCMSProposalV2 - Executes an MCMS proposal on a chain. For timelock proposal, use ExecuteMCMSTimelockProposalV2 instead. -func ExecuteMCMSProposalV2(t *testing.T, env deployment.Environment, proposal *mcmslib.Proposal) error { +func ExecuteMCMSProposalV2(t *testing.T, env cldf.Environment, proposal *mcmslib.Proposal) error { t.Log("Executing proposal") encoders, err := proposal.GetEncoders() @@ -317,7 +319,7 @@ func ExecuteMCMSProposalV2(t *testing.T, env deployment.Environment, proposal *m // ExecuteMCMSTimelockProposalV2 - Includes an option to set callProxy to execute the calls through a proxy. // If the callProxy is not set, the calls will be executed directly to the timelock. -func ExecuteMCMSTimelockProposalV2(t *testing.T, env deployment.Environment, timelockProposal *mcmslib.TimelockProposal, opts ...mcmslib.Option) error { +func ExecuteMCMSTimelockProposalV2(t *testing.T, env cldf.Environment, timelockProposal *mcmslib.TimelockProposal, opts ...mcmslib.Option) error { t.Log("Executing timelock proposal") // build a "chainSelector => executor" map @@ -421,7 +423,7 @@ func SingleGroupTimelockConfigV2(t *testing.T) commontypes.MCMSWithTimelockConfi } } -func findCallProxyAddress(t *testing.T, env deployment.Environment, chainSelector uint64) string { +func findCallProxyAddress(t *testing.T, env cldf.Environment, chainSelector uint64) string { addressesForChain, err := env.ExistingAddresses.AddressesForChain(chainSelector) require.NoError(t, err) diff --git a/deployment/common/proposalutils/propose.go b/deployment/common/proposalutils/propose.go index 3e09731dbe4..f72a43b0763 100644 --- a/deployment/common/proposalutils/propose.go +++ b/deployment/common/proposalutils/propose.go @@ -3,7 +3,6 @@ package proposalutils import ( "errors" "fmt" - "math/big" "time" mapset "github.com/deckarep/golang-set/v2" @@ -20,7 +19,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" ccipTypes "github.com/smartcontractkit/chainlink/deployment/common/types" ) @@ -94,7 +92,7 @@ func (tc *TimelockConfig) validateCommon() error { return nil } -func (tc *TimelockConfig) Validate(chain deployment.Chain, s state.MCMSWithTimelockState) error { +func (tc *TimelockConfig) Validate(chain cldf.Chain, s state.MCMSWithTimelockState) error { err := tc.validateCommon() if err != nil { return err @@ -120,7 +118,7 @@ func (tc *TimelockConfig) Validate(chain deployment.Chain, s state.MCMSWithTimel return nil } -func (tc *TimelockConfig) ValidateSolana(e deployment.Environment, chainSelector uint64) error { +func (tc *TimelockConfig) ValidateSolana(e cldf.Environment, chainSelector uint64) error { err := tc.validateCommon() if err != nil { return err @@ -241,7 +239,7 @@ func BuildProposalFromBatches( // BuildProposalFromBatchesV2 uses the new MCMS library which replaces the implementation in BuildProposalFromBatches. func BuildProposalFromBatchesV2( - e deployment.Environment, + e cldf.Environment, timelockAddressPerChain map[uint64]string, mcmsAddressPerChain map[uint64]string, inspectorPerChain map[uint64]mcmssdk.Inspector, batches []types.BatchOperation, @@ -293,7 +291,7 @@ func BuildProposalFromBatchesV2( } func buildProposalMetadataV2( - env deployment.Environment, + env cldf.Environment, chainSelectors []uint64, inspectorPerChain map[uint64]mcmssdk.Inspector, mcmsPerChain map[uint64]string, // can be proposer, canceller or bypasser @@ -358,14 +356,14 @@ func buildProposalMetadataV2( return metaDataPerChain, nil } -// AggregateProposals aggregates proposals from the legacy and new formats into a single proposal. -// Required if you are merging multiple changesets that have different proposal formats. +// AggregateProposals aggregates multiple MCMS proposals into a single proposal by combining their operations, and +// setting up the proposers and inspectors for each chain. It returns a single MCMS proposal that can be executed +// and signed. func AggregateProposals( - env deployment.Environment, + env cldf.Environment, mcmsEVMState map[uint64]state.MCMSWithTimelockState, mcmsSolanaState map[uint64]state.MCMSWithTimelockStateSolana, proposals []mcmslib.TimelockProposal, - legacyProposals []timelock.MCMSWithTimelockProposal, description string, mcmsConfig *TimelockConfig, ) (*mcmslib.TimelockProposal, error) { @@ -374,26 +372,8 @@ func AggregateProposals( } var batches []types.BatchOperation - // Add proposals that follow the legacy format to the aggregate. - for _, proposal := range legacyProposals { - for _, batchTransaction := range proposal.Transactions { - for _, transaction := range batchTransaction.Batch { - batchOperation, err := BatchOperationForChain( - uint64(batchTransaction.ChainIdentifier), - transaction.To.Hex(), - transaction.Data, - big.NewInt(0), - transaction.ContractType, - transaction.Tags, - ) - if err != nil { - return &mcmslib.TimelockProposal{}, fmt.Errorf("failed to create batch operation on chain with selector %d: %w", batchTransaction.ChainIdentifier, err) - } - batches = append(batches, batchOperation) - } - } - } - // Add proposals that follow the new format to the aggregate. + + // Add proposals to the aggregate. for _, proposal := range proposals { batches = append(batches, proposal.Operations...) } diff --git a/deployment/data-feeds/changeset/accept_ownership.go b/deployment/data-feeds/changeset/accept_ownership.go index a84f2bc6188..648edd5ab5e 100644 --- a/deployment/data-feeds/changeset/accept_ownership.go +++ b/deployment/data-feeds/changeset/accept_ownership.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonChangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -17,7 +17,7 @@ import ( // Once proposal is executed, new owned contracts can be imported into the addressbook. var AcceptOwnershipChangeset = cldf.CreateChangeSet(acceptOwnershipLogic, acceptOwnershipPrecondition) -func acceptOwnershipLogic(env deployment.Environment, c types.AcceptOwnershipConfig) (cldf.ChangesetOutput, error) { +func acceptOwnershipLogic(env cldf.Environment, c types.AcceptOwnershipConfig) (cldf.ChangesetOutput, error) { chain := env.Chains[c.ChainSelector] var mcmsProposals []ProposalData @@ -27,7 +27,7 @@ func acceptOwnershipLogic(env deployment.Environment, c types.AcceptOwnershipCon return cldf.ChangesetOutput{}, fmt.Errorf("failed to load the contract %w", err) } - tx, err := contract.AcceptOwnership(deployment.SimTransactOpts()) + tx, err := contract.AcceptOwnership(cldf.SimTransactOpts()) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create accept transfer ownership tx %w", err) } @@ -46,7 +46,7 @@ func acceptOwnershipLogic(env deployment.Environment, c types.AcceptOwnershipCon return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } -func acceptOwnershipPrecondition(env deployment.Environment, c types.AcceptOwnershipConfig) error { +func acceptOwnershipPrecondition(env cldf.Environment, c types.AcceptOwnershipConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/confirm_aggregator.go b/deployment/data-feeds/changeset/confirm_aggregator.go index 4c5cc294f22..9c6658305b6 100644 --- a/deployment/data-feeds/changeset/confirm_aggregator.go +++ b/deployment/data-feeds/changeset/confirm_aggregator.go @@ -8,7 +8,7 @@ import ( proxy "github.com/smartcontractkit/chainlink-evm/gethwrappers/data-feeds/generated/aggregator_proxy" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -16,7 +16,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var ConfirmAggregatorChangeset = cldf.CreateChangeSet(confirmAggregatorLogic, confirmAggregatorPrecondition) -func confirmAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAggregatorConfig) (cldf.ChangesetOutput, error) { +func confirmAggregatorLogic(env cldf.Environment, c types.ProposeConfirmAggregatorConfig) (cldf.ChangesetOutput, error) { chain := env.Chains[c.ChainSelector] aggregatorProxy, err := proxy.NewAggregatorProxy(c.ProxyAddress, chain.Client) @@ -26,7 +26,7 @@ func confirmAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAg txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } tx, err := aggregatorProxy.ConfirmAggregator(txOpt, c.NewAggregatorAddress) @@ -48,14 +48,14 @@ func confirmAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAg return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func confirmAggregatorPrecondition(env deployment.Environment, c types.ProposeConfirmAggregatorConfig) error { +func confirmAggregatorPrecondition(env cldf.Environment, c types.ProposeConfirmAggregatorConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/deploy.go b/deployment/data-feeds/changeset/deploy.go index e01e3a78206..e104344b78c 100644 --- a/deployment/data-feeds/changeset/deploy.go +++ b/deployment/data-feeds/changeset/deploy.go @@ -12,11 +12,10 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) -func DeployCache(chain deployment.Chain, labels []string) (*types.DeployCacheResponse, error) { +func DeployCache(chain cldf.Chain, labels []string) (*types.DeployCacheResponse, error) { cacheAddr, tx, cacheContract, err := cache.DeployDataFeedsCache(chain.DeployerKey, chain.Client) if err != nil { return nil, fmt.Errorf("failed to deploy DataFeedsCache: %w", err) @@ -50,7 +49,7 @@ func DeployCache(chain deployment.Chain, labels []string) (*types.DeployCacheRes return resp, nil } -func DeployAggregatorProxy(chain deployment.Chain, aggregator common.Address, accessController common.Address, labels []string) (*types.DeployProxyResponse, error) { +func DeployAggregatorProxy(chain cldf.Chain, aggregator common.Address, accessController common.Address, labels []string) (*types.DeployProxyResponse, error) { proxyAddr, tx, proxyContract, err := proxy.DeployAggregatorProxy(chain.DeployerKey, chain.Client, aggregator, accessController) if err != nil { return nil, fmt.Errorf("failed to deploy AggregatorProxy: %w", err) @@ -81,7 +80,7 @@ func DeployAggregatorProxy(chain deployment.Chain, aggregator common.Address, ac return resp, nil } -func DeployBundleAggregatorProxy(chain deployment.Chain, aggregator common.Address, owner common.Address, labels []string) (*types.DeployBundleAggregatorProxyResponse, error) { +func DeployBundleAggregatorProxy(chain cldf.Chain, aggregator common.Address, owner common.Address, labels []string) (*types.DeployBundleAggregatorProxyResponse, error) { proxyAddr, tx, proxyContract, err := bundleproxy.DeployBundleAggregatorProxy(chain.DeployerKey, chain.Client, aggregator, owner) if err != nil { return nil, fmt.Errorf("failed to deploy BundleAggregatorProxy: %w", err) diff --git a/deployment/data-feeds/changeset/deploy_aggregator_proxy.go b/deployment/data-feeds/changeset/deploy_aggregator_proxy.go index fbf8a5a511f..70508007cf5 100644 --- a/deployment/data-feeds/changeset/deploy_aggregator_proxy.go +++ b/deployment/data-feeds/changeset/deploy_aggregator_proxy.go @@ -8,8 +8,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -17,7 +15,7 @@ import ( // from addressbook to set it in the AggregatorProxy constructor. Returns a new addressbook with deploy AggregatorProxy contract addresses. var DeployAggregatorProxyChangeset = cldf.CreateChangeSet(deployAggregatorProxyLogic, deployAggregatorProxyPrecondition) -func deployAggregatorProxyLogic(env deployment.Environment, c types.DeployAggregatorProxyConfig) (cldf.ChangesetOutput, error) { +func deployAggregatorProxyLogic(env cldf.Environment, c types.DeployAggregatorProxyConfig) (cldf.ChangesetOutput, error) { lggr := env.Logger ab := cldf.NewMemoryAddressBook() @@ -44,7 +42,7 @@ func deployAggregatorProxyLogic(env deployment.Environment, c types.DeployAggreg return cldf.ChangesetOutput{AddressBook: ab}, nil } -func deployAggregatorProxyPrecondition(env deployment.Environment, c types.DeployAggregatorProxyConfig) error { +func deployAggregatorProxyPrecondition(env cldf.Environment, c types.DeployAggregatorProxyConfig) error { if len(c.AccessController) != len(c.ChainsToDeploy) { return errors.New("AccessController addresses must be provided for each chain to deploy") } diff --git a/deployment/data-feeds/changeset/deploy_bundle_aggregator_proxy.go b/deployment/data-feeds/changeset/deploy_bundle_aggregator_proxy.go index b536670ef20..ad9351254da 100644 --- a/deployment/data-feeds/changeset/deploy_bundle_aggregator_proxy.go +++ b/deployment/data-feeds/changeset/deploy_bundle_aggregator_proxy.go @@ -8,8 +8,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -18,7 +16,7 @@ import ( // Returns a new addressbook with deploy BundleAggregatorProxy contract addresses. var DeployBundleAggregatorProxyChangeset = cldf.CreateChangeSet(deployBundleAggregatorProxyLogic, deployBundleAggregatorProxyPrecondition) -func deployBundleAggregatorProxyLogic(env deployment.Environment, c types.DeployBundleAggregatorProxyConfig) (cldf.ChangesetOutput, error) { +func deployBundleAggregatorProxyLogic(env cldf.Environment, c types.DeployBundleAggregatorProxyConfig) (cldf.ChangesetOutput, error) { lggr := env.Logger ab := cldf.NewMemoryAddressBook() @@ -45,7 +43,7 @@ func deployBundleAggregatorProxyLogic(env deployment.Environment, c types.Deploy return cldf.ChangesetOutput{AddressBook: ab}, nil } -func deployBundleAggregatorProxyPrecondition(env deployment.Environment, c types.DeployBundleAggregatorProxyConfig) error { +func deployBundleAggregatorProxyPrecondition(env cldf.Environment, c types.DeployBundleAggregatorProxyConfig) error { for _, chainSelector := range c.ChainsToDeploy { _, ok := env.Chains[chainSelector] if !ok { diff --git a/deployment/data-feeds/changeset/deploy_cache.go b/deployment/data-feeds/changeset/deploy_cache.go index 62e037100fa..4a60b1b5df0 100644 --- a/deployment/data-feeds/changeset/deploy_cache.go +++ b/deployment/data-feeds/changeset/deploy_cache.go @@ -6,8 +6,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +13,7 @@ import ( // Returns a new addressbook with deployed DataFeedsCache contracts var DeployCacheChangeset = cldf.CreateChangeSet(deployCacheLogic, deployCachePrecondition) -func deployCacheLogic(env deployment.Environment, c types.DeployConfig) (cldf.ChangesetOutput, error) { +func deployCacheLogic(env cldf.Environment, c types.DeployConfig) (cldf.ChangesetOutput, error) { lggr := env.Logger ab := cldf.NewMemoryAddressBook() for _, chainSelector := range c.ChainsToDeploy { @@ -35,7 +33,7 @@ func deployCacheLogic(env deployment.Environment, c types.DeployConfig) (cldf.Ch return cldf.ChangesetOutput{AddressBook: ab}, nil } -func deployCachePrecondition(env deployment.Environment, c types.DeployConfig) error { +func deployCachePrecondition(env cldf.Environment, c types.DeployConfig) error { for _, chainSelector := range c.ChainsToDeploy { _, ok := env.Chains[chainSelector] if !ok { diff --git a/deployment/data-feeds/changeset/import_to_addressbook.go b/deployment/data-feeds/changeset/import_to_addressbook.go index 212ec0f8a76..a08d1f4853c 100644 --- a/deployment/data-feeds/changeset/import_to_addressbook.go +++ b/deployment/data-feeds/changeset/import_to_addressbook.go @@ -6,8 +6,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -21,7 +19,7 @@ type AddressesSchema struct { Label string `json:"label"` } -func importToAddressbookLogic(env deployment.Environment, c types.ImportToAddressbookConfig) (cldf.ChangesetOutput, error) { +func importToAddressbookLogic(env cldf.Environment, c types.ImportToAddressbookConfig) (cldf.ChangesetOutput, error) { ab := cldf.NewMemoryAddressBook() addresses, _ := LoadJSON[[]*AddressesSchema](c.InputFileName, c.InputFS) @@ -41,7 +39,7 @@ func importToAddressbookLogic(env deployment.Environment, c types.ImportToAddres return cldf.ChangesetOutput{AddressBook: ab}, nil } -func importToAddressbookPrecondition(env deployment.Environment, c types.ImportToAddressbookConfig) error { +func importToAddressbookPrecondition(env cldf.Environment, c types.ImportToAddressbookConfig) error { _, evmOK := env.Chains[c.ChainSelector] _, aptosOK := env.AptosChains[c.ChainSelector] _, solOK := env.SolChains[c.ChainSelector] diff --git a/deployment/data-feeds/changeset/jd_delete_jobs.go b/deployment/data-feeds/changeset/jd_delete_jobs.go index 561f0915ecc..0db31a2b8fb 100644 --- a/deployment/data-feeds/changeset/jd_delete_jobs.go +++ b/deployment/data-feeds/changeset/jd_delete_jobs.go @@ -6,7 +6,7 @@ import ( "time" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-feeds/offchain" ) @@ -18,7 +18,7 @@ const ( // DeleteJobsJDChangeset is a changeset that deletes jobs from JD either using job ids or workflow name var DeleteJobsJDChangeset = cldf.CreateChangeSet(deleteJobsJDLogic, deleteJobsJDPrecondition) -func deleteJobsJDLogic(env deployment.Environment, c types.DeleteJobsConfig) (cldf.ChangesetOutput, error) { +func deleteJobsJDLogic(env cldf.Environment, c types.DeleteJobsConfig) (cldf.ChangesetOutput, error) { ctx, cancel := context.WithTimeout(env.GetContext(), deleteJobTimeout) defer cancel() @@ -26,7 +26,7 @@ func deleteJobsJDLogic(env deployment.Environment, c types.DeleteJobsConfig) (cl return cldf.ChangesetOutput{}, nil } -func deleteJobsJDPrecondition(_ deployment.Environment, c types.DeleteJobsConfig) error { +func deleteJobsJDPrecondition(_ cldf.Environment, c types.DeleteJobsConfig) error { if len(c.JobIDs) == 0 && c.WorkflowName == "" { return errors.New("job ids or workflow name are required") } diff --git a/deployment/data-feeds/changeset/jd_propose_bt_jobs.go b/deployment/data-feeds/changeset/jd_propose_bt_jobs.go index 5482455ece1..9baceac9875 100644 --- a/deployment/data-feeds/changeset/jd_propose_bt_jobs.go +++ b/deployment/data-feeds/changeset/jd_propose_bt_jobs.go @@ -7,7 +7,7 @@ import ( "time" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-feeds/offchain" ) @@ -19,7 +19,7 @@ const ( // ProposeBtJobsToJDChangeset is a changeset that reads a boostrap spec from a file and proposes jobs to JD var ProposeBtJobsToJDChangeset = cldf.CreateChangeSet(proposeBtJobsToJDLogic, proposeBtJobsToJDPrecondition) -func proposeBtJobsToJDLogic(env deployment.Environment, c types.ProposeBtJobsConfig) (cldf.ChangesetOutput, error) { +func proposeBtJobsToJDLogic(env cldf.Environment, c types.ProposeBtJobsConfig) (cldf.ChangesetOutput, error) { ctx, cancel := context.WithTimeout(env.GetContext(), btTimeout) defer cancel() @@ -31,7 +31,7 @@ func proposeBtJobsToJDLogic(env deployment.Environment, c types.ProposeBtJobsCon return offchain.ProposeJobs(ctx, env, bootstrapJobSpec, nil, c.NodeFilter) } -func proposeBtJobsToJDPrecondition(env deployment.Environment, c types.ProposeBtJobsConfig) error { +func proposeBtJobsToJDPrecondition(env cldf.Environment, c types.ProposeBtJobsConfig) error { if c.NodeFilter == nil { return errors.New("node labels are required") } diff --git a/deployment/data-feeds/changeset/jd_propose_wf_jobs.go b/deployment/data-feeds/changeset/jd_propose_wf_jobs.go index afb3f751f0a..b882910c61a 100644 --- a/deployment/data-feeds/changeset/jd_propose_wf_jobs.go +++ b/deployment/data-feeds/changeset/jd_propose_wf_jobs.go @@ -10,7 +10,7 @@ import ( "time" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-feeds/offchain" "github.com/smartcontractkit/chainlink/deployment/data-feeds/view/v1_0" @@ -23,11 +23,11 @@ const ( // ProposeWFJobsToJDChangeset is a changeset that reads a feed state file, creates a workflow job spec from it and proposes it to JD. var ProposeWFJobsToJDChangeset = cldf.CreateChangeSet(proposeWFJobsToJDLogic, proposeWFJobsToJDPrecondition) -func proposeWFJobsToJDLogic(env deployment.Environment, c types.ProposeWFJobsConfig) (cldf.ChangesetOutput, error) { +func proposeWFJobsToJDLogic(env cldf.Environment, c types.ProposeWFJobsConfig) (cldf.ChangesetOutput, error) { ctx, cancel := context.WithTimeout(env.GetContext(), timeout) defer cancel() - chainInfo, _ := deployment.ChainInfo(c.ChainSelector) + chainInfo, _ := cldf.ChainInfo(c.ChainSelector) feedStatePath := filepath.Join("feeds", chainInfo.ChainName+".json") feedState, _ := LoadJSON[*v1_0.FeedState](feedStatePath, c.InputFS) @@ -132,7 +132,7 @@ func proposeWFJobsToJDLogic(env deployment.Environment, c types.ProposeWFJobsCon return out, nil } -func proposeWFJobsToJDPrecondition(env deployment.Environment, c types.ProposeWFJobsConfig) error { +func proposeWFJobsToJDPrecondition(env cldf.Environment, c types.ProposeWFJobsConfig) error { if c.MigrationName == "" { return errors.New("migration name is required") } @@ -166,7 +166,7 @@ func proposeWFJobsToJDPrecondition(env deployment.Environment, c types.ProposeWF return fmt.Errorf("failed to get consensus encoder abi: %w", err) } - chainInfo, err := deployment.ChainInfo(c.ChainSelector) + chainInfo, err := cldf.ChainInfo(c.ChainSelector) if err != nil { return fmt.Errorf("failed to get chain info for chain %d: %w", c.ChainSelector, err) } diff --git a/deployment/data-feeds/changeset/jd_register_nodes.go b/deployment/data-feeds/changeset/jd_register_nodes.go index dbe08dc8e59..4ebea50df2d 100644 --- a/deployment/data-feeds/changeset/jd_register_nodes.go +++ b/deployment/data-feeds/changeset/jd_register_nodes.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -34,7 +34,7 @@ type DONConfigSchema struct { const productLabel = "data-feeds" -func registerNodesToJDLogic(env deployment.Environment, c types.NodeConfig) (cldf.ChangesetOutput, error) { +func registerNodesToJDLogic(env cldf.Environment, c types.NodeConfig) (cldf.ChangesetOutput, error) { dons, _ := LoadJSON[[]*DONConfigSchema](c.InputFileName, c.InputFS) for _, don := range dons { @@ -101,7 +101,7 @@ func registerNodesToJDLogic(env deployment.Environment, c types.NodeConfig) (cld return cldf.ChangesetOutput{}, nil } -func registerNodesToJDLogicPrecondition(env deployment.Environment, c types.NodeConfig) error { +func registerNodesToJDLogicPrecondition(env cldf.Environment, c types.NodeConfig) error { if c.InputFileName == "" { return errors.New("input file name is required") } diff --git a/deployment/data-feeds/changeset/jd_update_nodes.go b/deployment/data-feeds/changeset/jd_update_nodes.go index 2e119c42484..2e0b51361fd 100644 --- a/deployment/data-feeds/changeset/jd_update_nodes.go +++ b/deployment/data-feeds/changeset/jd_update_nodes.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -22,7 +22,7 @@ type NodeConfigSchema struct { AppendLabels bool `json:"append_labels"` // if true, append new labels to existing labels, otherwise replace } -func updatesNodesJDLogic(env deployment.Environment, c types.NodeConfig) (cldf.ChangesetOutput, error) { +func updatesNodesJDLogic(env cldf.Environment, c types.NodeConfig) (cldf.ChangesetOutput, error) { nodes, _ := LoadJSON[[]*NodeConfigSchema](c.InputFileName, c.InputFS) for _, node := range nodes { @@ -58,7 +58,7 @@ func updatesNodesJDLogic(env deployment.Environment, c types.NodeConfig) (cldf.C return cldf.ChangesetOutput{}, nil } -func updatesNodesJDLogicPrecondition(env deployment.Environment, c types.NodeConfig) error { +func updatesNodesJDLogicPrecondition(env cldf.Environment, c types.NodeConfig) error { if c.InputFileName == "" { return errors.New("input file name is required") } diff --git a/deployment/data-feeds/changeset/migrate_feeds.go b/deployment/data-feeds/changeset/migrate_feeds.go index 1a8bb836132..d3b04ea9758 100644 --- a/deployment/data-feeds/changeset/migrate_feeds.go +++ b/deployment/data-feeds/changeset/migrate_feeds.go @@ -8,8 +8,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -26,7 +24,7 @@ type MigrationSchema struct { Description string `json:"description"` } -func migrateFeedsLogic(env deployment.Environment, c types.MigrationConfig) (cldf.ChangesetOutput, error) { +func migrateFeedsLogic(env cldf.Environment, c types.MigrationConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -58,20 +56,20 @@ func migrateFeedsLogic(env deployment.Environment, c types.MigrationConfig) (cld // Set the feed config tx, err := contract.SetDecimalFeedConfigs(chain.DeployerKey, dataIDs, descriptions, c.WorkflowMetadata) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } // Set the proxy to dataId mapping tx, err = contract.UpdateDataIdMappingsForProxies(chain.DeployerKey, addresses, dataIDs) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{AddressBook: ab}, nil } -func migrateFeedsPrecondition(env deployment.Environment, c types.MigrationConfig) error { +func migrateFeedsPrecondition(env cldf.Environment, c types.MigrationConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/new_feed_with_proxy.go b/deployment/data-feeds/changeset/new_feed_with_proxy.go index a8e8221eec8..02557adfa73 100644 --- a/deployment/data-feeds/changeset/new_feed_with_proxy.go +++ b/deployment/data-feeds/changeset/new_feed_with_proxy.go @@ -9,8 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" commonTypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" @@ -24,7 +22,7 @@ import ( // Returns a new addressbook with the new AggregatorProxy contracts address and MCMS proposal var NewFeedWithProxyChangeset = cldf.CreateChangeSet(newFeedWithProxyLogic, newFeedWithProxyPrecondition) -func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyConfig) (cldf.ChangesetOutput, error) { +func newFeedWithProxyLogic(env cldf.Environment, c types.NewFeedWithProxyConfig) (cldf.ChangesetOutput, error) { chain := env.Chains[c.ChainSelector] state, _ := LoadOnchainState(env) chainState := state.Chains[c.ChainSelector] @@ -52,7 +50,7 @@ func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyC AccessController: []common.Address{c.AccessController}, Labels: append([]string{c.Descriptions[index]}, c.Labels...), } - newEnv, err := RunChangeset(DeployAggregatorProxyChangeset, env, proxyConfig) + newEnv, err := changeset.RunChangeset(DeployAggregatorProxyChangeset, env, proxyConfig) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to execute DeployAggregatorProxyChangeset: %w", err) @@ -72,7 +70,7 @@ func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyC return cldf.ChangesetOutput{}, fmt.Errorf("failed to load proxy contract %w", err) } tx, err := proxyContract.TransferOwnership(chain.DeployerKey, common.HexToAddress(timelockAddr)) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } @@ -82,7 +80,7 @@ func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyC } // accept proxy ownership proposal - acceptProxyOwnerShipTx, err := proxyContract.AcceptOwnership(deployment.SimTransactOpts()) + acceptProxyOwnerShipTx, err := proxyContract.AcceptOwnership(cldf.SimTransactOpts()) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to create accept transfer ownership tx %w", err) } @@ -97,13 +95,13 @@ func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyC dataIDs, _ := FeedIDsToBytes16(c.DataIDs) // set feed config proposal - setFeedConfigTx, err := dataFeedsCache.SetDecimalFeedConfigs(deployment.SimTransactOpts(), dataIDs, c.Descriptions, c.WorkflowMetadata) + setFeedConfigTx, err := dataFeedsCache.SetDecimalFeedConfigs(cldf.SimTransactOpts(), dataIDs, c.Descriptions, c.WorkflowMetadata) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to set feed config %w", err) } // set feed proxy mapping proposal - setProxyMappingTx, err := dataFeedsCache.UpdateDataIdMappingsForProxies(deployment.SimTransactOpts(), proxyAddresses, dataIDs) + setProxyMappingTx, err := dataFeedsCache.UpdateDataIdMappingsForProxies(cldf.SimTransactOpts(), proxyAddresses, dataIDs) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to set proxy-dataId mapping %w", err) } @@ -130,7 +128,7 @@ func newFeedWithProxyLogic(env deployment.Environment, c types.NewFeedWithProxyC return cldf.ChangesetOutput{AddressBook: ab, MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposals}}, nil } -func newFeedWithProxyPrecondition(env deployment.Environment, c types.NewFeedWithProxyConfig) error { +func newFeedWithProxyPrecondition(env cldf.Environment, c types.NewFeedWithProxyConfig) error { if c.McmsConfig == nil { return errors.New("mcms config is required") } diff --git a/deployment/data-feeds/changeset/proposal.go b/deployment/data-feeds/changeset/proposal.go index c9db5bf87f7..3b25f87e750 100644 --- a/deployment/data-feeds/changeset/proposal.go +++ b/deployment/data-feeds/changeset/proposal.go @@ -10,7 +10,8 @@ import ( "github.com/smartcontractkit/mcms/sdk/evm" mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -22,7 +23,7 @@ type ProposalData struct { // MultiChainProposalConfig is a map of chain selector to a list of proposals to be executed on that chain type MultiChainProposalConfig map[uint64][]ProposalData -func BuildMultiChainProposals(env deployment.Environment, description string, proposalConfig MultiChainProposalConfig, minDelay time.Duration) (*mcmslib.TimelockProposal, error) { +func BuildMultiChainProposals(env cldf.Environment, description string, proposalConfig MultiChainProposalConfig, minDelay time.Duration) (*mcmslib.TimelockProposal, error) { state, _ := LoadOnchainState(env) var timelocksPerChain = map[uint64]string{} diff --git a/deployment/data-feeds/changeset/propose_aggregator.go b/deployment/data-feeds/changeset/propose_aggregator.go index 7c5c369bd22..c6ab9663fde 100644 --- a/deployment/data-feeds/changeset/propose_aggregator.go +++ b/deployment/data-feeds/changeset/propose_aggregator.go @@ -8,7 +8,7 @@ import ( proxy "github.com/smartcontractkit/chainlink-evm/gethwrappers/data-feeds/generated/aggregator_proxy" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -16,7 +16,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var ProposeAggregatorChangeset = cldf.CreateChangeSet(proposeAggregatorLogic, proposeAggregatorPrecondition) -func proposeAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAggregatorConfig) (cldf.ChangesetOutput, error) { +func proposeAggregatorLogic(env cldf.Environment, c types.ProposeConfirmAggregatorConfig) (cldf.ChangesetOutput, error) { chain := env.Chains[c.ChainSelector] aggregatorProxy, err := proxy.NewAggregatorProxy(c.ProxyAddress, chain.Client) @@ -26,7 +26,7 @@ func proposeAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAg txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } tx, err := aggregatorProxy.ProposeAggregator(txOpt, c.NewAggregatorAddress) @@ -47,14 +47,14 @@ func proposeAggregatorLogic(env deployment.Environment, c types.ProposeConfirmAg return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func proposeAggregatorPrecondition(env deployment.Environment, c types.ProposeConfirmAggregatorConfig) error { +func proposeAggregatorPrecondition(env cldf.Environment, c types.ProposeConfirmAggregatorConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/remove_dataid_proxy_mapping.go b/deployment/data-feeds/changeset/remove_dataid_proxy_mapping.go index dce836a5f32..b06ad540826 100644 --- a/deployment/data-feeds/changeset/remove_dataid_proxy_mapping.go +++ b/deployment/data-feeds/changeset/remove_dataid_proxy_mapping.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var RemoveFeedProxyMappingChangeset = cldf.CreateChangeSet(removeFeedProxyMappingLogic, removeFeedFeedProxyMappingPrecondition) -func removeFeedProxyMappingLogic(env deployment.Environment, c types.RemoveFeedProxyConfig) (cldf.ChangesetOutput, error) { +func removeFeedProxyMappingLogic(env cldf.Environment, c types.RemoveFeedProxyConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func removeFeedProxyMappingLogic(env deployment.Environment, c types.RemoveFeedP txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } tx, err := contract.RemoveDataIdMappingsForProxies(txOpt, c.ProxyAddresses) @@ -45,14 +45,14 @@ func removeFeedProxyMappingLogic(env deployment.Environment, c types.RemoveFeedP return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func removeFeedFeedProxyMappingPrecondition(env deployment.Environment, c types.RemoveFeedProxyConfig) error { +func removeFeedFeedProxyMappingPrecondition(env cldf.Environment, c types.RemoveFeedProxyConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/remove_feed.go b/deployment/data-feeds/changeset/remove_feed.go index 13f0c367640..72deef7d995 100644 --- a/deployment/data-feeds/changeset/remove_feed.go +++ b/deployment/data-feeds/changeset/remove_feed.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transactions with the deployer key. var RemoveFeedChangeset = cldf.CreateChangeSet(removeFeedLogic, removeFeedPrecondition) -func removeFeedLogic(env deployment.Environment, c types.RemoveFeedConfig) (cldf.ChangesetOutput, error) { +func removeFeedLogic(env cldf.Environment, c types.RemoveFeedConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func removeFeedLogic(env deployment.Environment, c types.RemoveFeedConfig) (cldf txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } dataIDs, _ := FeedIDsToBytes16(c.DataIDs) @@ -34,7 +34,7 @@ func removeFeedLogic(env deployment.Environment, c types.RemoveFeedConfig) (cldf } if c.McmsConfig == nil { - if _, err := deployment.ConfirmIfNoError(chain, removeConfigTx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, removeConfigTx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", removeConfigTx.Hash().String(), err) } } @@ -46,7 +46,7 @@ func removeFeedLogic(env deployment.Environment, c types.RemoveFeedConfig) (cldf } if c.McmsConfig == nil { - if _, err := deployment.ConfirmIfNoError(chain, removeProxyMappingTx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, removeProxyMappingTx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", removeProxyMappingTx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil @@ -72,7 +72,7 @@ func removeFeedLogic(env deployment.Environment, c types.RemoveFeedConfig) (cldf return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } -func removeFeedPrecondition(env deployment.Environment, c types.RemoveFeedConfig) error { +func removeFeedPrecondition(env cldf.Environment, c types.RemoveFeedConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/remove_feed_config.go b/deployment/data-feeds/changeset/remove_feed_config.go index 25da7e38398..e5bbc94fb5e 100644 --- a/deployment/data-feeds/changeset/remove_feed_config.go +++ b/deployment/data-feeds/changeset/remove_feed_config.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var RemoveFeedConfigChangeset = cldf.CreateChangeSet(removeFeedConfigLogic, removeFeedConfigPrecondition) -func removeFeedConfigLogic(env deployment.Environment, c types.RemoveFeedConfigCSConfig) (cldf.ChangesetOutput, error) { +func removeFeedConfigLogic(env cldf.Environment, c types.RemoveFeedConfigCSConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func removeFeedConfigLogic(env deployment.Environment, c types.RemoveFeedConfigC txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } dataIDs, _ := FeedIDsToBytes16(c.DataIDs) @@ -46,14 +46,14 @@ func removeFeedConfigLogic(env deployment.Environment, c types.RemoveFeedConfigC return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func removeFeedConfigPrecondition(env deployment.Environment, c types.RemoveFeedConfigCSConfig) error { +func removeFeedConfigPrecondition(env cldf.Environment, c types.RemoveFeedConfigCSConfig) error { if len(c.DataIDs) == 0 { return errors.New("dataIDs must not be empty") } diff --git a/deployment/data-feeds/changeset/set_bundle_feed_config.go b/deployment/data-feeds/changeset/set_bundle_feed_config.go index b9acdc3bcff..5306c76e3bf 100644 --- a/deployment/data-feeds/changeset/set_bundle_feed_config.go +++ b/deployment/data-feeds/changeset/set_bundle_feed_config.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var SetBundleFeedConfigChangeset = cldf.CreateChangeSet(setBundleFeedConfigLogic, setBundleFeedConfigPrecondition) -func setBundleFeedConfigLogic(env deployment.Environment, c types.SetFeedBundleConfig) (cldf.ChangesetOutput, error) { +func setBundleFeedConfigLogic(env cldf.Environment, c types.SetFeedBundleConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func setBundleFeedConfigLogic(env deployment.Environment, c types.SetFeedBundleC txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } dataIDs, _ := FeedIDsToBytes16(c.DataIDs) @@ -45,7 +45,7 @@ func setBundleFeedConfigLogic(env deployment.Environment, c types.SetFeedBundleC return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { if tx != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } @@ -56,7 +56,7 @@ func setBundleFeedConfigLogic(env deployment.Environment, c types.SetFeedBundleC return cldf.ChangesetOutput{}, nil } -func setBundleFeedConfigPrecondition(env deployment.Environment, c types.SetFeedBundleConfig) error { +func setBundleFeedConfigPrecondition(env cldf.Environment, c types.SetFeedBundleConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/set_feed_admin.go b/deployment/data-feeds/changeset/set_feed_admin.go index 76a76a3b1f4..ad0f6fb99f8 100644 --- a/deployment/data-feeds/changeset/set_feed_admin.go +++ b/deployment/data-feeds/changeset/set_feed_admin.go @@ -6,7 +6,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -14,7 +14,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var SetFeedAdminChangeset = cldf.CreateChangeSet(setFeedAdminLogic, setFeedAdminPrecondition) -func setFeedAdminLogic(env deployment.Environment, c types.SetFeedAdminConfig) (cldf.ChangesetOutput, error) { +func setFeedAdminLogic(env cldf.Environment, c types.SetFeedAdminConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -22,7 +22,7 @@ func setFeedAdminLogic(env deployment.Environment, c types.SetFeedAdminConfig) ( txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } tx, err := contract.SetFeedAdmin(txOpt, c.AdminAddress, c.IsAdmin) @@ -44,14 +44,14 @@ func setFeedAdminLogic(env deployment.Environment, c types.SetFeedAdminConfig) ( return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func setFeedAdminPrecondition(env deployment.Environment, c types.SetFeedAdminConfig) error { +func setFeedAdminPrecondition(env cldf.Environment, c types.SetFeedAdminConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/set_feed_config.go b/deployment/data-feeds/changeset/set_feed_config.go index 188cbe6773e..44efefe6d98 100644 --- a/deployment/data-feeds/changeset/set_feed_config.go +++ b/deployment/data-feeds/changeset/set_feed_config.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var SetFeedConfigChangeset = cldf.CreateChangeSet(setFeedConfigLogic, setFeedConfigPrecondition) -func setFeedConfigLogic(env deployment.Environment, c types.SetFeedDecimalConfig) (cldf.ChangesetOutput, error) { +func setFeedConfigLogic(env cldf.Environment, c types.SetFeedDecimalConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func setFeedConfigLogic(env deployment.Environment, c types.SetFeedDecimalConfig txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } dataIDs, _ := FeedIDsToBytes16(c.DataIDs) @@ -45,7 +45,7 @@ func setFeedConfigLogic(env deployment.Environment, c types.SetFeedDecimalConfig return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { if tx != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } @@ -56,7 +56,7 @@ func setFeedConfigLogic(env deployment.Environment, c types.SetFeedDecimalConfig return cldf.ChangesetOutput{}, nil } -func setFeedConfigPrecondition(env deployment.Environment, c types.SetFeedDecimalConfig) error { +func setFeedConfigPrecondition(env cldf.Environment, c types.SetFeedDecimalConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/state.go b/deployment/data-feeds/changeset/state.go index ad4a0cfa358..2addb759dbe 100644 --- a/deployment/data-feeds/changeset/state.go +++ b/deployment/data-feeds/changeset/state.go @@ -43,7 +43,7 @@ type DataFeedsOnChainState struct { Chains map[uint64]DataFeedsChainState } -func LoadOnchainState(e deployment.Environment) (DataFeedsOnChainState, error) { +func LoadOnchainState(e cldf.Environment) (DataFeedsOnChainState, error) { state := DataFeedsOnChainState{ Chains: make(map[uint64]DataFeedsChainState), } @@ -66,7 +66,7 @@ func LoadOnchainState(e deployment.Environment) (DataFeedsOnChainState, error) { } // LoadChainState Loads all state for a chain into state -func LoadChainState(logger logger.Logger, chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*DataFeedsChainState, error) { +func LoadChainState(logger logger.Logger, chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*DataFeedsChainState, error) { var state DataFeedsChainState mcmsWithTimelock, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addresses) @@ -114,10 +114,10 @@ func LoadChainState(logger logger.Logger, chain deployment.Chain, addresses map[ return &state, nil } -func (s DataFeedsOnChainState) View(chains []uint64, e deployment.Environment) (map[string]view.ChainView, error) { +func (s DataFeedsOnChainState) View(chains []uint64, e cldf.Environment) (map[string]view.ChainView, error) { m := make(map[string]view.ChainView) for _, chainSelector := range chains { - chainInfo, err := deployment.ChainInfo(chainSelector) + chainInfo, err := cldf.ChainInfo(chainSelector) if err != nil { return m, err } @@ -139,7 +139,7 @@ func (s DataFeedsOnChainState) View(chains []uint64, e deployment.Environment) ( return m, nil } -func GenerateFeedConfigView(e deployment.Environment, chainName string) *v1_0.FeedState { +func GenerateFeedConfigView(e cldf.Environment, chainName string) *v1_0.FeedState { baseDir := ".." envName := e.Name diff --git a/deployment/data-feeds/changeset/update_data_id_proxy.go b/deployment/data-feeds/changeset/update_data_id_proxy.go index 151798fd09c..22c018e4c25 100644 --- a/deployment/data-feeds/changeset/update_data_id_proxy.go +++ b/deployment/data-feeds/changeset/update_data_id_proxy.go @@ -7,7 +7,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" ) @@ -15,7 +15,7 @@ import ( // This changeset may return a timelock proposal if the MCMS config is provided, otherwise it will execute the transaction with the deployer key. var UpdateDataIDProxyChangeset = cldf.CreateChangeSet(updateDataIDProxyLogic, updateDataIDProxyPrecondition) -func updateDataIDProxyLogic(env deployment.Environment, c types.UpdateDataIDProxyConfig) (cldf.ChangesetOutput, error) { +func updateDataIDProxyLogic(env cldf.Environment, c types.UpdateDataIDProxyConfig) (cldf.ChangesetOutput, error) { state, _ := LoadOnchainState(env) chain := env.Chains[c.ChainSelector] chainState := state.Chains[c.ChainSelector] @@ -23,7 +23,7 @@ func updateDataIDProxyLogic(env deployment.Environment, c types.UpdateDataIDProx txOpt := chain.DeployerKey if c.McmsConfig != nil { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } dataIDs, _ := FeedIDsToBytes16(c.DataIDs) @@ -46,14 +46,14 @@ func updateDataIDProxyLogic(env deployment.Environment, c types.UpdateDataIDProx return cldf.ChangesetOutput{MCMSTimelockProposals: []mcmslib.TimelockProposal{*proposal}}, nil } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + if _, err := cldf.ConfirmIfNoError(chain, tx, err); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to confirm transaction: %s, %w", tx.Hash().String(), err) } return cldf.ChangesetOutput{}, nil } -func updateDataIDProxyPrecondition(env deployment.Environment, c types.UpdateDataIDProxyConfig) error { +func updateDataIDProxyPrecondition(env cldf.Environment, c types.UpdateDataIDProxyConfig) error { _, ok := env.Chains[c.ChainSelector] if !ok { return fmt.Errorf("chain not found in env %d", c.ChainSelector) diff --git a/deployment/data-feeds/changeset/utils.go b/deployment/data-feeds/changeset/utils.go index 2d0397e0c16..c56cb24277a 100644 --- a/deployment/data-feeds/changeset/utils.go +++ b/deployment/data-feeds/changeset/utils.go @@ -106,24 +106,3 @@ func GetDataFeedsCacheAddress(ab cldf.AddressBook, chainSelector uint64, label * return dataFeedsCacheAddress } - -type WrappedChangeSet[C any] struct { - operation cldf.ChangeSetV2[C] -} - -// RunChangeset is used to run a changeset in another changeset -// It executes VerifyPreconditions internally to handle changeset errors. -func RunChangeset[C any]( - operation cldf.ChangeSetV2[C], - env deployment.Environment, - config C, -) (cldf.ChangesetOutput, error) { - cs := WrappedChangeSet[C]{operation: operation} - - err := cs.operation.VerifyPreconditions(env, config) - if err != nil { - return cldf.ChangesetOutput{}, fmt.Errorf("failed to run precondition: %w", err) - } - - return cs.operation.Apply(env, config) -} diff --git a/deployment/data-feeds/changeset/validation.go b/deployment/data-feeds/changeset/validation.go index 91e841f3af5..6e06c1c3c3b 100644 --- a/deployment/data-feeds/changeset/validation.go +++ b/deployment/data-feeds/changeset/validation.go @@ -9,11 +9,9 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" commonTypes "github.com/smartcontractkit/chainlink/deployment/common/types" - - "github.com/smartcontractkit/chainlink/deployment" ) -func ValidateCacheForChain(env deployment.Environment, chainSelector uint64, cacheAddress common.Address) error { +func ValidateCacheForChain(env cldf.Environment, chainSelector uint64, cacheAddress common.Address) error { state, err := LoadOnchainState(env) if err != nil { return fmt.Errorf("failed to load on chain state %w", err) diff --git a/deployment/data-feeds/offchain/jd.go b/deployment/data-feeds/offchain/jd.go index b07f074df8b..8b3ef4fb0a6 100644 --- a/deployment/data-feeds/offchain/jd.go +++ b/deployment/data-feeds/offchain/jd.go @@ -11,7 +11,7 @@ import ( jdtypesv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" ) @@ -62,7 +62,7 @@ func (f *NodesFilter) filter() *nodeapiv1.ListNodesRequest_Filter { } } -func fetchNodesFromJD(ctx context.Context, env deployment.Environment, nodeFilters *NodesFilter) (nodes []*nodeapiv1.Node, err error) { +func fetchNodesFromJD(ctx context.Context, env cldf.Environment, nodeFilters *NodesFilter) (nodes []*nodeapiv1.Node, err error) { filter := nodeFilters.filter() resp, err := env.Offchain.ListNodes(ctx, &nodeapiv1.ListNodesRequest{Filter: filter}) @@ -76,7 +76,7 @@ func fetchNodesFromJD(ctx context.Context, env deployment.Environment, nodeFilte return resp.Nodes, nil } -func ProposeJobs(ctx context.Context, env deployment.Environment, workflowJobSpec string, workflowName *string, nodeFilters *NodesFilter) (cldf.ChangesetOutput, error) { +func ProposeJobs(ctx context.Context, env cldf.Environment, workflowJobSpec string, workflowName *string, nodeFilters *NodesFilter) (cldf.ChangesetOutput, error) { out := cldf.ChangesetOutput{ Jobs: []cldf.ProposedJob{}, } @@ -119,7 +119,7 @@ func ProposeJobs(ctx context.Context, env deployment.Environment, workflowJobSpe return out, nil } -func DeleteJobs(ctx context.Context, env deployment.Environment, jobIDs []string, workflowName string) { +func DeleteJobs(ctx context.Context, env cldf.Environment, jobIDs []string, workflowName string) { if len(jobIDs) == 0 { env.Logger.Debugf("jobIDs not present. Listing jobs to delete via workflow name") jobSelectors := []*jdtypesv1.Selector{ diff --git a/deployment/data-streams/changeset/channel-config-store/call_set_channel_definitions.go b/deployment/data-streams/changeset/channel-config-store/call_set_channel_definitions.go index 84befcf41f0..b86c7b1a748 100644 --- a/deployment/data-streams/changeset/channel-config-store/call_set_channel_definitions.go +++ b/deployment/data-streams/changeset/channel-config-store/call_set_channel_definitions.go @@ -8,6 +8,7 @@ import ( ethTypes "github.com/ethereum/go-ethereum/core/types" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -53,19 +54,19 @@ func (cfg SetChannelDefinitionsConfig) Validate() error { return nil } -func callSetChannelDefinitionsPrecondition(e deployment.Environment, cfg SetChannelDefinitionsConfig) error { +func callSetChannelDefinitionsPrecondition(e cldf.Environment, cfg SetChannelDefinitionsConfig) error { if len(cfg.DefinitionsByChain) == 0 { return errors.New("DefinitionsByChain cannot be empty") } for chainSel := range cfg.DefinitionsByChain { - if err := deployment.IsValidChainSelector(chainSel); err != nil { + if err := cldf.IsValidChainSelector(chainSel); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chainSel, err) } } return nil } -func callSetChannelDefinitions(e deployment.Environment, cfg SetChannelDefinitionsConfig) (cldf.ChangesetOutput, error) { +func callSetChannelDefinitions(e cldf.Environment, cfg SetChannelDefinitionsConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.ChannelConfigStore.String(), @@ -80,7 +81,7 @@ func callSetChannelDefinitions(e deployment.Environment, cfg SetChannelDefinitio return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "SetNativeSurcharge proposal") } -func maybeLoadChannelConfigStoreState(e deployment.Environment, chainSel uint64, contractAddr string) (*channel_config_store.ChannelConfigStore, error) { +func maybeLoadChannelConfigStoreState(e cldf.Environment, chainSel uint64, contractAddr string) (*channel_config_store.ChannelConfigStore, error) { if err := utils.ValidateContract(e, chainSel, contractAddr, types.ChannelConfigStore, deployment.Version1_0_0); err != nil { return nil, err } @@ -101,7 +102,7 @@ func doSetChannelDefinitions( c ChannelDefinition, ) (*ethTypes.Transaction, error) { return ccs.SetChannelDefinitions( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.DonID, c.S3URL, c.Hash, diff --git a/deployment/data-streams/changeset/channel-config-store/deploy_channel_config_store.go b/deployment/data-streams/changeset/channel-config-store/deploy_channel_config_store.go index da17eeefae0..a291091c6b4 100644 --- a/deployment/data-streams/changeset/channel-config-store/deploy_channel_config_store.go +++ b/deployment/data-streams/changeset/channel-config-store/deploy_channel_config_store.go @@ -6,6 +6,7 @@ import ( ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" @@ -35,19 +36,19 @@ func (cc DeployChannelConfigStoreConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for _, chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func deployChannelConfigStoreLogic(e deployment.Environment, cc DeployChannelConfigStoreConfig) (cldf.ChangesetOutput, error) { +func deployChannelConfigStoreLogic(e cldf.Environment, cc DeployChannelConfigStoreConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() err := deploy(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy ChannelConfigStore", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -69,7 +70,7 @@ func deployChannelConfigStoreLogic(e deployment.Environment, cc DeployChannelCon }, nil } -func deployChannelConfigStorePrecondition(_ deployment.Environment, cc DeployChannelConfigStoreConfig) error { +func deployChannelConfigStorePrecondition(_ cldf.Environment, cc DeployChannelConfigStoreConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployChannelConfigStoreConfig: %w", err) } @@ -77,7 +78,7 @@ func deployChannelConfigStorePrecondition(_ deployment.Environment, cc DeployCha return nil } -func deploy(e deployment.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployChannelConfigStoreConfig) error { +func deploy(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployChannelConfigStoreConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployChannelConfigStoreConfig: %w", err) } @@ -118,7 +119,7 @@ func deploy(e deployment.Environment, dataStore ds.MutableDataStore[metadata.Ser // channelConfigStoreDeployFn returns a function that deploys a ChannelConfigStore contract. func channelConfigStoreDeployFn() changeset.ContractDeployFn[*channel_config_store.ChannelConfigStore] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*channel_config_store.ChannelConfigStore] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*channel_config_store.ChannelConfigStore] { ccsAddr, ccsTx, ccs, err := channel_config_store.DeployChannelConfigStore( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/common.go b/deployment/data-streams/changeset/common.go index 0dd6213e5b9..1f77d0c320c 100644 --- a/deployment/data-streams/changeset/common.go +++ b/deployment/data-streams/changeset/common.go @@ -14,14 +14,13 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" ) const ( defaultJobSpecsTimeout = 120 * time.Second ) -func chainAndAddresses(e deployment.Environment, chainSel uint64) (chainID string, addresses map[string]cldf.TypeAndVersion, err error) { +func chainAndAddresses(e cldf.Environment, chainSel uint64) (chainID string, addresses map[string]cldf.TypeAndVersion, err error) { chainID, err = chainsel.GetChainIDFromSelector(chainSel) if err != nil { return "", nil, fmt.Errorf("failed to get chain ID from selector: %w", err) @@ -72,7 +71,7 @@ func proposeAllOrNothing(ctx context.Context, oc cldf.OffchainClient, prs []*job // fetchExternalJobID looks for an existing job that matches the given labels and returns its ID. // If no job is found, it returns a nil UUID. -func fetchExternalJobID(e deployment.Environment, nodeID string, selectors []*ptypes.Selector) (externalJobID uuid.UUID, err error) { +func fetchExternalJobID(e cldf.Environment, nodeID string, selectors []*ptypes.Selector) (externalJobID uuid.UUID, err error) { var nodeIDs []string if nodeID != "" { nodeIDs = []string{nodeID} @@ -89,7 +88,8 @@ func fetchExternalJobID(e deployment.Environment, nodeID string, selectors []*pt switch len(jobsResp.Jobs) { case 0: - // No job found, return nil UUID + // No job found, return a new UUID + externalJobID = uuid.New() case 1: // One job found, return its ID externalJobID, err = uuid.Parse(jobsResp.Jobs[0].Uuid) diff --git a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_promote_staging_config.go b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_promote_staging_config.go index 15c7a5e3ad7..5ab84867bfd 100644 --- a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_promote_staging_config.go +++ b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_promote_staging_config.go @@ -7,13 +7,14 @@ import ( "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/configurator" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" ) @@ -46,14 +47,14 @@ func (cfg PromoteStagingConfigConfig) Validate() error { func (pc PromoteStagingConfig) GetContractAddress() common.Address { return pc.ConfiguratorAddress } -func promoteStagingConfigPrecondition(_ deployment.Environment, cc PromoteStagingConfigConfig) error { +func promoteStagingConfigPrecondition(_ cldf.Environment, cc PromoteStagingConfigConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployConfiguratorConfig: %w", err) } return nil } -func promoteStagingConfigLogic(e deployment.Environment, cfg PromoteStagingConfigConfig) (cldf.ChangesetOutput, error) { +func promoteStagingConfigLogic(e cldf.Environment, cfg PromoteStagingConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.Configurator.String(), @@ -72,10 +73,10 @@ func doPromoteStagingConfig( c *configurator.Configurator, cfg PromoteStagingConfig, ) (*ethTypes.Transaction, error) { - return c.PromoteStagingConfig(deployment.SimTransactOpts(), cfg.ConfigID, cfg.IsGreenProduction) + return c.PromoteStagingConfig(cldf.SimTransactOpts(), cfg.ConfigID, cfg.IsGreenProduction) } -func LoadConfigurator(e deployment.Environment, chainSel uint64, contractAddr string) (*configurator.Configurator, error) { +func LoadConfigurator(e cldf.Environment, chainSel uint64, contractAddr string) (*configurator.Configurator, error) { chain, ok := e.Chains[chainSel] if !ok { return nil, fmt.Errorf("chain %d not found", chainSel) diff --git a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_production_config.go b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_production_config.go index 581bc40ff03..1f629459514 100644 --- a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_production_config.go +++ b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_production_config.go @@ -6,14 +6,13 @@ import ( ethTypes "github.com/ethereum/go-ethereum/core/types" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/configurator" - - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" ) var SetProductionConfigChangeset = cldf.CreateChangeSet(setProductionConfigLogic, setProductionConfigPrecondition) @@ -31,7 +30,7 @@ func (cfg SetProductionConfigConfig) Validate() error { return nil } -func setProductionConfigPrecondition(_ deployment.Environment, cfg SetProductionConfigConfig) error { +func setProductionConfigPrecondition(_ cldf.Environment, cfg SetProductionConfigConfig) error { if err := cfg.Validate(); err != nil { return fmt.Errorf("invalid DeployConfiguratorConfig: %w", err) } @@ -39,7 +38,7 @@ func setProductionConfigPrecondition(_ deployment.Environment, cfg SetProduction return nil } -func setProductionConfigLogic(e deployment.Environment, cfg SetProductionConfigConfig) (cldf.ChangesetOutput, error) { +func setProductionConfigLogic(e cldf.Environment, cfg SetProductionConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.Configurator.String(), @@ -58,7 +57,7 @@ func doSetProductionConfig( c *configurator.Configurator, prodCfg ConfiguratorConfig, ) (*ethTypes.Transaction, error) { - return c.SetProductionConfig(deployment.SimTransactOpts(), + return c.SetProductionConfig(cldf.SimTransactOpts(), prodCfg.ConfigID, prodCfg.Signers, prodCfg.OffchainTransmitters, diff --git a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_staging_config.go b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_staging_config.go index 6a67c1046ce..e735882c374 100644 --- a/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_staging_config.go +++ b/deployment/data-streams/changeset/configurator/v0_5_0/call_configurator_set_staging_config.go @@ -7,13 +7,13 @@ import ( "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/configurator" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" ) @@ -28,7 +28,7 @@ type SetStagingConfigConfig struct { MCMSConfig *types.MCMSConfig } -func setStagingConfigPrecondition(_ deployment.Environment, ss SetStagingConfigConfig) error { +func setStagingConfigPrecondition(_ cldf.Environment, ss SetStagingConfigConfig) error { if err := ss.Validate(); err != nil { return fmt.Errorf("invalid SetStagingConfigConfig: %w", err) } @@ -43,7 +43,7 @@ func (cfg SetStagingConfigConfig) Validate() error { return nil } -func setStagingConfigLogic(e deployment.Environment, cfg SetStagingConfigConfig) (cldf.ChangesetOutput, error) { +func setStagingConfigLogic(e cldf.Environment, cfg SetStagingConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.Configurator.String(), @@ -62,7 +62,7 @@ func doSetStagingConfig( c *configurator.Configurator, cfg ConfiguratorConfig, ) (*ethTypes.Transaction, error) { - return c.SetStagingConfig(deployment.SimTransactOpts(), + return c.SetStagingConfig(cldf.SimTransactOpts(), cfg.ConfigID, cfg.Signers, cfg.OffchainTransmitters, diff --git a/deployment/data-streams/changeset/configurator/v0_5_0/deploy_configurator.go b/deployment/data-streams/changeset/configurator/v0_5_0/deploy_configurator.go index bfcafd3facb..9ab71d384c2 100644 --- a/deployment/data-streams/changeset/configurator/v0_5_0/deploy_configurator.go +++ b/deployment/data-streams/changeset/configurator/v0_5_0/deploy_configurator.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/configurator" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" @@ -33,14 +34,14 @@ func (cc DeployConfiguratorConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for _, chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func deployConfiguratorLogic(e deployment.Environment, cc DeployConfiguratorConfig) (cldf.ChangesetOutput, error) { +func deployConfiguratorLogic(e cldf.Environment, cc DeployConfiguratorConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[ metadata.SerializedContractMetadata, ds.DefaultMetadata, @@ -49,7 +50,7 @@ func deployConfiguratorLogic(e deployment.Environment, cc DeployConfiguratorConf err := deploy(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy Configurator", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -72,7 +73,7 @@ func deployConfiguratorLogic(e deployment.Environment, cc DeployConfiguratorConf }, nil } -func deployConfiguratorPrecondition(_ deployment.Environment, cc DeployConfiguratorConfig) error { +func deployConfiguratorPrecondition(_ cldf.Environment, cc DeployConfiguratorConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployConfiguratorConfig: %w", err) } @@ -80,7 +81,7 @@ func deployConfiguratorPrecondition(_ deployment.Environment, cc DeployConfigura return nil } -func deploy(e deployment.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployConfiguratorConfig) error { +func deploy(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployConfiguratorConfig) error { for _, chainSel := range cc.ChainsToDeploy { chain, ok := e.Chains[chainSel] if !ok { @@ -117,7 +118,7 @@ func deploy(e deployment.Environment, dataStore ds.MutableDataStore[metadata.Ser } func DeployFn() changeset.ContractDeployFn[*configurator.Configurator] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*configurator.Configurator] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*configurator.Configurator] { ccsAddr, ccsTx, ccs, err := configurator.DeployConfigurator( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/deploy.go b/deployment/data-streams/changeset/deploy.go index 30d8bdd157e..aa9736b4f13 100644 --- a/deployment/data-streams/changeset/deploy.go +++ b/deployment/data-streams/changeset/deploy.go @@ -11,7 +11,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" ) @@ -27,7 +27,7 @@ type ( TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) } - ContractDeployFn[C Contract] func(chain deployment.Chain) *ContractDeployment[C] + ContractDeployFn[C Contract] func(chain cldf.Chain) *ContractDeployment[C] ContractDeployment[C Contract] struct { Address common.Address @@ -50,9 +50,9 @@ type DeploymentOutput[C Contract] struct { // DeployContract deploys a contract and saves the address to datastore. func DeployContract[C Contract]( - e deployment.Environment, + e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], - chain deployment.Chain, + chain cldf.Chain, deployFn ContractDeployFn[C], options *DeployOptions, ) (*ContractDeployment[C], error) { diff --git a/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit.go b/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit.go index 433824cc2f0..1c26ee43936 100644 --- a/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit.go +++ b/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -35,7 +35,7 @@ func (a PayLinkDeficit) GetContractAddress() common.Address { return a.FeeManagerAddress } -func (cs payLinkDeficit) Apply(e deployment.Environment, cfg PayLinkDeficitConfig) (cldf.ChangesetOutput, error) { +func (cs payLinkDeficit) Apply(e cldf.Environment, cfg PayLinkDeficitConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -50,12 +50,12 @@ func (cs payLinkDeficit) Apply(e deployment.Environment, cfg PayLinkDeficitConfi return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "Withdraw proposal") } -func (cs payLinkDeficit) VerifyPreconditions(e deployment.Environment, cfg PayLinkDeficitConfig) error { +func (cs payLinkDeficit) VerifyPreconditions(e cldf.Environment, cfg PayLinkDeficitConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -67,6 +67,6 @@ func doPayLinkDeficit( c PayLinkDeficit, ) (*goEthTypes.Transaction, error) { return fm.PayLinkDeficit( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.ConfigDigest) } diff --git a/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit_test.go b/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit_test.go index 619dbf77524..66b6052ed28 100644 --- a/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit_test.go +++ b/deployment/data-streams/changeset/fee-manager/call_pay_link_deficit_test.go @@ -10,6 +10,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/mock_fee_manager_v0_5_0" @@ -43,7 +44,7 @@ func TestPayLinkDeficit(t *testing.T) { deployMockCs := []commonChangesets.ConfiguredChangeSet{ commonChangesets.Configure(cldf.CreateChangeSet( - func(e deployment.Environment, config uint32) (cldf.ChangesetOutput, error) { + func(e cldf.Environment, config uint32) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() // This uses a MockFeeManager. The subject under test here is the PayLinkDeficit changeset. // This is modeled as a client/server test where the "client" is the PayLinkDeficit changeset @@ -62,7 +63,7 @@ func TestPayLinkDeficit(t *testing.T) { DataStore: sealedDS, }, nil }, - func(e deployment.Environment, config uint32) error { + func(e cldf.Environment, config uint32) error { return nil }, ), 1), @@ -117,7 +118,7 @@ func TestPayLinkDeficit(t *testing.T) { } func MockFeeManagerDeployFn(cfg DeployFeeManager) changeset.ContractDeployFn[*mock_fee_manager_v0_5_0.MockFeeManager] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*mock_fee_manager_v0_5_0.MockFeeManager] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*mock_fee_manager_v0_5_0.MockFeeManager] { ccsAddr, ccsTx, ccs, err := mock_fee_manager_v0_5_0.DeployMockFeeManager( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/fee-manager/call_set_native_surcharge.go b/deployment/data-streams/changeset/fee-manager/call_set_native_surcharge.go index 0a42460e154..aa08c3e2af9 100644 --- a/deployment/data-streams/changeset/fee-manager/call_set_native_surcharge.go +++ b/deployment/data-streams/changeset/fee-manager/call_set_native_surcharge.go @@ -11,7 +11,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -34,7 +33,7 @@ func (a SetNativeSurcharge) GetContractAddress() common.Address { return a.FeeManagerAddress } -func setNativeSurchargeLogic(e deployment.Environment, cfg SetNativeSurchargeConfig) (cldf.ChangesetOutput, error) { +func setNativeSurchargeLogic(e cldf.Environment, cfg SetNativeSurchargeConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -49,12 +48,12 @@ func setNativeSurchargeLogic(e deployment.Environment, cfg SetNativeSurchargeCon return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "SetNativeSurcharge proposal") } -func setNativeSurchargePrecondition(e deployment.Environment, cfg SetNativeSurchargeConfig) error { +func setNativeSurchargePrecondition(e cldf.Environment, cfg SetNativeSurchargeConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -66,6 +65,6 @@ func doSetNativeSurcharge( c SetNativeSurcharge, ) (*goEthTypes.Transaction, error) { return fm.SetNativeSurcharge( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.Surcharge) } diff --git a/deployment/data-streams/changeset/fee-manager/call_update_subscriber_discount.go b/deployment/data-streams/changeset/fee-manager/call_update_subscriber_discount.go index 94efa60f3c9..666013f401a 100644 --- a/deployment/data-streams/changeset/fee-manager/call_update_subscriber_discount.go +++ b/deployment/data-streams/changeset/fee-manager/call_update_subscriber_discount.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -38,7 +38,7 @@ func (a UpdateSubscriberDiscount) GetContractAddress() common.Address { return a.FeeManagerAddress } -func (cs discount) Apply(e deployment.Environment, cfg UpdateSubscriberDiscountConfig) (cldf.ChangesetOutput, error) { +func (cs discount) Apply(e cldf.Environment, cfg UpdateSubscriberDiscountConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -53,12 +53,12 @@ func (cs discount) Apply(e deployment.Environment, cfg UpdateSubscriberDiscountC return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "UpdateSubscriberDiscount proposal") } -func (cs discount) VerifyPreconditions(e deployment.Environment, cfg UpdateSubscriberDiscountConfig) error { +func (cs discount) VerifyPreconditions(e cldf.Environment, cfg UpdateSubscriberDiscountConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -70,7 +70,7 @@ func doUpdateSubscriberDiscount( c UpdateSubscriberDiscount, ) (*goEthTypes.Transaction, error) { return fm.UpdateSubscriberDiscount( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.SubscriberAddress, c.FeedID, c.TokenAddress, diff --git a/deployment/data-streams/changeset/fee-manager/call_update_subscriber_global_discount.go b/deployment/data-streams/changeset/fee-manager/call_update_subscriber_global_discount.go index 3890099da11..fce24f22603 100644 --- a/deployment/data-streams/changeset/fee-manager/call_update_subscriber_global_discount.go +++ b/deployment/data-streams/changeset/fee-manager/call_update_subscriber_global_discount.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -37,7 +37,7 @@ func (a UpdateSubscriberGlobalDiscount) GetContractAddress() common.Address { return a.FeeManagerAddress } -func (cs globalDiscount) Apply(e deployment.Environment, cfg UpdateSubscriberGlobalDiscountConfig) (cldf.ChangesetOutput, error) { +func (cs globalDiscount) Apply(e cldf.Environment, cfg UpdateSubscriberGlobalDiscountConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -52,12 +52,12 @@ func (cs globalDiscount) Apply(e deployment.Environment, cfg UpdateSubscriberGlo return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "UpdateSubscriberGlobalDiscount proposal") } -func (cs globalDiscount) VerifyPreconditions(e deployment.Environment, cfg UpdateSubscriberGlobalDiscountConfig) error { +func (cs globalDiscount) VerifyPreconditions(e cldf.Environment, cfg UpdateSubscriberGlobalDiscountConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -69,7 +69,7 @@ func doUpdateSubscriberGlobalDiscount( c UpdateSubscriberGlobalDiscount, ) (*goEthTypes.Transaction, error) { return fm.UpdateSubscriberGlobalDiscount( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.SubscriberAddress, c.TokenAddress, c.Discount) diff --git a/deployment/data-streams/changeset/fee-manager/call_withdraw.go b/deployment/data-streams/changeset/fee-manager/call_withdraw.go index e8d767a3dba..8605582a016 100644 --- a/deployment/data-streams/changeset/fee-manager/call_withdraw.go +++ b/deployment/data-streams/changeset/fee-manager/call_withdraw.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -38,7 +38,7 @@ func (a Withdraw) GetContractAddress() common.Address { return a.FeeManagerAddress } -func (cs withdraw) Apply(e deployment.Environment, cfg FeeManagerWithdrawConfig) (cldf.ChangesetOutput, error) { +func (cs withdraw) Apply(e cldf.Environment, cfg FeeManagerWithdrawConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -53,12 +53,12 @@ func (cs withdraw) Apply(e deployment.Environment, cfg FeeManagerWithdrawConfig) return mcmsutil.ExecuteOrPropose(e, txs, cfg.MCMSConfig, "Withdraw proposal") } -func (cs withdraw) VerifyPreconditions(e deployment.Environment, cfg FeeManagerWithdrawConfig) error { +func (cs withdraw) VerifyPreconditions(e cldf.Environment, cfg FeeManagerWithdrawConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } @@ -70,7 +70,7 @@ func doWithdraw( c Withdraw, ) (*goEthTypes.Transaction, error) { return fm.Withdraw( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), c.AssetAddress, c.RecipientAddress, c.Quantity) diff --git a/deployment/data-streams/changeset/fee-manager/deploy_fee_manager.go b/deployment/data-streams/changeset/fee-manager/deploy_fee_manager.go index 2f3f2e71c07..195e26969f4 100644 --- a/deployment/data-streams/changeset/fee-manager/deploy_fee_manager.go +++ b/deployment/data-streams/changeset/fee-manager/deploy_fee_manager.go @@ -6,9 +6,10 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/view/v0_5" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" @@ -44,19 +45,19 @@ func (cc DeployFeeManagerConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func deployFeeManagerLogic(e deployment.Environment, cc DeployFeeManagerConfig) (cldf.ChangesetOutput, error) { +func deployFeeManagerLogic(e cldf.Environment, cc DeployFeeManagerConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() err := deployFeeManager(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy FeeManager", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -79,11 +80,11 @@ func deployFeeManagerLogic(e deployment.Environment, cc DeployFeeManagerConfig) }, nil } -func deployFeeManagerPrecondition(_ deployment.Environment, cc DeployFeeManagerConfig) error { +func deployFeeManagerPrecondition(_ cldf.Environment, cc DeployFeeManagerConfig) error { return cc.Validate() } -func deployFeeManager(e deployment.Environment, +func deployFeeManager(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployFeeManagerConfig) error { if err := cc.Validate(); err != nil { @@ -127,7 +128,7 @@ func deployFeeManager(e deployment.Environment, // FeeManagerDeployFn returns a function that deploys a FeeManager contract. func FeeManagerDeployFn(cfg DeployFeeManager) changeset.ContractDeployFn[*fee_manager_v0_5_0.FeeManager] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*fee_manager_v0_5_0.FeeManager] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*fee_manager_v0_5_0.FeeManager] { ccsAddr, ccsTx, ccs, err := fee_manager_v0_5_0.DeployFeeManager( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/fee-manager/state.go b/deployment/data-streams/changeset/fee-manager/state.go index 0b0866454fd..7169ecf634b 100644 --- a/deployment/data-streams/changeset/fee-manager/state.go +++ b/deployment/data-streams/changeset/fee-manager/state.go @@ -5,15 +5,18 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/fee_manager_v0_5_0" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" ) func LoadFeeManagerState( - e deployment.Environment, + e cldf.Environment, chainSel uint64, contractAddr string, ) (*fee_manager_v0_5_0.FeeManager, error) { diff --git a/deployment/data-streams/changeset/fee-manager/test_helpers.go b/deployment/data-streams/changeset/fee-manager/test_helpers.go index 7c8b4aadbc4..3422d380856 100644 --- a/deployment/data-streams/changeset/fee-manager/test_helpers.go +++ b/deployment/data-streams/changeset/fee-manager/test_helpers.go @@ -7,6 +7,9 @@ import ( "github.com/stretchr/testify/require" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" commonchangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/testutil" @@ -14,7 +17,7 @@ import ( ) type DataStreamsTestEnvSetupOutput struct { - Env deployment.Environment + Env cldf.Environment LinkTokenAddress common.Address FeeManagerAddress common.Address } diff --git a/deployment/data-streams/changeset/helpers_test.go b/deployment/data-streams/changeset/helpers_test.go new file mode 100644 index 00000000000..933c8eda724 --- /dev/null +++ b/deployment/data-streams/changeset/helpers_test.go @@ -0,0 +1,161 @@ +/* +This file contains test helpers for the changeset package. +The filename has a suffix of "_test.go" in order to not be included in the production build. +*/ + +package changeset + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + + "github.com/smartcontractkit/chainlink/deployment" + commonChangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/testutil" + "github.com/smartcontractkit/chainlink/deployment/data-streams/jd" + "github.com/smartcontractkit/chainlink/deployment/data-streams/jobs" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" + "github.com/smartcontractkit/chainlink/deployment/environment/test" +) + +// sendTestLLOJobs sends some test LLO jobs, which we can then revoke, retrieve, delete, etc. +func sendTestLLOJobs(t *testing.T, e cldf.Environment, numOracles, numBootstraps int, autoApproveJobs bool) []cldf.ChangesetOutput { + chainSel := e.AllChainSelectors()[0] + configurator := "0x4170ed0880ac9a755fd29b2688956bd959f923f4" + err := e.ExistingAddresses.Save(chainSel, configurator, + cldf.TypeAndVersion{ + Type: "Configurator", + Version: deployment.Version1_0_0, + Labels: cldf.NewLabelSet("don-1"), + }) + require.NoError(t, err) + + bootstrapNodeNames, oracleNodeNames := collectNodeNames(t, e, numOracles, numBootstraps) + + var labels []*ptypes.Label + if !autoApproveJobs { + labels = append(labels, &ptypes.Label{ + Key: test.LabelDoNotAutoApprove, + }) + } + + config := CsDistributeLLOJobSpecsConfig{ + ChainSelectorEVM: chainSel, + Filter: &jd.ListFilter{ + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, + NumOracleNodes: numOracles, + NumBootstrapNodes: numBootstraps, + }, + FromBlock: 0, + ConfigMode: "bluegreen", + ChannelConfigStoreAddr: common.HexToAddress("DEAD"), + ChannelConfigStoreFromBlock: 0, + ConfiguratorAddress: configurator, + Labels: labels, + Servers: map[string]string{ + "mercury-pipeline-testnet-producer.TEST.cldev.cloud:1340": "0000005187b1498c0ccb2e56d5ee8040a03a4955822ed208749b474058fc3f9c", + }, + NodeNames: append(bootstrapNodeNames, oracleNodeNames...), + } + + _, out, err := commonChangesets.ApplyChangesetsV2(t, + e, + []commonChangesets.ConfiguredChangeSet{ + commonChangesets.Configure(CsDistributeLLOJobSpecs{}, config), + }, + ) + require.NoError(t, err) + return out +} + +// sendTestStreamJobs sends some test stream jobs, which we can then revoke, retrieve, delete, etc. +func sendTestStreamJobs(t *testing.T, e cldf.Environment, numOracles int, autoApproveJobs bool) []cldf.ChangesetOutput { + _, oracleNodeNames := collectNodeNames(t, e, numOracles, 0) + + var labels []*ptypes.Label + if !autoApproveJobs { + labels = append(labels, &ptypes.Label{ + Key: test.LabelDoNotAutoApprove, + }) + } + + config := CsDistributeStreamJobSpecsConfig{ + Filter: &jd.ListFilter{ + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, + NumOracleNodes: numOracles, + NumBootstrapNodes: 0, + }, + Streams: []StreamSpecConfig{ + { + StreamID: 1000001038, + Name: "ICP/USD-RefPrice", + StreamType: jobs.StreamTypeQuote, + ReportFields: jobs.QuoteReportFields{ + Bid: jobs.ReportFieldLLO{ + ResultPath: "data,bid", + }, + Benchmark: jobs.ReportFieldLLO{ + ResultPath: "data,mid", + }, + Ask: jobs.ReportFieldLLO{ + ResultPath: "data,ask", + }, + }, + EARequestParams: EARequestParams{ + Endpoint: "cryptolwba", + From: "ICP", + To: "USD", + }, + APIs: []string{"api1", "api2", "api3", "api4"}, + }, + }, + Labels: labels, + NodeNames: oracleNodeNames, + } + + _, out, err := commonChangesets.ApplyChangesetsV2(t, + e, + []commonChangesets.ConfiguredChangeSet{ + commonChangesets.Configure(CsDistributeStreamJobSpecs{}, config), + }, + ) + require.NoError(t, err) + return out +} + +func collectNodeNames(t *testing.T, e cldf.Environment, numOracles, numBootstraps int) (btNames, oracleNames []string) { + bootstrapNodeNames := make([]string, 0, numBootstraps) + oracleNodeNames := make([]string, 0, numOracles) + resp, err := e.Offchain.ListNodes(context.Background(), &node.ListNodesRequest{ + Filter: &node.ListNodesRequest_Filter{}, + }) + require.NoError(t, err) + for _, n := range resp.Nodes { + for _, label := range n.Labels { + if label.Key == devenv.LabelNodeTypeKey { + switch *label.Value { + case devenv.LabelNodeTypeValueBootstrap: + bootstrapNodeNames = append(bootstrapNodeNames, n.Name) + case devenv.LabelNodeTypeValuePlugin: + oracleNodeNames = append(oracleNodeNames, n.Name) + default: + t.Fatalf("unexpected n type: %s", *label.Value) + } + } + } + } + + return bootstrapNodeNames, oracleNodeNames +} diff --git a/deployment/data-streams/changeset/jd_distribute_llo_jobs.go b/deployment/data-streams/changeset/jd_distribute_llo_jobs.go index c0f07da97a3..1378adedf55 100644 --- a/deployment/data-streams/changeset/jd_distribute_llo_jobs.go +++ b/deployment/data-streams/changeset/jd_distribute_llo_jobs.go @@ -14,7 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/jd" "github.com/smartcontractkit/chainlink/deployment/data-streams/jobs" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" @@ -39,6 +39,7 @@ type CsDistributeLLOJobSpecsConfig struct { ChannelConfigStoreAddr common.Address ChannelConfigStoreFromBlock uint64 ConfiguratorAddress string + Labels []*ptypes.Label // Servers is a list of Data Engine Producer endpoints, where the key is the server URL and the value is its public key. // @@ -52,7 +53,7 @@ type CsDistributeLLOJobSpecsConfig struct { type CsDistributeLLOJobSpecs struct{} -func (CsDistributeLLOJobSpecs) Apply(e deployment.Environment, cfg CsDistributeLLOJobSpecsConfig) (cldf.ChangesetOutput, error) { +func (CsDistributeLLOJobSpecs) Apply(e cldf.Environment, cfg CsDistributeLLOJobSpecsConfig) (cldf.ChangesetOutput, error) { ctx, cancel := context.WithTimeout(e.GetContext(), defaultJobSpecsTimeout) defer cancel() @@ -62,7 +63,7 @@ func (CsDistributeLLOJobSpecs) Apply(e deployment.Environment, cfg CsDistributeL } // Add a label to the job spec to identify the related DON - labels := append([]*ptypes.Label(nil), + cfg.Labels = append(cfg.Labels, &ptypes.Label{ Key: utils.DonIdentifier(cfg.Filter.DONID, cfg.Filter.DONName), }, @@ -72,11 +73,11 @@ func (CsDistributeLLOJobSpecs) Apply(e deployment.Environment, cfg CsDistributeL }, ) - bootstrapProposals, err := generateBootstrapProposals(ctx, e, cfg, chainID, labels) + bootstrapProposals, err := generateBootstrapProposals(ctx, e, cfg, chainID, cfg.Labels) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate bootstrap proposals: %w", err) } - oracleProposals, err := generateOracleProposals(ctx, e, cfg, chainID, labels) + oracleProposals, err := generateOracleProposals(ctx, e, cfg, chainID, cfg.Labels) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to generate oracle proposals: %w", err) } @@ -91,7 +92,7 @@ func (CsDistributeLLOJobSpecs) Apply(e deployment.Environment, cfg CsDistributeL }, nil } -func generateBootstrapProposals(ctx context.Context, e deployment.Environment, cfg CsDistributeLLOJobSpecsConfig, chainID string, labels []*ptypes.Label) ([]*jobv1.ProposeJobRequest, error) { +func generateBootstrapProposals(ctx context.Context, e cldf.Environment, cfg CsDistributeLLOJobSpecsConfig, chainID string, labels []*ptypes.Label) ([]*jobv1.ProposeJobRequest, error) { bootstrapNodes, err := jd.FetchDONBootstrappersFromJD(ctx, e.Offchain, cfg.Filter, cfg.NodeNames) if err != nil { return nil, fmt.Errorf("failed to get bootstrap nodes: %w", err) @@ -152,7 +153,7 @@ func generateBootstrapProposals(ctx context.Context, e deployment.Environment, c return proposals, nil } -func generateOracleProposals(ctx context.Context, e deployment.Environment, cfg CsDistributeLLOJobSpecsConfig, chainID string, labels []*ptypes.Label) ([]*jobv1.ProposeJobRequest, error) { +func generateOracleProposals(ctx context.Context, e cldf.Environment, cfg CsDistributeLLOJobSpecsConfig, chainID string, labels []*ptypes.Label) ([]*jobv1.ProposeJobRequest, error) { // nils will be filled out later with n-specific values: lloSpec := &jobs.LLOJobSpec{ Base: jobs.Base{ @@ -252,7 +253,7 @@ func generateOracleProposals(ctx context.Context, e deployment.Environment, cfg } // chainConfigs returns a map of node IDs to their chain configs for the given chain ID. -func chainConfigs(ctx context.Context, e deployment.Environment, chainID string, nodes []*node.Node) (map[string]*node.OCR2Config, error) { +func chainConfigs(ctx context.Context, e cldf.Environment, chainID string, nodes []*node.Node) (map[string]*node.OCR2Config, error) { nodeConfigMap := make(map[string]*node.OCR2Config) for _, n := range nodes { ncf, err := e.Offchain.ListNodeChainConfigs(ctx, @@ -275,7 +276,7 @@ func chainConfigs(ctx context.Context, e deployment.Environment, chainID string, } // getBootstrapMultiAddr fetches the bootstrap node from Job Distributor and returns its multiaddr. -func getBootstrapMultiAddr(ctx context.Context, e deployment.Environment, cfg CsDistributeLLOJobSpecsConfig) (string, error) { +func getBootstrapMultiAddr(ctx context.Context, e cldf.Environment, cfg CsDistributeLLOJobSpecsConfig) (string, error) { // Get all bootstrap nodes for this DON. // We fetch these with a custom filter because the filter in the config defines which nodes need to be sent jobs // and this might not cover any bootstrap nodes. @@ -325,7 +326,7 @@ func getBootstrapMultiAddr(ctx context.Context, e deployment.Environment, cfg Cs return resp.ChainConfigs[0].Ocr2Config.Multiaddr, nil } -func (f CsDistributeLLOJobSpecs) VerifyPreconditions(_ deployment.Environment, config CsDistributeLLOJobSpecsConfig) error { +func (f CsDistributeLLOJobSpecs) VerifyPreconditions(_ cldf.Environment, config CsDistributeLLOJobSpecsConfig) error { if config.ChainSelectorEVM == 0 { return errors.New("chain selector is required") } diff --git a/deployment/data-streams/changeset/jd_distribute_llo_jobs_test.go b/deployment/data-streams/changeset/jd_distribute_llo_jobs_test.go index 1e35ff0a901..1adfb77ab54 100644 --- a/deployment/data-streams/changeset/jd_distribute_llo_jobs_test.go +++ b/deployment/data-streams/changeset/jd_distribute_llo_jobs_test.go @@ -1,17 +1,18 @@ package changeset import ( - "context" "strings" "testing" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + jdJob "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/testutil" @@ -25,10 +26,6 @@ func TestDistributeLLOJobSpecs(t *testing.T) { t.Parallel() t.Skip("Skipping testing in CI environment") // flaking on CI - const donID = 1 - const donName = "don" - const envName = "env" - env := testutil.NewMemoryEnvV2(t, testutil.MemoryEnvConfig{ ShouldDeployMCMS: false, ShouldDeployLinkToken: false, @@ -41,42 +38,22 @@ func TestDistributeLLOJobSpecs(t *testing.T) { }, { Key: devenv.LabelEnvironmentKey, - Value: pointer.To(envName), + Value: pointer.To(testutil.TestDON.Env), }, { - Key: utils.DonIdentifier(donID, donName), + Key: utils.DonIdentifier(testutil.TestDON.ID, testutil.TestDON.Name), }, }, }).Environment - // Collect the names of the nodes. - bootstrapNodeNames := make([]string, 0, 1) - oracleNodeNames := make([]string, 0, 2) - resp, err := env.Offchain.ListNodes(context.Background(), &node.ListNodesRequest{ - Filter: &node.ListNodesRequest_Filter{}, - }) - require.NoError(t, err) - for _, n := range resp.Nodes { - for _, label := range n.Labels { - if label.Key == devenv.LabelNodeTypeKey { - switch *label.Value { - case devenv.LabelNodeTypeValueBootstrap: - bootstrapNodeNames = append(bootstrapNodeNames, n.Name) - case devenv.LabelNodeTypeValuePlugin: - oracleNodeNames = append(oracleNodeNames, n.Name) - default: - t.Fatalf("unexpected n type: %s", *label.Value) - } - } - } - } + bootstrapNodeNames, oracleNodeNames := collectNodeNames(t, env, 2, 1) // pick the first EVM chain selector chainSelector := env.AllChainSelectors()[0] // insert a Configurator address for the given DON configuratorAddr := "0x4170ed0880ac9a755fd29b2688956bd959f923f4" - err = env.ExistingAddresses.Save(chainSelector, configuratorAddr, + err := env.ExistingAddresses.Save(chainSelector, configuratorAddr, cldf.TypeAndVersion{ Type: "Configurator", Version: deployment.Version1_0_0, @@ -120,9 +97,9 @@ chainID = '90000001' config := CsDistributeLLOJobSpecsConfig{ ChainSelectorEVM: chainSelector, Filter: &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 2, NumBootstrapNodes: 1, }, @@ -131,6 +108,12 @@ chainID = '90000001' ChannelConfigStoreAddr: common.HexToAddress("DEAD"), ChannelConfigStoreFromBlock: 0, ConfiguratorAddress: configuratorAddr, + Labels: []*ptypes.Label{ + { + Key: "customTestLabel", + Value: pointer.To("customTestValue"), + }, + }, Servers: map[string]string{ "mercury-pipeline-testnet-producer.TEST.cldev.cloud:1340": "0000005187b1498c0ccb2e56d5ee8040a03a4955822ed208749b474058fc3f9c", }, @@ -166,9 +149,9 @@ chainID = '90000001' prepConfFn: func(c CsDistributeLLOJobSpecsConfig) CsDistributeLLOJobSpecsConfig { c.NodeNames = append(bootstrapNodeNames, oracleNodeNames[:1]...) //nolint: gocritic // I want a combined list. GoCritic doesn't like it. c.Filter = &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 1, NumBootstrapNodes: 1, } @@ -184,9 +167,9 @@ chainID = '90000001' prepConfFn: func(c CsDistributeLLOJobSpecsConfig) CsDistributeLLOJobSpecsConfig { c.NodeNames = []string{oracleNodeNames[0]} c.Filter = &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 1, NumBootstrapNodes: 0, } @@ -253,6 +236,20 @@ chainID = '90000001' require.Equal(t, wantOracleSpec, spec) foundOracleJobs++ } + + // Ensure the labels are set correctly. + job, err := env.Offchain.GetJob(t.Context(), &jdJob.GetJobRequest{ + IdOneof: &jdJob.GetJobRequest_Id{Id: j.JobID}, + }) + require.NoError(t, err) + foundLabel := false + for _, label := range job.GetJob().GetLabels() { + if label.GetKey() == "customTestLabel" && label.GetValue() == "customTestValue" { + foundLabel = true + break + } + } + require.True(t, foundLabel, "customTestLabel not found in job labels") } require.Equal(t, tc.wantNumBootstrapJobs, foundBootstrapJobs) require.Equal(t, tc.wantNumOracleJobs, foundOracleJobs) diff --git a/deployment/data-streams/changeset/jd_distribute_stream_jobs.go b/deployment/data-streams/changeset/jd_distribute_stream_jobs.go index 71d41fdca74..16678c62ac4 100644 --- a/deployment/data-streams/changeset/jd_distribute_stream_jobs.go +++ b/deployment/data-streams/changeset/jd_distribute_stream_jobs.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/jd" "github.com/smartcontractkit/chainlink/deployment/data-streams/jobs" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" @@ -25,6 +25,7 @@ var _ cldf.ChangeSetV2[CsDistributeStreamJobSpecsConfig] = CsDistributeStreamJob type CsDistributeStreamJobSpecsConfig struct { Filter *jd.ListFilter Streams []StreamSpecConfig + Labels []*ptypes.Label // NodeNames specifies on which nodes to distribute the job specs. NodeNames []string @@ -48,12 +49,12 @@ type EARequestParams struct { type CsDistributeStreamJobSpecs struct{} -func (CsDistributeStreamJobSpecs) Apply(e deployment.Environment, cfg CsDistributeStreamJobSpecsConfig) (cldf.ChangesetOutput, error) { +func (CsDistributeStreamJobSpecs) Apply(e cldf.Environment, cfg CsDistributeStreamJobSpecsConfig) (cldf.ChangesetOutput, error) { ctx, cancel := context.WithTimeout(e.GetContext(), defaultJobSpecsTimeout) defer cancel() // Add a label to the job spec to identify the related DON - labels := append([]*ptypes.Label(nil), + cfg.Labels = append(cfg.Labels, &ptypes.Label{ Key: utils.DonIdentifier(cfg.Filter.DONID, cfg.Filter.DONName), }, @@ -67,7 +68,7 @@ func (CsDistributeStreamJobSpecs) Apply(e deployment.Environment, cfg CsDistribu var proposals []*jobv1.ProposeJobRequest for _, s := range cfg.Streams { for _, n := range oracleNodes { - localLabels := append(labels, //nolint: gocritic // obvious and readable locally modified copy of labels + localLabels := append(cfg.Labels, //nolint: gocritic // locally modified copy of labels &ptypes.Label{ Key: devenv.LabelStreamIDKey, Value: pointer.To(strconv.FormatUint(uint64(s.StreamID), 10)), @@ -155,7 +156,7 @@ func generateDatasources(cc StreamSpecConfig) []jobs.Datasource { return dss } -func (f CsDistributeStreamJobSpecs) VerifyPreconditions(_ deployment.Environment, config CsDistributeStreamJobSpecsConfig) error { +func (f CsDistributeStreamJobSpecs) VerifyPreconditions(_ cldf.Environment, config CsDistributeStreamJobSpecsConfig) error { if config.Filter == nil { return errors.New("filter is required") } @@ -190,8 +191,8 @@ func (f CsDistributeStreamJobSpecs) VerifyPreconditions(_ deployment.Environment } // The list of node names tells us which nodes to distribute the job specs to. // The size of that list needs to match the filter size, i.e. the number of nodes we expect to get from JD. - if config.Filter.NumOracleNodes+config.Filter.NumBootstrapNodes != len(config.NodeNames) { - return fmt.Errorf("number of node names (%d) does not match filter size (%d)", len(config.NodeNames), config.Filter.NumOracleNodes+config.Filter.NumBootstrapNodes) + if config.Filter.NumOracleNodes != len(config.NodeNames) { + return fmt.Errorf("number of node names (%d) does not match filter size (%d)", len(config.NodeNames), config.Filter.NumOracleNodes) } return nil diff --git a/deployment/data-streams/changeset/jd_distribute_stream_jobs_test.go b/deployment/data-streams/changeset/jd_distribute_stream_jobs_test.go index 6a870438834..f49fac1ffdd 100644 --- a/deployment/data-streams/changeset/jd_distribute_stream_jobs_test.go +++ b/deployment/data-streams/changeset/jd_distribute_stream_jobs_test.go @@ -5,6 +5,9 @@ import ( "github.com/stretchr/testify/require" + jdJob "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" @@ -18,15 +21,12 @@ import ( func TestDistributeStreamJobSpecs(t *testing.T) { t.Parallel() t.Skip("Skipping testing in CI environment") // flaking on CI - const donID = 1 - const donName = "don" - const envName = "envName" env := testutil.NewMemoryEnvV2(t, testutil.MemoryEnvConfig{ ShouldDeployMCMS: false, ShouldDeployLinkToken: false, NumNodes: 3, - NodeLabels: testutil.GetNodeLabels(donID, donName, envName), + NodeLabels: testutil.GetNodeLabels(testutil.TestDON.ID, testutil.TestDON.Name, testutil.TestDON.Env), CustomDBSetup: []string{ // Seed the database with the list of bridges we're using. `INSERT INTO bridge_types (name, url, confirmations, incoming_token_hash, salt, outgoing_token, created_at, updated_at) @@ -105,9 +105,9 @@ ask_price [type=median allowedFaults=3 index=2]; config := CsDistributeStreamJobSpecsConfig{ Filter: &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 3, }, Streams: []StreamSpecConfig{ @@ -134,6 +134,12 @@ ask_price [type=median allowedFaults=3 index=2]; APIs: []string{"api1", "api2", "api3", "api4"}, }, }, + Labels: []*ptypes.Label{ + { + Key: "customTestLabel", + Value: pointer.To("customTestValue"), + }, + }, NodeNames: []string{"node-0", "node-1", "node-2"}, } @@ -161,9 +167,9 @@ ask_price [type=median allowedFaults=3 index=2]; prepConfFn: func(c CsDistributeStreamJobSpecsConfig) CsDistributeStreamJobSpecsConfig { c.NodeNames = []string{"node-0"} c.Filter = &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 1, } return c @@ -177,9 +183,9 @@ ask_price [type=median allowedFaults=3 index=2]; prepConfFn: func(c CsDistributeStreamJobSpecsConfig) CsDistributeStreamJobSpecsConfig { c.NodeNames = []string{"node-1", "node-2"} c.Filter = &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 2, } return c @@ -192,9 +198,9 @@ ask_price [type=median allowedFaults=3 index=2]; prepConfFn: func(c CsDistributeStreamJobSpecsConfig) CsDistributeStreamJobSpecsConfig { c.NodeNames = []string{"non-existing-node"} c.Filter = &jd.ListFilter{ - DONID: donID, - DONName: donName, - EnvLabel: envName, + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 1, } return c @@ -230,6 +236,21 @@ ask_price [type=median allowedFaults=3 index=2]; testutil.StripLineContaining(out[0].Jobs[i].Spec, []string{"externalJobID"}), ) } + // Ensure the labels are set correctly + for _, job := range out[0].Jobs { + j, err := env.Offchain.GetJob(t.Context(), &jdJob.GetJobRequest{ + IdOneof: &jdJob.GetJobRequest_Id{Id: job.JobID}, + }) + require.NoError(t, err) + foundLabel := false + for _, label := range j.GetJob().GetLabels() { + if label.GetKey() == "customTestLabel" && label.GetValue() == "customTestValue" { + foundLabel = true + break + } + } + require.True(t, foundLabel, "customTestLabel not found in job labels") + } }) } } @@ -241,9 +262,9 @@ func TestValidatePreconditions(t *testing.T) { config := CsDistributeStreamJobSpecsConfig{ Filter: &jd.ListFilter{ - DONID: 1, - DONName: "don", - EnvLabel: "env", + DONID: testutil.TestDON.ID, + DONName: testutil.TestDON.Name, + EnvLabel: testutil.TestDON.Env, NumOracleNodes: 1, }, Streams: []StreamSpecConfig{ diff --git a/deployment/data-streams/changeset/jd_register_nodes.go b/deployment/data-streams/changeset/jd_register_nodes.go index a40d0affce9..df782b5a15b 100644 --- a/deployment/data-streams/changeset/jd_register_nodes.go +++ b/deployment/data-streams/changeset/jd_register_nodes.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -46,7 +46,7 @@ func validateNodeSlice(nodes []NodeCfg, nodeType string, donIndex int) error { return nil } -func registerNodesForDON(e deployment.Environment, donName string, donID uint64, nodes []NodeCfg, baseLabels []*ptypes.Label, nodeType string) { +func registerNodesForDON(e cldf.Environment, donName string, donID uint64, nodes []NodeCfg, baseLabels []*ptypes.Label, nodeType string) { for _, node := range nodes { labels := append([]*ptypes.Label(nil), baseLabels...) @@ -72,7 +72,7 @@ func registerNodesForDON(e deployment.Environment, donName string, donID uint64, } } -func registerNodesWithJDLogic(e deployment.Environment, cfg RegisterNodesInput) (cldf.ChangesetOutput, error) { +func registerNodesWithJDLogic(e cldf.Environment, cfg RegisterNodesInput) (cldf.ChangesetOutput, error) { baseLabels := []*ptypes.Label{ { Key: devenv.LabelProductKey, @@ -124,6 +124,6 @@ func (cfg RegisterNodesInput) Validate() error { return nil } -func registerNodesWithJDPrecondition(_ deployment.Environment, cfg RegisterNodesInput) error { +func registerNodesWithJDPrecondition(_ cldf.Environment, cfg RegisterNodesInput) error { return cfg.Validate() } diff --git a/deployment/data-streams/changeset/jd_revoke_jobs.go b/deployment/data-streams/changeset/jd_revoke_jobs.go new file mode 100644 index 00000000000..45feec61c0d --- /dev/null +++ b/deployment/data-streams/changeset/jd_revoke_jobs.go @@ -0,0 +1,97 @@ +package changeset + +import ( + "errors" + "fmt" + "strconv" + "strings" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" +) + +var _ cldf.ChangeSetV2[CsRevokeJobSpecsConfig] = CsRevokeJobSpecs{} + +// CsRevokeJobSpecsConfig is the configuration for the revoking a job. +// In order to revoke a job, we need to know one of two things: +// 1. The external job ID (UUID) of the job. +// 2. The stream ID to which the job belongs. +// +// Note that only one set of IDs (UUIDs or stream IDs) is allowed. +type CsRevokeJobSpecsConfig struct { + // UUIDs is a list of external job IDs to revoke. + UUIDs []string + + StreamIDs []uint32 +} + +type CsRevokeJobSpecs struct{} + +func (CsRevokeJobSpecs) Apply(e cldf.Environment, cfg CsRevokeJobSpecsConfig) (cldf.ChangesetOutput, error) { + var filter *jobv1.ListJobsRequest_Filter + switch { + case len(cfg.UUIDs) > 0 && len(cfg.StreamIDs) == 0: + filter = &jobv1.ListJobsRequest_Filter{ + Uuids: cfg.UUIDs, + } + case len(cfg.StreamIDs) > 0 && len(cfg.UUIDs) == 0: + ids := make([]string, len(cfg.StreamIDs)) + for i, id := range cfg.StreamIDs { + ids[i] = strconv.FormatUint(uint64(id), 10) + } + filter = &jobv1.ListJobsRequest_Filter{ + Selectors: []*ptypes.Selector{ + { + Key: devenv.LabelStreamIDKey, + Op: ptypes.SelectorOp_IN, + Value: pointer.To(strings.Join(ids, ",")), + }, + }, + } + default: + return cldf.ChangesetOutput{}, errors.New("either job ids or stream ids are required") + } + + // Fetch the internal job IDs from the job distributor: + jobsResp, err := e.Offchain.ListJobs(e.GetContext(), &jobv1.ListJobsRequest{ + Filter: filter, + }) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to list jobs: %w", err) + } + if len(cfg.UUIDs) > 0 && len(jobsResp.Jobs) != len(cfg.UUIDs) { + return cldf.ChangesetOutput{}, errors.New("failed to find jobs for all provided UUIDs") + } + + revokedJobs := make([]cldf.ProposedJob, 0, len(jobsResp.Jobs)) + for _, job := range jobsResp.Jobs { + resp, err := e.Offchain.RevokeJob(e.GetContext(), &jobv1.RevokeJobRequest{ + IdOneof: &jobv1.RevokeJobRequest_Id{ + Id: job.GetId(), + }, + }) + if err != nil { + return cldf.ChangesetOutput{}, fmt.Errorf("failed to revoke job: %w", err) + } + revokedJobs = append(revokedJobs, cldf.ProposedJob{ + JobID: resp.GetProposal().GetJobId(), + Spec: resp.GetProposal().GetSpec(), + }) + } + + return cldf.ChangesetOutput{ + Jobs: revokedJobs, + }, nil +} + +func (f CsRevokeJobSpecs) VerifyPreconditions(_ cldf.Environment, config CsRevokeJobSpecsConfig) error { + if (len(config.UUIDs) == 0 && len(config.StreamIDs) == 0) || (len(config.UUIDs) > 0 && len(config.StreamIDs) > 0) { + return errors.New("either job ids or stream ids are required") + } + + return nil +} diff --git a/deployment/data-streams/changeset/jd_revoke_jobs_test.go b/deployment/data-streams/changeset/jd_revoke_jobs_test.go new file mode 100644 index 00000000000..f6f0b6ddf27 --- /dev/null +++ b/deployment/data-streams/changeset/jd_revoke_jobs_test.go @@ -0,0 +1,173 @@ +package changeset + +import ( + "regexp" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + + "github.com/smartcontractkit/chainlink/deployment/common/changeset" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/testutil" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" +) + +func TestRevokeJobSpecs(t *testing.T) { + t.Parallel() + + const numBootstraps = 1 + const numOracles = 2 + + env := testutil.NewMemoryEnvV2(t, testutil.MemoryEnvConfig{ + ShouldDeployMCMS: false, + ShouldDeployLinkToken: false, + NumBootstrapNodes: numBootstraps, + NumNodes: numOracles, + NodeLabels: []*ptypes.Label{ + { + Key: devenv.LabelProductKey, + Value: pointer.To(utils.ProductLabel), + }, + { + Key: devenv.LabelEnvironmentKey, + Value: pointer.To(testutil.TestDON.Env), + }, + { + Key: utils.DonIdentifier(testutil.TestDON.ID, testutil.TestDON.Name), + }, + }, + CustomDBSetup: []string{ + // Seed the database with the list of bridges we're using. + `INSERT INTO bridge_types (name, url, confirmations, incoming_token_hash, salt, outgoing_token, created_at, updated_at) + VALUES ('bridge-api1', 'http://url', 0, '', '', '', now(), now());`, + `INSERT INTO bridge_types (name, url, confirmations, incoming_token_hash, salt, outgoing_token, created_at, updated_at) + VALUES ('bridge-api2', 'http://url', 0, '', '', '', now(), now());`, + `INSERT INTO bridge_types (name, url, confirmations, incoming_token_hash, salt, outgoing_token, created_at, updated_at) + VALUES ('bridge-api3', 'http://url', 0, '', '', '', now(), now());`, + `INSERT INTO bridge_types (name, url, confirmations, incoming_token_hash, salt, outgoing_token, created_at, updated_at) + VALUES ('bridge-api4', 'http://url', 0, '', '', '', now(), now());`, + }, + }).Environment + + uuidFromJobSpec := func(jobSpec string) string { + matches := regexp.MustCompile(`externalJobID\s*=\s*'([a-f0-9-]+)'`).FindStringSubmatch(jobSpec) + require.Len(t, matches, 2, "expected to find a UUID in the job spec") + return matches[1] + } + + // Create some jobs: + sentLLOJobs := sendTestLLOJobs(t, env, numOracles, numBootstraps, false) + require.Len(t, sentLLOJobs, 1) + require.Len(t, sentLLOJobs[0].Jobs, numBootstraps+numOracles) + + var oracleJobUUIDs, btJobUUIDs []string + for _, job := range sentLLOJobs[0].Jobs { + if strings.Contains(job.Spec, "bootstrap") { + btJobUUIDs = append(btJobUUIDs, uuidFromJobSpec(job.Spec)) + } else if strings.Contains(job.Spec, "offchainreporting2") { + oracleJobUUIDs = append(oracleJobUUIDs, uuidFromJobSpec(job.Spec)) + } + } + + // Create some stream jobs: + sentStreamJobs := sendTestStreamJobs(t, env, numOracles, false) + require.Len(t, sentStreamJobs, 1) + require.Len(t, sentStreamJobs[0].Jobs, numOracles) + + streamIDFromJobSpec := func(jobSpec string) string { + matches := regexp.MustCompile(`streamID\s*=\s*([0-9]+)`).FindStringSubmatch(jobSpec) + require.Len(t, matches, 2, "expected to find a stream ID in the job spec") + return matches[1] + } + + var streamIDs []uint32 + streamIDsToJobIDs := make(map[uint32][]string) + for _, job := range sentStreamJobs[0].Jobs { + s, e := strconv.ParseUint(streamIDFromJobSpec(job.Spec), 10, 32) + require.NoError(t, e) + streamIDs = append(streamIDs, uint32(s)) + streamIDsToJobIDs[uint32(s)] = append(streamIDsToJobIDs[uint32(s)], uuidFromJobSpec(job.Spec)) + } + + tests := []struct { + name string + uuids []string + streamIDs []uint32 + wantErr string + wantJobIDs []string + wantNumJobs int + }{ + { + name: "Revoke an oracle job", + uuids: oracleJobUUIDs, + wantJobIDs: oracleJobUUIDs, + wantNumJobs: numOracles, + }, + { + name: "Revoke the same job again", + uuids: oracleJobUUIDs, + wantNumJobs: numOracles, + wantErr: "failed to revoke job", + }, + { + name: "Revoke a bootstrap job", + uuids: btJobUUIDs, + wantJobIDs: btJobUUIDs, + wantNumJobs: numBootstraps, + }, + { + name: "Revoke a non-existing job", + uuids: []string{"non-existing-job"}, + wantErr: "failed to find jobs for all provided UUIDs", + }, + { + name: "Revoke a stream job", + streamIDs: []uint32{streamIDs[0]}, + wantNumJobs: numOracles, + wantJobIDs: streamIDsToJobIDs[streamIDs[0]], + }, + { + name: "Fail when both stream ids and uuids are provided", + uuids: oracleJobUUIDs, + streamIDs: streamIDs, + wantNumJobs: numOracles, + wantErr: "either job ids or stream ids are required", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + _, out, err := changeset.ApplyChangesetsV2(t, + env, + []changeset.ConfiguredChangeSet{ + changeset.Configure(CsRevokeJobSpecs{}, CsRevokeJobSpecsConfig{ + UUIDs: tc.uuids, + StreamIDs: tc.streamIDs, + }), + }) + if tc.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.wantErr, "unexpected error message") + return + } + require.NoError(t, err) + require.Len(t, out, 1) + require.Len(t, out[0].Jobs, tc.wantNumJobs) + for _, wantedJobID := range tc.wantJobIDs { + found := false + for _, job := range out[0].Jobs { + if job.JobID == wantedJobID { + found = true + break + } + } + require.True(t, found, "expected to find job %s in the output", wantedJobID) + } + }) + } +} diff --git a/deployment/data-streams/changeset/mcms/deploy_and_transfer_mcms.go b/deployment/data-streams/changeset/mcms/deploy_and_transfer_mcms.go index 8ee0d6905e7..7eaea4ba547 100644 --- a/deployment/data-streams/changeset/mcms/deploy_and_transfer_mcms.go +++ b/deployment/data-streams/changeset/mcms/deploy_and_transfer_mcms.go @@ -6,7 +6,7 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonChangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" @@ -27,7 +27,7 @@ func (cc DeployMCMSConfig) GetOwnershipConfig() types.OwnershipSettings { return cc.Ownership } -func deployAndTransferMcmsLogic(e deployment.Environment, cc DeployMCMSConfig) (cldf.ChangesetOutput, error) { +func deployAndTransferMcmsLogic(e cldf.Environment, cc DeployMCMSConfig) (cldf.ChangesetOutput, error) { cfgByChain := make(map[uint64]commontypes.MCMSWithTimelockConfigV2) for _, chain := range cc.ChainsToDeploy { cfgByChain[chain] = cc.Config @@ -88,7 +88,7 @@ func deployAndTransferMcmsLogic(e deployment.Environment, cc DeployMCMSConfig) ( MCMSTimelockProposals: proposals}, nil } -func deployAndTransferMcmsPrecondition(_ deployment.Environment, cc DeployMCMSConfig) error { +func deployAndTransferMcmsPrecondition(_ cldf.Environment, cc DeployMCMSConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployMCMSConfig: %w", err) } @@ -100,7 +100,7 @@ func (cc DeployMCMSConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for _, chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } diff --git a/deployment/data-streams/changeset/reward-manager/call_claim_rewards.go b/deployment/data-streams/changeset/reward-manager/call_claim_rewards.go index c8d64af5ef1..f3d01ebce03 100644 --- a/deployment/data-streams/changeset/reward-manager/call_claim_rewards.go +++ b/deployment/data-streams/changeset/reward-manager/call_claim_rewards.go @@ -11,7 +11,7 @@ import ( rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -41,14 +41,14 @@ func (cfg ClaimRewardsConfig) Validate() error { return nil } -func claimRewardsPrecondition(_ deployment.Environment, cc ClaimRewardsConfig) error { +func claimRewardsPrecondition(_ cldf.Environment, cc ClaimRewardsConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid ClaimRewards config: %w", err) } return nil } -func claimRewardsLogic(e deployment.Environment, cfg ClaimRewardsConfig) (cldf.ChangesetOutput, error) { +func claimRewardsLogic(e cldf.Environment, cfg ClaimRewardsConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.RewardManager.String(), @@ -65,7 +65,7 @@ func claimRewardsLogic(e deployment.Environment, cfg ClaimRewardsConfig) (cldf.C func doClaimRewards(vs *rewardManager.RewardManager, cr ClaimRewards) (*goEthTypes.Transaction, error) { return vs.ClaimRewards( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), cr.PoolIDs, ) } diff --git a/deployment/data-streams/changeset/reward-manager/call_pay_recipients.go b/deployment/data-streams/changeset/reward-manager/call_pay_recipients.go index 816d14e3637..fc91af23b2d 100644 --- a/deployment/data-streams/changeset/reward-manager/call_pay_recipients.go +++ b/deployment/data-streams/changeset/reward-manager/call_pay_recipients.go @@ -11,7 +11,7 @@ import ( rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -42,14 +42,14 @@ func (cfg PayRecipientsConfig) Validate() error { return nil } -func PayRecipientsPrecondition(_ deployment.Environment, cc PayRecipientsConfig) error { +func PayRecipientsPrecondition(_ cldf.Environment, cc PayRecipientsConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid PayRecipients config: %w", err) } return nil } -func PayRecipientsLogic(e deployment.Environment, cfg PayRecipientsConfig) (cldf.ChangesetOutput, error) { +func PayRecipientsLogic(e cldf.Environment, cfg PayRecipientsConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.RewardManager.String(), @@ -66,7 +66,7 @@ func PayRecipientsLogic(e deployment.Environment, cfg PayRecipientsConfig) (cldf func doPayRecipients(vs *rewardManager.RewardManager, pr PayRecipients) (*goEthTypes.Transaction, error) { return vs.PayRecipients( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), pr.PoolID, pr.Recipients, ) diff --git a/deployment/data-streams/changeset/reward-manager/call_set_fee_manager.go b/deployment/data-streams/changeset/reward-manager/call_set_fee_manager.go index 32ea1f92070..9a09b7288e7 100644 --- a/deployment/data-streams/changeset/reward-manager/call_set_fee_manager.go +++ b/deployment/data-streams/changeset/reward-manager/call_set_fee_manager.go @@ -44,7 +44,7 @@ func (cfg SetFeeManagerConfig) Validate() error { return nil } -func SetFeeManagerPrecondition(e deployment.Environment, sf SetFeeManagerConfig) error { +func SetFeeManagerPrecondition(e cldf.Environment, sf SetFeeManagerConfig) error { for chainSelector, configs := range sf.ConfigsByChain { for _, config := range configs { confState, err := loadRewardManagerState(e, chainSelector, config.RewardManagerAddress.Hex()) @@ -72,7 +72,7 @@ func SetFeeManagerPrecondition(e deployment.Environment, sf SetFeeManagerConfig) return nil } -func SetFeeManagerLogic(e deployment.Environment, cfg SetFeeManagerConfig) (cldf.ChangesetOutput, error) { +func SetFeeManagerLogic(e cldf.Environment, cfg SetFeeManagerConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.FeeManager.String(), @@ -89,7 +89,7 @@ func SetFeeManagerLogic(e deployment.Environment, cfg SetFeeManagerConfig) (cldf func doSetFeeManager(vs *rewardManager.RewardManager, sf SetFeeManager) (*goEthTypes.Transaction, error) { return vs.SetFeeManager( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), sf.FeeManagerAddress, ) } diff --git a/deployment/data-streams/changeset/reward-manager/call_set_reward_recipients.go b/deployment/data-streams/changeset/reward-manager/call_set_reward_recipients.go index d1b228eba05..5b2ad63b3a5 100644 --- a/deployment/data-streams/changeset/reward-manager/call_set_reward_recipients.go +++ b/deployment/data-streams/changeset/reward-manager/call_set_reward_recipients.go @@ -11,7 +11,7 @@ import ( rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -42,14 +42,14 @@ func (cfg SetRewardRecipientsConfig) Validate() error { return nil } -func setRewardRecipientsPrecondition(_ deployment.Environment, cc SetRewardRecipientsConfig) error { +func setRewardRecipientsPrecondition(_ cldf.Environment, cc SetRewardRecipientsConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid SetRewardRecipients config: %w", err) } return nil } -func setRewardRecipientsLogic(e deployment.Environment, cfg SetRewardRecipientsConfig) (cldf.ChangesetOutput, error) { +func setRewardRecipientsLogic(e cldf.Environment, cfg SetRewardRecipientsConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.RewardManager.String(), @@ -66,7 +66,7 @@ func setRewardRecipientsLogic(e deployment.Environment, cfg SetRewardRecipientsC func doSetRewardRecipients(vs *rewardManager.RewardManager, sr SetRewardRecipients) (*goEthTypes.Transaction, error) { return vs.SetRewardRecipients( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), sr.PoolID, sr.RewardRecipientAndWeights, ) diff --git a/deployment/data-streams/changeset/reward-manager/call_update_reward_recipients.go b/deployment/data-streams/changeset/reward-manager/call_update_reward_recipients.go index 482b10776aa..ce27fb1c594 100644 --- a/deployment/data-streams/changeset/reward-manager/call_update_reward_recipients.go +++ b/deployment/data-streams/changeset/reward-manager/call_update_reward_recipients.go @@ -11,7 +11,7 @@ import ( rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -42,14 +42,14 @@ func (cfg UpdateRewardRecipientsConfig) Validate() error { return nil } -func updateRewardRecipientsPrecondition(_ deployment.Environment, cc UpdateRewardRecipientsConfig) error { +func updateRewardRecipientsPrecondition(_ cldf.Environment, cc UpdateRewardRecipientsConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid UpdateRewardRecipients config: %w", err) } return nil } -func updateRewardRecipientsLogic(e deployment.Environment, cfg UpdateRewardRecipientsConfig) (cldf.ChangesetOutput, error) { +func updateRewardRecipientsLogic(e cldf.Environment, cfg UpdateRewardRecipientsConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.RewardManager.String(), @@ -66,7 +66,7 @@ func updateRewardRecipientsLogic(e deployment.Environment, cfg UpdateRewardRecip func doUpdateRewardRecipients(vs *rewardManager.RewardManager, ur UpdateRewardRecipients) (*goEthTypes.Transaction, error) { return vs.UpdateRewardRecipients( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), ur.PoolID, ur.RewardRecipientAndWeights, ) diff --git a/deployment/data-streams/changeset/reward-manager/deploy_reward_manager.go b/deployment/data-streams/changeset/reward-manager/deploy_reward_manager.go index d5479778a5c..1d9352c2da3 100644 --- a/deployment/data-streams/changeset/reward-manager/deploy_reward_manager.go +++ b/deployment/data-streams/changeset/reward-manager/deploy_reward_manager.go @@ -6,9 +6,10 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/view/v0_5" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" @@ -41,19 +42,19 @@ func (cc DeployRewardManagerConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func deployRewardManagerLogic(e deployment.Environment, cc DeployRewardManagerConfig) (cldf.ChangesetOutput, error) { +func deployRewardManagerLogic(e cldf.Environment, cc DeployRewardManagerConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() err := deployRewardManager(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy RewardManager", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -76,7 +77,7 @@ func deployRewardManagerLogic(e deployment.Environment, cc DeployRewardManagerCo }, nil } -func deployRewardManagerPrecondition(_ deployment.Environment, cc DeployRewardManagerConfig) error { +func deployRewardManagerPrecondition(_ cldf.Environment, cc DeployRewardManagerConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployRewardManagerConfig: %w", err) } @@ -84,7 +85,7 @@ func deployRewardManagerPrecondition(_ deployment.Environment, cc DeployRewardMa return nil } -func deployRewardManager(e deployment.Environment, +func deployRewardManager(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployRewardManagerConfig) error { if err := cc.Validate(); err != nil { @@ -127,7 +128,7 @@ func deployRewardManager(e deployment.Environment, } func RewardManagerDeployFn(linkAddress common.Address) changeset.ContractDeployFn[*rewardManager.RewardManager] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*rewardManager.RewardManager] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*rewardManager.RewardManager] { ccsAddr, ccsTx, ccs, err := rewardManager.DeployRewardManager( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/reward-manager/reward_manager.go b/deployment/data-streams/changeset/reward-manager/reward_manager.go index 020389c41e9..0a036203225 100644 --- a/deployment/data-streams/changeset/reward-manager/reward_manager.go +++ b/deployment/data-streams/changeset/reward-manager/reward_manager.go @@ -5,15 +5,18 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" + "github.com/smartcontractkit/chainlink/deployment" ) func loadRewardManagerState( - e deployment.Environment, + e cldf.Environment, chainSel uint64, contractAddr string, ) (*rewardManager.RewardManager, error) { diff --git a/deployment/data-streams/changeset/reward-manager/test_helpers.go b/deployment/data-streams/changeset/reward-manager/test_helpers.go index ccdb41ed1bb..a42d6de382b 100644 --- a/deployment/data-streams/changeset/reward-manager/test_helpers.go +++ b/deployment/data-streams/changeset/reward-manager/test_helpers.go @@ -6,6 +6,9 @@ import ( "github.com/stretchr/testify/require" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" dsTypes "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" @@ -22,7 +25,7 @@ import ( func RewardManagerDeploy( t *testing.T, cfg testutil.MemoryEnv, -) (deployment.Environment, common.Address) { +) (cldf.Environment, common.Address) { t.Helper() chainSelector := testutil.TestChain.Selector diff --git a/deployment/data-streams/changeset/save_contract_views.go b/deployment/data-streams/changeset/save_contract_views.go index 2a490e22980..3857f997e65 100644 --- a/deployment/data-streams/changeset/save_contract_views.go +++ b/deployment/data-streams/changeset/save_contract_views.go @@ -8,7 +8,7 @@ import ( ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" dsstate "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/state" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" @@ -30,11 +30,11 @@ func (cfg SaveContractViewsConfig) Validate() error { return nil } -func saveViewsPrecondition(_ deployment.Environment, cc SaveContractViewsConfig) error { +func saveViewsPrecondition(_ cldf.Environment, cc SaveContractViewsConfig) error { return cc.Validate() } -func saveViewsLogic(e deployment.Environment, cfg SaveContractViewsConfig) (cldf.ChangesetOutput, error) { +func saveViewsLogic(e cldf.Environment, cfg SaveContractViewsConfig) (cldf.ChangesetOutput, error) { updatedDataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() records, err := e.DataStore.Addresses().Fetch() if err != nil { diff --git a/deployment/data-streams/changeset/sequence/deploy_chain_contracts.go b/deployment/data-streams/changeset/sequence/deploy_chain_contracts.go index 72835a01128..7f2ec85f12f 100644 --- a/deployment/data-streams/changeset/sequence/deploy_chain_contracts.go +++ b/deployment/data-streams/changeset/sequence/deploy_chain_contracts.go @@ -9,10 +9,10 @@ import ( ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/verification" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" @@ -32,7 +32,7 @@ type DeployDataStreams struct { Ownership types.OwnershipFeature } -func deployDataStreamsLogic(e deployment.Environment, cc DeployDataStreamsConfig) (cldf.ChangesetOutput, error) { +func deployDataStreamsLogic(e cldf.Environment, cc DeployDataStreamsConfig) (cldf.ChangesetOutput, error) { deployedAddresses := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() // Prevents mutating environment state - injected environment is not expected to be updated during changeset Apply @@ -82,7 +82,7 @@ func deployDataStreamsLogic(e deployment.Environment, cc DeployDataStreamsConfig }, nil } -func deployDataStreamsPrecondition(_ deployment.Environment, cc DeployDataStreamsConfig) error { +func deployDataStreamsPrecondition(_ cldf.Environment, cc DeployDataStreamsConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployDataStreams config: %w", err) } @@ -101,7 +101,7 @@ func (cc DeployDataStreamsConfig) Validate() error { } for chain, cfg := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } diff --git a/deployment/data-streams/changeset/sequence/deploy_chain_contracts_evm.go b/deployment/data-streams/changeset/sequence/deploy_chain_contracts_evm.go index 16291014e8c..1aefcce462d 100644 --- a/deployment/data-streams/changeset/sequence/deploy_chain_contracts_evm.go +++ b/deployment/data-streams/changeset/sequence/deploy_chain_contracts_evm.go @@ -7,6 +7,9 @@ import ( "github.com/smartcontractkit/mcms" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + mcms2 "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/mcms" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" dsutil "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" @@ -19,7 +22,7 @@ import ( ) // deployChainComponentsEVM deploys all necessary components for a single evm chain -func deployChainComponentsEVM(env *deployment.Environment, chain uint64, cfg DeployDataStreams, +func deployChainComponentsEVM(env *cldf.Environment, chain uint64, cfg DeployDataStreams, newAddresses metadata.DataStreamsMutableDataStore) ([]mcms.TimelockProposal, error) { var timelockProposals []mcms.TimelockProposal // Step 1: Deploy MCMS if configured @@ -68,7 +71,7 @@ func deployChainComponentsEVM(env *deployment.Environment, chain uint64, cfg Dep } // deployVerifierProxy deploys VerifierProxy contract -func deployVerifierProxy(env *deployment.Environment, chain uint64, cfg DeployDataStreams, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { +func deployVerifierProxy(env *cldf.Environment, chain uint64, cfg DeployDataStreams, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { verifierProxyCfg := verification.DeployVerifierProxyConfig{ ChainsToDeploy: map[uint64]verification.DeployVerifierProxy{ chain: {}, @@ -96,7 +99,7 @@ func deployVerifierProxy(env *deployment.Environment, chain uint64, cfg DeployDa } // deployVerifier deploys Verifier contract -func deployVerifier(env *deployment.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { +func deployVerifier(env *cldf.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { verifierCfg := verification.DeployVerifierConfig{ ChainsToDeploy: map[uint64]verification.DeployVerifier{ chain: {VerifierProxyAddress: verifierProxyAddr}, @@ -124,7 +127,7 @@ func deployVerifier(env *deployment.Environment, chain uint64, cfg DeployDataStr } // initializeVerifier initializes the Verifier in VerifierProxy -func initializeVerifier(env *deployment.Environment, chain uint64, verifierProxyAddr, verifierAddr common.Address) error { +func initializeVerifier(env *cldf.Environment, chain uint64, verifierProxyAddr, verifierAddr common.Address) error { initVerifierCfg := verification.VerifierProxyInitializeVerifierConfig{ ConfigPerChain: map[uint64][]verification.InitializeVerifierConfig{ chain: {{ @@ -143,7 +146,7 @@ func initializeVerifier(env *deployment.Environment, chain uint64, verifierProxy } // setVerifierConfig sets the configuration for the Verifier -func setVerifierConfig(env *deployment.Environment, chain uint64, cfg DeployDataStreams, verifierAddr common.Address) error { +func setVerifierConfig(env *cldf.Environment, chain uint64, cfg DeployDataStreams, verifierAddr common.Address) error { setCfg := verification.SetConfigConfig{ ConfigsByChain: map[uint64][]verification.SetConfig{ chain: {verification.SetConfig{ @@ -165,7 +168,7 @@ func setVerifierConfig(env *deployment.Environment, chain uint64, cfg DeployData } // deployBillingComponents deploys and configures RewardManager and FeeManager -func deployBillingComponents(env *deployment.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) ([]mcms.TimelockProposal, error) { +func deployBillingComponents(env *cldf.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) ([]mcms.TimelockProposal, error) { var timelockProposals []mcms.TimelockProposal // Step 1: Deploy RewardManager @@ -201,7 +204,7 @@ func deployBillingComponents(env *deployment.Environment, chain uint64, cfg Depl } // deployRewardManager deploys the RewardManager contract -func deployRewardManager(env *deployment.Environment, chain uint64, cfg DeployDataStreams, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { +func deployRewardManager(env *cldf.Environment, chain uint64, cfg DeployDataStreams, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { rewardMgrCfg := rewardmanager.DeployRewardManagerConfig{ ChainsToDeploy: map[uint64]rewardmanager.DeployRewardManager{ chain: {LinkTokenAddress: cfg.Billing.Config.LinkTokenAddress}, @@ -229,7 +232,7 @@ func deployRewardManager(env *deployment.Environment, chain uint64, cfg DeployDa } // deployFeeManager deploys the FeeManager contract -func deployFeeManager(env *deployment.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr, rewardMgrAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { +func deployFeeManager(env *cldf.Environment, chain uint64, cfg DeployDataStreams, verifierProxyAddr, rewardMgrAddr common.Address, newAddresses metadata.DataStreamsMutableDataStore) (common.Address, []mcms.TimelockProposal, error) { feeMgrCfg := feemanager.DeployFeeManagerConfig{ ChainsToDeploy: map[uint64]feemanager.DeployFeeManager{ chain: { @@ -262,7 +265,7 @@ func deployFeeManager(env *deployment.Environment, chain uint64, cfg DeployDataS } // setNativeSurcharge sets the native surcharge on the FeeManager -func setNativeSurcharge(env *deployment.Environment, chain uint64, cfg DeployDataStreams, feeManagerAddr common.Address) error { +func setNativeSurcharge(env *cldf.Environment, chain uint64, cfg DeployDataStreams, feeManagerAddr common.Address) error { setNativeCfg := feemanager.SetNativeSurchargeConfig{ ConfigPerChain: map[uint64][]feemanager.SetNativeSurcharge{ chain: { @@ -283,7 +286,7 @@ func setNativeSurcharge(env *deployment.Environment, chain uint64, cfg DeployDat } // setFeeManagerOnVerifierProxy sets the FeeManager address on the VerifierProxy -func setFeeManagerOnVerifierProxy(env *deployment.Environment, chain uint64, verifierProxyAddr, feeManagerAddr common.Address) error { +func setFeeManagerOnVerifierProxy(env *cldf.Environment, chain uint64, verifierProxyAddr, feeManagerAddr common.Address) error { setFeeManagerCfg := verification.VerifierProxySetFeeManagerConfig{ ConfigPerChain: map[uint64][]verification.SetFeeManagerConfig{ chain: { @@ -304,7 +307,7 @@ func setFeeManagerOnVerifierProxy(env *deployment.Environment, chain uint64, ver } // setFeeManagerOnRewardManager sets the FeeManager address on the RewardManager -func setFeeManagerOnRewardManager(env *deployment.Environment, chain uint64, rewardMgrAddr, feeManagerAddr common.Address) error { +func setFeeManagerOnRewardManager(env *cldf.Environment, chain uint64, rewardMgrAddr, feeManagerAddr common.Address) error { rmSetFeeManagerCfg := rewardmanager.SetFeeManagerConfig{ ConfigsByChain: map[uint64][]rewardmanager.SetFeeManager{ chain: { @@ -326,12 +329,12 @@ func setFeeManagerOnRewardManager(env *deployment.Environment, chain uint64, rew type DeployOutput struct { Addresses []string - Environment deployment.Environment + Environment cldf.Environment Proposals []mcms.TimelockProposal } // deployMCMS deploys the MCMS contracts -func deployMCMS(env *deployment.Environment, chain uint64, cfg DeployDataStreams, cumulativeAddresses metadata.DataStreamsMutableDataStore) ([]mcms.TimelockProposal, error) { +func deployMCMS(env *cldf.Environment, chain uint64, cfg DeployDataStreams, cumulativeAddresses metadata.DataStreamsMutableDataStore) ([]mcms.TimelockProposal, error) { mcmsDeployCfg := mcms2.DeployMCMSConfig{ ChainsToDeploy: []uint64{chain}, Ownership: cfg.Ownership.AsSettings(), @@ -353,7 +356,7 @@ func deployMCMS(env *deployment.Environment, chain uint64, cfg DeployDataStreams // mergeNewAddresses merges new addresses into the existing environment and cumulative address book // This is used when chaining together changesets and accumulating addresses while also updating // the environment with new addresses so that downstream operations can use them -func mergeNewAddresses(env *deployment.Environment, +func mergeNewAddresses(env *cldf.Environment, cumulativeAddrs metadata.DataStreamsMutableDataStore, newAddrs ds.DataStore[ds.DefaultMetadata, ds.DefaultMetadata]) error { // Step 1 is update the existing environment to reflect newly deployed addresses diff --git a/deployment/data-streams/changeset/state/evm.go b/deployment/data-streams/changeset/state/evm.go index 0a31606b813..15f1f187208 100644 --- a/deployment/data-streams/changeset/state/evm.go +++ b/deployment/data-streams/changeset/state/evm.go @@ -9,6 +9,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" "github.com/smartcontractkit/chainlink/deployment/data-streams/contracts/evm" @@ -25,8 +28,6 @@ import ( rewardManager "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/reward_manager_v0_5_0" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0" verifier "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" - - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) type DataStreamsEVMChainState struct { @@ -48,7 +49,7 @@ type DataStreamsOnChainState struct { Chains map[uint64]DataStreamsEVMChainState } -func LoadOnchainState(e deployment.Environment) (DataStreamsOnChainState, error) { +func LoadOnchainState(e cldf.Environment) (DataStreamsOnChainState, error) { state := DataStreamsOnChainState{ Chains: make(map[uint64]DataStreamsEVMChainState), } @@ -74,7 +75,7 @@ func LoadOnchainState(e deployment.Environment) (DataStreamsOnChainState, error) } func LoadChainState(logger logger.Logger, - chain deployment.Chain, + chain cldf.Chain, addresses map[string]cldf.TypeAndVersion, mdStore datastore.ContractMetadataStore[metadata.SerializedContractMetadata]) (*DataStreamsEVMChainState, error) { var cc DataStreamsEVMChainState diff --git a/deployment/data-streams/changeset/testutil/test_helpers.go b/deployment/data-streams/changeset/testutil/test_helpers.go index 8a97e9690e0..5b3c48f55c9 100644 --- a/deployment/data-streams/changeset/testutil/test_helpers.go +++ b/deployment/data-streams/changeset/testutil/test_helpers.go @@ -10,12 +10,13 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + dsCs "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/mcms" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" @@ -25,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment" commonChangesets "github.com/smartcontractkit/chainlink/deployment/common/changeset" dsTypes "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -41,9 +41,20 @@ var TestChain = chainselectors.Chain{ VarName: "", } +// TestDON is the DON we use in tests. +var TestDON = struct { + ID uint64 + Name string + Env string +}{ + ID: 1, + Name: "don", + Env: "memory", +} + // NewMemoryEnv Deploys a memory environment with the provided number of nodes and optionally deploys MCMS and Timelock. // Deprecated: use NewMemoryEnvV2 instead. -func NewMemoryEnv(t *testing.T, deployMCMS bool, optionalNumNodes ...int) deployment.Environment { +func NewMemoryEnv(t *testing.T, deployMCMS bool, optionalNumNodes ...int) cldf.Environment { lggr := logger.TestLogger(t) // Default to 0 if no extra argument is provided @@ -89,7 +100,7 @@ type MemoryEnvConfig struct { } type MemoryEnv struct { - Environment deployment.Environment + Environment cldf.Environment Timelocks map[uint64]*proposalutils.TimelockExecutionContracts LinkTokenState *commonstate.LinkTokenState } @@ -189,9 +200,9 @@ func NewMemoryEnvV2(t *testing.T, cfg MemoryEnvConfig) MemoryEnv { // Deploy MCMS and Timelock, optionally transferring ownership of the provided contracts to Timelock func DeployMCMS( t *testing.T, - e deployment.Environment, + e cldf.Environment, addressesToTransfer ...map[uint64][]common.Address, -) (env deployment.Environment, mcmsState *commonChangesets.MCMSWithTimelockState, timelocks map[uint64]*proposalutils.TimelockExecutionContracts) { +) (env cldf.Environment, mcmsState *commonChangesets.MCMSWithTimelockState, timelocks map[uint64]*proposalutils.TimelockExecutionContracts) { t.Helper() chainSelector := TestChain.Selector diff --git a/deployment/data-streams/changeset/verification/call_activate_config.go b/deployment/data-streams/changeset/verification/call_activate_config.go index 5710ba48133..f1395a7f028 100644 --- a/deployment/data-streams/changeset/verification/call_activate_config.go +++ b/deployment/data-streams/changeset/verification/call_activate_config.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -39,11 +39,11 @@ func (cfg ActivateConfigConfig) Validate() error { return nil } -func activateConfigPrecondition(_ deployment.Environment, cc ActivateConfigConfig) error { +func activateConfigPrecondition(_ cldf.Environment, cc ActivateConfigConfig) error { return cc.Validate() } -func activateConfigLogic(e deployment.Environment, cfg ActivateConfigConfig) (cldf.ChangesetOutput, error) { +func activateConfigLogic(e cldf.Environment, cfg ActivateConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.VerifierProxy.String(), @@ -63,7 +63,7 @@ func doActivateConfig( ac ActivateConfig, ) (*goEthTypes.Transaction, error) { return v.ActivateConfig( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), ac.ConfigDigest, ) } diff --git a/deployment/data-streams/changeset/verification/call_deactivate_config.go b/deployment/data-streams/changeset/verification/call_deactivate_config.go index 9d2fca30171..ef8fb25256a 100644 --- a/deployment/data-streams/changeset/verification/call_deactivate_config.go +++ b/deployment/data-streams/changeset/verification/call_deactivate_config.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -40,14 +40,14 @@ func (cfg DeactivateConfigConfig) Validate() error { return nil } -func deactivateConfigPrecondition(_ deployment.Environment, cc DeactivateConfigConfig) error { +func deactivateConfigPrecondition(_ cldf.Environment, cc DeactivateConfigConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid ActivateConfig config: %w", err) } return nil } -func deactivateConfigLogic(e deployment.Environment, cfg DeactivateConfigConfig) (cldf.ChangesetOutput, error) { +func deactivateConfigLogic(e cldf.Environment, cfg DeactivateConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.VerifierProxy.String(), @@ -64,7 +64,7 @@ func deactivateConfigLogic(e deployment.Environment, cfg DeactivateConfigConfig) func doDeactivateConfig(v *verifier_v0_5_0.Verifier, ac DeactivateConfig) (*goEthTypes.Transaction, error) { return v.DeactivateConfig( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), ac.ConfigDigest, ) } diff --git a/deployment/data-streams/changeset/verification/call_initialize_verifier.go b/deployment/data-streams/changeset/verification/call_initialize_verifier.go index 465f5b9e734..8e351d5e637 100644 --- a/deployment/data-streams/changeset/verification/call_initialize_verifier.go +++ b/deployment/data-streams/changeset/verification/call_initialize_verifier.go @@ -10,7 +10,6 @@ import ( mcmslib "github.com/smartcontractkit/mcms" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -29,7 +28,7 @@ type InitializeVerifierConfig struct { VerifierAddress common.Address } -func verifierProxyInitializeVerifierLogic(e deployment.Environment, cfg VerifierProxyInitializeVerifierConfig) (cldf.ChangesetOutput, error) { +func verifierProxyInitializeVerifierLogic(e cldf.Environment, cfg VerifierProxyInitializeVerifierConfig) (cldf.ChangesetOutput, error) { txs, err := GetInitializeVerifierTxs(e, cfg) if err != nil { return cldf.ChangesetOutput{}, err @@ -51,7 +50,7 @@ func verifierProxyInitializeVerifierLogic(e deployment.Environment, cfg Verifier // GetInitializeVerifierTxs - returns the transactions to set a verifier on the verifier proxy. // Does not sign the TXs -func GetInitializeVerifierTxs(e deployment.Environment, cfg VerifierProxyInitializeVerifierConfig) ([]*txutil.PreparedTx, error) { +func GetInitializeVerifierTxs(e cldf.Environment, cfg VerifierProxyInitializeVerifierConfig) ([]*txutil.PreparedTx, error) { var preparedTxs []*txutil.PreparedTx for chainSelector, configs := range cfg.ConfigPerChain { for _, config := range configs { @@ -59,7 +58,7 @@ func GetInitializeVerifierTxs(e deployment.Environment, cfg VerifierProxyInitial if err != nil { return nil, fmt.Errorf("failed to load verifier proxy state: %w", err) } - tx, err := state.VerifierProxy.InitializeVerifier(deployment.SimTransactOpts(), config.VerifierAddress) + tx, err := state.VerifierProxy.InitializeVerifier(cldf.SimTransactOpts(), config.VerifierAddress) if err != nil { return nil, fmt.Errorf("failed to create InitializeVerifier transaction: %w", err) } @@ -74,12 +73,12 @@ func GetInitializeVerifierTxs(e deployment.Environment, cfg VerifierProxyInitial return preparedTxs, nil } -func verifierProxyInitializeVerifierPrecondition(e deployment.Environment, cfg VerifierProxyInitializeVerifierConfig) error { +func verifierProxyInitializeVerifierPrecondition(e cldf.Environment, cfg VerifierProxyInitializeVerifierConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } diff --git a/deployment/data-streams/changeset/verification/call_set_access_controller.go b/deployment/data-streams/changeset/verification/call_set_access_controller.go index 203fa46cf92..127da0bc788 100644 --- a/deployment/data-streams/changeset/verification/call_set_access_controller.go +++ b/deployment/data-streams/changeset/verification/call_set_access_controller.go @@ -9,7 +9,7 @@ import ( mcmslib "github.com/smartcontractkit/mcms" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -30,7 +30,7 @@ type SetAccessControllerConfig struct { AccessControllerAddress common.Address } -func (v verifierProxySetAccessController) Apply(e deployment.Environment, cfg VerifierProxySetAccessControllerConfig) (cldf.ChangesetOutput, error) { +func (v verifierProxySetAccessController) Apply(e cldf.Environment, cfg VerifierProxySetAccessControllerConfig) (cldf.ChangesetOutput, error) { txs, err := GetSetAccessControllerTxs(e, cfg) if err != nil { return cldf.ChangesetOutput{}, err @@ -52,7 +52,7 @@ func (v verifierProxySetAccessController) Apply(e deployment.Environment, cfg Ve // GetSetAccessControllerTxs - returns the transactions to set the access controller on the verifier proxy. // Does not sign the TXs -func GetSetAccessControllerTxs(e deployment.Environment, cfg VerifierProxySetAccessControllerConfig) ([]*txutil.PreparedTx, error) { +func GetSetAccessControllerTxs(e cldf.Environment, cfg VerifierProxySetAccessControllerConfig) ([]*txutil.PreparedTx, error) { var preparedTxs []*txutil.PreparedTx for chainSelector, configs := range cfg.ConfigPerChain { for _, config := range configs { @@ -60,7 +60,7 @@ func GetSetAccessControllerTxs(e deployment.Environment, cfg VerifierProxySetAcc if err != nil { return nil, fmt.Errorf("failed to load verifier proxy state: %w", err) } - tx, err := state.VerifierProxy.SetAccessController(deployment.SimTransactOpts(), config.AccessControllerAddress) + tx, err := state.VerifierProxy.SetAccessController(cldf.SimTransactOpts(), config.AccessControllerAddress) if err != nil { return nil, fmt.Errorf("failed to create SetAccessController transaction: %w", err) @@ -76,12 +76,12 @@ func GetSetAccessControllerTxs(e deployment.Environment, cfg VerifierProxySetAcc return preparedTxs, nil } -func (v verifierProxySetAccessController) VerifyPreconditions(e deployment.Environment, cfg VerifierProxySetAccessControllerConfig) error { +func (v verifierProxySetAccessController) VerifyPreconditions(e cldf.Environment, cfg VerifierProxySetAccessControllerConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } diff --git a/deployment/data-streams/changeset/verification/call_set_config.go b/deployment/data-streams/changeset/verification/call_set_config.go index 52a5ecdd86f..0aabffc9b06 100644 --- a/deployment/data-streams/changeset/verification/call_set_config.go +++ b/deployment/data-streams/changeset/verification/call_set_config.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -43,14 +43,14 @@ func (cfg SetConfigConfig) Validate() error { return nil } -func setConfigPrecondition(_ deployment.Environment, cc SetConfigConfig) error { +func setConfigPrecondition(_ cldf.Environment, cc SetConfigConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid SetConfig config: %w", err) } return nil } -func setConfigLogic(e deployment.Environment, cfg SetConfigConfig) (cldf.ChangesetOutput, error) { +func setConfigLogic(e cldf.Environment, cfg SetConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.Verifier.String(), @@ -67,7 +67,7 @@ func setConfigLogic(e deployment.Environment, cfg SetConfigConfig) (cldf.Changes func doSetConfig(v *verifier_v0_5_0.Verifier, ac SetConfig) (*goEthTypes.Transaction, error) { return v.SetConfig( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), ac.ConfigDigest, ac.Signers, ac.F, diff --git a/deployment/data-streams/changeset/verification/call_set_fee_manager.go b/deployment/data-streams/changeset/verification/call_set_fee_manager.go index 1b89d7f30f6..498e9af2043 100644 --- a/deployment/data-streams/changeset/verification/call_set_fee_manager.go +++ b/deployment/data-streams/changeset/verification/call_set_fee_manager.go @@ -9,7 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -28,7 +27,7 @@ type SetFeeManagerConfig struct { FeeManagerAddress common.Address } -func verifierProxySetFeeManagerLogic(e deployment.Environment, cfg VerifierProxySetFeeManagerConfig) (cldf.ChangesetOutput, error) { +func verifierProxySetFeeManagerLogic(e cldf.Environment, cfg VerifierProxySetFeeManagerConfig) (cldf.ChangesetOutput, error) { txs, err := GetSetFeeManagerTxs(e, cfg) if err != nil { return cldf.ChangesetOutput{}, err @@ -50,7 +49,7 @@ func verifierProxySetFeeManagerLogic(e deployment.Environment, cfg VerifierProxy // GetSetFeeManagerTxs - returns the transactions to set fee manager on the verifier proxy. // Does not sign the TXs -func GetSetFeeManagerTxs(e deployment.Environment, cfg VerifierProxySetFeeManagerConfig) ([]*txutil.PreparedTx, error) { +func GetSetFeeManagerTxs(e cldf.Environment, cfg VerifierProxySetFeeManagerConfig) ([]*txutil.PreparedTx, error) { var preparedTxs []*txutil.PreparedTx for chainSelector, configs := range cfg.ConfigPerChain { for _, config := range configs { @@ -58,7 +57,7 @@ func GetSetFeeManagerTxs(e deployment.Environment, cfg VerifierProxySetFeeManage if err != nil { return nil, fmt.Errorf("failed to load verifier proxy state: %w", err) } - tx, err := state.VerifierProxy.SetFeeManager(deployment.SimTransactOpts(), config.FeeManagerAddress) + tx, err := state.VerifierProxy.SetFeeManager(cldf.SimTransactOpts(), config.FeeManagerAddress) if err != nil { return nil, fmt.Errorf("failed to create SetFeeManager transaction: %w", err) } @@ -73,12 +72,12 @@ func GetSetFeeManagerTxs(e deployment.Environment, cfg VerifierProxySetFeeManage return preparedTxs, nil } -func verifierProxySetFeeManagerPrecondition(e deployment.Environment, cfg VerifierProxySetFeeManagerConfig) error { +func verifierProxySetFeeManagerPrecondition(e cldf.Environment, cfg VerifierProxySetFeeManagerConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } diff --git a/deployment/data-streams/changeset/verification/call_unset_verifier.go b/deployment/data-streams/changeset/verification/call_unset_verifier.go index ef190168610..9c3132ff026 100644 --- a/deployment/data-streams/changeset/verification/call_unset_verifier.go +++ b/deployment/data-streams/changeset/verification/call_unset_verifier.go @@ -9,7 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -30,7 +29,7 @@ type UnsetVerifierConfig struct { ConfigDigest [32]byte } -func (v verifierProxyUnsetVerifier) Apply(e deployment.Environment, cfg VerifierProxyUnsetVerifierConfig) (cldf.ChangesetOutput, error) { +func (v verifierProxyUnsetVerifier) Apply(e cldf.Environment, cfg VerifierProxyUnsetVerifierConfig) (cldf.ChangesetOutput, error) { txs, err := GetUnsetVerifierTxs(e, cfg) if err != nil { return cldf.ChangesetOutput{}, err @@ -52,7 +51,7 @@ func (v verifierProxyUnsetVerifier) Apply(e deployment.Environment, cfg Verifier // GetUnsetVerifierTxs - returns the transactions to run the operation on the verifier proxy. // Does not sign the TXs -func GetUnsetVerifierTxs(e deployment.Environment, cfg VerifierProxyUnsetVerifierConfig) ([]*txutil.PreparedTx, error) { +func GetUnsetVerifierTxs(e cldf.Environment, cfg VerifierProxyUnsetVerifierConfig) ([]*txutil.PreparedTx, error) { var preparedTxs []*txutil.PreparedTx for chainSelector, configs := range cfg.ConfigPerChain { for _, config := range configs { @@ -60,7 +59,7 @@ func GetUnsetVerifierTxs(e deployment.Environment, cfg VerifierProxyUnsetVerifie if err != nil { return nil, fmt.Errorf("failed to load verifier proxy state: %w", err) } - tx, err := state.VerifierProxy.UnsetVerifier(deployment.SimTransactOpts(), config.ConfigDigest) + tx, err := state.VerifierProxy.UnsetVerifier(cldf.SimTransactOpts(), config.ConfigDigest) if err != nil { return nil, fmt.Errorf("failed to create UnsetVerifier transaction: %w", err) } @@ -75,12 +74,12 @@ func GetUnsetVerifierTxs(e deployment.Environment, cfg VerifierProxyUnsetVerifie return preparedTxs, nil } -func (v verifierProxyUnsetVerifier) VerifyPreconditions(e deployment.Environment, cfg VerifierProxyUnsetVerifierConfig) error { +func (v verifierProxyUnsetVerifier) VerifyPreconditions(e cldf.Environment, cfg VerifierProxyUnsetVerifierConfig) error { if len(cfg.ConfigPerChain) == 0 { return errors.New("ConfigPerChain is empty") } for cs := range cfg.ConfigPerChain { - if err := deployment.IsValidChainSelector(cs); err != nil { + if err := cldf.IsValidChainSelector(cs); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", cs, err) } } diff --git a/deployment/data-streams/changeset/verification/call_update_config.go b/deployment/data-streams/changeset/verification/call_update_config.go index efdfc23b1d0..080d62a5fd6 100644 --- a/deployment/data-streams/changeset/verification/call_update_config.go +++ b/deployment/data-streams/changeset/verification/call_update_config.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/mcmsutil" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/txutil" @@ -42,14 +42,14 @@ func (cfg UpdateConfigConfig) Validate() error { return nil } -func updateConfigPrecondition(_ deployment.Environment, cc UpdateConfigConfig) error { +func updateConfigPrecondition(_ cldf.Environment, cc UpdateConfigConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid UpdateConfig config: %w", err) } return nil } -func updateConfigLogic(e deployment.Environment, cfg UpdateConfigConfig) (cldf.ChangesetOutput, error) { +func updateConfigLogic(e cldf.Environment, cfg UpdateConfigConfig) (cldf.ChangesetOutput, error) { txs, err := txutil.GetTxs( e, types.VerifierProxy.String(), @@ -66,7 +66,7 @@ func updateConfigLogic(e deployment.Environment, cfg UpdateConfigConfig) (cldf.C func doUpdateConfig(v *verifier_v0_5_0.Verifier, ac UpdateConfig) (*goEthTypes.Transaction, error) { return v.UpdateConfig( - deployment.SimTransactOpts(), + cldf.SimTransactOpts(), ac.ConfigDigest, ac.PrevSigners, ac.NewSigners, diff --git a/deployment/data-streams/changeset/verification/deploy_verifier.go b/deployment/data-streams/changeset/verification/deploy_verifier.go index 5f00fcd329e..580bece5479 100644 --- a/deployment/data-streams/changeset/verification/deploy_verifier.go +++ b/deployment/data-streams/changeset/verification/deploy_verifier.go @@ -6,13 +6,14 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/view/v0_5" verifier "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" @@ -40,19 +41,19 @@ func (cc DeployVerifierConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for chain := range cc.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func deployVerifierLogic(e deployment.Environment, cc DeployVerifierConfig) (cldf.ChangesetOutput, error) { +func deployVerifierLogic(e cldf.Environment, cc DeployVerifierConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() err := deployVerifier(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy Verifier", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -75,7 +76,7 @@ func deployVerifierLogic(e deployment.Environment, cc DeployVerifierConfig) (cld }, nil } -func deployVerifierPrecondition(_ deployment.Environment, cc DeployVerifierConfig) error { +func deployVerifierPrecondition(_ cldf.Environment, cc DeployVerifierConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployVerifierConfig: %w", err) } @@ -83,7 +84,7 @@ func deployVerifierPrecondition(_ deployment.Environment, cc DeployVerifierConfi return nil } -func deployVerifier(e deployment.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployVerifierConfig) error { +func deployVerifier(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cc DeployVerifierConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployVerifierConfig: %w", err) } @@ -125,7 +126,7 @@ func deployVerifier(e deployment.Environment, dataStore ds.MutableDataStore[meta } func VerifierDeployFn(verifierProxyAddress common.Address) changeset.ContractDeployFn[*verifier.Verifier] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*verifier.Verifier] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*verifier.Verifier] { ccsAddr, ccsTx, ccs, err := verifier.DeployVerifier( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/verification/deploy_verifier_proxy.go b/deployment/data-streams/changeset/verification/deploy_verifier_proxy.go index 3c4836cf731..4040cd89833 100644 --- a/deployment/data-streams/changeset/verification/deploy_verifier_proxy.go +++ b/deployment/data-streams/changeset/verification/deploy_verifier_proxy.go @@ -8,11 +8,13 @@ import ( "github.com/ethereum/go-ethereum/common" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/view/v0_5" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset" "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/metadata" @@ -49,19 +51,19 @@ func (cfg DeployVerifierProxyConfig) Validate() error { return errors.New("ChainsToDeploy is empty") } for chain := range cfg.ChainsToDeploy { - if err := deployment.IsValidChainSelector(chain); err != nil { + if err := cldf.IsValidChainSelector(chain); err != nil { return fmt.Errorf("invalid chain selector: %d - %w", chain, err) } } return nil } -func verifierProxyDeployLogic(e deployment.Environment, cc DeployVerifierProxyConfig) (cldf.ChangesetOutput, error) { +func verifierProxyDeployLogic(e cldf.Environment, cc DeployVerifierProxyConfig) (cldf.ChangesetOutput, error) { dataStore := ds.NewMemoryDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata]() err := deploy(e, dataStore, cc) if err != nil { e.Logger.Errorw("Failed to deploy VerifierProxy", "err", err) - return cldf.ChangesetOutput{}, deployment.MaybeDataErr(err) + return cldf.ChangesetOutput{}, cldf.MaybeDataErr(err) } records, err := dataStore.Addresses().Fetch() @@ -88,14 +90,14 @@ type HasOwnershipConfig interface { GetOwnershipConfig() types.OwnershipSettings } -func verifierProxyDeployPrecondition(_ deployment.Environment, cc DeployVerifierProxyConfig) error { +func verifierProxyDeployPrecondition(_ cldf.Environment, cc DeployVerifierProxyConfig) error { if err := cc.Validate(); err != nil { return fmt.Errorf("invalid DeployVerifierProxyConfig: %w", err) } return nil } -func deploy(e deployment.Environment, +func deploy(e cldf.Environment, dataStore ds.MutableDataStore[metadata.SerializedContractMetadata, ds.DefaultMetadata], cfg DeployVerifierProxyConfig) error { if err := cfg.Validate(); err != nil { @@ -139,7 +141,7 @@ func deploy(e deployment.Environment, // verifyProxyDeployFn returns a function that deploys a VerifyProxy contract. func verifyProxyDeployFn(cfg DeployVerifierProxy) changeset.ContractDeployFn[*verifier_proxy_v0_5_0.VerifierProxy] { - return func(chain deployment.Chain) *changeset.ContractDeployment[*verifier_proxy_v0_5_0.VerifierProxy] { + return func(chain cldf.Chain) *changeset.ContractDeployment[*verifier_proxy_v0_5_0.VerifierProxy] { addr, tx, contract, err := verifier_proxy_v0_5_0.DeployVerifierProxy( chain.DeployerKey, chain.Client, diff --git a/deployment/data-streams/changeset/verification/state.go b/deployment/data-streams/changeset/verification/state.go index fcdbceb6cfc..f63f19d88f4 100644 --- a/deployment/data-streams/changeset/verification/state.go +++ b/deployment/data-streams/changeset/verification/state.go @@ -5,12 +5,15 @@ import ( "github.com/ethereum/go-ethereum/common" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_v0_5_0" "github.com/smartcontractkit/chainlink-evm/gethwrappers/llo-feeds/generated/verifier_proxy_v0_5_0" + "github.com/smartcontractkit/chainlink/deployment" ) @@ -18,7 +21,7 @@ type VerifierProxyState struct { VerifierProxy *verifier_proxy_v0_5_0.VerifierProxy } -func maybeLoadVerifierProxyState(e deployment.Environment, chainSel uint64, contractAddr string) (*VerifierProxyState, error) { +func maybeLoadVerifierProxyState(e cldf.Environment, chainSel uint64, contractAddr string) (*VerifierProxyState, error) { if err := utils.ValidateContract(e, chainSel, contractAddr, types.VerifierProxy, deployment.Version0_5_0); err != nil { return nil, err } @@ -35,7 +38,7 @@ func maybeLoadVerifierProxyState(e deployment.Environment, chainSel uint64, cont VerifierProxy: vp, }, nil } -func loadVerifierState(e deployment.Environment, chainSel uint64, contractAddr string) (*verifier_v0_5_0.Verifier, error) { +func loadVerifierState(e cldf.Environment, chainSel uint64, contractAddr string) (*verifier_v0_5_0.Verifier, error) { chain, ok := e.Chains[chainSel] if !ok { return nil, fmt.Errorf("chain %d not found", chainSel) diff --git a/deployment/data-streams/changeset/verification/test_helpers.go b/deployment/data-streams/changeset/verification/test_helpers.go index 66bbe30db69..11d1b5ba47e 100644 --- a/deployment/data-streams/changeset/verification/test_helpers.go +++ b/deployment/data-streams/changeset/verification/test_helpers.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/require" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + dsutil "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" "github.com/smartcontractkit/chainlink/deployment/data-streams/view/v0_5" @@ -24,8 +26,8 @@ import ( // environment and the addresses of VerifierProxy and Verifier. func DeployVerifierProxyAndVerifier( t *testing.T, - e deployment.Environment, -) (env deployment.Environment, verifierProxyAddr common.Address, verifierAddr common.Address) { + e cldf.Environment, +) (env cldf.Environment, verifierProxyAddr common.Address, verifierAddr common.Address) { t.Helper() chainSelector := testutil.TestChain.Selector diff --git a/deployment/data-streams/utils/mcmsutil/mcmsutil.go b/deployment/data-streams/utils/mcmsutil/mcmsutil.go index ba4e382d4e5..229961807a5 100644 --- a/deployment/data-streams/utils/mcmsutil/mcmsutil.go +++ b/deployment/data-streams/utils/mcmsutil/mcmsutil.go @@ -11,12 +11,13 @@ import ( mcmslib "github.com/smartcontractkit/mcms" mcmstypes "github.com/smartcontractkit/mcms/types" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils" ds "github.com/smartcontractkit/chainlink-deployments-framework/datastore" - cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" dsTypes "github.com/smartcontractkit/chainlink/deployment/data-streams/changeset/types" @@ -24,7 +25,7 @@ import ( ) // CreateMCMSProposal creates a new MCMS proposal with prepared (but not sent) transactions. -func CreateMCMSProposal(e deployment.Environment, preparedTxs []*txutil.PreparedTx, mcmsMinDelay time.Duration, proposalName string) (*mcmslib.TimelockProposal, error) { +func CreateMCMSProposal(e cldf.Environment, preparedTxs []*txutil.PreparedTx, mcmsMinDelay time.Duration, proposalName string) (*mcmslib.TimelockProposal, error) { var chainSelectors []uint64 for _, tx := range preparedTxs { chainSelectors = append(chainSelectors, tx.ChainSelector) @@ -78,7 +79,7 @@ func CreateMCMSProposal(e deployment.Environment, preparedTxs []*txutil.Prepared // ExecuteOrPropose executes the transactions if no MCMS is configured, otherwise creates a proposal. func ExecuteOrPropose( - e deployment.Environment, + e cldf.Environment, txs []*txutil.PreparedTx, mcmsCfg *dsTypes.MCMSConfig, proposalName string, @@ -105,7 +106,7 @@ func ExecuteOrPropose( // The output will contain an MCMS timelock proposal for "AcceptOwnership" of those contracts // The newAddresses should be recently deployed addresses that are being transferred to MCMS and // should not be in `e` Environment -func TransferToMCMSWithTimelock(e deployment.Environment, newAddresses []ds.AddressRef, +func TransferToMCMSWithTimelock(e cldf.Environment, newAddresses []ds.AddressRef, mcmsConfig proposalutils.TimelockConfig) (cldf.ChangesetOutput, error) { // Map: chainselector -> List[Address] contractAddressesToTransfer := make(map[uint64][]common.Address) @@ -235,7 +236,7 @@ type HasOwnershipConfig interface { } func GetTransferOwnershipProposals[T HasOwnershipConfig]( - e deployment.Environment, cfg T, addresses []ds.AddressRef) ([]mcms.TimelockProposal, error) { + e cldf.Environment, cfg T, addresses []ds.AddressRef) ([]mcms.TimelockProposal, error) { var proposals []mcms.TimelockProposal if cfg.GetOwnershipConfig().ShouldTransfer && cfg.GetOwnershipConfig().MCMSProposalConfig != nil { res, err := TransferToMCMSWithTimelock(e, addresses, *cfg.GetOwnershipConfig().MCMSProposalConfig) diff --git a/deployment/data-streams/utils/txutil/get-tx.go b/deployment/data-streams/utils/txutil/get-tx.go index 74226d71a5d..2eeff3d6caf 100644 --- a/deployment/data-streams/utils/txutil/get-tx.go +++ b/deployment/data-streams/utils/txutil/get-tx.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" goEthTypes "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) // HasContractAddress is the generic interface for anything @@ -18,7 +18,7 @@ type HasContractAddress interface { // ContractLoader is a function that, given an Environment, chain selector, // and contract address, returns the strongly-typed contract “state” type ContractLoader[S any] func( - e deployment.Environment, + e cldf.Environment, chainSelector uint64, contractAddr string, ) (*S, error) @@ -37,7 +37,7 @@ type ContractMethod[S any, T any] func( // Calls the method function to build the transaction // Accumulates them into a slice of PreparedTx. func GetTxs[S any, T HasContractAddress]( - e deployment.Environment, + e cldf.Environment, contractType string, configsByChain map[uint64][]T, loader ContractLoader[S], diff --git a/deployment/data-streams/utils/txutil/transaction.go b/deployment/data-streams/utils/txutil/transaction.go index 0d6997f86e0..1296d479815 100644 --- a/deployment/data-streams/utils/txutil/transaction.go +++ b/deployment/data-streams/utils/txutil/transaction.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum" gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) // PreparedTx represents a transaction that was prepared but not sent to the chain. This is intended to be @@ -26,7 +26,7 @@ type ExecuteTxResult struct { // SignAndExecute signs and then executes transactions directly on the chain with the given deployer key configured // for the chain. The transactions should not be already sent to the chain. -func SignAndExecute(e deployment.Environment, preparedTxs []*PreparedTx) ([]ExecuteTxResult, error) { +func SignAndExecute(e cldf.Environment, preparedTxs []*PreparedTx) ([]ExecuteTxResult, error) { var executeTxResults []ExecuteTxResult // To execute the txs in parallel this would need to batch up the txs by chain to avoid nonce issues for _, tx := range preparedTxs { @@ -60,7 +60,7 @@ func SignAndExecute(e deployment.Environment, preparedTxs []*PreparedTx) ([]Exec } // reconfigureTx takes the tx `call data` and reconfigures the transaction to use valid nonce, gas price and gas limit -func reconfigureTx(ctx context.Context, chain deployment.Chain, preparedTx *PreparedTx) (*gethtypes.Transaction, error) { +func reconfigureTx(ctx context.Context, chain cldf.Chain, preparedTx *PreparedTx) (*gethtypes.Transaction, error) { nonce, err := chain.Client.NonceAt(ctx, chain.DeployerKey.From, nil) if err != nil { return nil, fmt.Errorf("chain %d: failed to get nonce: %w", chain.Selector, err) diff --git a/deployment/data-streams/utils/txutil/transaction_test.go b/deployment/data-streams/utils/txutil/transaction_test.go index 2e0526a7f59..e1e90c5645b 100644 --- a/deployment/data-streams/utils/txutil/transaction_test.go +++ b/deployment/data-streams/utils/txutil/transaction_test.go @@ -12,9 +12,9 @@ import ( "go.uber.org/zap/zapcore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + commonstate "github.com/smartcontractkit/chainlink/deployment/common/changeset/state" - "github.com/smartcontractkit/chainlink/deployment" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/types" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -90,13 +90,13 @@ func TestSignAndExecute_ContractInteraction(t *testing.T) { // grant minter permissions tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // Mint the deployer address some tokens tx, err = linkState.LinkToken.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(500)) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // Deployer should have the tokens @@ -114,7 +114,7 @@ func TestSignAndExecute_ContractInteraction(t *testing.T) { // Transfer some tokens to multiple receivers for _, receiver := range receivers { // This is the key part - generate a transaction with call data / arguments but do not send it - tx, err = linkState.LinkToken.Transfer(deployment.SimTransactOpts(), receiver, big.NewInt(100)) + tx, err = linkState.LinkToken.Transfer(cldf.SimTransactOpts(), receiver, big.NewInt(100)) require.NoError(t, err) preparedTxs = append(preparedTxs, &PreparedTx{ Tx: tx, diff --git a/deployment/environment/crib/ccip_deployer.go b/deployment/environment/crib/ccip_deployer.go index deaa6e6eae5..ab0020db6ef 100644 --- a/deployment/environment/crib/ccip_deployer.go +++ b/deployment/environment/crib/ccip_deployer.go @@ -16,6 +16,8 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5_1" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_1/token_pool" @@ -92,7 +94,7 @@ func DeployHomeChainContracts(ctx context.Context, lggr logger.Logger, envConfig if err != nil { return deployment.CapabilityRegistryConfig{}, e.ExistingAddresses, fmt.Errorf("changeset sequence execution failed with error: %w", err) } - state, err := changeset.LoadOnchainState(*e) + state, err := stateview.LoadOnchainState(*e) if err != nil { return deployment.CapabilityRegistryConfig{}, e.ExistingAddresses, fmt.Errorf("failed to load on chain state: %w", err) } @@ -124,7 +126,7 @@ func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig de return DeployCCIPOutput{}, fmt.Errorf("failed to apply changesets for setting up chain: %w", err) } - state, err := changeset.LoadOnchainState(*e) + state, err := stateview.LoadOnchainState(*e) if err != nil { return DeployCCIPOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -197,7 +199,7 @@ func ConnectCCIPLanes(ctx context.Context, lggr logger.Logger, envConfig devenv. } e.ExistingAddresses = ab - state, err := changeset.LoadOnchainState(*e) + state, err := stateview.LoadOnchainState(*e) if err != nil { return DeployCCIPOutput{}, fmt.Errorf("failed to load onchain state: %w", err) } @@ -275,7 +277,7 @@ func FundCCIPTransmitters(ctx context.Context, lggr logger.Logger, envConfig dev }, nil } -func setupChains(lggr logger.Logger, e *deployment.Environment, homeChainSel uint64) (deployment.Environment, error) { +func setupChains(lggr logger.Logger, e *cldf.Environment, homeChainSel uint64) (cldf.Environment, error) { chainSelectors := e.AllChainSelectors() chainConfigs := make(map[uint64]v1_6.ChainConfig) nodeInfo, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) @@ -348,24 +350,24 @@ func setupChains(lggr logger.Logger, e *deployment.Environment, homeChainSel uin return setupLinkPools(&env) } -func setupLinkPools(e *deployment.Environment) (deployment.Environment, error) { - state, err := changeset.LoadOnchainState(*e) +func setupLinkPools(e *cldf.Environment) (cldf.Environment, error) { + state, err := stateview.LoadOnchainState(*e) if err != nil { return *e, fmt.Errorf("failed to load onchain state: %w", err) } chainSelectors := e.AllChainSelectors() poolInput := make(map[uint64]v1_5_1.DeployTokenPoolInput) - pools := make(map[uint64]map[changeset.TokenSymbol]changeset.TokenPoolInfo) + pools := make(map[uint64]map[shared.TokenSymbol]v1_5_1.TokenPoolInfo) for _, chain := range chainSelectors { poolInput[chain] = v1_5_1.DeployTokenPoolInput{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, LocalTokenDecimals: 18, AllowList: []common.Address{}, TokenAddress: state.Chains[chain].LinkToken.Address(), } - pools[chain] = map[changeset.TokenSymbol]changeset.TokenPoolInfo{ - changeset.LinkSymbol: { - Type: changeset.BurnMintTokenPool, + pools[chain] = map[shared.TokenSymbol]v1_5_1.TokenPoolInfo{ + shared.LinkSymbol: { + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ExternalAdmin: e.Chains[chain].DeployerKey.From, }, @@ -375,25 +377,25 @@ func setupLinkPools(e *deployment.Environment) (deployment.Environment, error) { commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.DeployTokenPoolContractsChangeset), v1_5_1.DeployTokenPoolContractsConfig{ - TokenSymbol: changeset.LinkSymbol, + TokenSymbol: shared.LinkSymbol, NewPools: poolInput, }, ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ProposeAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ Pools: pools, }, ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.AcceptAdminRoleChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ Pools: pools, }, ), commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.SetPoolChangeset), - changeset.TokenAdminRegistryChangesetConfig{ + v1_5_1.TokenAdminRegistryChangesetConfig{ Pools: pools, }, ), @@ -403,16 +405,16 @@ func setupLinkPools(e *deployment.Environment) (deployment.Environment, error) { return *e, fmt.Errorf("failed to apply changesets: %w", err) } - state, err = changeset.LoadOnchainState(env) + state, err = stateview.LoadOnchainState(env) if err != nil { return *e, fmt.Errorf("failed to load onchain state: %w", err) } for _, chain := range chainSelectors { - linkPool := state.Chains[chain].BurnMintTokenPools[changeset.LinkSymbol][deployment.Version1_5_1] + linkPool := state.Chains[chain].BurnMintTokenPools[shared.LinkSymbol][deployment.Version1_5_1] linkToken := state.Chains[chain].LinkToken tx, err := linkToken.GrantMintAndBurnRoles(e.Chains[chain].DeployerKey, linkPool.Address()) - _, err = deployment.ConfirmIfNoError(e.Chains[chain], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[chain], tx, err) if err != nil { return *e, fmt.Errorf("failed to grant mint and burn roles for link pool: %w", err) } @@ -420,7 +422,7 @@ func setupLinkPools(e *deployment.Environment) (deployment.Environment, error) { return env, err } -func setupLanes(e *deployment.Environment, state changeset.CCIPOnChainState) (deployment.Environment, error) { +func setupLanes(e *cldf.Environment, state stateview.CCIPOnChainState) (cldf.Environment, error) { eg := xerrgroup.Group{} poolUpdates := make(map[uint64]v1_5_1.TokenPoolConfig) rateLimitPerChain := make(v1_5_1.RateLimiterPerChain) @@ -482,7 +484,7 @@ func setupLanes(e *deployment.Environment, state changeset.CCIPOnChainState) (de } mu.Lock() poolUpdates[src] = v1_5_1.TokenPoolConfig{ - Type: changeset.BurnMintTokenPool, + Type: shared.BurnMintTokenPool, Version: deployment.Version1_5_1, ChainUpdates: rateLimitPerChain, } @@ -532,7 +534,7 @@ func setupLanes(e *deployment.Environment, state changeset.CCIPOnChainState) (de _, err = commonchangeset.Apply(nil, *e, nil, commonchangeset.Configure( cldf.CreateLegacyChangeSet(v1_5_1.ConfigureTokenPoolContractsChangeset), v1_5_1.ConfigureTokenPoolContractsConfig{ - TokenSymbol: changeset.LinkSymbol, + TokenSymbol: shared.LinkSymbol, PoolUpdates: poolUpdates, }, )) @@ -540,7 +542,7 @@ func setupLanes(e *deployment.Environment, state changeset.CCIPOnChainState) (de return *e, err } -func mustOCR(e *deployment.Environment, homeChainSel uint64, feedChainSel uint64, newDons bool, rmnEnabled bool) (deployment.Environment, error) { +func mustOCR(e *cldf.Environment, homeChainSel uint64, feedChainSel uint64, newDons bool, rmnEnabled bool) (cldf.Environment, error) { chainSelectors := e.AllChainSelectors() var commitOCRConfigPerSelector = make(map[uint64]v1_6.CCIPOCRParams) var execOCRConfigPerSelector = make(map[uint64]v1_6.CCIPOCRParams) @@ -723,7 +725,7 @@ func SetupRMNNodeOnAllChains(ctx context.Context, lggr logger.Logger, envConfig return DeployCCIPOutput{}, fmt.Errorf("failed to set rmn node candidate: %w", err) } - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) if err != nil { return DeployCCIPOutput{}, fmt.Errorf("failed to load chain state: %w", err) } diff --git a/deployment/environment/crib/helpers.go b/deployment/environment/crib/helpers.go index 24d32344244..6c46f9921c7 100644 --- a/deployment/environment/crib/helpers.go +++ b/deployment/environment/crib/helpers.go @@ -2,6 +2,7 @@ package crib import ( "context" + "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -9,14 +10,15 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" "golang.org/x/sync/errgroup" - "math/big" - "github.com/smartcontractkit/chainlink-common/pkg/logger" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" ) -func distributeTransmitterFunds(lggr logger.Logger, nodeInfo []devenv.Node, env deployment.Environment) error { +func distributeTransmitterFunds(lggr logger.Logger, nodeInfo []devenv.Node, env cldf.Environment) error { transmittersStr := make([]common.Address, 0) fundingAmount := new(big.Int).Mul(deployment.UBigInt(100), deployment.UBigInt(1e18)) // 100 ETH @@ -40,7 +42,7 @@ func distributeTransmitterFunds(lggr logger.Logger, nodeInfo []devenv.Node, env return g.Wait() } -func SendFundsToAccounts(ctx context.Context, lggr logger.Logger, chain deployment.Chain, accounts []common.Address, fundingAmount *big.Int, sel uint64) error { +func SendFundsToAccounts(ctx context.Context, lggr logger.Logger, chain cldf.Chain, accounts []common.Address, fundingAmount *big.Int, sel uint64) error { latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) if err != nil { lggr.Errorw("could not get header, skipping chain", "chain", sel, "err", err) diff --git a/deployment/environment/crib/types.go b/deployment/environment/crib/types.go index 0eca2719dea..15bd6d1c40a 100644 --- a/deployment/environment/crib/types.go +++ b/deployment/environment/crib/types.go @@ -8,8 +8,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" ) @@ -28,12 +26,12 @@ type DeployCCIPOutput struct { NodeIDs []string } -func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, output DeployOutput) (*deployment.Environment, error) { +func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, output DeployOutput) (*cldf.Environment, error) { chains, err := devenv.NewChains(lggr, output.Chains) if err != nil { return nil, err } - return deployment.NewEnvironment( + return cldf.NewEnvironment( CRIB_ENV_NAME, lggr, output.AddressBook, diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index 51751ccbd05..ec61f37adf2 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -17,6 +17,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" ) @@ -31,14 +33,14 @@ type CribRPCs struct { // ChainConfig holds the configuration for a with a deployer key which can be used to send transactions to the chain. type ChainConfig struct { - ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains - ChainName string // name of the chain populated from chainselector repo - ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc - PreferredURLScheme deployment.URLSchemePreference // preferred url scheme for the chain - WSRPCs []CribRPCs // websocket rpcs to connect to the chain - HTTPRPCs []CribRPCs // http rpcs to connect to the chain - DeployerKey *bind.TransactOpts // key to deploy and configure contracts on the chain - Users []*bind.TransactOpts // map of addresses to their transact opts to interact with the chain as users + ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains + ChainName string // name of the chain populated from chainselector repo + ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc + PreferredURLScheme cldf.URLSchemePreference // preferred url scheme for the chain + WSRPCs []CribRPCs // websocket rpcs to connect to the chain + HTTPRPCs []CribRPCs // http rpcs to connect to the chain + DeployerKey *bind.TransactOpts // key to deploy and configure contracts on the chain + Users []*bind.TransactOpts // map of addresses to their transact opts to interact with the chain as users } func (c *ChainConfig) SetUsers(pvtkeys []string) error { @@ -95,11 +97,11 @@ func (c *ChainConfig) SetDeployerKey(pvtKeyStr *string) error { return nil } -func (c *ChainConfig) ToRPCs() []deployment.RPC { - var rpcs []deployment.RPC +func (c *ChainConfig) ToRPCs() []cldf.RPC { + var rpcs []cldf.RPC // assuming that the length of WSRPCs and HTTPRPCs is always the same for i, rpc := range c.WSRPCs { - rpcs = append(rpcs, deployment.RPC{ + rpcs = append(rpcs, cldf.RPC{ Name: fmt.Sprintf("%s-%d", c.ChainName, i), WSURL: rpc.External, HTTPURL: c.HTTPRPCs[i].External, // copying the corresponding HTTP RPC @@ -109,8 +111,8 @@ func (c *ChainConfig) ToRPCs() []deployment.RPC { return rpcs } -func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployment.Chain, error) { - chains := make(map[uint64]deployment.Chain) +func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]cldf.Chain, error) { + chains := make(map[uint64]cldf.Chain) var syncMap sync.Map g := new(errgroup.Group) for _, chainCfg := range configs { @@ -121,20 +123,20 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme return fmt.Errorf("failed to get selector from chain id %d: %w", chainCfg.ChainID, err) } - rpcConf := deployment.RPCConfig{ + rpcConf := cldf.RPCConfig{ ChainSelector: selector, RPCs: chainCfg.ToRPCs(), } - ec, err := deployment.NewMultiClient(logger, rpcConf) + ec, err := cldf.NewMultiClient(logger, rpcConf) if err != nil { return fmt.Errorf("failed to create multi client: %w", err) } - chainInfo, err := deployment.ChainInfo(selector) + chainInfo, err := cldf.ChainInfo(selector) if err != nil { return fmt.Errorf("failed to get chain info for chain %s: %w", chainCfg.ChainName, err) } - syncMap.Store(selector, deployment.Chain{ + syncMap.Store(selector, cldf.Chain{ Selector: selector, Client: ec, DeployerKey: chainCfg.DeployerKey, @@ -169,7 +171,7 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme err := g.Wait() syncMap.Range(func(sel, value interface{}) bool { - chains[sel.(uint64)] = value.(deployment.Chain) + chains[sel.(uint64)] = value.(cldf.Chain) return true }) return chains, err diff --git a/deployment/environment/devenv/environment.go b/deployment/environment/devenv/environment.go index e18dffaf98c..d7fd89af46d 100644 --- a/deployment/environment/devenv/environment.go +++ b/deployment/environment/devenv/environment.go @@ -9,8 +9,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - - "github.com/smartcontractkit/chainlink/deployment" ) const ( @@ -22,7 +20,7 @@ type EnvironmentConfig struct { JDConfig JDConfig } -func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { +func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config EnvironmentConfig) (*cldf.Environment, *DON, error) { chains, err := NewChains(lggr, config.Chains) if err != nil { return nil, nil, fmt.Errorf("failed to create chains: %w", err) @@ -53,7 +51,7 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir nodeIDs = jd.don.NodeIds() } - return deployment.NewEnvironment( + return cldf.NewEnvironment( DevEnv, lggr, cldf.NewMemoryAddressBook(), diff --git a/deployment/environment/memory/aptos_chains.go b/deployment/environment/memory/aptos_chains.go index 85970ee2dc6..2759a933601 100644 --- a/deployment/environment/memory/aptos_chains.go +++ b/deployment/environment/memory/aptos_chains.go @@ -21,7 +21,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/framework" "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -54,12 +55,12 @@ func createAptosAccount(t *testing.T, useDefault bool) *aptos.Account { } } -func GenerateChainsAptos(t *testing.T, numChains int) map[uint64]deployment.AptosChain { +func GenerateChainsAptos(t *testing.T, numChains int) map[uint64]cldf.AptosChain { testAptosChainSelectors := getTestAptosChainSelectors() if len(testAptosChainSelectors) < numChains { t.Fatalf("not enough test aptos chain selectors available") } - chains := make(map[uint64]deployment.AptosChain) + chains := make(map[uint64]cldf.AptosChain) for i := 0; i < numChains; i++ { selector := testAptosChainSelectors[i] chainID, err := chainsel.GetChainIDFromSelector(selector) @@ -67,7 +68,7 @@ func GenerateChainsAptos(t *testing.T, numChains int) map[uint64]deployment.Apto account := createAptosAccount(t, true) url, nodeClient := aptosChain(t, chainID, account.Address) - chains[selector] = deployment.AptosChain{ + chains[selector] = cldf.AptosChain{ Selector: selector, Client: nodeClient, DeployerSigner: account, @@ -150,7 +151,7 @@ func aptosChain(t *testing.T, chainID string, adminAddress aptos.AccountAddress) return url, client } -func createAptosChainConfig(chainID string, chain deployment.AptosChain) chainlink.RawConfig { +func createAptosChainConfig(chainID string, chain cldf.AptosChain) chainlink.RawConfig { chainConfig := chainlink.RawConfig{} chainConfig["Enabled"] = true diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index c6ff1ac1021..ef5ebf0b56c 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -62,11 +62,11 @@ type MemoryEnvironmentConfig struct { type NewNodesConfig struct { LogLevel zapcore.Level // EVM chains to be configured. Optional. - Chains map[uint64]deployment.Chain + Chains map[uint64]cldf.Chain // Solana chains to be configured. Optional. - SolChains map[uint64]deployment.SolChain + SolChains map[uint64]cldf.SolChain // Aptos chains to be configured. Optional. - AptosChains map[uint64]deployment.AptosChain + AptosChains map[uint64]cldf.AptosChain NumNodes int NumBootstraps int RegistryConfig deployment.CapabilityRegistryConfig @@ -75,8 +75,8 @@ type NewNodesConfig struct { } // For placeholders like aptos -func NewMemoryChain(t *testing.T, selector uint64) deployment.Chain { - return deployment.Chain{ +func NewMemoryChain(t *testing.T, selector uint64) cldf.Chain { + return cldf.Chain{ Selector: selector, Client: nil, DeployerKey: &bind.TransactOpts{}, @@ -88,7 +88,7 @@ func NewMemoryChain(t *testing.T, selector uint64) deployment.Chain { // Needed for environment variables on the node which point to prexisitng addresses. // i.e. CapReg. -func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { +func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]cldf.Chain, map[uint64][]*bind.TransactOpts) { mchains := GenerateChains(t, numChains, numUsers) users := make(map[uint64][]*bind.TransactOpts) for id, chain := range mchains { @@ -99,16 +99,16 @@ func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]depl return generateMemoryChain(t, mchains), users } -func NewMemoryChainsSol(t *testing.T, numChains int) map[uint64]deployment.SolChain { +func NewMemoryChainsSol(t *testing.T, numChains int) map[uint64]cldf.SolChain { mchains := GenerateChainsSol(t, numChains) return generateMemoryChainSol(mchains) } -func NewMemoryChainsAptos(t *testing.T, numChains int) map[uint64]deployment.AptosChain { +func NewMemoryChainsAptos(t *testing.T, numChains int) map[uint64]cldf.AptosChain { return GenerateChainsAptos(t, numChains) } -func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { +func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) (map[uint64]cldf.Chain, map[uint64][]*bind.TransactOpts) { mchains := GenerateChainsWithIds(t, chainIDs, numUsers) users := make(map[uint64][]*bind.TransactOpts) for id, chain := range mchains { @@ -119,14 +119,14 @@ func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) return generateMemoryChain(t, mchains), users } -func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]deployment.Chain { - chains := make(map[uint64]deployment.Chain) +func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]cldf.Chain { + chains := make(map[uint64]cldf.Chain) for cid, chain := range inputs { chain := chain chainInfo, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.FormatUint(cid, 10), chainsel.FamilyEVM) require.NoError(t, err) backend := NewBackend(chain.Backend) - chains[chainInfo.ChainSelector] = deployment.Chain{ + chains[chainInfo.ChainSelector] = cldf.Chain{ Selector: chainInfo.ChainSelector, Client: backend, DeployerKey: chain.DeployerKey, @@ -160,11 +160,11 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de return chains } -func generateMemoryChainSol(inputs map[uint64]SolanaChain) map[uint64]deployment.SolChain { - chains := make(map[uint64]deployment.SolChain) +func generateMemoryChainSol(inputs map[uint64]SolanaChain) map[uint64]cldf.SolChain { + chains := make(map[uint64]cldf.SolChain) for cid, chain := range inputs { chain := chain - chains[cid] = deployment.SolChain{ + chains[cid] = cldf.SolChain{ Selector: cid, Client: chain.Client, DeployerKey: &chain.DeployerKey, @@ -233,16 +233,16 @@ func NewNodes( func NewMemoryEnvironmentFromChainsNodes( ctx func() context.Context, lggr logger.Logger, - chains map[uint64]deployment.Chain, - solChains map[uint64]deployment.SolChain, - aptosChains map[uint64]deployment.AptosChain, + chains map[uint64]cldf.Chain, + solChains map[uint64]cldf.SolChain, + aptosChains map[uint64]cldf.AptosChain, nodes map[string]Node, -) deployment.Environment { +) cldf.Environment { var nodeIDs []string for id := range nodes { nodeIDs = append(nodeIDs, id) } - return *deployment.NewEnvironment( + return *cldf.NewEnvironment( Memory, lggr, cldf.NewMemoryAddressBook(), @@ -261,7 +261,7 @@ func NewMemoryEnvironmentFromChainsNodes( } // To be used by tests and any kind of deployment logic. -func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { +func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) cldf.Environment { chains, _ := NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain) solChains := NewMemoryChainsSol(t, config.SolChains) aptosChains := NewMemoryChainsAptos(t, config.AptosChains) @@ -284,7 +284,7 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Lev }) nodeIDs = append(nodeIDs, id) } - return *deployment.NewEnvironment( + return *cldf.NewEnvironment( Memory, lggr, cldf.NewMemoryAddressBook(), diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index e2f9389ab34..4889ee728fd 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -37,6 +37,8 @@ import ( solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" @@ -234,11 +236,11 @@ type NewNodeConfig struct { // Port for the P2P V2 listener. Port int // EVM chains to be configured. Optional. - Chains map[uint64]deployment.Chain + Chains map[uint64]cldf.Chain // Solana chains to be configured. Optional. - Solchains map[uint64]deployment.SolChain + Solchains map[uint64]cldf.SolChain // Aptos chains to be configured. Optional. - Aptoschains map[uint64]deployment.AptosChain + Aptoschains map[uint64]cldf.AptosChain LogLevel zapcore.Level Bootstrap bool RegistryConfig deployment.CapabilityRegistryConfig @@ -429,9 +431,9 @@ type Keys struct { func CreateKeys(t *testing.T, app chainlink.Application, - chains map[uint64]deployment.Chain, - solchains map[uint64]deployment.SolChain, - aptoschains map[uint64]deployment.AptosChain, + chains map[uint64]cldf.Chain, + solchains map[uint64]cldf.SolChain, + aptoschains map[uint64]cldf.AptosChain, ) Keys { ctx := t.Context() _, err := app.GetKeyStore().P2P().Create(ctx) @@ -614,7 +616,7 @@ func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { } } -func createSolanaChainConfig(chainID string, chain deployment.SolChain) *solcfg.TOMLConfig { +func createSolanaChainConfig(chainID string, chain cldf.SolChain) *solcfg.TOMLConfig { chainConfig := solcfg.Chain{} chainConfig.SetDefaults() diff --git a/deployment/environment/test/job_service_client.go b/deployment/environment/test/job_service_client.go index 96a606603c0..a45e640061e 100644 --- a/deployment/environment/test/job_service_client.go +++ b/deployment/environment/test/job_service_client.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" "github.com/google/uuid" @@ -11,6 +12,7 @@ import ( "google.golang.org/grpc" jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -30,6 +32,10 @@ type JobServiceClient struct { jobApproverStore getter[JobApprover] } +const ( + LabelDoNotAutoApprove = "doNotAutoApprove" +) + func NewJobServiceClient(jg getter[JobApprover]) *JobServiceClient { return &JobServiceClient{ jobStore: newMapJobStore(), @@ -156,19 +162,30 @@ func (j *JobServiceClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobR RemoteUUID: uuid.MustParse(extractor.ExternalJobID), Version: proposalVersion, } - err = n.AutoApproveJob(ctx, pargs) - if err != nil { - return nil, fmt.Errorf("failed to auto approve job: %w", err) + // Allow for skipping auto-approval by supplying the LabelDoNotAutoApprove label. + autoApprove := true + for _, label := range in.Labels { + if label.Key == LabelDoNotAutoApprove { + autoApprove = false + break + } + } + status := jobv1.ProposalStatus_PROPOSAL_STATUS_PENDING + if autoApprove { + err = n.AutoApproveJob(ctx, pargs) + if err != nil { + return nil, fmt.Errorf("failed to auto approve job: %w", err) + } + status = jobv1.ProposalStatus_PROPOSAL_STATUS_APPROVED } storeProposalID := uuid.Must(uuid.NewRandom()).String() p := &jobv1.ProposeJobResponse{Proposal: &jobv1.Proposal{ // make the proposal id the same as the job id for further reference // if you are changing this make sure to change the GetProposal and ListJobs method implementation - Id: storeProposalID, - Revision: int64(proposalVersion), - // Auto approve for now - Status: jobv1.ProposalStatus_PROPOSAL_STATUS_APPROVED, + Id: storeProposalID, + Revision: int64(proposalVersion), + Status: status, DeliveryStatus: jobv1.ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_DELIVERED, Spec: in.Spec, JobId: extractor.ExternalJobID, @@ -182,13 +199,13 @@ func (j *JobServiceClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobR ) storeErr = j.proposalStore.put(storeProposalID, p.Proposal) - if err != nil { + if storeErr != nil { return nil, fmt.Errorf("failed to save proposal: %w", err) } defer func() { // cleanup if we fail to save the job if storeErr != nil { - j.proposalStore.delete(storeProposalID) //nolint:errcheck // ignore error nothing to do + _ = j.proposalStore.delete(storeProposalID) } }() @@ -226,8 +243,39 @@ func getProposalVersion(proposals []*jobv1.Proposal) int32 { } func (j *JobServiceClient) RevokeJob(ctx context.Context, in *jobv1.RevokeJobRequest, opts ...grpc.CallOption) (*jobv1.RevokeJobResponse, error) { - // TODO CCIP-3108 implement me - panic("implement me") + // Get all proposals for this job. + proposals, err := j.proposalStore.list(&jobv1.ListProposalsRequest_Filter{ + JobIds: []string{in.GetId()}, + }) + if err != nil { + return nil, fmt.Errorf("failed to list proposals: %w", err) + } + if len(proposals) == 0 { + return nil, fmt.Errorf("no proposals found for job %s", in.GetId()) + } + // Get the latest proposal. + prop := proposals[0] + for _, p := range proposals { + if p != nil && p.UpdatedAt != nil && + (prop == nil || prop.UpdatedAt == nil || p.UpdatedAt.GetNanos() > prop.UpdatedAt.GetNanos()) { + prop = p + } + } + // Check if it's revokable. + if prop.Status != jobv1.ProposalStatus_PROPOSAL_STATUS_PENDING && + prop.Status != jobv1.ProposalStatus_PROPOSAL_STATUS_CANCELLED { + return nil, fmt.Errorf("proposal %s is not revokable: status %s", prop.Id, prop.Status.String()) + } + // Revoke it. + prop.Status = jobv1.ProposalStatus_PROPOSAL_STATUS_REVOKED + // Store the revoked version. + err = j.proposalStore.put(prop.Id, prop) + if err != nil { + return nil, fmt.Errorf("failed to save proposal: %w", err) + } + return &jobv1.RevokeJobResponse{ + Proposal: prop, + }, nil } func (j *JobServiceClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, opts ...grpc.CallOption) (*jobv1.DeleteJobResponse, error) { @@ -308,8 +356,20 @@ func (m *mapJobStore) get(jobID string) (*jobv1.Job, error) { } func (m *mapJobStore) list(filter *jobv1.ListJobsRequest_Filter) ([]*jobv1.Job, error) { - if filter != nil && filter.NodeIds != nil && filter.Uuids != nil && filter.Ids != nil { - return nil, errors.New("only one of NodeIds, Uuids or Ids can be set") + if filter != nil { + counter := 0 + if filter.NodeIds != nil { + counter++ + } + if filter.Uuids != nil { + counter++ + } + if filter.Ids != nil { + counter++ + } + if counter > 1 { + return nil, errors.New("only one of NodeIds, Uuids or Ids can be set") + } } m.mu.Lock() defer m.mu.Unlock() @@ -321,6 +381,9 @@ func (m *mapJobStore) list(filter *jobv1.ListJobsRequest_Filter) ([]*jobv1.Job, if filter == nil || (filter.NodeIds == nil && filter.Uuids == nil && filter.Ids == nil) { for _, job := range m.jobs { + if filter != nil && !matchesSelectors(filter.Selectors, job) { + continue + } jobs = append(jobs, job) } return jobs, nil @@ -358,6 +421,9 @@ func (m *mapJobStore) list(filter *jobv1.ListJobsRequest_Filter) ([]*jobv1.Job, } for _, job := range m.jobs { + if !matchesSelectors(filter.Selectors, job) { + continue + } if _, ok := wantedJobIDs[job.Id]; ok { jobs = append(jobs, job) } @@ -365,6 +431,63 @@ func (m *mapJobStore) list(filter *jobv1.ListJobsRequest_Filter) ([]*jobv1.Job, return jobs, nil } +func matchesSelectors(selectors []*ptypes.Selector, job *jobv1.Job) bool { + for _, selector := range selectors { + label := labelForKey(selector.Key, job.Labels) + switch selector.Op { + case ptypes.SelectorOp_EXIST: + return label != nil + case ptypes.SelectorOp_NOT_EXIST: + return label == nil + case ptypes.SelectorOp_EQ: + if label == nil || *label.Value != *selector.Value { + return false + } + case ptypes.SelectorOp_NOT_EQ: + if label != nil && *label.Value == *selector.Value { + return false + } + case ptypes.SelectorOp_IN: + if label == nil || label.Value == nil || selector.Value == nil { + return false + } + list := strings.Split(*selector.Value, ",") + found := false + for _, v := range list { + if *label.Value == v { + found = true + break + } + } + if !found { + return false + } + case ptypes.SelectorOp_NOT_IN: + if label != nil && label.Value != nil { + list := strings.Split(*selector.Value, ",") + for _, v := range list { + if *label.Value == v { + return false + } + } + } + default: + return false + } + } + + return true +} + +func labelForKey(key string, labels []*ptypes.Label) *ptypes.Label { + for _, label := range labels { + if label.Key == key { + return label + } + } + return nil +} + func (m *mapJobStore) delete(jobID string) error { m.mu.Lock() defer m.mu.Unlock() diff --git a/deployment/environment/test/job_service_client_test.go b/deployment/environment/test/job_service_client_test.go index 9869724b24f..98897d47411 100644 --- a/deployment/environment/test/job_service_client_test.go +++ b/deployment/environment/test/job_service_client_test.go @@ -9,7 +9,11 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/v2/core/services/feeds" ) @@ -146,6 +150,30 @@ func TestProposeJob(t *testing.T) { require.Equal(t, jobv1.ProposalStatus_PROPOSAL_STATUS_APPROVED, resp.Proposal.Status) }) + t.Run("successful job proposal without approval", func(t *testing.T) { + externalJobID := uuid.NewString() + jobSpec := createValidJobSpec(externalJobID) + + req := &jobv1.ProposeJobRequest{ + NodeId: "node-1", + Spec: jobSpec, + Labels: []*ptypes.Label{ + { + Key: LabelDoNotAutoApprove, + }, + }, + } + + resp, err := client.ProposeJob(ctx, req) + require.NoError(t, err) + require.NotNil(t, resp) + require.NotNil(t, resp.Proposal) + require.Equal(t, externalJobID, resp.Proposal.JobId) + require.Equal(t, jobSpec, resp.Proposal.Spec) + require.Equal(t, int64(1), resp.Proposal.Revision) + require.Equal(t, jobv1.ProposalStatus_PROPOSAL_STATUS_PENDING, resp.Proposal.Status) + }) + t.Run("node not found", func(t *testing.T) { externalJobID := uuid.NewString() jobSpec := createValidJobSpec(externalJobID) @@ -209,6 +237,83 @@ name = "Test Job" }) } +func TestRevokeJob(t *testing.T) { + t.Parallel() + + mockGetter := &mockJobApproverGetter{ + jobApprovers: make(map[string]*mockJobApprover), + } + mockGetter.jobApprovers["node-1"] = &mockJobApprover{} + client := NewJobServiceClient(mockGetter) + + proposeJob := func(autoApprove bool) *jobv1.Proposal { + externalJobID := uuid.NewString() + jobSpec := createValidJobSpec(externalJobID) + + labels := []*ptypes.Label{} + if !autoApprove { + labels = append(labels, &ptypes.Label{ + Key: LabelDoNotAutoApprove, + }) + } + req := &jobv1.ProposeJobRequest{ + NodeId: "node-1", + Spec: jobSpec, + Labels: labels, + } + + resp, err := client.ProposeJob(t.Context(), req) + require.NoError(t, err) + + return resp.GetProposal() + } + + tests := []struct { + name string + autoApprove bool + overrideJobID string + expectedError string + }{ + { + name: "successful revoke job", + autoApprove: false, + }, + { + name: "cannot revoke approved job", + autoApprove: true, + expectedError: "is not revokable: status PROPOSAL_STATUS_APPROVED", + }, + { + name: "job not found", + overrideJobID: "non-existent-job", + expectedError: "no proposals found for job", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + job := proposeJob(tc.autoApprove) + + if tc.overrideJobID != "" { + job.JobId = tc.overrideJobID + } + + resp, err := client.RevokeJob(t.Context(), &jobv1.RevokeJobRequest{ + IdOneof: &jobv1.RevokeJobRequest_Id{Id: job.JobId}, + }) + if tc.expectedError != "" { + require.Error(t, err) + require.Nil(t, resp) + require.Contains(t, err.Error(), tc.expectedError) + } else { + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, job.JobId, resp.Proposal.JobId) + } + }) + } +} + func TestGetJob(t *testing.T) { t.Parallel() ctx := context.Background() @@ -668,6 +773,287 @@ func TestMapProposalStore(t *testing.T) { }) } +func TestMatchesSelectors(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + selectors []*ptypes.Selector + job *jobv1.Job + expected bool + }{ + // SelectorOp_EXIST cases + { + name: "SelectorOp_EXIST match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_EXIST, + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + }, + }, + }, + expected: true, + }, + { + name: "SelectorOp_EXIST does not exist", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_EXIST, + }, + }, + job: &jobv1.Job{}, + expected: false, + }, + // SelectorOp_NOT_EXIST cases + { + name: "SelectorOp_NOT_EXIST match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_EXIST, + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + }, + }, + }, + expected: false, + }, + { + name: "SelectorOp_NOT_EXIST does not exist", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_EXIST, + }, + }, + job: &jobv1.Job{}, + expected: true, + }, + // SelectorOp_EQ cases + { + name: "SelectorOp_EQ match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("value1"), + }, + }, + }, + expected: true, + }, + { + name: "SelectorOp_EQ mismatched label value", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("NOT THE VALUE WE NEED"), + }, + }, + }, + expected: false, + }, + { + name: "SelectorOp_EQ with missing label", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{}, + expected: false, + }, + // SelectorOp_NOT_EQ cases + { + name: "SelectorOp_NOT_EQ match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("value1"), + }, + }, + }, + expected: false, + }, + { + name: "SelectorOp_NOT_EQ mismatched label value", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("NOT THE VALUE WE NEED"), + }, + }, + }, + expected: true, + }, + { + name: "SelectorOp_NOT_EQ with missing label", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_EQ, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{}, + expected: true, + }, + // SelectorOp_IN cases + { + name: "SelectorOp_IN match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_IN, + Value: pointer.To("value1,value2"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("value1"), + }, + }, + }, + expected: true, + }, + { + name: "SelectorOp_IN mismatched label value", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_IN, + Value: pointer.To("value1,value2"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("NOT THE VALUE WE NEED"), + }, + }, + }, + expected: false, + }, + { + name: "SelectorOp_IN with missing label", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_IN, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{}, + expected: false, + }, + // SelectorOp_NOT_IN cases + { + name: "SelectorOp_NOT_IN match", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_IN, + Value: pointer.To("value1,value2"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("value1"), + }, + }, + }, + expected: false, + }, + { + name: "SelectorOp_NOT_IN mismatched label value", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_IN, + Value: pointer.To("value1,value2"), + }, + }, + job: &jobv1.Job{ + Labels: []*ptypes.Label{ + { + Key: "label1", + Value: pointer.To("NOT THE VALUE WE NEED"), + }, + }, + }, + expected: true, + }, + { + name: "SelectorOp_NOT_IN with missing label", + selectors: []*ptypes.Selector{ + { + Key: "label1", + Op: ptypes.SelectorOp_NOT_IN, + Value: pointer.To("value1"), + }, + }, + job: &jobv1.Job{}, + expected: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := matchesSelectors(tc.selectors, tc.job) + require.Equal(t, tc.expected, result) + }) + } +} + // need some non-ocr job type to avoid the ocr validation and the p2pwrapper check func createValidJobSpec(externalJobID string) string { tomlString := ` diff --git a/deployment/go.mod b/deployment/go.mod index 29a20dbe678..9b4c106615d 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -31,21 +31,21 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250502210357-2df484128afa github.com/smartcontractkit/chainlink-protos/job-distributor v0.9.0 github.com/smartcontractkit/chainlink-protos/orchestrator v0.5.0 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 github.com/smartcontractkit/freeport v0.1.0 - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 - github.com/smartcontractkit/mcms v0.18.0 + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 + github.com/smartcontractkit/mcms v0.19.2 github.com/spf13/cast v1.7.1 github.com/stretchr/testify v1.10.0 github.com/test-go/testify v1.1.4 diff --git a/deployment/go.sum b/deployment/go.sum index 20a5561968c..8280181ab1d 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1232,24 +1232,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1270,8 +1270,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 h1:ks1FuQQ6f7PY/97VFXxtZhAyWZaT0NCvhT+1wKgyOt0= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4/go.mod h1:zw3QH/GTvPl/7Cjyw+y4cJYnP16QHTEh7wWLJQd9lM8= github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 h1:+kwLuO9kcq1+ZbRUQjxX1SQmzlL2M6ZP6+L0xQMtmkU= @@ -1288,10 +1288,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/deployment/helpers.go b/deployment/helpers.go index 18976f73a73..a157fd5e481 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -13,6 +13,8 @@ import ( "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" ) func GetErrorReasonFromTx(client bind.ContractBackend, from common.Address, tx *types.Transaction, receipt *types.Receipt) (string, error) { @@ -60,7 +62,7 @@ func parseError(txError error) (string, error) { return callErr.Data, nil } -func ValidateSelectorsInEnvironment(e Environment, chains []uint64) error { +func ValidateSelectorsInEnvironment(e cldf.Environment, chains []uint64) error { for _, chain := range chains { _, evmOk := e.Chains[chain] _, solOk := e.SolChains[chain] diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go index 60d53063222..4ac192ca058 100644 --- a/deployment/keystone/changeset/accept_ownership.go +++ b/deployment/keystone/changeset/accept_ownership.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) @@ -19,14 +19,14 @@ type AcceptAllOwnershipRequest struct { var _ cldf.ChangeSet[*AcceptAllOwnershipRequest] = AcceptAllOwnershipsProposal // AcceptAllOwnershipsProposal creates a MCMS proposal to call accept ownership on all the Keystone contracts in the address book. -func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnershipRequest) (cldf.ChangesetOutput, error) { +func AcceptAllOwnershipsProposal(e cldf.Environment, req *AcceptAllOwnershipRequest) (cldf.ChangesetOutput, error) { chainSelector := req.ChainSelector minDelay := req.MinDelay chain := e.Chains[chainSelector] addrBook := e.ExistingAddresses r, err := getContractSetsV2(e.Logger, getContractSetsRequestV2{ - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ req.ChainSelector: chain, }, AddressBook: addrBook, diff --git a/deployment/keystone/changeset/add_capabilities.go b/deployment/keystone/changeset/add_capabilities.go index 0350ff320cd..27b62cae40a 100644 --- a/deployment/keystone/changeset/add_capabilities.go +++ b/deployment/keystone/changeset/add_capabilities.go @@ -12,7 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -28,7 +28,7 @@ type AddCapabilitiesRequest struct { RegistryRef datastore.AddressRefKey } -func (r *AddCapabilitiesRequest) Validate(env deployment.Environment) error { +func (r *AddCapabilitiesRequest) Validate(env cldf.Environment) error { if r.RegistryChainSel == 0 { return errors.New("registry chain selector must be set") } @@ -44,7 +44,7 @@ func (r *AddCapabilitiesRequest) Validate(env deployment.Environment) error { // if the environment has a non-empty datastore, the registry ref must be set // prevents accidental usage of the old address book -func shouldUseDatastore(env deployment.Environment, ref datastore.AddressRefKey) error { +func shouldUseDatastore(env cldf.Environment, ref datastore.AddressRefKey) error { if addrs, err := env.DataStore.Addresses().Fetch(); err == nil { if len(addrs) != 0 && ref == nil { return errors.New("This environment has been migrated to DataStore: address ref key must not be nil") @@ -66,7 +66,7 @@ var _ cldf.ChangeSet[*AddCapabilitiesRequest] = AddCapabilities // // When using MCMS, the output will contain a single proposal with a single batch containing all capabilities to be added. // When not using MCMS, each capability will be added in a separate transaction. -func AddCapabilities(env deployment.Environment, req *AddCapabilitiesRequest) (cldf.ChangesetOutput, error) { +func AddCapabilities(env cldf.Environment, req *AddCapabilitiesRequest) (cldf.ChangesetOutput, error) { err := req.Validate(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to validate request: %w", err) diff --git a/deployment/keystone/changeset/add_dons.go b/deployment/keystone/changeset/add_dons.go index 703f4fd0acd..6882d15f94d 100644 --- a/deployment/keystone/changeset/add_dons.go +++ b/deployment/keystone/changeset/add_dons.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -91,7 +92,7 @@ type AddDonsRequest struct { RegistryRef datastore.AddressRefKey } -func (r *AddDonsRequest) Validate(e deployment.Environment) error { +func (r *AddDonsRequest) Validate(e cldf.Environment) error { for _, don := range r.DONs { if err := don.Validate(); err != nil { return fmt.Errorf("invalid DON to register: %w", err) @@ -139,7 +140,7 @@ func (r AddDonsRequest) convertInternal(registry *kcr.CapabilitiesRegistry) (don // See [AddNodes] and [AddCapabilities] for more detail // If the DON already exists, it will do nothing. The DON is identified by the P2P addresses of the nodes. // If you need to update the DON, use [UpdateDon]. -func AddDons(env deployment.Environment, req *AddDonsRequest) (cldf.ChangesetOutput, error) { +func AddDons(env cldf.Environment, req *AddDonsRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(env); err != nil { return cldf.ChangesetOutput{}, err } diff --git a/deployment/keystone/changeset/add_nodes.go b/deployment/keystone/changeset/add_nodes.go index 76bba19e6f4..9779c7d133b 100644 --- a/deployment/keystone/changeset/add_nodes.go +++ b/deployment/keystone/changeset/add_nodes.go @@ -197,7 +197,7 @@ type AddNodesRequest struct { RegistryRef datastore.AddressRefKey } -func (r *AddNodesRequest) Validate(env deployment.Environment) error { +func (r *AddNodesRequest) Validate(env cldf.Environment) error { if len(r.CreateNodeRequests) == 0 { return errors.New("must provide create node requests") } @@ -214,7 +214,7 @@ func (r *AddNodesRequest) Validate(env deployment.Environment) error { var _ cldf.ChangeSet[*AddNodesRequest] = AddNodes -func AddNodes(env deployment.Environment, req *AddNodesRequest) (cldf.ChangesetOutput, error) { +func AddNodes(env cldf.Environment, req *AddNodesRequest) (cldf.ChangesetOutput, error) { err := req.Validate(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid request: %w", err) diff --git a/deployment/keystone/changeset/add_nops.go b/deployment/keystone/changeset/add_nops.go index b1d14ad53d2..0e8df9a68ff 100644 --- a/deployment/keystone/changeset/add_nops.go +++ b/deployment/keystone/changeset/add_nops.go @@ -13,7 +13,6 @@ import ( kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -27,7 +26,7 @@ type AddNopsRequest struct { RegistryRef datastore.AddressRefKey } -func (req *AddNopsRequest) Validate(env deployment.Environment) error { +func (req *AddNopsRequest) Validate(env cldf.Environment) error { if len(req.Nops) == 0 { return errors.New("no NOPs provided") } @@ -42,7 +41,7 @@ func (req *AddNopsRequest) Validate(env deployment.Environment) error { var _ cldf.ChangeSet[*AddNopsRequest] = AddNops -func AddNops(env deployment.Environment, req *AddNopsRequest) (cldf.ChangesetOutput, error) { +func AddNops(env cldf.Environment, req *AddNopsRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid request: %w", err) } diff --git a/deployment/keystone/changeset/addrbook_utils.go b/deployment/keystone/changeset/addrbook_utils.go index a363d36b04c..41bf2decde0 100644 --- a/deployment/keystone/changeset/addrbook_utils.go +++ b/deployment/keystone/changeset/addrbook_utils.go @@ -9,8 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - capReg "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" feeds_consumer "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/feeds_consumer_1_0_0" keystoneForwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" @@ -27,7 +25,7 @@ type contractConstructor[T any] func(address common.Address, client bind.Contrac // It uses the provided constructor to initialize matching contracts for the given chain. func getContractsFromAddrBook[T any]( addrBook cldf.AddressBook, - chain deployment.Chain, + chain cldf.Chain, desiredType cldf.ContractType, constructor contractConstructor[T], ) ([]*T, error) { @@ -56,7 +54,7 @@ func getContractsFromAddrBook[T any]( } // capRegistriesFromAddrBook retrieves CapabilitiesRegistry contracts for the given chain. -func capRegistriesFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*capReg.CapabilitiesRegistry, error) { +func capRegistriesFromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*capReg.CapabilitiesRegistry, error) { return getContractsFromAddrBook[capReg.CapabilitiesRegistry]( addrBook, chain, @@ -66,7 +64,7 @@ func capRegistriesFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain } // ocr3FromAddrBook retrieves OCR3Capability contracts for the given chain. -func ocr3FromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*ocr3Capability.OCR3Capability, error) { +func ocr3FromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*ocr3Capability.OCR3Capability, error) { return getContractsFromAddrBook[ocr3Capability.OCR3Capability]( addrBook, chain, @@ -76,7 +74,7 @@ func ocr3FromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*ocr } // forwardersFromAddrBook retrieves KeystoneForwarder contracts for the given chain. -func forwardersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*keystoneForwarder.KeystoneForwarder, error) { +func forwardersFromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*keystoneForwarder.KeystoneForwarder, error) { return getContractsFromAddrBook[keystoneForwarder.KeystoneForwarder]( addrBook, chain, @@ -86,7 +84,7 @@ func forwardersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ( } // feedsConsumersFromAddrBook retrieves FeedsConsumer contracts for the given chain. -func feedsConsumersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*feeds_consumer.KeystoneFeedsConsumer, error) { +func feedsConsumersFromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*feeds_consumer.KeystoneFeedsConsumer, error) { return getContractsFromAddrBook[feeds_consumer.KeystoneFeedsConsumer]( addrBook, chain, @@ -96,7 +94,7 @@ func feedsConsumersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chai } // proposersFromAddrBook retrieves ManyChainMultiSig proposer contracts for the given chain. -func proposersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*ccipowner.ManyChainMultiSig, error) { +func proposersFromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*ccipowner.ManyChainMultiSig, error) { return getContractsFromAddrBook[ccipowner.ManyChainMultiSig]( addrBook, chain, @@ -106,7 +104,7 @@ func proposersFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([ } // timelocksFromAddrBook retrieves RBACTimelock contracts for the given chain. -func timelocksFromAddrBook(addrBook cldf.AddressBook, chain deployment.Chain) ([]*ccipowner.RBACTimelock, error) { +func timelocksFromAddrBook(addrBook cldf.AddressBook, chain cldf.Chain) ([]*ccipowner.RBACTimelock, error) { return getContractsFromAddrBook[ccipowner.RBACTimelock]( addrBook, chain, diff --git a/deployment/keystone/changeset/append_node_capabilities.go b/deployment/keystone/changeset/append_node_capabilities.go index 52b3b0c53a3..113c0d9e3ab 100644 --- a/deployment/keystone/changeset/append_node_capabilities.go +++ b/deployment/keystone/changeset/append_node_capabilities.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -25,7 +24,7 @@ type AppendNodeCapabilitiesRequest = MutateNodeCapabilitiesRequest // AppendNodeCapabilities adds any new capabilities to the registry, merges the new capabilities with the existing capabilities // of the node, and updates the nodes in the registry host the union of the new and existing capabilities. -func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilitiesRequest) (cldf.ChangesetOutput, error) { +func AppendNodeCapabilities(env cldf.Environment, req *AppendNodeCapabilitiesRequest) (cldf.ChangesetOutput, error) { c, capReg, err := req.convert(env, req.RegistryRef) if err != nil { return cldf.ChangesetOutput{}, err @@ -70,7 +69,7 @@ func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilit return out, nil } -func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment, ref datastore.AddressRefKey) (*internal.AppendNodeCapabilitiesRequest, *OwnedContract[*kcr.CapabilitiesRegistry], error) { +func (req *AppendNodeCapabilitiesRequest) convert(e cldf.Environment, ref datastore.AddressRefKey) (*internal.AppendNodeCapabilitiesRequest, *OwnedContract[*kcr.CapabilitiesRegistry], error) { if err := req.Validate(e); err != nil { return nil, nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err) } diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index 8be1afbc751..c157271c304 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -8,7 +8,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -20,7 +19,7 @@ type InitialContractsCfg struct { OCR3Config *kslib.OracleConfig } -func ConfigureInitialContractsChangeset(e deployment.Environment, cfg InitialContractsCfg) (cldf.ChangesetOutput, error) { +func ConfigureInitialContractsChangeset(e cldf.Environment, cfg InitialContractsCfg) (cldf.ChangesetOutput, error) { req := &kslib.ConfigureContractsRequest{ Env: &e, RegistryChainSel: cfg.RegistryChainSel, diff --git a/deployment/keystone/changeset/contract_set.go b/deployment/keystone/changeset/contract_set.go index 6534fb099d7..80fe49c6fa0 100644 --- a/deployment/keystone/changeset/contract_set.go +++ b/deployment/keystone/changeset/contract_set.go @@ -29,7 +29,7 @@ type contractSetV2 struct { // getContractSetsRequestV2 is the request structure for getting contract sets. type getContractSetsRequestV2 struct { AddressBook cldf.AddressBook - Chains map[uint64]deployment.Chain + Chains map[uint64]cldf.Chain Labels []string } @@ -108,7 +108,7 @@ func getContractSetsV2(lggr logger.Logger, req getContractSetsRequestV2) (*getCo return out, nil } -func loadContractSetV2(lggr logger.Logger, addressBook cldf.AddressBook, chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*contractSetV2, error) { +func loadContractSetV2(lggr logger.Logger, addressBook cldf.AddressBook, chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*contractSetV2, error) { var out contractSetV2 handlers := map[cldf.ContractType]func(string) error{ diff --git a/deployment/keystone/changeset/contracts.go b/deployment/keystone/changeset/contracts.go index d077b5c7604..7bdb3e338c8 100644 --- a/deployment/keystone/changeset/contracts.go +++ b/deployment/keystone/changeset/contracts.go @@ -37,7 +37,7 @@ type OwnedContract[T Ownable] struct { // NewOwnable creates an OwnedContract instance. // It checks if the contract is owned by a timelock contract and loads the MCMS state if necessary. -func NewOwnable[T Ownable](contract T, ab cldf.AddressBook, chain deployment.Chain) (*OwnedContract[T], error) { +func NewOwnable[T Ownable](contract T, ab cldf.AddressBook, chain cldf.Chain) (*OwnedContract[T], error) { var timelockTV = cldf.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) // Look for MCMS contracts that might be owned by the contract @@ -74,7 +74,7 @@ func NewOwnable[T Ownable](contract T, ab cldf.AddressBook, chain deployment.Cha // NewOwnable creates an OwnedContract instance. // It checks if the contract is owned by a timelock contract and loads the MCMS state if necessary. -func NewOwnableV2[T Ownable](contract T, ab datastore.AddressRefStore, chain deployment.Chain) (*OwnedContract[T], error) { +func NewOwnableV2[T Ownable](contract T, ab datastore.AddressRefStore, chain cldf.Chain) (*OwnedContract[T], error) { var timelockTV = cldf.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) // Look for MCMS contracts that might be owned by the contract @@ -116,7 +116,7 @@ func NewOwnableV2[T Ownable](contract T, ab datastore.AddressRefStore, chain dep } // GetOwnerTypeAndVersion retrieves the owner type and version of a contract. -func GetOwnerTypeAndVersion[T Ownable](contract T, ab cldf.AddressBook, chain deployment.Chain) (*cldf.TypeAndVersion, error) { +func GetOwnerTypeAndVersion[T Ownable](contract T, ab cldf.AddressBook, chain cldf.Chain) (*cldf.TypeAndVersion, error) { // Get the contract owner owner, err := contract.Owner(nil) if err != nil { @@ -148,7 +148,7 @@ func GetOwnerTypeAndVersion[T Ownable](contract T, ab cldf.AddressBook, chain de } // GetOwnerTypeAndVersionV2 retrieves the owner type and version of a contract using the datastore instead of the address book. -func GetOwnerTypeAndVersionV2[T Ownable](contract T, ab datastore.AddressRefStore, chain deployment.Chain) (*cldf.TypeAndVersion, error) { +func GetOwnerTypeAndVersionV2[T Ownable](contract T, ab datastore.AddressRefStore, chain cldf.Chain) (*cldf.TypeAndVersion, error) { // Get the contract owner owner, err := contract.Owner(nil) if err != nil { @@ -177,7 +177,7 @@ func GetOwnerTypeAndVersionV2[T Ownable](contract T, ab datastore.AddressRefStor // GetOwnableContract retrieves a contract instance of type T from the address book. // If `targetAddr` is provided, it will look for that specific address. // If not, it will default to looking one contract of type T, and if it doesn't find exactly one, it will error. -func GetOwnableContract[T Ownable](ab cldf.AddressBook, chain deployment.Chain, targetAddr *string) (*T, error) { +func GetOwnableContract[T Ownable](ab cldf.AddressBook, chain cldf.Chain, targetAddr *string) (*T, error) { var contractType cldf.ContractType // Determine contract type based on T switch any(*new(T)).(type) { @@ -237,7 +237,7 @@ func GetOwnableContract[T Ownable](ab cldf.AddressBook, chain deployment.Chain, // GetOwnableContractV2 retrieves a contract instance of type T from the datastore. // If `targetAddr` is provided, it will look for that specific address. // If not, it will default to looking one contract of type T, and if it doesn't find exactly one, it will error. -func GetOwnableContractV2[T Ownable](addrs datastore.AddressRefStore, chain deployment.Chain, targetAddr string) (*T, error) { +func GetOwnableContractV2[T Ownable](addrs datastore.AddressRefStore, chain cldf.Chain, targetAddr string) (*T, error) { // Determine contract type based on T switch any(*new(T)).(type) { case *forwarder.KeystoneForwarder: @@ -265,7 +265,7 @@ func GetOwnableContractV2[T Ownable](addrs datastore.AddressRefStore, chain depl } // createContractInstance is a helper function to create contract instances -func createContractInstance[T Ownable](addr string, chain deployment.Chain) (*T, error) { +func createContractInstance[T Ownable](addr string, chain cldf.Chain) (*T, error) { var instance T var err error @@ -294,7 +294,7 @@ func createContractInstance[T Ownable](addr string, chain deployment.Chain) (*T, } // GetOwnedContract is a helper function that gets a contract and wraps it in OwnedContract -func GetOwnedContract[T Ownable](addressBook cldf.AddressBook, chain deployment.Chain, addr string) (*OwnedContract[T], error) { +func GetOwnedContract[T Ownable](addressBook cldf.AddressBook, chain cldf.Chain, addr string) (*OwnedContract[T], error) { contract, err := GetOwnableContract[T](addressBook, chain, &addr) if err != nil { return nil, fmt.Errorf("failed to get contract at %s: %w", addr, err) @@ -308,7 +308,7 @@ func GetOwnedContract[T Ownable](addressBook cldf.AddressBook, chain deployment. return ownedContract, nil } -func GetOwnedContractV2[T Ownable](addrs datastore.AddressRefStore, chain deployment.Chain, addr string) (*OwnedContract[T], error) { +func GetOwnedContractV2[T Ownable](addrs datastore.AddressRefStore, chain cldf.Chain, addr string) (*OwnedContract[T], error) { addresses := addrs.Filter(datastore.AddressRefByChainSelector(chain.Selector)) var foundAddr bool @@ -335,7 +335,7 @@ func GetOwnedContractV2[T Ownable](addrs datastore.AddressRefStore, chain deploy } // loadCapabilityRegistry loads the CapabilitiesRegistry contract from the address book or datastore. -func loadCapabilityRegistry(registryChain deployment.Chain, env deployment.Environment, ref datastore.AddressRefKey) (*OwnedContract[*capabilities_registry.CapabilitiesRegistry], error) { +func loadCapabilityRegistry(registryChain cldf.Chain, env cldf.Environment, ref datastore.AddressRefKey) (*OwnedContract[*capabilities_registry.CapabilitiesRegistry], error) { err := shouldUseDatastore(env, ref) if err != nil { return nil, fmt.Errorf("failed to check registry ref: %w", err) @@ -354,7 +354,7 @@ func loadCapabilityRegistry(registryChain deployment.Chain, env deployment.Envir // TODO: CRE-400 remove this once we have migrated all environments to use datastore // This is a temporary backward compatibility until all the CLD environments are migrated to use datastore cs, err := getContractSetsV2(env.Logger, getContractSetsRequestV2{ - Chains: map[uint64]deployment.Chain{registryChain.Selector: registryChain}, + Chains: map[uint64]cldf.Chain{registryChain.Selector: registryChain}, AddressBook: env.ExistingAddresses, //nolint:staticcheck // TODO CRE-400 remove this once we have migrated all environments to use datastore }) if err != nil { diff --git a/deployment/keystone/changeset/deploy_balance_reader.go b/deployment/keystone/changeset/deploy_balance_reader.go index b41477884b5..baca6f04396 100644 --- a/deployment/keystone/changeset/deploy_balance_reader.go +++ b/deployment/keystone/changeset/deploy_balance_reader.go @@ -9,7 +9,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -22,7 +21,7 @@ type DeployBalanceReaderRequest struct { // DeployBalanceReader deploys the BalanceReader contract to all chains in the environment // callers must merge the output addressbook with the existing one // Deprecated: use DeployBalanceReaderV2 instead -func DeployBalanceReader(env deployment.Environment, cfg DeployBalanceReaderRequest) (cldf.ChangesetOutput, error) { +func DeployBalanceReader(env cldf.Environment, cfg DeployBalanceReaderRequest) (cldf.ChangesetOutput, error) { out := cldf.ChangesetOutput{ AddressBook: cldf.NewMemoryAddressBook(), DataStore: datastore.NewMemoryDataStore[datastore.DefaultMetadata, datastore.DefaultMetadata](), @@ -52,7 +51,7 @@ func DeployBalanceReader(env deployment.Environment, cfg DeployBalanceReaderRequ return out, nil } -func DeployBalanceReaderV2(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployBalanceReaderV2(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { req.deployFn = internal.DeployBalanceReader return deploy(env, req) } diff --git a/deployment/keystone/changeset/deploy_consumer.go b/deployment/keystone/changeset/deploy_consumer.go index 9fbec8552b8..0b7f1c7840f 100644 --- a/deployment/keystone/changeset/deploy_consumer.go +++ b/deployment/keystone/changeset/deploy_consumer.go @@ -2,7 +2,7 @@ package changeset import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -13,13 +13,13 @@ type DeployFeedsConsumerRequest struct { var _ cldf.ChangeSet[*DeployFeedsConsumerRequest] = DeployFeedsConsumer // DeployFeedsConsumer deploys the FeedsConsumer contract to the chain with the given chainSelector. -func DeployFeedsConsumer(env deployment.Environment, req *DeployFeedsConsumerRequest) (cldf.ChangesetOutput, error) { +func DeployFeedsConsumer(env cldf.Environment, req *DeployFeedsConsumerRequest) (cldf.ChangesetOutput, error) { return DeployFeedsConsumerV2(env, &DeployRequestV2{ ChainSel: req.ChainSelector, }) } -func DeployFeedsConsumerV2(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployFeedsConsumerV2(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { req.deployFn = kslib.DeployFeedsConsumer return deploy(env, req) } diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 11c641d24b7..885a4e41384 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -13,7 +13,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -28,7 +27,7 @@ type DeployForwarderRequest struct { // callers must merge the output addressbook with the existing one // TODO: add selectors to deploy only to specific chains // Deprecated: use DeployForwarderV2 instead -func DeployForwarderX(env deployment.Environment, cfg DeployForwarderRequest) (cldf.ChangesetOutput, error) { +func DeployForwarderX(env cldf.Environment, cfg DeployForwarderRequest) (cldf.ChangesetOutput, error) { lggr := env.Logger ab := cldf.NewMemoryAddressBook() selectors := cfg.ChainSelectors @@ -51,7 +50,7 @@ func DeployForwarderX(env deployment.Environment, cfg DeployForwarderRequest) (c return cldf.ChangesetOutput{AddressBook: ab}, nil } -func DeployForwarder(env deployment.Environment, cfg DeployForwarderRequest) (cldf.ChangesetOutput, error) { +func DeployForwarder(env cldf.Environment, cfg DeployForwarderRequest) (cldf.ChangesetOutput, error) { var out cldf.ChangesetOutput out.AddressBook = cldf.NewMemoryAddressBook() //nolint:staticcheck // TODO CRE-400 out.DataStore = datastore.NewMemoryDataStore[datastore.DefaultMetadata, datastore.DefaultMetadata]() @@ -82,7 +81,7 @@ func DeployForwarder(env deployment.Environment, cfg DeployForwarderRequest) (cl } // DeployForwarderV2 deploys the KeystoneForwarder contract to the specified chain -func DeployForwarderV2(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployForwarderV2(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { req.deployFn = internal.DeployForwarder return deploy(env, req) } @@ -112,7 +111,7 @@ func (r ConfigureForwardContractsRequest) UseMCMS() bool { return r.MCMSConfig != nil } -func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardContractsRequest) (cldf.ChangesetOutput, error) { +func ConfigureForwardContracts(env cldf.Environment, req ConfigureForwardContractsRequest) (cldf.ChangesetOutput, error) { wfDon, err := internal.NewRegisteredDon(env, internal.RegisteredDonConfig{ NodeIDs: req.WFNodeIDs, Name: req.WFDonName, diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index b5e027dcf35..33215fdd11b 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -15,8 +15,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/environment/memory" @@ -79,7 +77,7 @@ func TestConfigureForwarders(t *testing.T) { }, } - excludeChainsIfNeeded := func(excludeChains bool, env deployment.Environment) (uint64, map[uint64]struct{}) { + excludeChainsIfNeeded := func(excludeChains bool, env cldf.Environment) (uint64, map[uint64]struct{}) { if !excludeChains { return 0, nil } diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index 250219982f2..8fe107c51be 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -14,15 +14,14 @@ import ( "github.com/smartcontractkit/mcms/sdk" mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - internal "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) var _ cldf.ChangeSet[uint64] = DeployOCR3 // Deprecated: use DeployOCR3V2 instead -func DeployOCR3(env deployment.Environment, registryChainSel uint64) (cldf.ChangesetOutput, error) { +func DeployOCR3(env cldf.Environment, registryChainSel uint64) (cldf.ChangesetOutput, error) { return DeployOCR3V2(env, &DeployRequestV2{ ChainSel: registryChainSel, }) @@ -30,7 +29,7 @@ func DeployOCR3(env deployment.Environment, registryChainSel uint64) (cldf.Chang var _ cldf.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract -func DeployOCR3V2(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployOCR3V2(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { req.deployFn = internal.DeployOCR3 return deploy(env, req) } @@ -51,7 +50,7 @@ func (cfg ConfigureOCR3Config) UseMCMS() bool { return cfg.MCMSConfig != nil } -func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) (cldf.ChangesetOutput, error) { +func ConfigureOCR3Contract(env cldf.Environment, cfg ConfigureOCR3Config) (cldf.ChangesetOutput, error) { resp, err := internal.ConfigureOCR3ContractFromJD(&env, internal.ConfigureOCR3Config{ ChainSel: cfg.ChainSel, NodeIDs: cfg.NodeIDs, diff --git a/deployment/keystone/changeset/deploy_registry.go b/deployment/keystone/changeset/deploy_registry.go index f9fd418c89a..fad3360baed 100644 --- a/deployment/keystone/changeset/deploy_registry.go +++ b/deployment/keystone/changeset/deploy_registry.go @@ -9,20 +9,19 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) var _ cldf.ChangeSet[uint64] = DeployCapabilityRegistry // Depreciated: use DeployCapabilityRegistryV2 instead -func DeployCapabilityRegistry(env deployment.Environment, registrySelector uint64) (cldf.ChangesetOutput, error) { +func DeployCapabilityRegistry(env cldf.Environment, registrySelector uint64) (cldf.ChangesetOutput, error) { return DeployCapabilityRegistryV2(env, &DeployRequestV2{ ChainSel: registrySelector, }) } -func DeployCapabilityRegistryV2(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployCapabilityRegistryV2(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { req.deployFn = kslib.DeployCapabilitiesRegistry return deploy(env, req) } @@ -33,10 +32,10 @@ type DeployRequestV2 = struct { Qualifier string Labels *datastore.LabelSet - deployFn func(ctx context.Context, chain deployment.Chain, ab cldf.AddressBook) (*kslib.DeployResponse, error) + deployFn func(ctx context.Context, chain cldf.Chain, ab cldf.AddressBook) (*kslib.DeployResponse, error) } -func deploy(env deployment.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { +func deploy(env cldf.Environment, req *DeployRequestV2) (cldf.ChangesetOutput, error) { lggr := env.Logger chain, ok := env.Chains[req.ChainSel] if !ok { diff --git a/deployment/keystone/changeset/internal/append_node_capabilities.go b/deployment/keystone/changeset/internal/append_node_capabilities.go index 909ae3bcd2d..beb3d42e06b 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities.go @@ -5,14 +5,16 @@ import ( "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type AppendNodeCapabilitiesRequest struct { - Chain deployment.Chain + Chain cldf.Chain CapabilitiesRegistry *kcr.CapabilitiesRegistry P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability diff --git a/deployment/keystone/changeset/internal/append_node_capabilities_test.go b/deployment/keystone/changeset/internal/append_node_capabilities_test.go index 52b1ed23912..ac3dbbe656e 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities_test.go @@ -9,7 +9,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" @@ -58,7 +57,7 @@ func TestAppendNodeCapabilities(t *testing.T) { args: args{ lggr: lggr, req: &internal.AppendNodeCapabilitiesRequest{ - Chain: deployment.Chain{}, + Chain: cldf.Chain{}, }, initialState: &kstest.SetupTestRegistryRequest{}, }, diff --git a/deployment/keystone/changeset/internal/capability_management.go b/deployment/keystone/changeset/internal/capability_management.go index 7ec5b8d22a4..2fc2ed1bacc 100644 --- a/deployment/keystone/changeset/internal/capability_management.go +++ b/deployment/keystone/changeset/internal/capability_management.go @@ -9,14 +9,16 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) // AddCapabilities adds the capabilities to the registry // // It is idempotent. It deduplicates the input capabilities. -func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) (*mcmstypes.BatchOperation, error) { +func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain cldf.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) (*mcmstypes.BatchOperation, error) { if len(capabilities) == 0 { return nil, nil } @@ -31,7 +33,7 @@ func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, cha tx, err := registry.AddCapabilities(chain.DeployerKey, deduped) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -44,10 +46,10 @@ func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, cha return nil, nil } -func addCapabilitiesMCMSProposal(registry *kcr.CapabilitiesRegistry, caps []kcr.CapabilitiesRegistryCapability, regChain deployment.Chain) (*mcmstypes.BatchOperation, error) { - tx, err := registry.AddCapabilities(deployment.SimTransactOpts(), caps) +func addCapabilitiesMCMSProposal(registry *kcr.CapabilitiesRegistry, caps []kcr.CapabilitiesRegistryCapability, regChain cldf.Chain) (*mcmstypes.BatchOperation, error) { + tx, err := registry.AddCapabilities(cldf.SimTransactOpts(), caps) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } diff --git a/deployment/keystone/changeset/internal/capability_registry_deployer.go b/deployment/keystone/changeset/internal/capability_registry_deployer.go index 66ea35e29e1..1bf1b8fe00f 100644 --- a/deployment/keystone/changeset/internal/capability_registry_deployer.go +++ b/deployment/keystone/changeset/internal/capability_registry_deployer.go @@ -13,8 +13,6 @@ import ( capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - - "github.com/smartcontractkit/chainlink/deployment" ) type CapabilitiesRegistryDeployer struct { @@ -70,7 +68,7 @@ func (c *CapabilitiesRegistryDeployer) Deploy(req DeployRequest) (*DeployRespons return resp, nil } -func estimateDeploymentGas(client deployment.OnchainClient, bytecode string) (uint64, error) { +func estimateDeploymentGas(client cldf.OnchainClient, bytecode string) (uint64, error) { // fake contract address required for gas estimation, otherwise it will fail contractAddress := common.HexToAddress("0x0000000000000000000000000000000000000000") diff --git a/deployment/keystone/changeset/internal/contract_set.go b/deployment/keystone/changeset/internal/contract_set.go index bb7f0bc3046..fb528c0b46c 100644 --- a/deployment/keystone/changeset/internal/contract_set.go +++ b/deployment/keystone/changeset/internal/contract_set.go @@ -5,19 +5,17 @@ import ( "fmt" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - - "github.com/smartcontractkit/chainlink/deployment" ) type deployContractsRequest struct { - chain deployment.Chain + chain cldf.Chain isRegistryChain bool ad cldf.AddressBook } // DeployCapabilitiesRegistry deploys the CapabilitiesRegistry contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployCapabilitiesRegistry(_ context.Context, chain deployment.Chain, ab cldf.AddressBook) (*DeployResponse, error) { +func DeployCapabilitiesRegistry(_ context.Context, chain cldf.Chain, ab cldf.AddressBook) (*DeployResponse, error) { capabilitiesRegistryDeployer, err := NewCapabilitiesRegistryDeployer() capabilitiesRegistryResp, err := capabilitiesRegistryDeployer.Deploy(DeployRequest{Chain: chain}) if err != nil { @@ -32,7 +30,7 @@ func DeployCapabilitiesRegistry(_ context.Context, chain deployment.Chain, ab cl // DeployOCR3 deploys the OCR3Capability contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployOCR3(_ context.Context, chain deployment.Chain, ab cldf.AddressBook) (*DeployResponse, error) { +func DeployOCR3(_ context.Context, chain cldf.Chain, ab cldf.AddressBook) (*DeployResponse, error) { ocr3Deployer, err := NewOCR3Deployer() if err != nil { return nil, fmt.Errorf("failed to create OCR3Deployer: %w", err) @@ -51,7 +49,7 @@ func DeployOCR3(_ context.Context, chain deployment.Chain, ab cldf.AddressBook) // DeployForwarder deploys the KeystoneForwarder contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployForwarder(ctx context.Context, chain deployment.Chain, ab cldf.AddressBook) (*DeployResponse, error) { +func DeployForwarder(ctx context.Context, chain cldf.Chain, ab cldf.AddressBook) (*DeployResponse, error) { forwarderDeployer, err := NewKeystoneForwarderDeployer() if err != nil { return nil, fmt.Errorf("failed to create KeystoneForwarderDeployer: %w", err) @@ -69,7 +67,7 @@ func DeployForwarder(ctx context.Context, chain deployment.Chain, ab cldf.Addres // DeployFeedsConsumer deploys the KeystoneFeedsConsumer contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployFeedsConsumer(_ context.Context, chain deployment.Chain, ab cldf.AddressBook) (*DeployResponse, error) { +func DeployFeedsConsumer(_ context.Context, chain cldf.Chain, ab cldf.AddressBook) (*DeployResponse, error) { consumerDeploy, err := NewKeystoneFeedsConsumerDeployer() if err != nil { return nil, err @@ -87,7 +85,7 @@ func DeployFeedsConsumer(_ context.Context, chain deployment.Chain, ab cldf.Addr // DeployForwarder deploys the BalanceReader contract to the chain // and saves the address in the address book. This mutates the address book. -func DeployBalanceReader(_ context.Context, chain deployment.Chain, ab cldf.AddressBook) (*DeployResponse, error) { +func DeployBalanceReader(_ context.Context, chain cldf.Chain, ab cldf.AddressBook) (*DeployResponse, error) { balanceReaderDeployer, err := NewBalanceReaderDeployer() if err != nil { return nil, fmt.Errorf("failed to create BalanceReaderDeployer: %w", err) diff --git a/deployment/keystone/changeset/internal/deploy.go b/deployment/keystone/changeset/internal/deploy.go index 45a5256e861..dfc1123f844 100644 --- a/deployment/keystone/changeset/internal/deploy.go +++ b/deployment/keystone/changeset/internal/deploy.go @@ -34,7 +34,7 @@ import ( type ConfigureContractsRequest struct { RegistryChainSel uint64 - Env *deployment.Environment + Env *cldf.Environment Dons []DonCapabilities // externally sourced based on the environment OCR3Config *OracleConfig // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config @@ -145,7 +145,7 @@ func DonInfos(dons []DonCapabilities, jd cldf.OffchainClient) ([]DonInfo, error) return donInfos, nil } -func getRegistryContract(e *deployment.Environment, registryChainSel uint64) (*capabilities_registry.CapabilitiesRegistry, *deployment.Chain, error) { +func getRegistryContract(e *cldf.Environment, registryChainSel uint64) (*capabilities_registry.CapabilitiesRegistry, *cldf.Chain, error) { registryChain, ok := e.Chains[registryChainSel] if !ok { return nil, nil, fmt.Errorf("chain %d not found in environment", registryChainSel) @@ -294,7 +294,7 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req *ConfigureRe // Depreciated: use changeset.ConfigureOCR3Contract instead // ocr3 contract on the registry chain for the wf dons -func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfig) error { +func ConfigureOCR3Contract(env *cldf.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfig) error { registryChain, ok := env.Chains[chainSel] if !ok { return fmt.Errorf("chain %d not found in environment", chainSel) @@ -354,7 +354,7 @@ type ConfigureOCR3Config struct { } // Depreciated: use changeset.ConfigureOCR3Contract instead -func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3Config) (*ConfigureOCR3Resp, error) { +func ConfigureOCR3ContractFromJD(env *cldf.Environment, cfg ConfigureOCR3Config) (*ConfigureOCR3Resp, error) { prefix := "" if cfg.DryRun { prefix = "DRY RUN: " @@ -410,7 +410,7 @@ type RegisteredCapability struct { Config *capabilitiespb.CapabilityConfig } -func FromCapabilitiesRegistryCapability(capReg *capabilities_registry.CapabilitiesRegistryCapability, cfg *capabilitiespb.CapabilityConfig, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { +func FromCapabilitiesRegistryCapability(capReg *capabilities_registry.CapabilitiesRegistryCapability, cfg *capabilitiespb.CapabilityConfig, e cldf.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { registry, _, err := getRegistryContract(&e, registryChainSelector) if err != nil { return nil, fmt.Errorf("failed to get registry: %w", err) @@ -434,7 +434,7 @@ func NewRegisteredCapability(registry *capabilities_registry.CapabilitiesRegistr } type RegisterNOPSRequest struct { - Env *deployment.Environment + Env *cldf.Environment RegistryChainSelector uint64 Nops []capabilities_registry.CapabilitiesRegistryNodeOperator UseMCMS bool @@ -493,7 +493,7 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque tx, err := registry.AddNodeOperators(registryChain.DeployerKey, nops) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } @@ -522,10 +522,10 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque return resp, nil } -func addNOPsMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator, regChain deployment.Chain) (*mcmstypes.BatchOperation, error) { - tx, err := registry.AddNodeOperators(deployment.SimTransactOpts(), nops) +func addNOPsMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator, regChain cldf.Chain) (*mcmstypes.BatchOperation, error) { + tx, err := registry.AddNodeOperators(cldf.SimTransactOpts(), nops) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } @@ -539,7 +539,7 @@ func addNOPsMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, n // register nodes type RegisterNodesRequest struct { - Env *deployment.Environment + Env *cldf.Environment RegistryChainSelector uint64 NopToNodeIDs map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string DonToNodes map[string][]deployment.Node @@ -646,7 +646,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode CapabilitiesRegistry: registry, }) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodes: %w", err) } @@ -683,7 +683,7 @@ type AddNodesResponse struct { } type AddNodesRequest struct { - RegistryChain deployment.Chain + RegistryChain cldf.Chain CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry NodeParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams // the node id to the node params may be any node-unique identifier such as p2p, csa, etc @@ -727,7 +727,7 @@ func AddNodes(lggr logger.Logger, req *AddNodesRequest) (*AddNodesResponse, erro tx, err := registry.AddNodes(req.RegistryChain.DeployerKey, nodes2Add) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) // no typed errors in the abi, so we have to do string matching // try to add all nodes in one go, if that fails, fall back to 1-by-1 return nil, fmt.Errorf("failed to call AddNodes for bulk add nodes: %w", err) @@ -755,7 +755,7 @@ func getNodesToRegister( err error ) if ni, err = registry.GetNode(&bind.CallOpts{}, nodeParams.P2pId); err != nil { - if err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err); strings.Contains(err.Error(), "NodeDoesNotExist") { + if err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err); strings.Contains(err.Error(), "NodeDoesNotExist") { if nodeParams.EncryptionPublicKey == ([32]byte{}) { return nil, fmt.Errorf("invalid workflow key (cannot be empty or zero) for nodeID: %s", nodeID) } @@ -776,9 +776,9 @@ func getNodesToRegister( // addNodesMCMSProposal generates a single call to AddNodes for all the node params at once. func addNodesMCMSProposal(registry *capabilities_registry.CapabilitiesRegistry, params []capabilities_registry.CapabilitiesRegistryNodeParams, regChainSel uint64) (*mcmstypes.BatchOperation, error) { - tx, err := registry.AddNodes(deployment.SimTransactOpts(), params) + tx, err := registry.AddNodes(cldf.SimTransactOpts(), params) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to simulate call to AddNodes: %w", err) } @@ -797,11 +797,11 @@ type DONToRegister struct { } type RegisterDonsRequest struct { - Env *deployment.Environment + Env *cldf.Environment RegistryChainSelector uint64 Registry *capabilities_registry.CapabilitiesRegistry - RegistryChain *deployment.Chain + RegistryChain *cldf.Chain NodeIDToP2PID map[string][32]byte DonToCapabilities map[string][]RegisteredCapability @@ -866,7 +866,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes donInfos, err := registry.GetDONs(&bind.CallOpts{}) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } existingDONs := make(map[string]struct{}) @@ -923,14 +923,14 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes txOpts := registryChain.DeployerKey if req.UseMCMS { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } lggr.Debugw("calling add don", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F, "p2pids", p2pIds, "node count", len(p2pIds)) tx, err := registry.AddDON(txOpts, p2pIds, cfgs, true, wfSupported, don.F) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err) } @@ -981,7 +981,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } } if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } if !foundAll { @@ -1018,7 +1018,7 @@ func containsAllDONs(donInfos []capabilities_registry.CapabilitiesRegistryDONInf // configureForwarder sets the config for the forwarder contract on the chain for all Dons that accept workflows // dons that don't accept workflows are not registered with the forwarder -func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon, useMCMS bool) (map[uint64]mcmstypes.BatchOperation, error) { +func configureForwarder(lggr logger.Logger, chain cldf.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon, useMCMS bool) (map[uint64]mcmstypes.BatchOperation, error) { if fwdr == nil { return nil, errors.New("nil forwarder contract") } @@ -1033,17 +1033,17 @@ func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.Key signers := dn.Signers(chainsel.FamilyEVM) txOpts := chain.DeployerKey if useMCMS { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := fwdr.SetConfig(txOpts, dn.Info.Id, ver, dn.Info.F, signers) if err != nil { - err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) + err = cldf.DecodeErr(kf.KeystoneForwarderABI, err) return nil, fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) } if !useMCMS { _, err = chain.Confirm(tx) if err != nil { - err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) + err = cldf.DecodeErr(kf.KeystoneForwarderABI, err) return nil, fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) } } else { diff --git a/deployment/keystone/changeset/internal/deploy_test.go b/deployment/keystone/changeset/internal/deploy_test.go index 12b99dc26ab..7d4ff1bd8ab 100644 --- a/deployment/keystone/changeset/internal/deploy_test.go +++ b/deployment/keystone/changeset/internal/deploy_test.go @@ -37,9 +37,9 @@ func Test_RegisterNOPS(t *testing.T) { Name: "test-nop", }) useMCMS = true - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -240,9 +240,9 @@ func Test_RegisterNodes(t *testing.T) { rc, _ := kstest.MustAddCapabilities(t, lggr, caps2Add, chain, registry) t.Run(tc.name, func(t *testing.T) { - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -301,9 +301,9 @@ func Test_RegisterNodes(t *testing.T) { t.Run("no ops in proposal if node already exists", func(t *testing.T) { useMCMS = true - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -352,9 +352,9 @@ func Test_RegisterNodes(t *testing.T) { t.Run("no new nodes to add results in no mcms ops", func(t *testing.T) { useMCMS = true - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -398,9 +398,9 @@ func Test_RegisterDons(t *testing.T) { ) t.Run("success create add DONs mcms proposal", func(t *testing.T) { useMCMS = true - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -494,9 +494,9 @@ func Test_RegisterDons(t *testing.T) { regContract = setupResp.CapabilitiesRegistry ) - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ setupResp.Chain.Selector: setupResp.Chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -531,9 +531,9 @@ func Test_RegisterDons(t *testing.T) { t.Run("success create add DONs mcms proposal with multiple DONs", func(t *testing.T) { useMCMS = true - env := &deployment.Environment{ + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ diff --git a/deployment/keystone/changeset/internal/forwarder_deployer.go b/deployment/keystone/changeset/internal/forwarder_deployer.go index 0719c04829e..2892fcec096 100644 --- a/deployment/keystone/changeset/internal/forwarder_deployer.go +++ b/deployment/keystone/changeset/internal/forwarder_deployer.go @@ -12,8 +12,6 @@ import ( forwarder "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/forwarder_1_0_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - - "github.com/smartcontractkit/chainlink/deployment" ) const ( @@ -88,7 +86,7 @@ type ConfigureForwarderContractsResponse struct { // Depreciated: use [changeset.ConfigureForwardContracts] instead // ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS // the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment -func ConfigureForwardContracts(env *deployment.Environment, req ConfigureForwarderContractsRequest) (*ConfigureForwarderContractsResponse, error) { +func ConfigureForwardContracts(env *cldf.Environment, req ConfigureForwarderContractsRequest) (*ConfigureForwarderContractsResponse, error) { contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, diff --git a/deployment/keystone/changeset/internal/ocr3config.go b/deployment/keystone/changeset/internal/ocr3config.go index cd9a4c9bef1..fc0f8107642 100644 --- a/deployment/keystone/changeset/internal/ocr3config.go +++ b/deployment/keystone/changeset/internal/ocr3config.go @@ -26,6 +26,7 @@ import ( kocr3 "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/ocr3_capability_1_0_0" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -350,7 +351,7 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets cldf.OCRSecret type configureOCR3Request struct { cfg *OracleConfig - chain deployment.Chain + chain cldf.Chain contract *kocr3.OCR3Capability nodes []deployment.Node dryRun bool @@ -383,7 +384,7 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er txOpt := req.chain.DeployerKey if req.useMCMS { - txOpt = deployment.SimTransactOpts() + txOpt = cldf.SimTransactOpts() } tx, err := req.contract.SetConfig(txOpt, @@ -395,7 +396,7 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er ocrConfig.OffchainConfig, ) if err != nil { - err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) + err = cldf.DecodeErr(kocr3.OCR3CapabilityABI, err) return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %T: %w", req.contract.Address().String(), req.useMCMS, err) } @@ -403,7 +404,7 @@ func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, er if !req.useMCMS { _, err = req.chain.Confirm(tx) if err != nil { - err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) + err = cldf.DecodeErr(kocr3.OCR3CapabilityABI, err) return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) } } else { diff --git a/deployment/keystone/changeset/internal/ocr3config_test.go b/deployment/keystone/changeset/internal/ocr3config_test.go index 857e7415704..f648d9bbd22 100644 --- a/deployment/keystone/changeset/internal/ocr3config_test.go +++ b/deployment/keystone/changeset/internal/ocr3config_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/view" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -92,7 +93,7 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { r := configureOCR3Request{ cfg: &cfg, nodes: nodes, - chain: deployment.Chain{ + chain: cldf.Chain{ Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, }, ocrSecrets: cldf.XXXGenerateTestOCRSecrets(), @@ -112,7 +113,7 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { r := configureOCR3Request{ cfg: &cfg2, nodes: nodes, - chain: deployment.Chain{ + chain: cldf.Chain{ Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, }, ocrSecrets: cldf.XXXGenerateTestOCRSecrets(), @@ -126,7 +127,7 @@ func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { r := configureOCR3Request{ cfg: &cfg2, nodes: nodes, - chain: deployment.Chain{ + chain: cldf.Chain{ Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, }, ocrSecrets: cldf.XXXGenerateTestOCRSecrets(), diff --git a/deployment/keystone/changeset/internal/remove_dons.go b/deployment/keystone/changeset/internal/remove_dons.go index 12ee1d7700d..481ef21f1f1 100644 --- a/deployment/keystone/changeset/internal/remove_dons.go +++ b/deployment/keystone/changeset/internal/remove_dons.go @@ -9,13 +9,15 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" ) // RemoveDONsRequest holds the parameters for the RemoveDONs operation. type RemoveDONsRequest struct { - Chain deployment.Chain + Chain cldf.Chain CapabilitiesRegistry *kcr.CapabilitiesRegistry DONs []uint32 UseMCMS bool @@ -58,12 +60,12 @@ func RemoveDONs(lggr logger.Logger, req *RemoveDONsRequest) (*RemoveDONsResponse } if req.UseMCMS { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := req.CapabilitiesRegistry.RemoveDONs(txOpts, req.DONs) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call RemoveDONs: %w", err) } diff --git a/deployment/keystone/changeset/internal/remove_dons_test.go b/deployment/keystone/changeset/internal/remove_dons_test.go index c18aa295067..7e6812ebba7 100644 --- a/deployment/keystone/changeset/internal/remove_dons_test.go +++ b/deployment/keystone/changeset/internal/remove_dons_test.go @@ -13,6 +13,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/data-streams/utils/pointer" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -23,7 +26,7 @@ import ( func Test_RemoveDONsRequest_validate(t *testing.T) { type fields struct { DONs []uint32 - chain deployment.Chain + chain cldf.Chain capabilitiesRegistry *kcr.CapabilitiesRegistry } tests := []struct { @@ -35,7 +38,7 @@ func Test_RemoveDONsRequest_validate(t *testing.T) { name: "missing capabilities registry", fields: fields{ DONs: []uint32{1}, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: nil, }, wantErr: true, @@ -44,7 +47,7 @@ func Test_RemoveDONsRequest_validate(t *testing.T) { name: "empty DONs list", fields: fields{ DONs: []uint32{}, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: &kcr.CapabilitiesRegistry{}, }, wantErr: true, @@ -53,7 +56,7 @@ func Test_RemoveDONsRequest_validate(t *testing.T) { name: "success", fields: fields{ DONs: []uint32{1}, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: &kcr.CapabilitiesRegistry{}, }, wantErr: false, @@ -140,7 +143,7 @@ func TestRemoveDONs(t *testing.T) { initialCapCfg = kstest.GetDefaultCapConfig(t, initialCap) ) - setupEnv := func(t *testing.T) (deployment.Chain, *kcr.CapabilitiesRegistry, []kcr.CapabilitiesRegistryDONInfo) { + setupEnv := func(t *testing.T) (cldf.Chain, *kcr.CapabilitiesRegistry, []kcr.CapabilitiesRegistryDONInfo) { // 1) Set up chain + registry cfg := setupUpdateDonTestConfig{ dons: []internal.DonInfo{ diff --git a/deployment/keystone/changeset/internal/state.go b/deployment/keystone/changeset/internal/state.go index 188ee85c922..1cb014230e7 100644 --- a/deployment/keystone/changeset/internal/state.go +++ b/deployment/keystone/changeset/internal/state.go @@ -20,7 +20,7 @@ import ( ) type GetContractSetsRequest struct { - Chains map[uint64]deployment.Chain + Chains map[uint64]cldf.Chain AddressBook cldf.AddressBook // Labels indicates the label set that a contract must include to be considered as a member @@ -90,7 +90,7 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr // loadContractSet loads the MCMS state and then sets the Keystone contract state. func loadContractSet( lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, addresses map[string]cldf.TypeAndVersion, ) (*ContractSet, error) { var out ContractSet @@ -112,7 +112,7 @@ func loadContractSet( func setContracts( lggr logger.Logger, addresses map[string]cldf.TypeAndVersion, - client deployment.OnchainClient, + client cldf.OnchainClient, set *ContractSet, ) error { for addr, tv := range addresses { diff --git a/deployment/keystone/changeset/internal/state_test.go b/deployment/keystone/changeset/internal/state_test.go index 637c7d086ee..38670203912 100644 --- a/deployment/keystone/changeset/internal/state_test.go +++ b/deployment/keystone/changeset/internal/state_test.go @@ -54,7 +54,7 @@ func Test_GetContractSet(t *testing.T) { giveAB, ) req := &GetContractSetsRequest{ - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: { Selector: chain.Selector, }, @@ -101,7 +101,7 @@ func Test_GetContractSet(t *testing.T) { giveAB, ) req := &GetContractSetsRequest{ - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: { Selector: chain.Selector, }, diff --git a/deployment/keystone/changeset/internal/types.go b/deployment/keystone/changeset/internal/types.go index 05a1710d2ec..4155e76e9a4 100644 --- a/deployment/keystone/changeset/internal/types.go +++ b/deployment/keystone/changeset/internal/types.go @@ -41,7 +41,7 @@ type DeployResponse struct { } type DeployRequest struct { - Chain deployment.Chain + Chain cldf.Chain } type DonNode struct { @@ -253,7 +253,7 @@ type RegisteredDonConfig struct { RegistryChainSel uint64 } -func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*RegisteredDon, error) { +func NewRegisteredDon(env cldf.Environment, cfg RegisteredDonConfig) (*RegisteredDon, error) { // load the don info from the capabilities registry r, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go index db1c44d4467..72a3209cf06 100644 --- a/deployment/keystone/changeset/internal/update_don.go +++ b/deployment/keystone/changeset/internal/update_don.go @@ -16,7 +16,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -28,7 +30,7 @@ type CapabilityConfig struct { } type UpdateDonRequest struct { - Chain deployment.Chain + Chain cldf.Chain CapabilitiesRegistry *kcr.CapabilitiesRegistry P2PIDs []p2pkey.PeerID // this is the unique identifier for the don @@ -100,11 +102,11 @@ func UpdateDon(_ logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, erro txOpts := req.Chain.DeployerKey if req.UseMCMS { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } tx, err := registry.UpdateDON(txOpts, don.Id, don.NodeP2PIds, cfgs, don.IsPublic, don.F) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateDON: %w", err) } var ops types.BatchOperation diff --git a/deployment/keystone/changeset/internal/update_don_test.go b/deployment/keystone/changeset/internal/update_don_test.go index e4954c4bb0e..a1ff88ca5d7 100644 --- a/deployment/keystone/changeset/internal/update_don_test.go +++ b/deployment/keystone/changeset/internal/update_don_test.go @@ -18,6 +18,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" kscs "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -236,7 +239,7 @@ type setupUpdateDonTestConfig struct { type setupUpdateDonTestResult struct { registry *kcr.CapabilitiesRegistry - chain deployment.Chain + chain cldf.Chain } func registerTestDon(t *testing.T, lggr logger.Logger, cfg setupUpdateDonTestConfig) *kstest.SetupTestRegistryResponse { diff --git a/deployment/keystone/changeset/internal/update_node_capabilities.go b/deployment/keystone/changeset/internal/update_node_capabilities.go index 82fc17173c9..1c1ca32a4b1 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities.go @@ -6,12 +6,14 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type UpdateNodeCapabilitiesImplRequest struct { - Chain deployment.Chain + Chain cldf.Chain CapabilitiesRegistry *kcr.CapabilitiesRegistry P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability diff --git a/deployment/keystone/changeset/internal/update_node_capabilities_test.go b/deployment/keystone/changeset/internal/update_node_capabilities_test.go index 072945b4c78..4c86092b684 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities_test.go @@ -10,7 +10,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -56,7 +55,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { args: args{ lggr: lggr, req: &internal.UpdateNodeCapabilitiesImplRequest{ - Chain: deployment.Chain{}, + Chain: cldf.Chain{}, }, initialState: &kstest.SetupTestRegistryRequest{}, }, diff --git a/deployment/keystone/changeset/internal/update_nodes.go b/deployment/keystone/changeset/internal/update_nodes.go index 4f768b649d7..e123ae4c117 100644 --- a/deployment/keystone/changeset/internal/update_nodes.go +++ b/deployment/keystone/changeset/internal/update_nodes.go @@ -14,10 +14,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - - "github.com/smartcontractkit/chainlink/deployment" ) type NodeUpdate struct { @@ -29,7 +30,7 @@ type NodeUpdate struct { } type UpdateNodesRequest struct { - Chain deployment.Chain + Chain cldf.Chain CapabilitiesRegistry *kcr.CapabilitiesRegistry P2pToUpdates map[p2pkey.PeerID]NodeUpdate @@ -103,17 +104,17 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo params, err := req.NodeParams() if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to make node params: %w", err) } txOpts := req.Chain.DeployerKey if req.UseMCMS { - txOpts = deployment.SimTransactOpts() + txOpts = cldf.SimTransactOpts() } registry := req.CapabilitiesRegistry tx, err := registry.UpdateNodes(txOpts, params) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateNodes: %w", err) } @@ -145,7 +146,7 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo } // AppendCapabilities appends the capabilities to the existing capabilities of the nodes listed in p2pIds in the registry -func AppendCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, p2pIds []p2pkey.PeerID, capabilities []kcr.CapabilitiesRegistryCapability) (map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability, error) { +func AppendCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain cldf.Chain, p2pIds []p2pkey.PeerID, capabilities []kcr.CapabilitiesRegistryCapability) (map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability, error) { out := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) allCapabilities, err := registry.GetCapabilities(&bind.CallOpts{}) if err != nil { @@ -202,7 +203,7 @@ func makeNodeParams(registry *kcr.CapabilitiesRegistry, nodes, err := registry.GetNodesByP2PIds(&bind.CallOpts{}, PeerIDsToBytes(p2pIds)) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to get nodes by p2p ids: %w", err) } for _, node := range nodes { diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go index eba436f3b0d..035a15871cf 100644 --- a/deployment/keystone/changeset/internal/update_nodes_test.go +++ b/deployment/keystone/changeset/internal/update_nodes_test.go @@ -20,7 +20,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/values" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/deployment" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" @@ -31,7 +33,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { type fields struct { p2pToUpdates map[p2pkey.PeerID]internal.NodeUpdate nopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc - chain deployment.Chain + chain cldf.Chain capabilitiesRegistry *kcr.CapabilitiesRegistry } tests := []struct { @@ -44,7 +46,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { fields: fields{ p2pToUpdates: map[p2pkey.PeerID]internal.NodeUpdate{}, nopToNodes: nil, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: nil, }, wantErr: true, @@ -58,7 +60,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { }, }, nopToNodes: nil, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: nil, }, wantErr: true, @@ -72,7 +74,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { }, }, nopToNodes: nil, - chain: deployment.Chain{}, + chain: cldf.Chain{}, capabilitiesRegistry: nil, }, wantErr: true, @@ -582,7 +584,7 @@ func TestUpdateNodes(t *testing.T) { toRegister := p2pToCapabilitiesUpdated[testPeerID(t, "peerID_1")] tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := cldf.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -690,9 +692,9 @@ func testPeerID(t *testing.T, s string) p2pkey.PeerID { return p2pkey.PeerID(out) } -func testChain(t *testing.T) deployment.Chain { +func testChain(t *testing.T) cldf.Chain { chains, _ := memory.NewMemoryChains(t, 1, 5) - var chain deployment.Chain + var chain cldf.Chain for _, c := range chains { chain = c break diff --git a/deployment/keystone/changeset/remove_dons.go b/deployment/keystone/changeset/remove_dons.go index 09dc0d244a3..4a3d72e7308 100644 --- a/deployment/keystone/changeset/remove_dons.go +++ b/deployment/keystone/changeset/remove_dons.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -29,7 +28,7 @@ type RemoveDONsRequest struct { RegistryRef datastore.AddressRefKey } -func (r *RemoveDONsRequest) Validate(e deployment.Environment) error { +func (r *RemoveDONsRequest) Validate(e cldf.Environment) error { if len(r.DONs) == 0 { return errors.New("dons is required") } @@ -54,7 +53,7 @@ func (r RemoveDONsRequest) UseMCMS() bool { } // RemoveDONs removes a DON from the capabilities registry -func RemoveDONs(env deployment.Environment, req *RemoveDONsRequest) (cldf.ChangesetOutput, error) { +func RemoveDONs(env cldf.Environment, req *RemoveDONsRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(env); err != nil { return cldf.ChangesetOutput{}, err } diff --git a/deployment/keystone/changeset/state.go b/deployment/keystone/changeset/state.go index 98c80b3776b..4d824af77a3 100644 --- a/deployment/keystone/changeset/state.go +++ b/deployment/keystone/changeset/state.go @@ -21,7 +21,7 @@ import ( ) type GetContractSetsRequest struct { - Chains map[uint64]deployment.Chain + Chains map[uint64]cldf.Chain AddressBook cldf.AddressBook // Labels indicates the label set that a contract must include to be considered as a member @@ -115,7 +115,7 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr return resp, nil } -func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[string]cldf.TypeAndVersion) (*ContractSet, error) { +func loadContractSet(lggr logger.Logger, chain cldf.Chain, addresses map[string]cldf.TypeAndVersion) (*ContractSet, error) { var out ContractSet mcmsWithTimelock, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addresses) if err != nil { diff --git a/deployment/keystone/changeset/test/env_setup.go b/deployment/keystone/changeset/test/env_setup.go index 8910d9a9a47..4612b42ff75 100644 --- a/deployment/keystone/changeset/test/env_setup.go +++ b/deployment/keystone/changeset/test/env_setup.go @@ -109,7 +109,7 @@ var _ testEnvIface = (*EnvWrapper)(nil) type EnvWrapper struct { t *testing.T - Env deployment.Environment + Env cldf.Environment RegistrySelector uint64 dons testDons @@ -130,7 +130,7 @@ func (te EnvWrapper) OwnedCapabilityRegistry() *changeset.OwnedContract[*kcr.Cap return loadOneContract[*kcr.CapabilitiesRegistry](te.t, te.Env, te.Env.Chains[te.RegistrySelector], registryQualifier) } -func loadOneContract[T changeset.Ownable](t *testing.T, env deployment.Environment, chain deployment.Chain, qualifier string) *changeset.OwnedContract[T] { +func loadOneContract[T changeset.Ownable](t *testing.T, env cldf.Environment, chain cldf.Chain, qualifier string) *changeset.OwnedContract[T] { t.Helper() addrs := env.DataStore.Addresses().Filter(datastore.AddressRefByQualifier(qualifier)) require.Len(t, addrs, 1) @@ -189,14 +189,14 @@ func (te EnvWrapper) GetP2PIDs(donName string) P2PIDs { return te.dons.Get(donName).GetP2PIDs() } -func initEnv(t *testing.T, nChains int) (registryChainSel uint64, env deployment.Environment) { +func initEnv(t *testing.T, nChains int) (registryChainSel uint64, env cldf.Environment) { chains, _ := memory.NewMemoryChains(t, nChains, 1) registryChainSel = registryChain(t, chains) // note that all the nodes require TOML configuration of the cap registry address // and writers need forwarder address as TOML config // we choose to use changesets to deploy the initial contracts because that's how it's done in the real world // this requires a initial environment to house the address book - env = deployment.Environment{ + env = cldf.Environment{ GetContext: t.Context, Logger: logger.Test(t), Chains: chains, @@ -279,7 +279,7 @@ func setupTestEnv(t *testing.T, c EnvWrapperConfig) EnvWrapper { lggr.Debug("done init env") var ( dons testDons - env deployment.Environment + env cldf.Environment ) if c.useInMemoryNodes { dons, env = setupMemoryNodeTest(t, registryChainSel, envWithContracts.Chains, c) @@ -415,7 +415,7 @@ func setupTestEnv(t *testing.T, c EnvWrapperConfig) EnvWrapper { } } -func setupViewOnlyNodeTest(t *testing.T, registryChainSel uint64, chains map[uint64]deployment.Chain, c EnvWrapperConfig) (testDons, deployment.Environment) { +func setupViewOnlyNodeTest(t *testing.T, registryChainSel uint64, chains map[uint64]cldf.Chain, c EnvWrapperConfig) (testDons, cldf.Environment) { // now that we have the initial contracts deployed, we can configure the nodes with the addresses dons := newViewOnlyDons() for _, donCfg := range []DonConfig{c.WFDonConfig, c.AssetDonConfig, c.WriterDonConfig} { @@ -442,7 +442,7 @@ func setupViewOnlyNodeTest(t *testing.T, registryChainSel uint64, chains map[uin dons.Put(newViewOnlyDon(donCfg.Name, n)) } - env := deployment.NewEnvironment( + env := cldf.NewEnvironment( "view only nodes", logger.Test(t), cldf.NewMemoryAddressBook(), @@ -462,7 +462,7 @@ func setupViewOnlyNodeTest(t *testing.T, registryChainSel uint64, chains map[uin return dons, *env } -func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint64]deployment.Chain, c EnvWrapperConfig) (testDons, deployment.Environment) { +func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint64]cldf.Chain, c EnvWrapperConfig) (testDons, cldf.Environment) { // now that we have the initial contracts deployed, we can configure the nodes with the addresses // TODO: configure the nodes with the correct override functions lggr := logger.Test(t) @@ -471,7 +471,7 @@ func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint6 Contract: [20]byte{}, } - wfChains := map[uint64]deployment.Chain{} + wfChains := map[uint64]cldf.Chain{} wfChains[registryChainSel] = chains[registryChainSel] wfConf := memory.NewNodesConfig{ LogLevel: zapcore.InfoLevel, @@ -486,7 +486,7 @@ func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint6 wfNodes := memory.NewNodes(t, wfConf) require.Len(t, wfNodes, c.WFDonConfig.N) - writerChains := map[uint64]deployment.Chain{} + writerChains := map[uint64]cldf.Chain{} maps.Copy(writerChains, chains) cwConf := memory.NewNodesConfig{ LogLevel: zapcore.InfoLevel, @@ -501,7 +501,7 @@ func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint6 cwNodes := memory.NewNodes(t, cwConf) require.Len(t, cwNodes, c.WriterDonConfig.N) - assetChains := map[uint64]deployment.Chain{} + assetChains := map[uint64]cldf.Chain{} assetChains[registryChainSel] = chains[registryChainSel] assetCfg := memory.NewNodesConfig{ LogLevel: zapcore.InfoLevel, @@ -525,7 +525,7 @@ func setupMemoryNodeTest(t *testing.T, registryChainSel uint64, chains map[uint6 return dons, env } -func registryChain(t *testing.T, chains map[uint64]deployment.Chain) uint64 { +func registryChain(t *testing.T, chains map[uint64]cldf.Chain) uint64 { var registryChainSel uint64 = math.MaxUint64 for sel := range chains { if sel < registryChainSel { @@ -537,7 +537,7 @@ func registryChain(t *testing.T, chains map[uint64]deployment.Chain) uint64 { // validateInitialChainState checks that the initial chain state // has the expected contracts deployed -func validateInitialChainState(t *testing.T, env deployment.Environment, registryChainSel uint64) { +func validateInitialChainState(t *testing.T, env cldf.Environment, registryChainSel uint64) { ad := env.ExistingAddresses // all contracts on registry chain registryChainAddrs, err := ad.AddressesForChain(registryChainSel) diff --git a/deployment/keystone/changeset/test/registry.go b/deployment/keystone/changeset/test/registry.go index 05fb9021b49..c1b0149aa66 100644 --- a/deployment/keystone/changeset/test/registry.go +++ b/deployment/keystone/changeset/test/registry.go @@ -47,7 +47,7 @@ type SetupTestRegistryRequest struct { type SetupTestRegistryResponse struct { CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry - Chain deployment.Chain + Chain cldf.Chain RegistrySelector uint64 CapabilityCache *CapabilityCache Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded @@ -154,7 +154,7 @@ func MustAddCapabilities( t *testing.T, lggr logger.Logger, in map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability, - chain deployment.Chain, + chain cldf.Chain, registry *capabilities_registry.CapabilitiesRegistry, ) ([]internal.RegisteredCapability, *CapabilityCache) { t.Helper() @@ -215,7 +215,7 @@ func ToP2PToCapabilities( return out } -func deployCapReg(t *testing.T, chain deployment.Chain) *capabilities_registry.CapabilitiesRegistry { +func deployCapReg(t *testing.T, chain cldf.Chain) *capabilities_registry.CapabilitiesRegistry { capabilitiesRegistryDeployer, err := internal.NewCapabilitiesRegistryDeployer() require.NoError(t, err) _, err = capabilitiesRegistryDeployer.Deploy(internal.DeployRequest{Chain: chain}) @@ -223,10 +223,10 @@ func deployCapReg(t *testing.T, chain deployment.Chain) *capabilities_registry.C return capabilitiesRegistryDeployer.Contract() } -func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator) *internal.RegisterNOPSResponse { - env := &deployment.Environment{ +func addNops(t *testing.T, lggr logger.Logger, chain cldf.Chain, registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator) *internal.RegisterNOPSResponse { + env := &cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chain.Selector: chain, }, ExistingAddresses: cldf.NewMemoryAddressBookFromMap(map[uint64]map[string]cldf.TypeAndVersion{ @@ -250,13 +250,13 @@ func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry func AddNodes( t *testing.T, lggr logger.Logger, - chain deployment.Chain, + chain cldf.Chain, registry *capabilities_registry.CapabilitiesRegistry, nodes []capabilities_registry.CapabilitiesRegistryNodeParams, ) { tx, err := registry.AddNodes(chain.DeployerKey, nodes) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddNodes: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -266,7 +266,7 @@ func AddNodes( func addDons( t *testing.T, _ logger.Logger, - chain deployment.Chain, + chain cldf.Chain, registry *capabilities_registry.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don, @@ -296,7 +296,7 @@ func addDons( f := len(don.P2PIDs)/3 + 1 tx, err := registry.AddDON(chain.DeployerKey, internal.PeerIDsToBytes(don.P2PIDs), capConfigs, isPublic, acceptsWorkflows, uint8(f)) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddDON: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -346,7 +346,7 @@ func (cc *CapabilityCache) Get(c capabilities_registry.CapabilitiesRegistryCapab // AddCapabilities adds the capabilities to the registry and returns the registered capabilities // if the capability is already registered, it will not be re-registered // if duplicate capabilities are passed, they will be deduped -func (cc *CapabilityCache) AddCapabilities(_ logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { +func (cc *CapabilityCache) AddCapabilities(_ logger.Logger, chain cldf.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { t := cc.t var out []internal.RegisteredCapability // get the registered capabilities & dedup @@ -373,7 +373,7 @@ func (cc *CapabilityCache) AddCapabilities(_ logger.Logger, chain deployment.Cha } tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -395,9 +395,9 @@ func (cc *CapabilityCache) AddCapabilities(_ logger.Logger, chain deployment.Cha return out } -func testChain(t *testing.T) deployment.Chain { +func testChain(t *testing.T) cldf.Chain { chains, _ := memory.NewMemoryChains(t, 1, 5) - var chain deployment.Chain + var chain cldf.Chain for _, c := range chains { chain = c break diff --git a/deployment/keystone/changeset/update_don.go b/deployment/keystone/changeset/update_don.go index dc05389d97a..4bf3253a74e 100644 --- a/deployment/keystone/changeset/update_don.go +++ b/deployment/keystone/changeset/update_don.go @@ -6,7 +6,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" @@ -30,7 +29,7 @@ type UpdateDonRequest struct { RegistryRef datastore.AddressRefKey } -func (r *UpdateDonRequest) Validate(env deployment.Environment) error { +func (r *UpdateDonRequest) Validate(env cldf.Environment) error { if len(r.P2PIDs) == 0 { return errors.New("p2pIDs is required") } @@ -54,7 +53,7 @@ type UpdateDonResponse struct { // UpdateDon updates the capabilities of a Don // This a complex action in practice that involves registering missing capabilities, adding the nodes, and updating // the capabilities of the DON -func UpdateDon(env deployment.Environment, req *UpdateDonRequest) (cldf.ChangesetOutput, error) { +func UpdateDon(env cldf.Environment, req *UpdateDonRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid request: %w", err) } @@ -109,7 +108,7 @@ func appendRequest(r *UpdateDonRequest) *AppendNodeCapabilitiesRequest { return out } -func updateDonRequest(env deployment.Environment, r *UpdateDonRequest) (*internal.UpdateDonRequest, error) { +func updateDonRequest(env cldf.Environment, r *UpdateDonRequest) (*internal.UpdateDonRequest, error) { capReg, err := loadCapabilityRegistry(env.Chains[r.RegistryChainSel], env, r.RegistryRef) if err != nil { return nil, fmt.Errorf("failed to load capability registry: %w", err) diff --git a/deployment/keystone/changeset/update_node_capabilities.go b/deployment/keystone/changeset/update_node_capabilities.go index 2003c84dcbb..a6d9cedb8d1 100644 --- a/deployment/keystone/changeset/update_node_capabilities.go +++ b/deployment/keystone/changeset/update_node_capabilities.go @@ -67,7 +67,7 @@ type MutateNodeCapabilitiesRequest struct { RegistryRef datastore.AddressRefKey } -func (req *MutateNodeCapabilitiesRequest) Validate(e deployment.Environment) error { +func (req *MutateNodeCapabilitiesRequest) Validate(e cldf.Environment) error { if len(req.P2pToCapabilities) == 0 { return errors.New("p2pToCapabilities is empty") } @@ -90,7 +90,7 @@ func (req *MutateNodeCapabilitiesRequest) UseMCMS() bool { return req.MCMSConfig != nil } -func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e deployment.Environment) (*internal.UpdateNodeCapabilitiesImplRequest, *OwnedContract[*kcr.CapabilitiesRegistry], error) { +func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e cldf.Environment) (*internal.UpdateNodeCapabilitiesImplRequest, *OwnedContract[*kcr.CapabilitiesRegistry], error) { if err := req.Validate(e); err != nil { return nil, nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err) } @@ -109,7 +109,7 @@ func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e de } // UpdateNodeCapabilities updates the capabilities of nodes in the registry -func UpdateNodeCapabilities(env deployment.Environment, req *UpdateNodeCapabilitiesRequest) (cldf.ChangesetOutput, error) { +func UpdateNodeCapabilities(env cldf.Environment, req *UpdateNodeCapabilitiesRequest) (cldf.ChangesetOutput, error) { c, capReg, err := req.updateNodeCapabilitiesImplRequest(env) if err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("failed to convert request: %w", err) diff --git a/deployment/keystone/changeset/update_nodes.go b/deployment/keystone/changeset/update_nodes.go index ef98cc502fa..cd7fa2465a2 100644 --- a/deployment/keystone/changeset/update_nodes.go +++ b/deployment/keystone/changeset/update_nodes.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -36,7 +35,7 @@ type UpdateNodesRequest struct { RegistryRef datastore.AddressRefKey } -func (r *UpdateNodesRequest) Validate(e deployment.Environment) error { +func (r *UpdateNodesRequest) Validate(e cldf.Environment) error { if r.P2pToUpdates == nil { return errors.New("P2pToUpdates must be non-nil") } @@ -65,7 +64,7 @@ type NodeUpdate = internal.NodeUpdate // UpdateNodes updates a set of nodes. // The nodes and capabilities in the request must already exist in the registry contract. -func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (cldf.ChangesetOutput, error) { +func UpdateNodes(env cldf.Environment, req *UpdateNodesRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(env); err != nil { return cldf.ChangesetOutput{}, fmt.Errorf("invalid request: %w", err) } diff --git a/deployment/keystone/changeset/view_test.go b/deployment/keystone/changeset/view_test.go index d0bdbb0691a..775ea9f864a 100644 --- a/deployment/keystone/changeset/view_test.go +++ b/deployment/keystone/changeset/view_test.go @@ -12,6 +12,8 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-deployments-framework/datastore" + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" @@ -53,16 +55,16 @@ func TestKeystoneView(t *testing.T) { WriterDonConfig: test.DonConfig{N: 4, Name: "writerDon"}, NumChains: 1, }) - registryChain := env.Env.AllChainSelectors()[0] + originalAddressBook := env.Env.ExistingAddresses oracleConfig.TransmissionSchedule = []int{len(env.Env.NodeIDs)} addrs := env.Env.DataStore.Addresses().Filter( - datastore.AddressRefByChainSelector(registryChain), + datastore.AddressRefByChainSelector(env.RegistrySelector), ) var newOCR3Addr, newForwarderAddr, newWorkflowRegistryAddr, newCapabilityRegistryAddr string for _, addr := range addrs { - if newForwarderAddr != "" && newOCR3Addr != "" { + if newForwarderAddr != "" && newOCR3Addr != "" && newWorkflowRegistryAddr != "" && newCapabilityRegistryAddr != "" { break } switch addr.Type { @@ -108,7 +110,7 @@ func TestKeystoneView(t *testing.T) { var outView changeset.KeystoneView require.NoError(t, json.Unmarshal(b, &outView)) - chainID, err := chain_selectors.ChainIdFromSelector(registryChain) + chainID, err := chain_selectors.ChainIdFromSelector(env.RegistrySelector) require.NoError(t, err) chainName, err := chain_selectors.NameFromChainId(chainID) require.NoError(t, err) @@ -131,48 +133,54 @@ func TestKeystoneView(t *testing.T) { t.Run("successfully generates a view of the keystone state with multiple contracts of the same type per chain", func(t *testing.T) { oracleConfigCopy := oracleConfig + var localAddrsBook deployment.AddressBook // Deploy a new forwarder contract - resp, err := changeset.DeployForwarderV2(env.Env, &changeset.DeployRequestV2{ChainSel: registryChain}) + resp, err := changeset.DeployForwarderV2(env.Env, &changeset.DeployRequestV2{ChainSel: env.RegistrySelector}) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, resp.DataStore.Merge(env.Env.DataStore)) //nolint:staticcheck // Temporarily using deprecated AddressBook until migration is complete - require.NoError(t, env.Env.ExistingAddresses.Merge(resp.AddressBook)) + localAddrsBook = resp.AddressBook env.Env.DataStore = resp.DataStore.Seal() // Deploy a new workflow registry contract - resp, err = workflowregistry.DeployV2(env.Env, &changeset.DeployRequestV2{ChainSel: registryChain}) + resp, err = workflowregistry.DeployV2(env.Env, &changeset.DeployRequestV2{ChainSel: env.RegistrySelector}) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, resp.DataStore.Merge(env.Env.DataStore)) //nolint:staticcheck // Temporarily using deprecated AddressBook until migration is complete - require.NoError(t, env.Env.ExistingAddresses.Merge(resp.AddressBook)) + require.NoError(t, localAddrsBook.Merge(resp.AddressBook)) env.Env.DataStore = resp.DataStore.Seal() // Deploy a new OCR3 contract - resp, err = changeset.DeployOCR3V2(env.Env, &changeset.DeployRequestV2{ChainSel: registryChain}) + resp, err = changeset.DeployOCR3V2(env.Env, &changeset.DeployRequestV2{ChainSel: env.RegistrySelector}) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, resp.DataStore.Merge(env.Env.DataStore)) //nolint:staticcheck // Temporarily using deprecated AddressBook until migration is complete - require.NoError(t, env.Env.ExistingAddresses.Merge(resp.AddressBook)) + require.NoError(t, localAddrsBook.Merge(resp.AddressBook)) env.Env.DataStore = resp.DataStore.Seal() // Deploy a new capability registry contract - resp, err = changeset.DeployCapabilityRegistryV2(env.Env, &changeset.DeployRequestV2{ChainSel: registryChain}) + resp, err = changeset.DeployCapabilityRegistryV2(env.Env, &changeset.DeployRequestV2{ChainSel: env.RegistrySelector}) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, resp.DataStore.Merge(env.Env.DataStore)) //nolint:staticcheck // Temporarily using deprecated AddressBook until migration is complete - require.NoError(t, env.Env.ExistingAddresses.Merge(resp.AddressBook)) + require.NoError(t, localAddrsBook.Merge(resp.AddressBook)) + env.Env.DataStore = resp.DataStore.Seal() + env.Env.ExistingAddresses = localAddrsBook var ocr3Addr, forwarderAddr, workflowRegistryAddr, capabilityRegistryAddr string existingAddrs := env.Env.DataStore.Addresses().Filter( - datastore.AddressRefByChainSelector(registryChain), + datastore.AddressRefByChainSelector(env.RegistrySelector), ) for _, addr := range existingAddrs { + if ocr3Addr != "" && forwarderAddr != "" && workflowRegistryAddr != "" && capabilityRegistryAddr != "" { + break + } switch addr.Type { case datastore.ContractType(internal.OCR3Capability): if addr.Address != newOCR3Addr { @@ -211,12 +219,43 @@ func TestKeystoneView(t *testing.T) { _, err = changeset.ConfigureOCR3Contract(env.Env, cfg) require.NoError(t, err) + ocr3CapCfg := test.GetDefaultCapConfig(t, internal.OCR3Cap) + var wfNodes []string for _, id := range env.GetP2PIDs("wfDon") { wfNodes = append(wfNodes, id.String()) } + + wfDonCapabilities := internal.DonCapabilities{ + Name: "wfDon", + Nops: []internal.NOP{ + { + Name: "nop 1", + Nodes: wfNodes, + }, + }, + Capabilities: []internal.DONCapabilityWithConfig{ + {Capability: internal.OCR3Cap, Config: ocr3CapCfg}, + }, + } + var allDons = []internal.DonCapabilities{wfDonCapabilities} + cr, err := changeset.GetOwnedContractV2[*capabilities_registry.CapabilitiesRegistry]( + env.Env.DataStore.Addresses(), env.Env.Chains[env.RegistrySelector], capabilityRegistryAddr, + ) + require.NoError(t, err) + + _, err = internal.ConfigureRegistry(t.Context(), env.Env.Logger, &internal.ConfigureRegistryRequest{ + ConfigureContractsRequest: internal.ConfigureContractsRequest{ + RegistryChainSel: env.RegistrySelector, + Env: &env.Env, + Dons: allDons, + }, + CapabilitiesRegistry: cr.Contract, + }, nil) + require.NoError(t, err) + _, err = changeset.ConfigureForwardContracts(env.Env, changeset.ConfigureForwardContractsRequest{ - WFDonName: "test-wf-don", + WFDonName: "wfDon", WFNodeIDs: wfNodes, RegistryChainSel: env.RegistrySelector, }) @@ -232,7 +271,7 @@ func TestKeystoneView(t *testing.T) { var outView changeset.KeystoneView require.NoError(t, json.Unmarshal(b, &outView)) - chainID, err := chain_selectors.ChainIdFromSelector(registryChain) + chainID, err := chain_selectors.ChainIdFromSelector(env.RegistrySelector) require.NoError(t, err) chainName, err := chain_selectors.NameFromChainId(chainID) require.NoError(t, err) @@ -261,7 +300,7 @@ func TestKeystoneView(t *testing.T) { t.Run("generates a partial view of the keystone state with OCR3 not configured", func(t *testing.T) { // Deploy a new OCR3 contract - resp, err := changeset.DeployOCR3(env.Env, registryChain) + resp, err := changeset.DeployOCR3(env.Env, env.RegistrySelector) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, env.Env.ExistingAddresses.Merge(resp.AddressBook)) @@ -275,7 +314,7 @@ func TestKeystoneView(t *testing.T) { var outView changeset.KeystoneView require.NoError(t, json.Unmarshal(b, &outView)) - chainID, err := chain_selectors.ChainIdFromSelector(registryChain) + chainID, err := chain_selectors.ChainIdFromSelector(env.RegistrySelector) require.NoError(t, err) chainName, err := chain_selectors.NameFromChainId(chainID) require.NoError(t, err) @@ -290,6 +329,7 @@ func TestKeystoneView(t *testing.T) { }) t.Run("fails to generate a view of the keystone state with a bad OracleConfig", func(t *testing.T) { + env.Env.ExistingAddresses = originalAddressBook oracleConfigCopy := oracleConfig oracleConfigCopy.DeltaRoundMillis = 0 oracleConfigCopy.DeltaProgressMillis = 0 diff --git a/deployment/keystone/changeset/workflowregistry/deploy.go b/deployment/keystone/changeset/workflowregistry/deploy.go index 810d5d4ab2a..ed81d6cebf0 100644 --- a/deployment/keystone/changeset/workflowregistry/deploy.go +++ b/deployment/keystone/changeset/workflowregistry/deploy.go @@ -8,13 +8,12 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) var _ cldf.ChangeSet[uint64] = Deploy -func Deploy(env deployment.Environment, registrySelector uint64) (cldf.ChangesetOutput, error) { +func Deploy(env cldf.Environment, registrySelector uint64) (cldf.ChangesetOutput, error) { lggr := env.Logger chain, ok := env.Chains[registrySelector] if !ok { @@ -30,7 +29,7 @@ func Deploy(env deployment.Environment, registrySelector uint64) (cldf.Changeset return cldf.ChangesetOutput{AddressBook: ab}, nil } -func DeployV2(env deployment.Environment, req *changeset.DeployRequestV2) (cldf.ChangesetOutput, error) { +func DeployV2(env cldf.Environment, req *changeset.DeployRequestV2) (cldf.ChangesetOutput, error) { lggr := env.Logger chain, ok := env.Chains[req.ChainSel] if !ok { diff --git a/deployment/keystone/changeset/workflowregistry/setup_test.go b/deployment/keystone/changeset/workflowregistry/setup_test.go index 37e8b627f21..3147164e00c 100644 --- a/deployment/keystone/changeset/workflowregistry/setup_test.go +++ b/deployment/keystone/changeset/workflowregistry/setup_test.go @@ -10,14 +10,13 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) type SetupTestWorkflowRegistryResponse struct { Registry *workflow_registry.WorkflowRegistry - Chain deployment.Chain + Chain cldf.Chain RegistrySelector uint64 AddressBook cldf.AddressBook } @@ -46,9 +45,9 @@ func SetupTestWorkflowRegistry(t *testing.T, lggr logger.Logger, chainSel uint64 } } -func testChain(t *testing.T) deployment.Chain { +func testChain(t *testing.T) cldf.Chain { chains, _ := memory.NewMemoryChains(t, 1, 5) - var chain deployment.Chain + var chain cldf.Chain for _, c := range chains { chain = c break diff --git a/deployment/keystone/changeset/workflowregistry/strategies.go b/deployment/keystone/changeset/workflowregistry/strategies.go index ebc73bdc567..743027c8733 100644 --- a/deployment/keystone/changeset/workflowregistry/strategies.go +++ b/deployment/keystone/changeset/workflowregistry/strategies.go @@ -12,7 +12,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -22,7 +21,7 @@ type strategy interface { } type simpleTransaction struct { - chain deployment.Chain + chain cldf.Chain } func (s *simpleTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (cldf.ChangesetOutput, error) { @@ -41,11 +40,11 @@ type mcmsTransaction struct { Address common.Address ChainSel uint64 ContractSet *changeset.ContractSet - Env deployment.Environment + Env cldf.Environment } func (m *mcmsTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (cldf.ChangesetOutput, error) { - opts := deployment.SimTransactOpts() + opts := cldf.SimTransactOpts() tx, err := callFn(opts) if err != nil { diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go index 18069e6db75..f81c8e9362d 100644 --- a/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go +++ b/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" workflow_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/workflow/generated/workflow_registry_wrapper" @@ -33,7 +32,7 @@ func (r *UpdateAllowedDonsRequest) Validate() error { } // UpdateAllowedDons updates the list of DONs that workflows can be sent to. -func UpdateAllowedDons(env deployment.Environment, req *UpdateAllowedDonsRequest) (cldf.ChangesetOutput, error) { +func UpdateAllowedDons(env cldf.Environment, req *UpdateAllowedDonsRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(); err != nil { return cldf.ChangesetOutput{}, err } @@ -76,7 +75,7 @@ func UpdateAllowedDons(env deployment.Environment, req *UpdateAllowedDonsRequest return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { tx, err := registry.UpdateAllowedDONs(opts, req.DonIDs, req.Allowed) if err != nil { - err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + err = cldf.DecodeErr(workflow_registry.WorkflowRegistryABI, err) } return tx, err }) diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go index a90920ea5c6..81bb1b9921f 100644 --- a/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go +++ b/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go @@ -12,7 +12,7 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" @@ -32,9 +32,9 @@ func TestUpdateAllowedDons(t *testing.T) { assert.Empty(t, dons) - env := deployment.Environment{ + env := cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chainSel: resp.Chain, }, ExistingAddresses: resp.AddressBook, diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go index 2d26ca583a0..80fa51ce572 100644 --- a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go +++ b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" workflow_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/workflow/generated/workflow_registry_wrapper" @@ -35,7 +34,7 @@ func (r *UpdateAuthorizedAddressesRequest) Validate() error { return nil } -func getWorkflowRegistry(env deployment.Environment, chainSel uint64) (*workflow_registry.WorkflowRegistry, error) { +func getWorkflowRegistry(env cldf.Environment, chainSel uint64) (*workflow_registry.WorkflowRegistry, error) { resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ Chains: env.Chains, AddressBook: env.ExistingAddresses, @@ -53,7 +52,7 @@ func getWorkflowRegistry(env deployment.Environment, chainSel uint64) (*workflow } // UpdateAuthorizedAddresses updates the list of DONs that workflows can be sent to. -func UpdateAuthorizedAddresses(env deployment.Environment, req *UpdateAuthorizedAddressesRequest) (cldf.ChangesetOutput, error) { +func UpdateAuthorizedAddresses(env cldf.Environment, req *UpdateAuthorizedAddressesRequest) (cldf.ChangesetOutput, error) { if err := req.Validate(); err != nil { return cldf.ChangesetOutput{}, err } @@ -101,7 +100,7 @@ func UpdateAuthorizedAddresses(env deployment.Environment, req *UpdateAuthorized return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { tx, err := registry.UpdateAuthorizedAddresses(opts, addr, req.Allowed) if err != nil { - err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + err = cldf.DecodeErr(workflow_registry.WorkflowRegistryABI, err) } return tx, err }) diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go index 077c3e04b24..7a754340a01 100644 --- a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go +++ b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" @@ -33,9 +33,9 @@ func TestUpdateAuthorizedAddresses(t *testing.T) { assert.Empty(t, authorizedAddresses) - env := deployment.Environment{ + env := cldf.Environment{ Logger: lggr, - Chains: map[uint64]deployment.Chain{ + Chains: map[uint64]cldf.Chain{ chainSel: resp.Chain, }, ExistingAddresses: resp.AddressBook, diff --git a/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go b/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go index 5574f8152ce..70da139149d 100644 --- a/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go +++ b/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go @@ -11,7 +11,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -37,7 +36,7 @@ func (c *workflowRegistryDeployer) Deploy(req changeset.DeployRequest) (*changes req.Chain.DeployerKey, req.Chain.Client) if err != nil { - return nil, deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) + return nil, cldf.DecodeErr(workflow_registry.WorkflowRegistryABI, err) } _, err = req.Chain.Confirm(tx) @@ -64,7 +63,7 @@ func (c *workflowRegistryDeployer) Deploy(req changeset.DeployRequest) (*changes // deployWorkflowRegistry deploys the WorkflowRegistry contract to the chain // and saves the address in the address book. This mutates the address book. -func deployWorkflowRegistry(chain deployment.Chain, ab cldf.AddressBook) (*changeset.DeployResponse, error) { +func deployWorkflowRegistry(chain cldf.Chain, ab cldf.AddressBook) (*changeset.DeployResponse, error) { deployer, err := newWorkflowRegistryDeployer() resp, err := deployer.Deploy(changeset.DeployRequest{Chain: chain}) if err != nil { diff --git a/deployment/keystone/test/changeset/capability_registry.go b/deployment/keystone/test/changeset/capability_registry.go index ea63f15990c..44ac1a00680 100644 --- a/deployment/keystone/test/changeset/capability_registry.go +++ b/deployment/keystone/test/changeset/capability_registry.go @@ -6,11 +6,12 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" capabilities_registry "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) @@ -19,7 +20,7 @@ type HydrateConfig struct { } // HydrateCapabilityRegistry deploys a new capabilities registry contract and hydrates it with the provided data. -func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env deployment.Environment, cfg HydrateConfig) (*capabilities_registry.CapabilitiesRegistry, error) { +func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env cldf.Environment, cfg HydrateConfig) (*capabilities_registry.CapabilitiesRegistry, error) { t.Helper() chainSelector, err := chainsel.SelectorFromChainId(cfg.ChainID) if err != nil { @@ -50,13 +51,13 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env nopsParams := v.NopsToNopsParams() tx, err := deployedContract.AddNodeOperators(chain.DeployerKey, nopsParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = cldf.ConfirmIfNoError(chain, tx, cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add node operators: %w", err) } capabilitiesParams := v.CapabilitiesToCapabilitiesParams() tx, err = deployedContract.AddCapabilities(chain.DeployerKey, capabilitiesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = cldf.ConfirmIfNoError(chain, tx, cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -65,7 +66,7 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env return nil, fmt.Errorf("failed to convert nodes to nodes params: %w", err) } tx, err = deployedContract.AddNodes(chain.DeployerKey, nodesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = cldf.ConfirmIfNoError(chain, tx, cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add nodes: %w", err) } @@ -79,7 +80,7 @@ func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env peerIds = append(peerIds, id) } tx, err = deployedContract.AddDON(chain.DeployerKey, peerIds, cfgs, don.IsPublic, don.AcceptsWorkflows, don.F) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { + if _, err = cldf.ConfirmIfNoError(chain, tx, cldf.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { return nil, fmt.Errorf("failed to add don: %w", err) } } diff --git a/go.mod b/go.mod index 3de9217e75d..6cefb5e48c0 100644 --- a/go.mod +++ b/go.mod @@ -74,13 +74,13 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250502210357-2df484128afa @@ -88,10 +88,10 @@ require ( github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250501150903-3e93089d9ad5 github.com/smartcontractkit/chainlink-protos/orchestrator v0.5.0 github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 github.com/smartcontractkit/chainlink-tron/relayer v0.0.10 github.com/smartcontractkit/freeport v0.1.0 - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 diff --git a/go.sum b/go.sum index 0e627236312..3c17c47712a 100644 --- a/go.sum +++ b/go.sum @@ -1076,22 +1076,22 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7 h1:j6Vo/NX2ABsPdGxETC5pfQLcz/h6iLJu/Yx+8AhPa34= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250425163923-16aa375957b7/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1110,8 +1110,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-tron/relayer v0.0.10 h1:JMAe0YmiaMMm/2Ip5tB8R3JFK9jIpVY2HMIfkq5hKBU= github.com/smartcontractkit/chainlink-tron/relayer v0.0.10/go.mod h1:r+PL9PgWWVErgY686mKZp+B6Xn//WEnUkFdobJAYOAo= github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d h1:qLmSOOtB/Ogn79eIDkuujOu8M5Jd747V1H7Brk/nTvo= @@ -1120,8 +1120,8 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 00d402ebcec..3648cca5a18 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -45,11 +45,11 @@ require ( github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-protos/job-distributor v0.9.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -58,8 +58,8 @@ require ( github.com/smartcontractkit/chainlink-testing-framework/sentinel v0.1.2 github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.0 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.51.0 - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 - github.com/smartcontractkit/mcms v0.18.0 + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 + github.com/smartcontractkit/mcms v0.19.2 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 github.com/subosito/gotenv v1.6.0 @@ -450,7 +450,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect @@ -461,7 +461,7 @@ require ( 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/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 // indirect github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250422175525-b7575d96bd4d // indirect github.com/smartcontractkit/freeport v0.1.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index f3304881712..b70769043de 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,24 +1466,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1504,8 +1504,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 h1:ks1FuQQ6f7PY/97VFXxtZhAyWZaT0NCvhT+1wKgyOt0= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4/go.mod h1:zw3QH/GTvPl/7Cjyw+y4cJYnP16QHTEh7wWLJQd9lM8= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 h1:S5HND0EDtlA+xp2E+mD11DlUTp2wD6uojwixye8ZB/k= @@ -1530,10 +1530,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/integration-tests/load/ccip/ccip_staging_test.go b/integration-tests/load/ccip/ccip_staging_test.go index be615e54333..8736bee42fb 100644 --- a/integration-tests/load/ccip/ccip_staging_test.go +++ b/integration-tests/load/ccip/ccip_staging_test.go @@ -12,7 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/wasp" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/crib" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -37,7 +38,7 @@ func TestStaging_CCIP_Load(t *testing.T) { require.NoError(t, err) require.NotNil(t, env) userOverrides.Validate(t, env) - state, err := ccipchangeset.LoadOnchainState(*env) + state, err := stateview.LoadOnchainState(*env) require.NoError(t, err) // initialize additional accounts on other chains diff --git a/integration-tests/load/ccip/ccip_test.go b/integration-tests/load/ccip/ccip_test.go index eb89661238f..974e227e996 100644 --- a/integration-tests/load/ccip/ccip_test.go +++ b/integration-tests/load/ccip/ccip_test.go @@ -9,6 +9,9 @@ import ( "github.com/gagliardetto/solana-go" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -16,9 +19,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/deployment" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-testing-framework/wasp" @@ -93,7 +93,7 @@ func TestCCIPLoad_RPS(t *testing.T) { // Keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) - state, err := ccipchangeset.LoadOnchainState(*env) + state, err := stateview.LoadOnchainState(*env) require.NoError(t, err) finalSeqNrCommitChannels := make(map[uint64]chan finalSeqNrReport) @@ -277,8 +277,8 @@ func TestCCIPLoad_RPS(t *testing.T) { func prepareAccountToSendLink( t *testing.T, - state ccipchangeset.CCIPOnChainState, - e deployment.Environment, + state stateview.CCIPOnChainState, + e cldf.Environment, src uint64, srcAccount *bind.TransactOpts) error { lggr := logger.Test(t) @@ -288,7 +288,7 @@ func prepareAccountToSendLink( lggr.Infow("Granting mint and burn roles") tx, err := srcLink.GrantMintAndBurnRoles(srcDeployer, srcAccount.From) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) if err != nil { return err } @@ -300,7 +300,7 @@ func prepareAccountToSendLink( srcAccount.From, big.NewInt(20_000), ) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) if err != nil { return err } @@ -310,6 +310,6 @@ func prepareAccountToSendLink( // Approve the router to spend the tokens and confirm the tx's // To prevent having to approve the router for every transfer, we approve a sufficiently large amount tx, err = srcLink.Approve(srcAccount, state.Chains[src].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) return err } diff --git a/integration-tests/load/ccip/destination_gun.go b/integration-tests/load/ccip/destination_gun.go index c5c056bf85a..b11d3cd0760 100644 --- a/integration-tests/load/ccip/destination_gun.go +++ b/integration-tests/load/ccip/destination_gun.go @@ -30,8 +30,10 @@ import ( selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" - "github.com/smartcontractkit/chainlink/deployment" - ccipchangeset "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" ) @@ -42,8 +44,8 @@ type SeqNumRange struct { type DestinationGun struct { l logger.Logger - env deployment.Environment - state *ccipchangeset.CCIPOnChainState + env cldf.Environment + state *stateview.CCIPOnChainState roundNum *atomic.Int32 chainSelector uint64 receiver common.Address @@ -57,8 +59,8 @@ type DestinationGun struct { func NewDestinationGun( l logger.Logger, chainSelector uint64, - env deployment.Environment, - state *ccipchangeset.CCIPOnChainState, + env cldf.Environment, + state *stateview.CCIPOnChainState, receiver common.Address, overrides *ccip.LoadConfig, evmSourceKeys map[uint64]*bind.TransactOpts, @@ -106,7 +108,7 @@ func (m *DestinationGun) Call(_ *wasp.Generator) *wasp.Response { m.l.Errorw("Failed to transmit message", "gun", waspGroup, "sourceChainFamily", selectorFamily, - err, deployment.MaybeDataErr(err)) + err, cldf.MaybeDataErr(err)) if m.metricPipe != nil { // in the event of an error, still push a metric // sequence numbers start at 1 so using 0 as a sentinel value @@ -159,7 +161,7 @@ func (m *DestinationGun) sendEVMMessage(src uint64) error { m.l.Errorw("could not get fee ", "dstChainSelector", m.chainSelector, "fee", fee, - "err", deployment.MaybeDataErr(err)) + "err", cldf.MaybeDataErr(err)) return err } if msg.FeeToken == common.HexToAddress("0x0") { @@ -181,13 +183,13 @@ func (m *DestinationGun) sendEVMMessage(src uint64) error { m.l.Errorw("execution reverted from ", "sourceChain", src, "destchain", m.chainSelector, - "err", deployment.MaybeDataErr(err)) + "err", cldf.MaybeDataErr(err)) return err } _, err = m.env.Chains[src].Confirm(tx) if err != nil { - m.l.Errorw("could not confirm tx on source", "tx", tx, "err", deployment.MaybeDataErr(err)) + m.l.Errorw("could not confirm tx on source", "tx", tx, "err", cldf.MaybeDataErr(err)) return err } @@ -365,7 +367,7 @@ func (m *DestinationGun) sendSolanaMessage(src uint64) error { m.l.Errorw("failed to build instruction", "src", src, "dest", m.chainSelector, - "err", deployment.MaybeDataErr(err)) + "err", cldf.MaybeDataErr(err)) return err } diff --git a/integration-tests/load/ccip/helpers.go b/integration-tests/load/ccip/helpers.go index e82c72a1ca3..55e81158bb7 100644 --- a/integration-tests/load/ccip/helpers.go +++ b/integration-tests/load/ccip/helpers.go @@ -28,6 +28,9 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/nonce_manager" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/environment/crib" @@ -58,7 +61,7 @@ func subscribeTransmitEvents( startBlock *uint64, srcChainSel uint64, loadFinished chan struct{}, - client deployment.OnchainClient, + client cldf.OnchainClient, wg *sync.WaitGroup, metricPipe chan messageData, finalSeqNrCommitChannels map[uint64]chan finalSeqNrReport, @@ -168,7 +171,7 @@ func subscribeCommitEvents( srcChains []uint64, startBlock *uint64, chainSelector uint64, - client deployment.OnchainClient, + client cldf.OnchainClient, finalSeqNrs chan finalSeqNrReport, wg *sync.WaitGroup, metricPipe chan messageData, @@ -297,7 +300,7 @@ func subscribeExecutionEvents( srcChains []uint64, startBlock *uint64, chainSelector uint64, - client deployment.OnchainClient, + client cldf.OnchainClient, finalSeqNrs chan finalSeqNrReport, wg *sync.WaitGroup, metricPipe chan messageData, @@ -479,7 +482,7 @@ func subscribeSkippedIncorrectNonce( } // fundAdditionalKeys will create len(targetChains) new addresses, and send funds to them on every targetChain -func fundAdditionalKeys(lggr logger.Logger, e deployment.Environment, destChains []uint64) (map[uint64][]*bind.TransactOpts, error) { +func fundAdditionalKeys(lggr logger.Logger, e cldf.Environment, destChains []uint64) (map[uint64][]*bind.TransactOpts, error) { deployerMap := make(map[uint64][]*bind.TransactOpts) addressMap := make(map[uint64][]common.Address) numAccounts := len(destChains) @@ -522,8 +525,8 @@ func fundAdditionalKeys(lggr logger.Logger, e deployment.Environment, destChains } return deployerMap, nil } -func reclaimFunds(lggr logger.Logger, e deployment.Environment, addressesByChain map[uint64][]*bind.TransactOpts, returnAddress common.Address) error { - removeFundsFromAccounts := func(ctx context.Context, lggr logger.Logger, chain deployment.Chain, addresses []*bind.TransactOpts, returnAddress common.Address, sel uint64) error { +func reclaimFunds(lggr logger.Logger, e cldf.Environment, addressesByChain map[uint64][]*bind.TransactOpts, returnAddress common.Address) error { + removeFundsFromAccounts := func(ctx context.Context, lggr logger.Logger, chain cldf.Chain, addresses []*bind.TransactOpts, returnAddress common.Address, sel uint64) error { for _, deployer := range addresses { balance, err := chain.Client.BalanceAt(ctx, deployer.From, nil) if err != nil { diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 2ce3a4b6e69..6123755bd7d 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -27,10 +27,11 @@ require ( github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 + github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -437,10 +438,9 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect - github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250502210357-2df484128afa // indirect @@ -451,14 +451,14 @@ require ( 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/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.51.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250422175525-b7575d96bd4d // indirect github.com/smartcontractkit/freeport v0.1.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 // indirect - github.com/smartcontractkit/mcms v0.18.0 // indirect + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 // indirect + github.com/smartcontractkit/mcms v0.19.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 // indirect github.com/sony/gobreaker/v2 v2.1.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 3bdbd7f58a0..75cf848950b 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1447,24 +1447,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1485,8 +1485,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4 h1:ks1FuQQ6f7PY/97VFXxtZhAyWZaT0NCvhT+1wKgyOt0= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.4/go.mod h1:zw3QH/GTvPl/7Cjyw+y4cJYnP16QHTEh7wWLJQd9lM8= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.5 h1:S5HND0EDtlA+xp2E+mD11DlUTp2wD6uojwixye8ZB/k= @@ -1509,10 +1509,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/integration-tests/smoke/ccip/ccip_add_chain_test.go b/integration-tests/smoke/ccip/ccip_add_chain_test.go index 6cdfe4e82ec..49d072aa54e 100644 --- a/integration-tests/smoke/ccip/ccip_add_chain_test.go +++ b/integration-tests/smoke/ccip/ccip_add_chain_test.go @@ -11,8 +11,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - ccipcs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" @@ -55,7 +56,7 @@ func Test_AddChain(t *testing.T) { ///////////////////////////////////// e = setupChain(t, e, tEnv, toDeploy, false) - state, err := ccipcs.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) tEnv.UpdateDeployedEnvironment(e) // check RMNRemote is up and RMNProxy is correctly wired. @@ -175,7 +176,7 @@ func Test_AddChain(t *testing.T) { // transferred to MCMS. e = setupChain(t, e, tEnv, []uint64{remainingChain}, true) - state, err = ccipcs.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) tEnv.UpdateDeployedEnvironment(e) @@ -199,7 +200,7 @@ func Test_AddChain(t *testing.T) { true, // mcmsEnabled ) - state, err = ccipcs.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) assertChainWiringOutbound( @@ -317,7 +318,7 @@ func Test_AddChain(t *testing.T) { true, // mcmsEnabled ) - state, err = ccipcs.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) assertChainWiringOutbound( @@ -536,7 +537,7 @@ func setupChain(t *testing.T, e testhelpers.DeployedEnv, tEnv testhelpers.TestEn // It doesn't check that the existingChains have the newChain enabled as a dest. func assertChainWiringInbound( t *testing.T, - state ccipcs.CCIPOnChainState, + state stateview.CCIPOnChainState, newChain uint64, existingChains []uint64, testRouterEnabled bool, @@ -582,7 +583,7 @@ func assertChainWiringInbound( // It doesn't check that the newChain can process the requests. func assertChainWiringOutbound( t *testing.T, - state ccipcs.CCIPOnChainState, + state stateview.CCIPOnChainState, newChain uint64, existingChains []uint64, testRouterEnabled bool, @@ -732,7 +733,7 @@ func offRampSourceUpdates(t *testing.T, dests []uint64, sources []uint64, testRo return } -func assertRMNRemoteAndProxyState(t *testing.T, chains []uint64, state ccipcs.CCIPOnChainState) { +func assertRMNRemoteAndProxyState(t *testing.T, chains []uint64, state stateview.CCIPOnChainState) { for _, chain := range chains { require.NotEqual(t, common.Address{}, state.Chains[chain].RMNRemote.Address()) _, err := state.Chains[chain].RMNRemote.GetCursedSubjects(&bind.CallOpts{ @@ -756,7 +757,7 @@ func transferToMCMSAndRenounceTimelockDeployer( t *testing.T, e testhelpers.DeployedEnv, chains []uint64, - state ccipcs.CCIPOnChainState, + state stateview.CCIPOnChainState, onlyChainContracts bool, ) { apps := make([]commonchangeset.ConfiguredChangeSet, 0, len(chains)+1) diff --git a/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go index 5a3903e29de..a336b37311d 100644 --- a/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/exp/maps" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/messagingtest" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" ) @@ -31,7 +31,7 @@ func Test_CCIP_Messaging_EVM2Aptos(t *testing.T) { t.Log("Deploying CCIPDummyReceiver...") testhelpers.DeployAptosCCIPReceiver(t, e.Env) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) sourceChain := evmChainSelectors[0] diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go index 45af4381be5..bce252362d1 100644 --- a/integration-tests/smoke/ccip/ccip_batching_test.go +++ b/integration-tests/smoke/ccip/ccip_batching_test.go @@ -15,15 +15,17 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/multicall3" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" ) @@ -33,7 +35,7 @@ const ( type batchTestSetup struct { e testhelpers.DeployedEnv - state changeset.CCIPOnChainState + state stateview.CCIPOnChainState sourceChain1 uint64 sourceChain2 uint64 destChain uint64 @@ -53,7 +55,7 @@ func newBatchTestSetup(t *testing.T, opts ...testhelpers.TestOps) batchTestSetup options..., ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChainSelectors := maps.Keys(e.Env.Chains) @@ -366,7 +368,7 @@ type outputErr[T any] struct { func assertExecAsync( t *testing.T, e testhelpers.DeployedEnv, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, seqNums []uint64, @@ -389,7 +391,7 @@ func assertExecAsync( func assertCommitReportsAsync( t *testing.T, e testhelpers.DeployedEnv, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, startSeqNum, @@ -415,7 +417,7 @@ func sendMessagesAsync( ctx context.Context, t *testing.T, e testhelpers.DeployedEnv, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, sourceChainSelector, destChainSelector uint64, numMessages int, @@ -458,7 +460,7 @@ func sendMessagesAsync( func sendMessages( ctx context.Context, t *testing.T, - sourceChain deployment.Chain, + sourceChain cldf.Chain, sourceTransactOpts *bind.TransactOpts, sourceOnRamp onramp.OnRampInterface, sourceRouter *router.Router, @@ -493,7 +495,7 @@ func sendMessages( }, calls, ) - _, err = deployment.ConfirmIfNoError(sourceChain, tx, err) + _, err = cldf.ConfirmIfNoError(sourceChain, tx, err) if err != nil { return fmt.Errorf("send messages via multicall3: %w", err) } diff --git a/integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go b/integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go index c238ce57e5f..c46c14f3061 100644 --- a/integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go +++ b/integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -13,11 +13,13 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/deployment" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" ccipChangesetSolana "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" commonSolana "github.com/smartcontractkit/chainlink/deployment/common/changeset/solana" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" @@ -479,7 +481,7 @@ func runRmnUncurseTest(t *testing.T, tc CurseTestCase) { verifyNoActiveCurseOnAllChains(t, &e) } -func transferRMNContractToMCMS(t *testing.T, e *testhelpers.DeployedEnv, state changeset.CCIPOnChainState) { +func transferRMNContractToMCMS(t *testing.T, e *testhelpers.DeployedEnv, state stateview.CCIPOnChainState) { contractsByChain := make(map[uint64][]common.Address) rmnRemotePerChain := v1_6.BuildRMNRemotePerChain(e.Env, state) rmnRemoteAddressesByChain := make(map[uint64]common.Address) @@ -494,7 +496,7 @@ func transferRMNContractToMCMS(t *testing.T, e *testhelpers.DeployedEnv, state c } contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) - timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + timelocksPerChain := deployergroup.BuildTimelockPerChain(e.Env, state) // This is required because RMN Contracts is initially owned by the deployer _, err := commonchangeset.Apply(t, e.Env, timelocksPerChain, commonchangeset.Configure( @@ -558,7 +560,7 @@ func runRmnUncurseMCMSTest(t *testing.T, tc CurseTestCase, action types.Timelock IncludeNotConnectedLanes: true, } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) verifyNoActiveCurseOnAllChains(t, &e) @@ -696,7 +698,7 @@ func runRmnCurseMCMSTest(t *testing.T, tc CurseTestCase, action types.TimelockAc IncludeNotConnectedLanes: true, } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) verifyNoActiveCurseOnAllChains(t, &e) @@ -859,7 +861,7 @@ func TestRMNUncurseForceOption(t *testing.T) { return v1_6.GetAllCursableChainsSelector(e.Env)[id] } - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) transferRMNContractToMCMS(t, &e, state) diff --git a/integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go b/integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go index abaa962ad90..4ceb52f7250 100644 --- a/integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go +++ b/integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go @@ -12,10 +12,13 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/deployergroup" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" @@ -73,7 +76,7 @@ func TestUpdateRMNConfig(t *testing.T) { func TestSetDynamicConfig(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) rmnHome := state.Chains[e.HomeChainSel].RMNHome @@ -138,7 +141,7 @@ func TestSetDynamicConfig(t *testing.T) { func TestRevokeConfig(t *testing.T) { e, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) rmnHome := state.Chains[e.HomeChainSel].RMNHome @@ -182,7 +185,7 @@ func TestRevokeConfig(t *testing.T) { func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { e, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) contractsByChain := make(map[uint64][]common.Address) @@ -193,7 +196,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) - timelocksPerChain := changeset.BuildTimelockPerChain(e.Env, state) + timelocksPerChain := deployergroup.BuildTimelockPerChain(e.Env, state) if tc.useMCMS { // This is required because RMNHome is initially owned by the deployer _, err = commonchangeset.Apply(t, e.Env, timelocksPerChain, @@ -252,7 +255,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { require.NoError(t, err) - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) @@ -324,7 +327,7 @@ func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { } } -func buildRMNRemoteAddressPerChain(e deployment.Environment, state changeset.CCIPOnChainState) map[uint64]common.Address { +func buildRMNRemoteAddressPerChain(e cldf.Environment, state stateview.CCIPOnChainState) map[uint64]common.Address { rmnRemotePerChain := v1_6.BuildRMNRemotePerChain(e, state) rmnRemoteAddressPerChain := make(map[uint64]common.Address) for chain, remote := range rmnRemotePerChain { @@ -369,7 +372,7 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { ) require.NoError(t, err) contractsByChain := make(map[uint64][]common.Address) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) for _, chain := range allChains { rmnProxy := state.Chains[chain].RMNProxy @@ -431,7 +434,7 @@ func TestSetRMNRemoteOnRMNProxy(t *testing.T) { ), ) require.NoError(t, err) - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) for _, chain := range allChains { rmnProxy := state.Chains[chain].RMNProxy diff --git a/integration-tests/smoke/ccip/ccip_disable_lane_test.go b/integration-tests/smoke/ccip/ccip_disable_lane_test.go index dc26de51813..c921aa87b46 100644 --- a/integration-tests/smoke/ccip/ccip_disable_lane_test.go +++ b/integration-tests/smoke/ccip/ccip_disable_lane_test.go @@ -14,10 +14,11 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" ) @@ -30,7 +31,7 @@ func TestDisableLane(t *testing.T) { ) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) // add all lanes diff --git a/integration-tests/smoke/ccip/ccip_fees_test.go b/integration-tests/smoke/ccip/ccip_fees_test.go index 67d43a8dd53..82009f8b06b 100644 --- a/integration-tests/smoke/ccip/ccip_fees_test.go +++ b/integration-tests/smoke/ccip/ccip_fees_test.go @@ -13,10 +13,13 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/feestest" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -26,7 +29,7 @@ func setupNewFeeToken( tenv testhelpers.DeployedEnv, deployer *bind.TransactOpts, chainSelector uint64, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, tokenSymbol string, tokenDecimals uint8, ) (feeToken *burn_mint_erc677.BurnMintERC677) { @@ -40,27 +43,27 @@ func setupNewFeeToken( tokenDecimals, big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), ) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) lggr.Infow("Deployed new fee token", "tokenAddress", tokenAddress) // grant mint role tx, err = token.GrantMintRole(deployer, deployer.From) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // mint token and approve to router tx, err = token.Mint(deployer, deployer.From, deployment.E18Mult(10_000)) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) tx, err = token.Approve(deployer, state.Chains[chainSelector].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) // add this new fee token to fee quoter tx, err = state.Chains[chain.Selector].FeeQuoter.ApplyFeeTokensUpdates(deployer, []common.Address{}, []common.Address{tokenAddress}) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) lggr.Infow("Added new fee token to fee quoter", "tokenAddress", tokenAddress) @@ -77,7 +80,7 @@ func setupNewFeeToken( GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{}, }, ) - _, err = deployment.ConfirmIfNoError(chain, tx, err) + _, err = cldf.ConfirmIfNoError(chain, tx, err) require.NoError(t, err) lggr.Infow("Set price for new fee token", "tokenAddress", tokenAddress) @@ -88,7 +91,7 @@ func setupNewFeeToken( // approves the router to spend the tokens func setupTokens( t *testing.T, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, tenv testhelpers.DeployedEnv, src, dest uint64, transferTokenMintAmount, @@ -121,7 +124,7 @@ func setupTokens( e.Chains[src].DeployerKey.From, transferTokenMintAmount, ) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) require.NoError(t, err) // Mint a destination token @@ -130,23 +133,23 @@ func setupTokens( e.Chains[dest].DeployerKey.From, transferTokenMintAmount, ) - _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[dest], tx, err) require.NoError(t, err) // Approve the router to spend the tokens and confirm the tx's // To prevent having to approve the router for every transfer, we approve a sufficiently large amount tx, err = srcToken.Approve(e.Chains[src].DeployerKey, state.Chains[src].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) require.NoError(t, err) tx, err = dstToken.Approve(e.Chains[dest].DeployerKey, state.Chains[dest].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[dest], tx, err) require.NoError(t, err) // Grant mint and burn roles to the deployer key for the newly deployed linkToken // Since those roles are not granted automatically tx, err = linkToken.GrantMintAndBurnRoles(e.Chains[src].DeployerKey, e.Chains[src].DeployerKey.From) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) require.NoError(t, err) // Mint link token and confirm the tx @@ -155,7 +158,7 @@ func setupTokens( e.Chains[src].DeployerKey.From, feeTokenMintAmount, ) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) + _, err = cldf.ConfirmIfNoError(e.Chains[src], tx, err) require.NoError(t, err) return srcToken, dstToken @@ -175,7 +178,7 @@ func Test_CCIPFees(t *testing.T) { destChain := allChains[1] // Get new state after migration. - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) srcToken, dstToken := setupTokens( diff --git a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go index b202c976815..ae98c2e1a6e 100644 --- a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go +++ b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go @@ -12,9 +12,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" ) @@ -32,7 +32,7 @@ func Test_CCIPGasPriceUpdatesWriteFrequency(t *testing.T) { return params }), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) testhelpers.AddLanesForAll(t, &e, state) @@ -138,7 +138,7 @@ func Test_CCIPGasPriceUpdatesDeviation(t *testing.T) { return params }), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) testhelpers.AddLanesForAll(t, &e, state) diff --git a/integration-tests/smoke/ccip/ccip_message_limitations_test.go b/integration-tests/smoke/ccip/ccip_message_limitations_test.go index ee3c5bbdf9a..740f07515f7 100644 --- a/integration-tests/smoke/ccip/ccip_message_limitations_test.go +++ b/integration-tests/smoke/ccip/ccip_message_limitations_test.go @@ -14,10 +14,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" + "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" mlt "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/messagelimitationstest" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" ) @@ -28,7 +29,7 @@ func Test_CCIPMessageLimitations(t *testing.T) { testEnv, _, _ := testsetups.NewIntegrationEnvironment(t) chains := maps.Keys(testEnv.Env.Chains) - onChainState, err := changeset.LoadOnchainState(testEnv.Env) + onChainState, err := stateview.LoadOnchainState(testEnv.Env) require.NoError(t, err) testhelpers.AddLanesForAll(t, &testEnv, onChainState) diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip/ccip_messaging_test.go index 50b87a67705..2254ddb017b 100644 --- a/integration-tests/smoke/ccip/ccip_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_messaging_test.go @@ -24,12 +24,13 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" mt "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/messagingtest" soltesthelpers "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers/solana" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" "github.com/smartcontractkit/chainlink/deployment/ccip/manualexechelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/memory" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" @@ -55,7 +56,7 @@ func Test_CCIPMessaging_EVM2EVM(t *testing.T) { })), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChainSelectors := maps.Keys(e.Env.Chains) @@ -222,7 +223,7 @@ func Test_CCIPMessaging_EVM2Solana(t *testing.T) { // TODO: do this as part of setup testhelpers.DeploySolanaCcipReceiver(t, e.Env) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChainSelectors := maps.Keys(e.Env.Chains) @@ -398,7 +399,7 @@ func Test_CCIPMessaging_Solana2EVM(t *testing.T) { ctx := testhelpers.Context(t) e, _, _ := testsetups.NewIntegrationEnvironment(t, testhelpers.WithSolChains(1)) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChainSelectors := maps.Keys(e.Env.Chains) @@ -478,7 +479,7 @@ func (s *monitorState) incReExecutions() { func monitorReExecutions( ctx context.Context, t *testing.T, - state changeset.CCIPOnChainState, + state stateview.CCIPOnChainState, destChain uint64, ss *monitorState, ) { diff --git a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go index 1d564c8eb6c..7b43b0f8be8 100644 --- a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go +++ b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go @@ -18,8 +18,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_5_0/evm_2_evm_onramp" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment" @@ -68,7 +70,7 @@ func TestV1_5_Message_RMNRemote(t *testing.T) { }, }), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectors() src1, dest := allChains[0], allChains[1] @@ -98,7 +100,7 @@ func TestV1_5_Message_RMNRemote(t *testing.T) { ), ) require.NoError(t, err) - oldState, err := changeset.LoadOnchainState(e.Env) + oldState, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) @@ -194,7 +196,7 @@ func TestV1_5_Message_RMNRemote_Curse(t *testing.T) { }, }), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectors() src1, dest := allChains[0], allChains[1] @@ -224,7 +226,7 @@ func TestV1_5_Message_RMNRemote_Curse(t *testing.T) { ), ) require.NoError(t, err) - oldState, err := changeset.LoadOnchainState(e.Env) + oldState, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) @@ -330,7 +332,7 @@ func TestV1_5_Message_RMNRemote_Curse_Uncurse(t *testing.T) { }, }), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChains := e.Env.AllChainSelectors() src1, dest := allChains[0], allChains[1] @@ -360,7 +362,7 @@ func TestV1_5_Message_RMNRemote_Curse_Uncurse(t *testing.T) { ), ) require.NoError(t, err) - oldState, err := changeset.LoadOnchainState(e.Env) + oldState, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) envNodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) require.NoError(t, err) @@ -403,7 +405,7 @@ func TestV1_5_Message_RMNRemote_Curse_Uncurse(t *testing.T) { require.NoError(t, err) // reload state after adding lanes - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) tEnv.UpdateDeployedEnvironment(e) @@ -515,7 +517,7 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { // between nodes' calculated digest and the digest set on the contract testhelpers.WithChainIDs([]uint64{chainselectors.GETH_TESTNET.EvmChainID}), ) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) allChainsExcept1337 := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) @@ -554,7 +556,7 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { ) require.NoError(t, err) // reload state after adding lanes - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) tEnv.UpdateDeployedEnvironment(e) // ensure that all lanes are functional @@ -684,7 +686,7 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { ), ) require.NoError(t, err) - state, err = changeset.LoadOnchainState(e.Env) + state, err = stateview.LoadOnchainState(e.Env) require.NoError(t, err) // Enable a single 1.6 lane with test router @@ -843,7 +845,7 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { func sendContinuousMessages( t *testing.T, e *testhelpers.DeployedEnv, - state *changeset.CCIPOnChainState, + state *stateview.CCIPOnChainState, src, dest uint64, done chan bool, ) (uint64, []*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested, []*onramp.OnRampCCIPMessageSent) { @@ -886,7 +888,7 @@ func sendContinuousMessages( func sendMessageInRealRouter( t *testing.T, e *testhelpers.DeployedEnv, - state *changeset.CCIPOnChainState, + state *stateview.CCIPOnChainState, src, dest uint64, ) any { cfg := &testhelpers.CCIPSendReqConfig{ diff --git a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go index dc043eda65a..3e17279ce87 100644 --- a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go +++ b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go @@ -16,9 +16,11 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -43,7 +45,7 @@ func Test_OutOfOrderExecution(t *testing.T) { ) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) allChainSelectors := maps.Keys(e.Chains) @@ -266,7 +268,7 @@ func Test_OutOfOrderExecution(t *testing.T) { func pickFirstAvailableUser( tenv testhelpers.DeployedEnv, sourceChain uint64, - e deployment.Environment, + e cldf.Environment, ) (*bind.TransactOpts, error) { for _, user := range tenv.Users[sourceChain] { if user == nil { diff --git a/integration-tests/smoke/ccip/ccip_reader_test.go b/integration-tests/smoke/ccip/ccip_reader_test.go index 6107676ff4a..90a481fb3c3 100644 --- a/integration-tests/smoke/ccip/ccip_reader_test.go +++ b/integration-tests/smoke/ccip/ccip_reader_test.go @@ -33,8 +33,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/integration-tests/utils/pgtest" @@ -52,6 +53,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/offramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/rmn_remote" + evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -822,7 +824,7 @@ func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { t.Parallel() ctx := tests.Context(t) env, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) + state, err := stateview.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() @@ -1186,7 +1188,7 @@ func TestCCIPReader_DiscoverContracts(t *testing.T) { func Test_GetChainFeePriceUpdates(t *testing.T) { t.Parallel() env, _ := testhelpers.NewMemoryEnvironment(t, testhelpers.WithNumOfChains(3)) - state, err := changeset.LoadOnchainState(env.Env) + state, err := stateview.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() @@ -1291,7 +1293,7 @@ func Test_LinkPriceUSD(t *testing.T) { t.Parallel() ctx := tests.Context(t) env, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) + state, err := stateview.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() @@ -1326,7 +1328,7 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { t.Parallel() ctx := tests.Context(t) env, _ := testhelpers.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) + state, err := stateview.LoadOnchainState(env.Env) require.NoError(t, err) selectors := env.Env.AllChainSelectors() diff --git a/integration-tests/smoke/ccip/ccip_reorg_test.go b/integration-tests/smoke/ccip/ccip_reorg_test.go index afde363bcef..4c841477362 100644 --- a/integration-tests/smoke/ccip/ccip_reorg_test.go +++ b/integration-tests/smoke/ccip/ccip_reorg_test.go @@ -26,9 +26,12 @@ import ( ctf_client "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment" - ccipcs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" @@ -317,7 +320,7 @@ func setupReorgTest(t *testing.T, testOpts ...testhelpers.TestOps) ( logging.Logger, *testsetups.DeployedLocalDevEnvironment, []string, - ccipcs.CCIPOnChainState, + stateview.CCIPOnChainState, devenv.RMNCluster, ) { require.Equal(t, os.Getenv(testhelpers.ENVTESTTYPE), string(testhelpers.Docker), @@ -331,7 +334,7 @@ func setupReorgTest(t *testing.T, testOpts ...testhelpers.TestOps) ( require.NoError(t, err) nonBootstrapP2PIDs := getNonBootstrapP2PIDs(nodeInfos) - state, err := ccipcs.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) return e, l, dockerEnv, nonBootstrapP2PIDs, state, rmnCluster @@ -377,8 +380,8 @@ func getHeadTrackerService(t *testing.T, chainSelector uint64) string { // Send CCIP message helper func sendCCIPMessage( t *testing.T, - env deployment.Environment, - state ccipcs.CCIPOnChainState, + env cldf.Environment, + state stateview.CCIPOnChainState, sourceSelector, destSelector uint64, l logging.Logger, ) *onramp.OnRampCCIPMessageSent { diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go index a55df6ea304..ec5a4cffb6b 100644 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ b/integration-tests/smoke/ccip/ccip_rmn_test.go @@ -28,9 +28,9 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" @@ -331,7 +331,7 @@ func runRmnTestCase(t *testing.T, tc rmnTestCase) { ) tc.populateFields(t, envWithRMN, rmnCluster) - onChainState, err := changeset.LoadOnchainState(envWithRMN.Env) + onChainState, err := stateview.LoadOnchainState(envWithRMN.Env) require.NoError(t, err) homeChainState, ok := onChainState.Chains[envWithRMN.HomeChainSel] @@ -743,7 +743,7 @@ func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context return disabledNodes } -func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) (map[uint64]*uint64, map[testhelpers.SourceDestPair]uint64, map[testhelpers.SourceDestPair][]uint64) { +func (tc rmnTestCase) sendMessages(t *testing.T, onChainState stateview.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) (map[uint64]*uint64, map[testhelpers.SourceDestPair]uint64, map[testhelpers.SourceDestPair][]uint64) { startBlocks := make(map[uint64]*uint64) seqNumCommit := make(map[testhelpers.SourceDestPair]uint64) seqNumExec := make(map[testhelpers.SourceDestPair][]uint64) @@ -778,7 +778,7 @@ func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnCh return startBlocks, seqNumCommit, seqNumExec } -func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { +func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState stateview.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { for _, remoteCfg := range tc.remoteChainsConfig { remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] chState, ok := onChainState.Chains[remoteSel] @@ -813,7 +813,7 @@ func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing } } -func (tc rmnTestCase) callContractsToCurseAndRevokeCurse(ctx context.Context, eg *errgroup.Group, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { +func (tc rmnTestCase) callContractsToCurseAndRevokeCurse(ctx context.Context, eg *errgroup.Group, t *testing.T, onChainState stateview.CCIPOnChainState, envWithRMN testhelpers.DeployedEnv) { for _, remoteCfg := range tc.remoteChainsConfig { remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] chState, ok := onChainState.Chains[remoteSel] @@ -882,12 +882,12 @@ func configureAndPromoteRMNHome( tc *rmnTestCase, envWithRMN testhelpers.DeployedEnv, rmnCluster devenv.RMNCluster, -) changeset.CCIPOnChainState { +) stateview.CCIPOnChainState { ctx := testcontext.Get(t) tc.populateFields(t, envWithRMN, rmnCluster) // Load on-chain state - onChainState, err := changeset.LoadOnchainState(envWithRMN.Env) + onChainState, err := stateview.LoadOnchainState(envWithRMN.Env) require.NoError(t, err) // Get the home chain state and the candidate/active digests @@ -956,7 +956,7 @@ func configureAndPromoteRMNHome( return onChainState } -func performReorgTest(t *testing.T, e testhelpers.DeployedEnv, l logging.Logger, dockerEnv *testsetups.DeployedLocalDevEnvironment, state changeset.CCIPOnChainState, nonBootstrapP2PIDs []string) (sourceSelector uint64, destSelector uint64) { +func performReorgTest(t *testing.T, e testhelpers.DeployedEnv, l logging.Logger, dockerEnv *testsetups.DeployedLocalDevEnvironment, state stateview.CCIPOnChainState, nonBootstrapP2PIDs []string) (sourceSelector uint64, destSelector uint64) { // Chain setup allChains := e.Env.AllChainSelectors() require.GreaterOrEqual(t, len(allChains), 2) diff --git a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go index 8632bee9f64..ff0a166c1f9 100644 --- a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go +++ b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go @@ -20,10 +20,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/fee_quoter" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" ) @@ -39,7 +39,7 @@ func Test_CCIPTokenPriceUpdates(t *testing.T) { } return params })) - state, err := changeset.LoadOnchainState(e.Env) + state, err := stateview.LoadOnchainState(e.Env) require.NoError(t, err) testhelpers.AddLanesForAll(t, &e, state) @@ -92,7 +92,7 @@ func Test_CCIPTokenPriceUpdates(t *testing.T) { }) require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) + _, err = cldf.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) require.NoError(t, err) t.Logf("manually editing token prices") diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go index a6c9d9f2306..ee26b7ee440 100644 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ b/integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -20,12 +20,13 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/utils" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/message_hasher" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -48,7 +49,7 @@ func TestTokenTransfer_EVM2EVM(t *testing.T) { testhelpers.WithNumOfUsersPerChain(3)) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.GreaterOrEqual(t, len(e.Chains), 2) @@ -249,7 +250,7 @@ func TestTokenTransfer_EVM2Solana(t *testing.T) { testhelpers.WithSolChains(1)) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.GreaterOrEqual(t, len(e.Chains), 2) @@ -383,7 +384,7 @@ func TestTokenTransfer_Solana2EVM(t *testing.T) { testhelpers.WithSolChains(1)) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) require.GreaterOrEqual(t, len(e.Chains), 2) diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go index e876774e157..df6c69f65dd 100644 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ b/integration-tests/smoke/ccip/ccip_usdc_test.go @@ -11,15 +11,17 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" "github.com/smartcontractkit/chainlink-evm/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -41,7 +43,7 @@ func TestUSDCTokenTransfer(t *testing.T) { ) e := tenv.Env - state, err := changeset.LoadOnchainState(e) + state, err := stateview.LoadOnchainState(e) require.NoError(t, err) allChainSelectors := maps.Keys(e.Chains) @@ -238,8 +240,8 @@ func TestUSDCTokenTransfer(t *testing.T) { func updateFeeQuoters( t *testing.T, lggr logger.Logger, - e deployment.Environment, - state changeset.CCIPOnChainState, + e cldf.Environment, + state stateview.CCIPOnChainState, chainA, chainB, chainC uint64, aChainUSDC, bChainUSDC, cChainUSDC *burn_mint_erc677.BurnMintERC677, ) error { diff --git a/integration-tests/testconfig/ccip/chaos.go b/integration-tests/testconfig/ccip/chaos.go index 37a8fcbf2bc..acd4262245d 100644 --- a/integration-tests/testconfig/ccip/chaos.go +++ b/integration-tests/testconfig/ccip/chaos.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/stretchr/testify/require" ) @@ -17,7 +17,7 @@ type ChaosConfig struct { ExperimentInjectionInterval string } -func (l *ChaosConfig) Validate(t *testing.T, e *deployment.Environment) { +func (l *ChaosConfig) Validate(t *testing.T, e *cldf.Environment) { require.NotEmpty(t, l.Namespace, "k8s namespace can't be empty") require.NotEmpty(t, l.DashboardUIDs, "dashboard UIDs can't be empty") require.NotEmpty(t, l.ExperimentFullInterval, "experiment full interval can't be null, use Go time format 1h2m3s") diff --git a/integration-tests/testconfig/ccip/load.go b/integration-tests/testconfig/ccip/load.go index a9493c4f296..9a699d6ee37 100644 --- a/integration-tests/testconfig/ccip/load.go +++ b/integration-tests/testconfig/ccip/load.go @@ -3,13 +3,12 @@ package ccip import ( "errors" "fmt" - "testing" "time" "github.com/AlekSi/pointer" - "github.com/smartcontractkit/chainlink/deployment" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/stretchr/testify/require" ) @@ -41,7 +40,7 @@ const ( ChaosModeTypeFull ) -func (l *LoadConfig) Validate(t *testing.T, e *deployment.Environment) { +func (l *LoadConfig) Validate(t *testing.T, e *cldf.Environment) { _, err := time.ParseDuration(*l.LoadDuration) require.NoError(t, err, "LoadDuration must be a valid duration") diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/testsetups/ccip/test_helpers.go index ef4ce85458b..8ea8be60756 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/testsetups/ccip/test_helpers.go @@ -35,8 +35,8 @@ import ( evmcfg "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" clclient "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -277,7 +277,7 @@ func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv testhelpers.Deploye bootstrappers := nodes.BootstrapLocators() // Just set all RMN nodes to support all chains. - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := stateview.LoadOnchainState(tenv.Env) require.NoError(t, err) var chainParams []devenv.ChainParam var remoteChains []devenv.RemoteChains diff --git a/plugins/chainlink.prebuilt.Dockerfile b/plugins/chainlink.prebuilt.Dockerfile new file mode 100644 index 00000000000..ecc191ded20 --- /dev/null +++ b/plugins/chainlink.prebuilt.Dockerfile @@ -0,0 +1,18 @@ +## +# Takes Chainlink core as a base image and layers in private plugins. +## +ARG BASE_IMAGE=public.ecr.aws/chainlink/chainlink:v2.23.0-plugins + +## +# Final image +## +FROM ${BASE_IMAGE} AS final +# This directory should contain a bin/ subdir with the plugins and an optional lib/ subdir with shared libraries. +ARG PKG_PATH=./build + +# Copy/override any (optional) additional shared libraries. +# Square brackets in "li[b]" make this path optional - Docker build won't fail +# if the directory doesn't exist. +COPY ${PKG_PATH}/li[b] /usr/lib/ +# Copy/override plugins. +COPY ${PKG_PATH}/bin /usr/local/bin diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index 7b03d6a1bf6..6da30bd305e 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -25,7 +25,7 @@ plugins: solana: - moduleURI: "github.com/smartcontractkit/chainlink-solana" - gitRef: "v1.1.2-0.20250506153227-c817e421ec21" + gitRef: "v1.1.2-0.20250514193018-0b7546926e11" installPath: "github.com/smartcontractkit/chainlink-solana/pkg/solana/cmd/chainlink-solana" aptos: diff --git a/system-tests/lib/cre/contracts/contracts.go b/system-tests/lib/cre/contracts/contracts.go index a87d0a13484..7dd2d0c425d 100644 --- a/system-tests/lib/cre/contracts/contracts.go +++ b/system-tests/lib/cre/contracts/contracts.go @@ -15,6 +15,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" df_changeset "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset" df_changeset_types "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" @@ -422,7 +423,7 @@ func ConfigureDataFeedsCache(testLogger zerolog.Logger, input *types.ConfigureDa AdminAddress: input.AdminAddress, IsAdmin: true, } - _, setAdminErr := df_changeset.RunChangeset(df_changeset.SetFeedAdminChangeset, *input.CldEnv, setAdminConfig) + _, setAdminErr := changeset.RunChangeset(df_changeset.SetFeedAdminChangeset, *input.CldEnv, setAdminConfig) if setAdminErr != nil { return nil, errors.Wrap(setAdminErr, "failed to set feed admin") } @@ -442,7 +443,7 @@ func ConfigureDataFeedsCache(testLogger zerolog.Logger, input *types.ConfigureDa feeIDs = append(feeIDs, feedID[:32]) } - _, setFeedConfigErr := df_changeset.RunChangeset(df_changeset.SetFeedConfigChangeset, *input.CldEnv, df_changeset_types.SetFeedDecimalConfig{ + _, setFeedConfigErr := changeset.RunChangeset(df_changeset.SetFeedConfigChangeset, *input.CldEnv, df_changeset_types.SetFeedDecimalConfig{ ChainSelector: input.ChainSelector, CacheAddress: input.DataFeedsCacheAddress, DataIDs: feeIDs, diff --git a/system-tests/lib/cre/devenv/devenv.go b/system-tests/lib/cre/devenv/devenv.go index cac3cab26f8..23baf82796b 100644 --- a/system-tests/lib/cre/devenv/devenv.go +++ b/system-tests/lib/cre/devenv/devenv.go @@ -10,7 +10,7 @@ import ( "google.golang.org/grpc/credentials" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -28,7 +28,7 @@ func BuildFullCLDEnvironment(lgr logger.Logger, input *types.FullCLDEnvironmentI return nil, errors.Wrap(err, "input validation failed") } - envs := make([]*deployment.Environment, len(input.NodeSetOutput)) + envs := make([]*cldf.Environment, len(input.NodeSetOutput)) dons := make([]*devenv.DON, len(input.NodeSetOutput)) var allNodesInfo []devenv.NodeInfo @@ -143,7 +143,7 @@ func BuildFullCLDEnvironment(lgr logger.Logger, input *types.FullCLDEnvironmentI // we assume that all DONs run on the same chain and that there's only one chain output := &types.FullCLDEnvironmentOutput{ - Environment: &deployment.Environment{ + Environment: &cldf.Environment{ Name: envs[0].Name, Logger: envs[0].Logger, ExistingAddresses: input.ExistingAddresses, diff --git a/system-tests/lib/cre/environment/environment.go b/system-tests/lib/cre/environment/environment.go index 8defcca9516..2f6e706ab4e 100644 --- a/system-tests/lib/cre/environment/environment.go +++ b/system-tests/lib/cre/environment/environment.go @@ -24,7 +24,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" workflow_registry_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" @@ -66,7 +65,7 @@ const ( type SetupOutput struct { WorkflowRegistryConfigurationOutput *keystonetypes.WorkflowRegistryOutput - CldEnvironment *deployment.Environment + CldEnvironment *cldf.Environment BlockchainOutput []*BlockchainOutput DonTopology *keystonetypes.DonTopology NodeOutput []*keystonetypes.WrappedNodeOutput @@ -155,7 +154,7 @@ func SetupTestEnvironment( return nil, pkgerrors.Wrap(allChainsErr, "failed to create chains") } - allChainsCLDEnvironment := &deployment.Environment{ + allChainsCLDEnvironment := &cldf.Environment{ Logger: singeFileLogger, Chains: allChains, ExistingAddresses: cldf.NewMemoryAddressBook(), diff --git a/system-tests/lib/cre/types/keystone.go b/system-tests/lib/cre/types/keystone.go index d5c01d71b31..f1d2380870e 100644 --- a/system-tests/lib/cre/types/keystone.go +++ b/system-tests/lib/cre/types/keystone.go @@ -11,7 +11,6 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/system-tests/lib/nix" @@ -44,7 +43,7 @@ type NodeIndexToSecretsOverride = map[int]string type WorkflowRegistryInput struct { ChainSelector uint64 `toml:"-"` - CldEnv *deployment.Environment `toml:"-"` + CldEnv *cldf.Environment `toml:"-"` AllowedDonIDs []uint32 `toml:"-"` WorkflowOwners []common.Address `toml:"-"` Out *WorkflowRegistryOutput `toml:"out"` @@ -86,7 +85,7 @@ type ConfigureDataFeedsCacheOutput struct { } type ConfigureDataFeedsCacheInput struct { - CldEnv *deployment.Environment `toml:"-"` + CldEnv *cldf.Environment `toml:"-"` ChainSelector uint64 `toml:"-"` FeedIDs []string `toml:"-"` Descriptions []string `toml:"-"` @@ -138,7 +137,7 @@ type WrappedNodeOutput struct { } type CreateJobsInput struct { - CldEnv *deployment.Environment + CldEnv *cldf.Environment DonTopology *DonTopology DonToJobSpecs DonsToJobSpecs } @@ -203,7 +202,7 @@ func (d *DebugInput) Validate() error { type ConfigureKeystoneInput struct { ChainSelector uint64 Topology *Topology - CldEnv *deployment.Environment + CldEnv *cldf.Environment OCR3Config keystone_changeset.OracleConfig } @@ -458,7 +457,7 @@ func (f *FullCLDEnvironmentInput) Validate() error { } type FullCLDEnvironmentOutput struct { - Environment *deployment.Environment + Environment *cldf.Environment DonTopology *DonTopology } @@ -548,7 +547,7 @@ type CapabilitiesBinaryPathFactoryFn = func(donMetadata *DonMetadata) ([]string, type JobSpecFactoryFn = func(input *JobSpecFactoryInput) (DonsToJobSpecs, error) type JobSpecFactoryInput struct { - CldEnvironment *deployment.Environment + CldEnvironment *cldf.Environment BlockchainOutput *blockchain.Output DonTopology *DonTopology AddressBook cldf.AddressBook @@ -567,6 +566,7 @@ type RegisterWorkflowWithCRECLIInput struct { CRESettingsFile *os.File NewWorkflow *NewWorkflow ExistingWorkflow *ExistingWorkflow + CRECLIProfile string } type NewWorkflow struct { diff --git a/system-tests/lib/cre/workflow/workflow.go b/system-tests/lib/cre/workflow/workflow.go index 60b79dc77d6..9718549f495 100644 --- a/system-tests/lib/cre/workflow/workflow.go +++ b/system-tests/lib/cre/workflow/workflow.go @@ -31,13 +31,24 @@ func RegisterWithCRECLI(input cretypes.RegisterWorkflowWithCRECLIInput) error { return errors.Wrap(pkErr, "failed to set CRE_ETH_PRIVATE_KEY") } + // This env var is required by the CRE CLI + profileErr := os.Setenv("CRE_PROFILE", input.CRECLIProfile) + if profileErr != nil { + return errors.Wrap(pkErr, "failed to set CRE_PROFILE") + } + + creCLIWorkflowSettingsFile, err := libcrecli.PrepareCRECLIWorkflowSettingsFile(input.CRECLIProfile, input.WorkflowOwnerAddress, input.WorkflowName) + if err != nil { + return err + } + var workflowURL string var workflowConfigURL *string var workflowSecretsURL *string // compile and upload the workflow, if we are not using an existing one if input.ShouldCompileNewWorkflow { - compilationResult, compileErr := libcrecli.CompileWorkflow(input.CRECLIAbsPath, input.NewWorkflow.FolderLocation, input.NewWorkflow.WorkflowFileName, input.NewWorkflow.ConfigFilePath, input.CRESettingsFile) + compilationResult, compileErr := libcrecli.CompileWorkflow(input.CRECLIAbsPath, input.NewWorkflow.FolderLocation, input.NewWorkflow.WorkflowFileName, input.NewWorkflow.ConfigFilePath, creCLIWorkflowSettingsFile, input.CRESettingsFile) if compileErr != nil { return errors.Wrap(compileErr, "failed to compile workflow") } @@ -46,7 +57,7 @@ func RegisterWithCRECLI(input cretypes.RegisterWorkflowWithCRECLIInput) error { workflowConfigURL = &compilationResult.ConfigURL if input.NewWorkflow.SecretsFilePath != nil && *input.NewWorkflow.SecretsFilePath != "" { - secretsURL, secretsErr := libcrecli.EncryptSecrets(input.CRECLIAbsPath, *input.NewWorkflow.SecretsFilePath, input.NewWorkflow.Secrets, input.CRESettingsFile) + secretsURL, secretsErr := libcrecli.EncryptSecrets(input.CRECLIAbsPath, *input.NewWorkflow.SecretsFilePath, input.NewWorkflow.Secrets, creCLIWorkflowSettingsFile) if secretsErr != nil { return errors.Wrap(secretsErr, "failed to encrypt workflow secrets") } @@ -58,7 +69,7 @@ func RegisterWithCRECLI(input cretypes.RegisterWorkflowWithCRECLIInput) error { workflowSecretsURL = input.ExistingWorkflow.SecretsURL } - registerErr := libcrecli.DeployWorkflow(input.CRECLIAbsPath, input.WorkflowName, workflowURL, workflowConfigURL, workflowSecretsURL, input.CRESettingsFile) + registerErr := libcrecli.DeployWorkflow(input.CRECLIAbsPath, workflowURL, workflowConfigURL, workflowSecretsURL, creCLIWorkflowSettingsFile) if registerErr != nil { return errors.Wrap(registerErr, "failed to register workflow") } diff --git a/system-tests/lib/crecli/commands.go b/system-tests/lib/crecli/commands.go index 1d485c0f006..775ddd3b6c4 100644 --- a/system-tests/lib/crecli/commands.go +++ b/system-tests/lib/crecli/commands.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "regexp" "strconv" "strings" @@ -18,10 +19,28 @@ type CompilationResult struct { ConfigURL string } -func CompileWorkflow(creCLICommandPath, workflowFolder, workflowFileName string, configFile *string, settingsFile *os.File) (CompilationResult, error) { +func CompileWorkflow(creCLICommandPath, workflowFolder, workflowFileName string, configFile *string, workflowSettingsFile, settingsFile *os.File) (CompilationResult, error) { var outputBuffer bytes.Buffer - compileArgs := []string{"workflow", "compile", "-S", settingsFile.Name()} + // the CLI expects the workflow code to be located in the same directory as its `go.mod`` file. That's why we assume that the file, which + // the CLI also expects `cre.yaml` settings file to be present either in the present directory or any of its parent tree directories. + + cliFile, err := os.Create(filepath.Join(workflowFolder, CRECLISettingsFileName)) + if err != nil { + return CompilationResult{}, err + } + + settingsFileBytes, err := os.ReadFile(settingsFile.Name()) + if err != nil { + return CompilationResult{}, err + } + + _, err = cliFile.Write(settingsFileBytes) + if err != nil { + return CompilationResult{}, err + } + + compileArgs := []string{"workflow", "compile", "-S", workflowSettingsFile.Name()} if configFile != nil { compileArgs = append(compileArgs, "-c", *configFile) } @@ -31,7 +50,7 @@ func CompileWorkflow(creCLICommandPath, workflowFolder, workflowFileName string, compileCmd.Stderr = &outputBuffer // the CLI expects the workflow code to be located in the same directory as its `go.mod` file compileCmd.Dir = workflowFolder - err := compileCmd.Start() + err = compileCmd.Start() if err != nil { return CompilationResult{}, errors.Wrap(err, "failed to start compile command") } @@ -73,8 +92,8 @@ func CompileWorkflow(creCLICommandPath, workflowFolder, workflowFileName string, } // Same command to register a workflow or update an existing one -func DeployWorkflow(creCLICommandPath, workflowName, workflowURL string, configURL, secretsURL *string, settingsFile *os.File) error { - commandArgs := []string{"workflow", "deploy", workflowName, "-b", workflowURL, "-S", settingsFile.Name(), "-v"} +func DeployWorkflow(creCLICommandPath, workflowURL string, configURL, secretsURL *string, settingsFile *os.File) error { + commandArgs := []string{"workflow", "deploy", "-b", workflowURL, "-S", settingsFile.Name(), "-v"} if configURL != nil { commandArgs = append(commandArgs, "-c", *configURL) } @@ -85,8 +104,13 @@ func DeployWorkflow(creCLICommandPath, workflowName, workflowURL string, configU deployCmd := exec.Command(creCLICommandPath, commandArgs...) // #nosec G204 deployCmd.Stdout = os.Stdout deployCmd.Stderr = os.Stderr - if err := deployCmd.Start(); err != nil { - return errors.Wrap(err, "failed to start register command") + if startErr := deployCmd.Start(); startErr != nil { + return errors.Wrap(startErr, "failed to start deploy command") + } + + waitErr := deployCmd.Wait() + if waitErr != nil { + return errors.Wrap(waitErr, "failed to wait for deploy command") } return nil @@ -141,7 +165,7 @@ func SetFeedAdmin(creCLICommandPath string, chainID int, adminAddress common.Add waitErr := setFeedAdminCmd.Wait() fmt.Println("Set Feed Admin output:\n", outputBuffer.String()) if waitErr != nil { - return errors.Wrap(waitErr, "failed to wait for compile command") + return errors.Wrap(waitErr, "failed to wait for set feed admin command") } return nil @@ -194,7 +218,7 @@ func SetFeedConfig(creCLICommandPath, feedID, feedDecimals, feedDescription stri waitErr := setFeedConfigCmd.Wait() fmt.Println("Set Feed Config output:\n", outputBuffer.String()) if waitErr != nil { - return errors.Wrap(waitErr, "failed to wait for compile command") + return errors.Wrap(waitErr, "failed to wait for set feed config command") } return nil diff --git a/system-tests/lib/crecli/settings.go b/system-tests/lib/crecli/settings.go index 13cd661e556..86b33e6dd86 100644 --- a/system-tests/lib/crecli/settings.go +++ b/system-tests/lib/crecli/settings.go @@ -15,39 +15,48 @@ import ( ) const ( - CRECLISettingsFileName = ".cre-cli-settings.yaml" + CRECLISettingsFileName = "cre.yaml" + CRECLIWorkflowSettingsFile = "workflow.yaml" + CRECLIProfile = "test" ) +type Profiles struct { + Test Settings `yaml:"test,omitempty"` + Staging Settings `yaml:"staging,omitempty"` + ProductionTestinet Settings `yaml:"production-testnet,omitempty"` + Production Settings `yaml:"production,omitempty"` +} + type Settings struct { - DevPlatform DevPlatform `yaml:"dev-platform"` - UserWorkflow UserWorkflow `yaml:"user-workflow"` - Logging Logging `yaml:"logging"` - McmsConfig McmsConfig `yaml:"mcms-config"` - Contracts Contracts `yaml:"contracts"` - Rpcs []RPC `yaml:"rpcs"` + DevPlatform DevPlatform `yaml:"dev-platform,omitempty"` + UserWorkflow UserWorkflow `yaml:"user-workflow,omitempty"` + Logging Logging `yaml:"logging,omitempty"` + McmsConfig McmsConfig `yaml:"mcms-config,omitempty"` + Contracts Contracts `yaml:"contracts,omitempty"` + Rpcs []RPC `yaml:"rpcs,omitempty"` + WorkflowStorage WorkflowStorage `yaml:"workflow_storage,omitempty"` } type DevPlatform struct { - CapabilitiesRegistryAddress string `yaml:"capabilities-registry-contract-address"` - DonID uint32 `yaml:"don-id"` - WorkflowRegistryAddress string `yaml:"workflow-registry-contract-address"` + DonID uint32 `yaml:"don-id,omitempty"` } type UserWorkflow struct { - WorkflowOwnerAddress string `yaml:"workflow-owner-address"` + WorkflowOwnerAddress string `yaml:"workflow-owner-address,omitempty"` + WorkflowName string `yaml:"workflow-name,omitempty"` } type Logging struct { - SethConfigPath string `yaml:"seth-config-path"` + SethConfigPath string `yaml:"seth-config-path,omitempty"` } type McmsConfig struct { - ProposalsDirectory string `yaml:"proposals-directory"` + ProposalsDirectory string `yaml:"proposals-directory,omitempty"` } type Contracts struct { - ContractRegistry []ContractRegistry `yaml:"registries"` - DataFeeds []ContractRegistry `yaml:"data-feeds"` + ContractRegistry []ContractRegistry `yaml:"registries,omitempty"` + DataFeeds []ContractRegistry `yaml:"data-feeds,omitempty"` Keystone []ContractRegistry `yaml:"keystone"` } @@ -62,6 +71,14 @@ type RPC struct { URL string `yaml:"url"` } +type WorkflowStorage struct { + Gist Gist `yaml:"gist"` +} + +type Gist struct { + GithubToken string `yaml:"github_token"` +} + type PoRWorkflowConfig struct { FeedID string `json:"feed_id"` URL string `json:"url"` @@ -70,9 +87,28 @@ type PoRWorkflowConfig struct { AuthKeySecretName *string `json:"auth_key_secret_name,omitempty"` } +func setProfile(profile string, settings Settings) (Profiles, error) { + var profiles Profiles + + switch profile { + case "test": + profiles = Profiles{Test: settings} + case "staging": + profiles = Profiles{Staging: settings} + case "production-testnet": + profiles = Profiles{ProductionTestinet: settings} + case "production": + profiles = Profiles{Production: settings} + default: + return Profiles{}, errors.Errorf("invalid profile: %s", profile) + } + + return profiles, nil +} + // rpcs: chainSelector -> url -func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.AddressBook, donID uint32, homeChainSelector uint64, rpcs map[uint64]string) (*os.File, error) { - settingsFile, err := os.CreateTemp("", CRECLISettingsFileName) +func PrepareCRECLISettingsFile(profile string, workflowOwner common.Address, addressBook cldf.AddressBook, donID uint32, homeChainSelector uint64, rpcs map[uint64]string) (*os.File, error) { + settingsFile, err := os.Create(CRECLISettingsFileName) if err != nil { return nil, errors.Wrap(err, "failed to create CRE CLI settings file") } @@ -87,11 +123,9 @@ func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.Ad return nil, errors.Wrapf(workflowRegistryErr, "failed to get workflow registry address for chain %d", homeChainSelector) } - settings := Settings{ + profileSettings := Settings{ DevPlatform: DevPlatform{ - CapabilitiesRegistryAddress: capRegAddr.Hex(), - DonID: donID, - WorkflowRegistryAddress: workflowRegistryAddr.Hex(), + DonID: donID, }, UserWorkflow: UserWorkflow{ WorkflowOwnerAddress: workflowOwner.Hex(), @@ -114,10 +148,15 @@ func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.Ad }, }, }, + WorkflowStorage: WorkflowStorage{ + Gist: Gist{ + GithubToken: `${CRE_GITHUB_API_TOKEN}`, + }, + }, } for chainSelector, rpc := range rpcs { - settings.Rpcs = append(settings.Rpcs, RPC{ + profileSettings.Rpcs = append(profileSettings.Rpcs, RPC{ ChainSelector: chainSelector, URL: rpc, }) @@ -131,7 +170,7 @@ func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.Ad for chainSelector := range addresses { dfAddr, dfErr := contracts.FindAddressesForChain(addressBook, chainSelector, df_changeset.DataFeedsCache.String()) if dfErr == nil { - settings.Contracts.DataFeeds = append(settings.Contracts.DataFeeds, ContractRegistry{ + profileSettings.Contracts.DataFeeds = append(profileSettings.Contracts.DataFeeds, ContractRegistry{ Name: df_changeset.DataFeedsCache.String(), Address: dfAddr.Hex(), ChainSelector: chainSelector, @@ -141,7 +180,7 @@ func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.Ad forwaderAddr, forwaderErr := contracts.FindAddressesForChain(addressBook, chainSelector, string(keystone_changeset.KeystoneForwarder)) if forwaderErr == nil { - settings.Contracts.Keystone = append(settings.Contracts.Keystone, ContractRegistry{ + profileSettings.Contracts.Keystone = append(profileSettings.Contracts.Keystone, ContractRegistry{ Name: keystone_changeset.KeystoneForwarder.String(), Address: forwaderAddr.Hex(), ChainSelector: chainSelector, @@ -150,14 +189,50 @@ func PrepareCRECLISettingsFile(workflowOwner common.Address, addressBook cldf.Ad // it is okay if there's no keystone forwarder address for a chain } - settingsMarshalled, err := yaml.Marshal(settings) - if err != nil { - return nil, errors.Wrap(err, "failed to marshal CRE CLI settings") + settings, settingsErr := setProfile(profile, profileSettings) + if settingsErr != nil { + return nil, errors.Wrap(settingsErr, "failed to set profile") + } + + settingsMarshalled, settingsMarshalledErr := yaml.Marshal(settings) + if settingsMarshalledErr != nil { + return nil, errors.Wrap(settingsMarshalledErr, "failed to marshal CRE CLI settings") } - _, err = settingsFile.Write(settingsMarshalled) + _, writeErr := settingsFile.Write(settingsMarshalled) + if writeErr != nil { + return nil, errors.Wrapf(writeErr, "failed to write %s settings file", CRECLISettingsFileName) + } + + return settingsFile, nil +} + +func PrepareCRECLIWorkflowSettingsFile(profile string, workflowOwner common.Address, workflowName string) (*os.File, error) { + settingsFile, err := os.CreateTemp("", CRECLIWorkflowSettingsFile) if err != nil { - return nil, errors.Wrapf(err, "failed to write %s settings file", CRECLISettingsFileName) + return nil, errors.Wrap(err, "failed to create CRE CLI workflow settings file") + } + + profileSettings := Settings{ + UserWorkflow: UserWorkflow{ + WorkflowOwnerAddress: workflowOwner.Hex(), + WorkflowName: workflowName, + }, + } + + settings, settingsErr := setProfile(profile, profileSettings) + if settingsErr != nil { + return nil, errors.Wrap(settingsErr, "failed to set profile") + } + + settingsMarshalled, marshallErr := yaml.Marshal(settings) + if marshallErr != nil { + return nil, errors.Wrap(marshallErr, "failed to marshal CRE CLI settings") + } + + _, writeErr := settingsFile.Write(settingsMarshalled) + if writeErr != nil { + return nil, errors.Wrapf(writeErr, "failed to write %s settings file", CRECLIWorkflowSettingsFile) } return settingsFile, nil diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index ea4e6cd5ed1..44e7265639f 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -21,9 +21,9 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-protos/job-distributor v0.9.0 github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5 github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 @@ -354,10 +354,10 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb // indirect - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect @@ -368,13 +368,13 @@ require ( 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/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250422175525-b7575d96bd4d // indirect github.com/smartcontractkit/freeport v0.1.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 // indirect - github.com/smartcontractkit/mcms v0.18.0 // indirect + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 // indirect + github.com/smartcontractkit/mcms v0.19.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 10e89b4e899..4cbcc51011e 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1220,24 +1220,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1258,8 +1258,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5 h1:Lk5iUhW5fstUDmHGfnBHro/RAWvxxkMGgfs4ZMXtMqs= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5/go.mod h1:+C1jbf+diirCT09w9huU9jBKxG6pMRQclGRGJX4+n5Q= github.com/smartcontractkit/chainlink-testing-framework/lib v1.52.4 h1:+kwLuO9kcq1+ZbRUQjxX1SQmzlL2M6ZP6+L0xQMtmkU= @@ -1276,10 +1276,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/system-tests/tests/.gitignore b/system-tests/tests/.gitignore index 5b4fff6a1be..8fd92102822 100644 --- a/system-tests/tests/.gitignore +++ b/system-tests/tests/.gitignore @@ -17,4 +17,4 @@ cre_v* crib-configs/ cache/ -cre.settings.yaml \ No newline at end of file +cre.yaml \ No newline at end of file diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index f11edfa0751..0815e0add17 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -25,10 +25,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.20250509155341-2b5a5170a351 + github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd - github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca + github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee github.com/smartcontractkit/chainlink-protos/job-distributor v0.9.0 github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.7 @@ -36,7 +36,7 @@ require ( github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.0 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.51.0 github.com/smartcontractkit/chainlink/system-tests/lib v0.0.0-20250402195829-918b2a02a926 - github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 + github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 golang.org/x/sync v0.13.0 @@ -427,10 +427,10 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb // indirect - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250509160340-4f4a9265e657 // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20250502210357-2df484128afa // indirect @@ -440,13 +440,13 @@ require ( 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/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250422175525-b7575d96bd4d // indirect github.com/smartcontractkit/freeport v0.1.0 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect - github.com/smartcontractkit/mcms v0.18.0 // indirect + github.com/smartcontractkit/mcms v0.19.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 43d06e364e3..f1f34a546cd 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,24 +1422,24 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570 h1:WpL5O0u6CAcgy2QZPymsTVUyMQuDjPbHxtSrFKuOPR4= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250512161950-c68a88cbc570/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb h1:/UcEnsms6CP2tRiR899zPd1JBgEjH0t7keDBOR1xANY= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250512172541-23f36acc56bb/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990 h1:jswzyxv1bIt9gjmEaMPyTRDVMnOjH+AZEFJfHP94sdY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250508225633-13a092427990/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351 h1:luR7oS01qzkw8anxnSYaXurzKzMdgl5ROKFm1/I6llY= -github.com/smartcontractkit/chainlink-common v0.7.1-0.20250509155341-2b5a5170a351/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219 h1:StDuhkPCkKIvlydzXbuqNixH3j/Aa0/OBGCm/ZUPFGc= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250514155910-8d5e392a0219/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219 h1:EXH0/VMhIO3Vy63FaWJ4zzqKXsgiMOOLddWvdhNT9Y4= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250514155910-8d5e392a0219/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94 h1:t+OpHI0Xjekd0raLk2z8aaQ9Qi0oHuUN6vYI/Td1B0s= +github.com/smartcontractkit/chainlink-common v0.7.1-0.20250513180746-113c305fde94/go.mod h1:uNF6+noody47ZdmRwymDZAnQ7eKTXLzMKvl41LA63lo= 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.20250417193446-eeb0a7d1e049 h1:7HwYt8rDz1ehTcB28oNipdTZUtV17F2sfkLTLtMJC4c= github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049/go.mod h1:2MggrMtbhqr0u4U2pcYa21lvAtvaeSawjxdIy1ytHWE= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd h1:CQ2Go+jr6EIPsHKiTWWJb9b7Atr5rlDxYYNebD0rDC8= github.com/smartcontractkit/chainlink-deployments-framework v0.0.15-0.20250508081139-ee24199564bd/go.mod h1:mL2A8XfX+KipiqgBarPaBxULqVLSJRZ6HYObxFncMEM= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca h1:F7u+fZEPLN6onVa3qTkHn96Qd9mC2R2JTmdwBYxzNs8= -github.com/smartcontractkit/chainlink-evm v0.0.0-20250509162544-26e3267013ca/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee h1:anqvcHMU3Cw8Z+NbJZwNKDfxjoQzKB0qqfcA7vbD/QU= +github.com/smartcontractkit/chainlink-evm v0.0.0-20250512171455-818eb49fe8ee/go.mod h1:45uPLLRG/RZlZT0U5ikI3LJORNeu+kfZSlw5M2PLId0= 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/chains v0.0.0-20250509160340-4f4a9265e657 h1:CK4v+IXsvYfzwHbZakJt/RpiWNkkiVIJ6ynGGOo7buc= @@ -1460,8 +1460,8 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.0 h1:79Z9N9dMbMVRGaLoDPAQ+ github.com/smartcontractkit/chainlink-protos/svr v1.1.0/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5 h1:iF7WucN9ZxJLbDuyB2co0mGPytFY9NdEBeQHY1+bJnc= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250501150903-3e93089d9ad5/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21 h1:LFEIZBjZlR40JnyEa7zrZVhbPamH8UpRqVd6BWfOrPo= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250506153227-c817e421ec21/go.mod h1:WMiLd17wUYRmIQFg6KmcwA0UnNJTsJ3GOoYy8K4ez2Q= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11 h1:Ybr+UUHHhZIPgCDmHXt+exR6sMoUzhQjss9cQNrY0lg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250514193018-0b7546926e11/go.mod h1:gLFSnWHGOiFLiUr6PIJ08q2ZvhUdKsjYY5+UxR4SHlg= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5 h1:Lk5iUhW5fstUDmHGfnBHro/RAWvxxkMGgfs4ZMXtMqs= github.com/smartcontractkit/chainlink-testing-framework/framework v0.7.5/go.mod h1:+C1jbf+diirCT09w9huU9jBKxG6pMRQclGRGJX4+n5Q= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.7 h1:ANltXlvv6CbOXieasPD9erc4BewtCHm1tKDPAYvuWLw= @@ -1484,10 +1484,10 @@ github.com/smartcontractkit/freeport v0.1.0 h1:3MZHeti5m+tSTBCq5R8rhawFHxrnQZYBZ github.com/smartcontractkit/freeport v0.1.0/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0 h1:yGD0bRNoIQ9vOILzlYg4AiGKMKpJNqi7eIMpW7QIO9Y= -github.com/smartcontractkit/libocr v0.0.0-20250408131511-c90716988ee0/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= -github.com/smartcontractkit/mcms v0.18.0 h1:XGCKHPmgRRLmd5b0oIx+KIi3yfYsOZ2SO0DqkamYPgw= -github.com/smartcontractkit/mcms v0.18.0/go.mod h1:Xbxs9YxB7+JWX0nbGDikoAk4KlPmfNzAzyAOSz8OHcE= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4 h1:pFqWExLVU/i9zYWVb4KR2K6mDFCg3+LyeqF/fsmxlAk= +github.com/smartcontractkit/libocr v0.0.0-20250513175559-61c382d6cee4/go.mod h1:lzZ0Hq8zK1FfPb7aHuKQKrsWlrsCtBs6gNRNXh59H7Q= +github.com/smartcontractkit/mcms v0.19.2 h1:z99AGjYf83XOm6tn/7beRFji09S4H7Bko3KvXaXWLM4= +github.com/smartcontractkit/mcms v0.19.2/go.mod h1:LsHh9Tazb41glEZv4IdwFOG/D65nvpekCS3jOsDr9H0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= diff --git a/system-tests/tests/load/cre/workflow-don-load-test-streams.toml b/system-tests/tests/load/cre/workflow-don-load-test-streams.toml index 186fc06b7b4..a593bf64b2b 100644 --- a/system-tests/tests/load/cre/workflow-don-load-test-streams.toml +++ b/system-tests/tests/load/cre/workflow-don-load-test-streams.toml @@ -12,7 +12,7 @@ duration = "2h" image = "job-distributor:0.9.0" [[mock_capabilities]] - name="streams-triggeer" + name="streams-trigger" version= "2.0.0" type="trigger" description="streams trigger mock" diff --git a/system-tests/tests/smoke/cre/cmd/download/download.go b/system-tests/tests/smoke/cre/cmd/download/download.go index 142514bcfbd..e041cb1071c 100644 --- a/system-tests/tests/smoke/cre/cmd/download/download.go +++ b/system-tests/tests/smoke/cre/cmd/download/download.go @@ -13,24 +13,24 @@ import ( ) var ( - capabilityVersion string - capabilityName string + capabilitiesVersion string + capabilityNames []string creCliVersion string outputDir string ghReadTokenEnvVarName string ) -var downloadCapabilityCmd = &cobra.Command{ - Use: "capability", - Short: "Download a capability binary", - Long: `Download a capability binary from GitHub releases`, +var downloadCapabilitiesCmd = &cobra.Command{ + Use: "capabilities", + Short: "Download capability binaries", + Long: `Download capability binaries from GitHub releases`, RunE: func(cmd *cobra.Command, args []string) error { githubToken, err := ghToken() if err != nil { return err } - return downloadCapability(githubToken, capabilityName, capabilityVersion) + return downloadCapabilities(githubToken, capabilitiesVersion, capabilityNames) }, } @@ -51,7 +51,7 @@ var downloadCreCliCmd = &cobra.Command{ var downloadAllCmd = &cobra.Command{ Use: "all", Short: "Download all binaries", - Long: `Download both the cron capability and CRE CLI binaries`, + Long: `Download both capabilities and CRE CLI binaries`, RunE: func(cmd *cobra.Command, args []string) error { githubToken, err := ghToken() if err != nil { @@ -60,7 +60,7 @@ var downloadAllCmd = &cobra.Command{ fmt.Println("Downloading all binaries...") - if err := downloadCapability(githubToken, capabilityName, capabilityVersion); err != nil { + if err := downloadCapabilities(githubToken, capabilitiesVersion, capabilityNames); err != nil { return err } @@ -78,14 +78,14 @@ func init() { DownloadCmd.PersistentFlags().StringVar(&outputDir, "output-dir", ".", "Directory to save the binaries (defaults to current directory)") DownloadCmd.PersistentFlags().StringVar(&ghReadTokenEnvVarName, "gh-token-env-var-name", "GITHUB_READ_TOKEN", "Name of the environment variable that contains the GitHub read token") - downloadCapabilityCmd.Flags().StringVar(&capabilityName, "name", "", "Name of the capability to download (requires GITHUB_READ_TOKEN)") - downloadCapabilityCmd.Flags().StringVar(&capabilityVersion, "version", "", "Version of the capability to download (requires GITHUB_READ_TOKEN)") + downloadCapabilitiesCmd.Flags().StringSliceVar(&capabilityNames, "names", []string{}, "Names of the capabilities to download (requires GITHUB_READ_TOKEN)") + downloadCapabilitiesCmd.Flags().StringVar(&capabilitiesVersion, "version", "", "Version of the capabilities to download (requires GITHUB_READ_TOKEN)") downloadCreCliCmd.Flags().StringVar(&creCliVersion, "version", "", "Version of the CRE CLI to download (requires GITHUB_READ_TOKEN)") - downloadAllCmd.Flags().StringVar(&capabilityName, "capability-name", "", "Name of the capability to download (requires GITHUB_READ_TOKEN)") - downloadAllCmd.Flags().StringVar(&capabilityVersion, "capability-version", "", "Version of the capability to download (requires GITHUB_READ_TOKEN)") + downloadAllCmd.Flags().StringSliceVar(&capabilityNames, "capability-names", []string{}, "Names of the capabilities to download (requires GITHUB_READ_TOKEN)") + downloadAllCmd.Flags().StringVar(&capabilitiesVersion, "capability-version", "", "Version of the capabilities to download (requires GITHUB_READ_TOKEN)") downloadAllCmd.Flags().StringVar(&creCliVersion, "cre-cli-version", "", "Version of the CRE CLI to download (requires GITHUB_READ_TOKEN)") - DownloadCmd.AddCommand(downloadCapabilityCmd) + DownloadCmd.AddCommand(downloadCapabilitiesCmd) DownloadCmd.AddCommand(downloadCreCliCmd) DownloadCmd.AddCommand(downloadAllCmd) } @@ -130,27 +130,29 @@ func ghToken() (string, error) { return githubToken, nil } -func downloadCapability(githubToken, name, version string) error { - if name == "" { - return errors.New("name flag is required") +func downloadCapabilities(githubToken, version string, names []string) error { + if len(names) == 0 { + return errors.New("names flag is required") } if version == "" { return errors.New("version flag is required") } - fmt.Printf("Downloading %s capability binary version %s...\n", name, version) - path, err := keystonecapabilities.DownloadCapabilityFromRelease(githubToken, version, name) - if err != nil { - return errors.Wrapf(err, "failed to download %s capability", name) - } + for _, name := range names { + fmt.Printf("Downloading %s capability binary version %s...\n", name, version) + path, err := keystonecapabilities.DownloadCapabilityFromRelease(githubToken, version, name) + if err != nil { + return errors.Wrapf(err, "failed to download %s capability", name) + } - fmt.Printf("%s capability binary downloaded to: %s\n", name, path) + fmt.Printf("%s capability binary downloaded to: %s\n", name, path) - if outputDir != "" && outputDir != "." { - if err := moveFile(path, outputDir); err != nil { - return fmt.Errorf("failed to move binary to output path: %w", err) + if outputDir != "" && outputDir != "." { + if err := moveFile(path, outputDir); err != nil { + return fmt.Errorf("failed to move binary to output path: %w", err) + } + fmt.Printf("Moved binary to: %s\n", filepath.Join(outputDir, filepath.Base(path))) } - fmt.Printf("Moved binary to: %s\n", filepath.Join(outputDir, filepath.Base(path))) } return nil diff --git a/system-tests/tests/smoke/cre/cmd/environment/environment.go b/system-tests/tests/smoke/cre/cmd/environment/environment.go index c56ea6f143a..c9e50e3b5be 100644 --- a/system-tests/tests/smoke/cre/cmd/environment/environment.go +++ b/system-tests/tests/smoke/cre/cmd/environment/environment.go @@ -174,6 +174,7 @@ var startCmd = &cobra.Command{ rpcs[bcOut.ChainSelector] = bcOut.BlockchainOutput.Nodes[0].ExternalHTTPUrl } creCLISettingsFile, settingsErr := crecli.PrepareCRECLISettingsFile( + crecli.CRECLIProfile, homeChainOut.SethClient.MustGetRootKeyAddress(), output.CldEnvironment.ExistingAddresses, //nolint:staticcheck // won't migrate now output.DonTopology.WorkflowDonID, @@ -185,13 +186,13 @@ var startCmd = &cobra.Command{ return settingsErr } - // Copy the file to current directory as cre.settings.yaml + // Copy the file to current directory as cre.yaml currentDir, cErr := os.Getwd() if cErr != nil { return cErr } - targetPath := filepath.Join(currentDir, "cre.settings.yaml") + targetPath := filepath.Join(currentDir, "cre.yaml") input, err := os.ReadFile(creCLISettingsFile.Name()) if err != nil { return err diff --git a/system-tests/tests/smoke/cre/environment-capabilities-don-ci.toml b/system-tests/tests/smoke/cre/environment-capabilities-don-ci.toml index fdc1233b405..8d23ae292be 100644 --- a/system-tests/tests/smoke/cre/environment-capabilities-don-ci.toml +++ b/system-tests/tests/smoke/cre/environment-capabilities-don-ci.toml @@ -30,7 +30,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_linux_amd64" # must be linux/amd64 to match our CI runner + cre_cli_binary_path = "./cre_v0.2.0_linux_amd64" # must be linux/amd64 to match our CI runner [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/environment-capabilities-don-crib.toml b/system-tests/tests/smoke/cre/environment-capabilities-don-crib.toml index 20747abab0a..a799e4bb436 100644 --- a/system-tests/tests/smoke/cre/environment-capabilities-don-crib.toml +++ b/system-tests/tests/smoke/cre/environment-capabilities-don-crib.toml @@ -33,7 +33,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_darwin_arm64" + cre_cli_binary_path = "./cre_v0.2.0_darwin_arm64" [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/environment-capabilities-don.toml b/system-tests/tests/smoke/cre/environment-capabilities-don.toml index 0f7d6d4b3a1..8592d85a043 100644 --- a/system-tests/tests/smoke/cre/environment-capabilities-don.toml +++ b/system-tests/tests/smoke/cre/environment-capabilities-don.toml @@ -27,7 +27,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_darwin_arm64" + cre_cli_binary_path = "./cre_v0.2.0_darwin_arm64" [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/environment-gateway-don-ci.toml b/system-tests/tests/smoke/cre/environment-gateway-don-ci.toml index 658e00b4fa7..83ad346a361 100644 --- a/system-tests/tests/smoke/cre/environment-gateway-don-ci.toml +++ b/system-tests/tests/smoke/cre/environment-gateway-don-ci.toml @@ -33,7 +33,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_linux_amd64" # must be linux/amd64 to match our CI runner + cre_cli_binary_path = "./cre_v0.2.0_linux_amd64" # must be linux/amd64 to match our CI runner [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/environment-gateway-don.toml b/system-tests/tests/smoke/cre/environment-gateway-don.toml index b2bdfcc2bf3..e76a6dce173 100644 --- a/system-tests/tests/smoke/cre/environment-gateway-don.toml +++ b/system-tests/tests/smoke/cre/environment-gateway-don.toml @@ -31,7 +31,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_darwin_arm64" + cre_cli_binary_path = "./cre_v0.2.0_darwin_arm64" [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/environment-one-don-multichain-ci.toml b/system-tests/tests/smoke/cre/environment-one-don-multichain-ci.toml index 002eefab667..02f20c203e2 100644 --- a/system-tests/tests/smoke/cre/environment-one-don-multichain-ci.toml +++ b/system-tests/tests/smoke/cre/environment-one-don-multichain-ci.toml @@ -49,7 +49,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_linux_amd64" # must be linux/amd64 to match our CI runner + cre_cli_binary_path = "./cre_v0.2.0_linux_amd64" # must be linux/amd64 to match our CI runner [[nodesets]] http_port_range_start = 10100 diff --git a/system-tests/tests/smoke/cre/environment-one-don-multichain.toml b/system-tests/tests/smoke/cre/environment-one-don-multichain.toml index aa03fb96f89..45c95312cfc 100644 --- a/system-tests/tests/smoke/cre/environment-one-don-multichain.toml +++ b/system-tests/tests/smoke/cre/environment-one-don-multichain.toml @@ -41,7 +41,7 @@ workflow_name = "porfeedtwo" [dependencies] - cre_cli_binary_path = "./cre_v0.1.5_darwin_arm64" + cre_cli_binary_path = "./cre_v0.2.0_darwin_arm64" cron_capability_binary_path = "./cron" [[nodesets]] diff --git a/system-tests/tests/smoke/cre/environment-one-don-single-chain.toml b/system-tests/tests/smoke/cre/environment-one-don-single-chain.toml index 1893d525397..a9d01b20848 100644 --- a/system-tests/tests/smoke/cre/environment-one-don-single-chain.toml +++ b/system-tests/tests/smoke/cre/environment-one-don-single-chain.toml @@ -31,7 +31,7 @@ [dependencies] cron_capability_binary_path = "./cron" - cre_cli_binary_path = "./cre_v0.1.5_darwin_arm64" + cre_cli_binary_path = "./cre_v0.2.0_darwin_arm64" [[nodesets]] nodes = 5 diff --git a/system-tests/tests/smoke/cre/guidelines.md b/system-tests/tests/smoke/cre/guidelines.md index 99181ded5c7..7cbd1f2e0ac 100644 --- a/system-tests/tests/smoke/cre/guidelines.md +++ b/system-tests/tests/smoke/cre/guidelines.md @@ -99,7 +99,7 @@ Or pull from your internal registry and update the image name in `environment-*. Download the CLI binary for your system from the [dev-platform repo](https://github.com/smartcontractkit/dev-platform). You can also build it locally. -**Required version**: `v0.1.5` +**Required version**: ` v0.2.0` --- diff --git a/system-tests/tests/smoke/cre/por_test.go b/system-tests/tests/smoke/cre/por_test.go index bf4f44f2215..9d37b5c939d 100644 --- a/system-tests/tests/smoke/cre/por_test.go +++ b/system-tests/tests/smoke/cre/por_test.go @@ -20,6 +20,7 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink/deployment/common/changeset" df_changeset "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset" df_changeset_types "github.com/smartcontractkit/chainlink/deployment/data-feeds/changeset/types" keystone_changeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" @@ -38,7 +39,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/gethwrappers/data-feeds/generated/data_feeds_cache" - "github.com/smartcontractkit/chainlink/deployment" cldlogger "github.com/smartcontractkit/chainlink/deployment/logger" corevm "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -177,9 +177,6 @@ type DependenciesConfig struct { } const ( - CronBinaryVersion = "v1.0.2-alpha" - CRECLIBinaryVersion = "v0.1.5" - AuthorizationKeySecretName = "AUTH_KEY" // TODO: use once we can run these tests in CI (https://smartcontract-it.atlassian.net/browse/DX-589) // AuthorizationKey = "12a-281j&@91.sj1:_}" @@ -237,12 +234,13 @@ type registerPoRWorkflowInput struct { creCLIAbsPath string creCLIsettingsFile *os.File authKey string + creCLIProfile string } type configureDataFeedsCacheInput struct { useCRECLI bool chainSelector uint64 - fullCldEnvironment *deployment.Environment + fullCldEnvironment *cldf.Environment workflowName string feedID string sethClient *seth.Client @@ -274,6 +272,10 @@ func configureDataFeedsCacheContract(testLogger zerolog.Logger, input *configure if err != nil { return errors.Wrap(err, "failed to set CRE_ETH_PRIVATE_KEY") } + err = os.Setenv("CRE_PROFILE", libcrecli.CRECLIProfile) + if err != nil { + return errors.Wrap(err, "failed to set CRE_PROFILE") + } dfAdminErr := libcrecli.SetFeedAdmin(input.creCLIAbsPath, chainIDInt, input.sethClient.MustGetRootKeyAddress(), input.settingsFile) if dfAdminErr != nil { @@ -415,6 +417,7 @@ func registerPoRWorkflow(input registerPoRWorkflowInput) error { CRESettingsFile: input.creCLIsettingsFile, WorkflowName: input.WorkflowConfig.WorkflowName, ShouldCompileNewWorkflow: input.WorkflowConfig.ShouldCompileNewWorkflow, + CRECLIProfile: input.creCLIProfile, } if input.WorkflowConfig.ShouldCompileNewWorkflow { @@ -545,7 +548,7 @@ func setupPoRTestEnvironment( Labels: []string{"data-feeds"}, // label required by the changeset } - dfOutput, dfErr := df_changeset.RunChangeset(df_changeset.DeployCacheChangeset, *universalSetupOutput.CldEnvironment, deployConfig) + dfOutput, dfErr := changeset.RunChangeset(df_changeset.DeployCacheChangeset, *universalSetupOutput.CldEnvironment, deployConfig) require.NoError(t, dfErr, "failed to deploy data feed cache contract") mergeErr := universalSetupOutput.CldEnvironment.ExistingAddresses.Merge(dfOutput.AddressBook) //nolint:staticcheck // won't migrate now @@ -567,6 +570,7 @@ func setupPoRTestEnvironment( // create CRE CLI settings file var settingsErr error creCLISettingsFile, settingsErr = libcrecli.PrepareCRECLISettingsFile( + libcrecli.CRECLIProfile, bo.SethClient.MustGetRootKeyAddress(), universalSetupOutput.CldEnvironment.ExistingAddresses, //nolint:staticcheck // won't migrate now universalSetupOutput.DonTopology.WorkflowDonID, @@ -609,6 +613,7 @@ func setupPoRTestEnvironment( creCLIAbsPath: creCLIAbsPath, creCLIsettingsFile: creCLISettingsFile, writeTargetName: corevm.GenerateWriteTargetName(bo.ChainID), + creCLIProfile: libcrecli.CRECLIProfile, } workflowErr := registerPoRWorkflow(registerInput) diff --git a/tools/bin/go_core_ccip_deployment_tests b/tools/bin/go_core_ccip_deployment_tests index 7523b4863bb..d24c8f9176b 100755 --- a/tools/bin/go_core_ccip_deployment_tests +++ b/tools/bin/go_core_ccip_deployment_tests @@ -10,7 +10,7 @@ if [[ -n "$USE_FLAKEGUARD" ]]; then # Install flakeguard go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@bc66d27e3325a1fecedc0fc932d13d3e54ff6f25 # Install gotestsum to parse JSON test outputs from flakeguard to console outputs - go install gotest.tools/gotestsum@latest + go install gotest.tools/gotestsum@v1.12.2 # Make sure bins are in PATH PATH=$PATH:$(go env GOPATH)/bin diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 0778b10c6b9..d2b48dcff2c 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -11,7 +11,7 @@ if [[ -n "$USE_FLAKEGUARD" ]]; then # Install flakeguard go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@bc66d27e3325a1fecedc0fc932d13d3e54ff6f25 # Install gotestsum to parse JSON test outputs from flakeguard to console outputs - go install gotest.tools/gotestsum@latest + go install gotest.tools/gotestsum@v1.12.2 # Make sure bins are in PATH PATH=$PATH:$(go env GOPATH)/bin export PATH From b8c017a1a079ba60a5e11becdb91567c5364f3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 15 May 2025 17:18:12 +0200 Subject: [PATCH 094/136] Fix --- deployment/ccip/changeset/aptos/config/lane_test.go | 2 +- deployment/ccip/changeset/testhelpers/test_environment.go | 4 ++-- deployment/go.mod | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/deployment/ccip/changeset/aptos/config/lane_test.go b/deployment/ccip/changeset/aptos/config/lane_test.go index d8bf9a3828c..fadca0298c4 100644 --- a/deployment/ccip/changeset/aptos/config/lane_test.go +++ b/deployment/ccip/changeset/aptos/config/lane_test.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/stretchr/testify/assert" - "github.com/test-go/testify/require" + "github.com/stretchr/testify/require" ) func TestToEVMUpdateLanesConfig(t *testing.T) { diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 9d9cebc3ac5..707b589ae8d 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -886,8 +886,8 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn // #nosec G115 - Overflow is not a concern in this test scenario FChain: uint8(len(nodeInfo.NonBootstraps().PeerIDs()) / 3), EncodableChainConfig: chainconfig.ChainConfig{ - GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.GasPriceDeviationPPB)}, - DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(globals.DAGasPriceDeviationPPB)}, + GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(DefaultGasPriceDeviationPPB)}, + DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(DefaultDAGasPriceDeviationPPB)}, OptimisticConfirmations: globals.OptimisticConfirmations, }, } diff --git a/deployment/go.mod b/deployment/go.mod index aeb719246ce..9b15767cb67 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -49,7 +49,6 @@ require ( github.com/smartcontractkit/mcms v0.19.2 github.com/spf13/cast v1.7.1 github.com/stretchr/testify v1.10.0 - github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.37.0 github.com/zksync-sdk/zksync2-go v1.0.0 go.uber.org/multierr v1.11.0 From 214ad6e3f4e6e83ffcaa13f4c2de2606bccc0ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 16 May 2025 00:29:15 +0200 Subject: [PATCH 095/136] Install Aptos CLI and LOOP plugins --- .github/integration-in-memory-tests.yml | 2 ++ .github/workflows/integration-in-memory-tests.yml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 3a668aec196..0fdf7d752b8 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -307,5 +307,7 @@ runner-test-matrix: - Nightly Integration CCIP Tests test_cmd: cd smoke/ccip && go test ccip_aptos_messaging_test.go -timeout 15m -test.parallel=1 -count=1 -json test_go_project_path: integration-tests + aptos-cli: 7.2.0 + install-plugins-public: true # END: CCIP tests diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index 4cc535d4803..51a20f307be 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -74,7 +74,7 @@ jobs: contents: read needs: changes if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@639ad9c899df967dc44b86520db48e19c8abeaca + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@d2b98bb94371b8b6bda8980a9d43418af01c5f1d with: workflow_name: Run CCIP Integration Tests For PR chainlink_version: ${{ inputs.cl_ref || github.sha }} @@ -102,7 +102,7 @@ jobs: contents: read needs: changes if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@639ad9c899df967dc44b86520db48e19c8abeaca + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@d2b98bb94371b8b6bda8980a9d43418af01c5f1d with: workflow_name: Run CCIP Integration Tests For Merge Queue chainlink_version: ${{ inputs.cl_ref || github.sha }} From 1d9e03a48ef976185489ee51d005e1b20cbeac94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 16 May 2025 01:32:34 +0200 Subject: [PATCH 096/136] Update CI --- .github/integration-in-memory-tests.yml | 4 +- .../ccip/ccipaptos/executecodec_test.go | 6 ++- .../ccip/ccipevm/executecodec_test.go | 9 ++-- .../ccip/ccipsolana/executecodec_test.go | 6 +-- .../ccip/ccipsolana/gas_helpers_test.go | 8 ++-- .../ccip/ccipsolana/msghasher_test.go | 4 +- .../aptos/cs_set_ocr3_offramp_test.go | 9 ++-- .../aptos/cs_update_aptos_lanes_test.go | 5 ++- deployment/ccip/changeset/aptos/state_test.go | 45 ++++++++++--------- 9 files changed, 53 insertions(+), 43 deletions(-) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 0fdf7d752b8..de81612a000 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -307,7 +307,7 @@ runner-test-matrix: - Nightly Integration CCIP Tests test_cmd: cd smoke/ccip && go test ccip_aptos_messaging_test.go -timeout 15m -test.parallel=1 -count=1 -json test_go_project_path: integration-tests - aptos-cli: 7.2.0 - install-plugins-public: true + aptos_cli: 7.2.0 + install_plugins_public: true # END: CCIP tests diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index 5773e707a4c..81363832404 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -11,6 +11,8 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -88,7 +90,7 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big func TestExecutePluginCodecV1(t *testing.T) { ctx := testutils.Context(t) - mockExtraDataCodec := &mocks.ExtraDataCodec{} + mockExtraDataCodec := mocks.NewSourceChainExtraDataCodec(t) destGasAmount := rand.Uint32() gasLimit := utils.RandUint256() @@ -152,7 +154,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - codec := NewExecutePluginCodecV1(mockExtraDataCodec) + codec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) // randomExecuteReport now uses the new encoding internally report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go index 9eba720264a..18b8f4ce313 100644 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ b/core/capabilities/ccip/ccipevm/executecodec_test.go @@ -18,12 +18,13 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/assets" evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink-evm/pkg/utils" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) var randomExecuteReport = func(t *testing.T, d *testSetupData, chainSelector uint64, gasLimit *big.Int, destGasAmount uint32) cciptypes.ExecutePluginReport { @@ -182,7 +183,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - codec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + codec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) report := tc.report(randomExecuteReport(t, d, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) if tc.expErr { diff --git a/core/capabilities/ccip/ccipsolana/executecodec_test.go b/core/capabilities/ccip/ccipsolana/executecodec_test.go index 8fe8e69b003..a675d4ce3fd 100644 --- a/core/capabilities/ccip/ccipsolana/executecodec_test.go +++ b/core/capabilities/ccip/ccipsolana/executecodec_test.go @@ -179,7 +179,7 @@ func TestExecutePluginCodecV1(t *testing.T) { "accountIsWritableBitmap": uint64(2), "TokenReceiver": [32]byte(solanago.MustPublicKeyFromBase58("42Gia5bGsh8R2S44e37t9fsucap1qsgjr6GjBmWotgdF").Bytes()), }, nil).Maybe() - cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -257,7 +257,7 @@ func Test_DecodingExecuteReport(t *testing.T) { err = onChainReport.MarshalWithEncoder(encoder) require.NoError(t, err) - executeCodec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + executeCodec := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) decode, err := executeCodec.Decode(testutils.Context(t), buf.Bytes()) require.NoError(t, err) @@ -273,7 +273,7 @@ func Test_DecodingExecuteReport(t *testing.T) { t.Run("decode Borsh encoded execute report", func(t *testing.T) { ocrReport := randomExecuteReport(t, 124615329519749607) - cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + cd := NewExecutePluginCodecV1(ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) encodedReport, err := cd.Encode(testutils.Context(t), ocrReport) require.NoError(t, err) diff --git a/core/capabilities/ccip/ccipsolana/gas_helpers_test.go b/core/capabilities/ccip/ccipsolana/gas_helpers_test.go index dc9e8c81409..3cecf212cb1 100644 --- a/core/capabilities/ccip/ccipsolana/gas_helpers_test.go +++ b/core/capabilities/ccip/ccipsolana/gas_helpers_test.go @@ -5,9 +5,11 @@ import ( "testing" chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/stretchr/testify/assert" "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/fee_quoter" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" @@ -56,7 +58,7 @@ func Test_calculateMessageMaxGas(t *testing.T) { } // Set the source chain selector to be EVM for now msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.SOLANA_TESTNET.Selector) - ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{})} + ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{}, ccipaptos.ExtraDataDecoder{})} got := ep.CalculateMessageMaxGas(msg) t.Log(got) assert.Equalf(t, tt.want, got, "calculateMessageMaxGas(%v, %v)", tt.args.dataLen, tt.args.numTokens) @@ -96,7 +98,7 @@ func TestCalculateMaxGas(t *testing.T) { } msg.Header.SourceChainSelector = ccipocr3.ChainSelector(chainsel.SOLANA_TESTNET.Selector) - ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{})} + ep := EstimateProvider{extraDataCodec: ccipcommon.NewExtraDataCodec(ccipevm.ExtraDataCodec{}, ExtraDataCodec{}, ccipaptos.ExtraDataDecoder{})} gotTree := ep.CalculateMerkleTreeGas(tt.numRequests) gotMsg := ep.CalculateMessageMaxGas(msg) t.Log("want", tt.want, "got", gotTree+gotMsg) diff --git a/core/capabilities/ccip/ccipsolana/msghasher_test.go b/core/capabilities/ccip/ccipsolana/msghasher_test.go index 5f2beb269ab..0e7212fd04e 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher_test.go +++ b/core/capabilities/ccip/ccipsolana/msghasher_test.go @@ -59,7 +59,7 @@ func TestMessageHasher_InvalidReceiver(t *testing.T) { [32]byte(solana.SystemProgramID.Bytes()), }, }, nil).Maybe() - msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) _, err := msgHasher.Hash(testutils.Context(t), any2AnyMsg) require.Error(t, err) } @@ -82,7 +82,7 @@ func TestMessageHasher_InvalidDestinationTokenAddress(t *testing.T) { [32]byte(solana.SystemProgramID.Bytes()), }, }, nil).Maybe() - msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec)) + msgHasher := NewMessageHasherV1(logger.Test(t), ccipcommon.NewExtraDataCodec(mockExtraDataCodec, mockExtraDataCodec, mockExtraDataCodec)) _, err := msgHasher.Hash(testutils.Context(t), any2AnyMsg) require.Error(t, err) } diff --git a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go index 28f388fdaf2..42c76bf5071 100644 --- a/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go +++ b/deployment/ccip/changeset/aptos/cs_set_ocr3_offramp_test.go @@ -5,16 +5,17 @@ import ( "time" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_offramp" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + mcmstypes "github.com/smartcontractkit/mcms/types" + "github.com/stretchr/testify/require" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/globals" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - mcmstypes "github.com/smartcontractkit/mcms/types" - "github.com/stretchr/testify/require" ) func TestSetOCR3Offramp_Apply(t *testing.T) { @@ -41,7 +42,7 @@ func TestSetOCR3Offramp_Apply(t *testing.T) { require.NoError(t, err) // Load onchain state - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) require.NoError(t, err, "must load onchain state") // bind ccip aptos diff --git a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go index 9fbc10db905..b52ea1641ec 100644 --- a/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go +++ b/deployment/ccip/changeset/aptos/cs_update_aptos_lanes_test.go @@ -17,11 +17,12 @@ import ( mcmstypes "github.com/smartcontractkit/mcms/types" "github.com/smartcontractkit/chainlink-aptos/bindings/bind" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + aptoscs "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/aptos/config" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/testhelpers" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_6" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" @@ -54,7 +55,7 @@ func TestAddAptosLanes_Apply(t *testing.T) { }) require.NoError(t, err) - state, err := changeset.LoadOnchainState(env) + state, err := stateview.LoadOnchainState(env) require.NoError(t, err, "must load onchain state") // bind ccip aptos diff --git a/deployment/ccip/changeset/aptos/state_test.go b/deployment/ccip/changeset/aptos/state_test.go index 178e7301f8c..3441d338272 100644 --- a/deployment/ccip/changeset/aptos/state_test.go +++ b/deployment/ccip/changeset/aptos/state_test.go @@ -6,83 +6,86 @@ import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/stretchr/testify/assert" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/deployment/ccip/shared" + aptosstate "github.com/smartcontractkit/chainlink/deployment/ccip/shared/stateview/aptos" ) func TestLoadOnchainStateAptos(t *testing.T) { tests := []struct { name string - env deployment.Environment - want map[uint64]changeset.AptosCCIPChainState + env cldf.Environment + want map[uint64]aptosstate.CCIPChainState err error wantErrStr string }{ { name: "success - empty env.AptosChains", - env: deployment.Environment{}, - want: map[uint64]changeset.AptosCCIPChainState{}, + env: cldf.Environment{}, + want: map[uint64]aptosstate.CCIPChainState{}, err: nil, }, { name: "success - chain not found in ab returns empty state", - env: deployment.Environment{ - AptosChains: map[uint64]deployment.AptosChain{ + env: cldf.Environment{ + AptosChains: map[uint64]cldf.AptosChain{ 743186221051783445: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, }, ), }, - want: map[uint64]changeset.AptosCCIPChainState{ + want: map[uint64]aptosstate.CCIPChainState{ 743186221051783445: {}, }, err: nil, }, { name: "success - loads multiple aptos chains state", - env: deployment.Environment{ - AptosChains: map[uint64]deployment.AptosChain{ + env: cldf.Environment{ + AptosChains: map[uint64]cldf.AptosChain{ 743186221051783445: {}, 4457093679053095497: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]cldf.TypeAndVersion{ 4457093679053095497: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, }, 743186221051783445: { - mockMCMSAddress: {Type: changeset.AptosMCMSType}, - mockCCIPAddress: {Type: changeset.AptosCCIPType}, + mockMCMSAddress: {Type: shared.AptosMCMSType}, + mockAddress: {Type: shared.AptosCCIPType}, }, }, ), }, - want: map[uint64]changeset.AptosCCIPChainState{ + want: map[uint64]aptosstate.CCIPChainState{ 4457093679053095497: { MCMSAddress: mustParseAddress(t, mockMCMSAddress), }, 743186221051783445: { MCMSAddress: mustParseAddress(t, mockMCMSAddress), - CCIPAddress: mustParseAddress(t, mockCCIPAddress), + CCIPAddress: mustParseAddress(t, mockAddress), }, }, err: nil, }, { name: "error - failed to parse address", - env: deployment.Environment{ - AptosChains: map[uint64]deployment.AptosChain{ + env: cldf.Environment{ + AptosChains: map[uint64]cldf.AptosChain{ 743186221051783445: {}, }, ExistingAddresses: getTestAddressBook( + t, map[uint64]map[string]cldf.TypeAndVersion{ 743186221051783445: { - mockBadAddress: {Type: changeset.AptosMCMSType}, + "invalidaddress": {Type: shared.AptosMCMSType}, }, }, ), @@ -95,7 +98,7 @@ func TestLoadOnchainStateAptos(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := changeset.LoadOnchainStateAptos(tt.env) + got, err := aptosstate.LoadOnchainStateAptos(tt.env) if tt.err != nil { assert.Error(t, err) assert.Contains(t, err.Error(), tt.wantErrStr) From c3590b2656a71dd05b0127d0f8cd58ed38283356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 16 May 2025 01:38:57 +0200 Subject: [PATCH 097/136] Upgrade run-e2e-tests workflow --- .github/workflows/integration-in-memory-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index 51a20f307be..4b221acc7ee 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -74,7 +74,7 @@ jobs: contents: read needs: changes if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@d2b98bb94371b8b6bda8980a9d43418af01c5f1d + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@6f44fa461b22a801cc46e1a2f7ea7852a979dc8a with: workflow_name: Run CCIP Integration Tests For PR chainlink_version: ${{ inputs.cl_ref || github.sha }} @@ -102,7 +102,7 @@ jobs: contents: read needs: changes if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@d2b98bb94371b8b6bda8980a9d43418af01c5f1d + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@6f44fa461b22a801cc46e1a2f7ea7852a979dc8a with: workflow_name: Run CCIP Integration Tests For Merge Queue chainlink_version: ${{ inputs.cl_ref || github.sha }} From 5968eb492630a1e3feaf1de3eae67e950c5e16d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 16 May 2025 02:16:44 +0200 Subject: [PATCH 098/136] Upgrade run-e2e-tests workflow --- .github/workflows/integration-in-memory-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index 4b221acc7ee..9599288284d 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -74,7 +74,7 @@ jobs: contents: read needs: changes if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@6f44fa461b22a801cc46e1a2f7ea7852a979dc8a + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@2ec5925da7b7c08a4260f40192d76e192b7c3961 with: workflow_name: Run CCIP Integration Tests For PR chainlink_version: ${{ inputs.cl_ref || github.sha }} @@ -102,7 +102,7 @@ jobs: contents: read needs: changes if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@6f44fa461b22a801cc46e1a2f7ea7852a979dc8a + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@2ec5925da7b7c08a4260f40192d76e192b7c3961 with: workflow_name: Run CCIP Integration Tests For Merge Queue chainlink_version: ${{ inputs.cl_ref || github.sha }} From aab5c38565777ffae036cc1379c2e937f9352eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 16 May 2025 02:26:13 +0200 Subject: [PATCH 099/136] Upgrade run-e2e-tests workflow --- .github/workflows/integration-in-memory-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index 9599288284d..b86e4273e0e 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -74,7 +74,7 @@ jobs: contents: read needs: changes if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@2ec5925da7b7c08a4260f40192d76e192b7c3961 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@a17a745159d7537f85956899a38262ece7408e6e with: workflow_name: Run CCIP Integration Tests For PR chainlink_version: ${{ inputs.cl_ref || github.sha }} @@ -102,7 +102,7 @@ jobs: contents: read needs: changes if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@2ec5925da7b7c08a4260f40192d76e192b7c3961 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@a17a745159d7537f85956899a38262ece7408e6e with: workflow_name: Run CCIP Integration Tests For Merge Queue chainlink_version: ${{ inputs.cl_ref || github.sha }} From 36a3b03a590382df82cb72f5c181bc0c237a9796 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:48:53 +0400 Subject: [PATCH 100/136] core/capabilities/ccip/ccipaptos: add initial ccipaptos implementation --- .../ccip/ccipaptos/addresscodec.go | 69 ++++ .../ccip/ccipaptos/addresscodec_test.go | 121 ++++++ .../ccip/ccipaptos/commitcodec.go | 168 ++++++++ .../ccip/ccipaptos/commitcodec_test.go | 163 ++++++++ .../ccip/ccipaptos/executecodec.go | 343 ++++++++++++++++ .../ccip/ccipaptos/executecodec_test.go | 179 +++++++++ .../ccip/ccipaptos/extradatadecoder.go | 150 +++++++ .../ccip/ccipaptos/extradatadecoder_test.go | 110 ++++++ .../ccip/ccipaptos/gas_helpers.go | 22 ++ core/capabilities/ccip/ccipaptos/msghasher.go | 367 ++++++++++++++++++ .../ccip/ccipaptos/msghasher_test.go | 93 +++++ core/capabilities/ccip/ccipaptos/rmncrypto.go | 20 + core/capabilities/ccip/ccipaptos/tokendata.go | 18 + core/capabilities/ccip/ccipaptos/utils.go | 23 ++ 14 files changed, 1846 insertions(+) create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec.go create mode 100644 core/capabilities/ccip/ccipaptos/addresscodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec.go create mode 100644 core/capabilities/ccip/ccipaptos/commitcodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec.go create mode 100644 core/capabilities/ccip/ccipaptos/executecodec_test.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder.go create mode 100644 core/capabilities/ccip/ccipaptos/extradatadecoder_test.go create mode 100644 core/capabilities/ccip/ccipaptos/gas_helpers.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher.go create mode 100644 core/capabilities/ccip/ccipaptos/msghasher_test.go create mode 100644 core/capabilities/ccip/ccipaptos/rmncrypto.go create mode 100644 core/capabilities/ccip/ccipaptos/tokendata.go create mode 100644 core/capabilities/ccip/ccipaptos/utils.go diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go new file mode 100644 index 00000000000..73ee4bb79c0 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -0,0 +1,69 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" +) + +type AddressCodec struct{} + +func (a AddressCodec) AddressBytesToString(addr []byte) (string, error) { + return addressBytesToString(addr) +} + +func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { + return addressStringToBytes(addr) +} + +func addressBytesToString(addr []byte) (string, error) { + if len(addr) != 32 { + return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + + accAddress := aptos.AccountAddress(addr) + return accAddress.String(), nil +} + +func addressStringToBytes(addr string) ([]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress[:], nil +} + +func addressStringToBytes32(addr string) ([32]byte, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress, nil +} + +func addressBytesToBytes32(addr []byte) ([32]byte, error) { + if len(addr) > 32 { + return [32]byte{}, fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + } + var result [32]byte + // Left pad by copying to the end of the 32 byte array + copy(result[32-len(addr):], addr) + return result, nil +} + +// takes a valid Aptos address string and converts it into canonical format. +func addressStringToString(addr string) (string, error) { + var accAddress aptos.AccountAddress + err := accAddress.ParseStringRelaxed(addr) + if err != nil { + return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + } + return accAddress.String(), nil +} + +func addressIsValid(addr string) bool { + _, err := addressStringToBytes(addr) + return err == nil +} diff --git a/core/capabilities/ccip/ccipaptos/addresscodec_test.go b/core/capabilities/ccip/ccipaptos/addresscodec_test.go new file mode 100644 index 00000000000..b40c52ce522 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/addresscodec_test.go @@ -0,0 +1,121 @@ +package ccipaptos + +import ( + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func generateAddressBytes32() [32]byte { + var result [32]byte + _, err := rand.Read(result[:]) + if err != nil { + panic(fmt.Sprintf("failed to generate random address bytes: %v", err)) + } + return result +} + +func generateAddressBytes() []byte { + a := generateAddressBytes32() + return a[:] +} + +func generateAddressString() string { + addressBytes := generateAddressBytes() + addressString, err := addressBytesToString(addressBytes) + if err != nil { + panic(fmt.Sprintf("failed to generate random address string: %v", err)) + } + return addressString +} + +func TestAddressBytesToString(t *testing.T) { + tests := []struct { + name string + inHex string + isErr bool + expected string + }{ + { + "empty", + "", + true, + "", + }, + { + "equal to 32 bytes", + "0102030405060102030405060102030405060102030405060102030405060101", + false, + "0x0102030405060102030405060102030405060102030405060102030405060101", + }, + { + "longer than required", + "0102030405060102030405060102030405060102030405060102030405060101FFFFFFFFFF", + true, + "", + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + bytes, err := hex.DecodeString(test.inHex) + require.NoError(t, err) + + if test.isErr { + _, err := codec.AddressBytesToString(bytes) + require.Error(t, err, fmt.Sprintf("expected error for %s, input %s", test.name, test.inHex)) + } else { + actual, err := codec.AddressBytesToString(bytes) + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } + }) + } +} + +func TestAddressStringToBytes(t *testing.T) { + tests := []struct { + name string + in string + expected []byte + expectedErr error + }{ + { + "hand crafted", + "0x0102030405060102030405060102030405060102030405060102030405060101", + []byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x01, 0x01, + }, + nil, + }, + { + "hand crafted error", + "invalidAddress", + nil, + errors.New("failed to decode Aptos address 'invalidAddress': invalid address"), + }, + } + + codec := AddressCodec{} + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual, err := codec.AddressStringToBytes(test.in) + if test.expectedErr == nil { + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go new file mode 100644 index 00000000000..0fc28059a38 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -0,0 +1,168 @@ +package ccipaptos + +import ( + "context" + "fmt" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. +// Compatible with ccip::offramp version 1.6.0 +type CommitPluginCodecV1 struct{} + +func NewCommitPluginCodecV1() *CommitPluginCodecV1 { + return &CommitPluginCodecV1{} +} + +func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { + s := &bcs.Serializer{} + bcs.SerializeSequenceWithFunction(report.PriceUpdates.TokenPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.TokenPrice) { + sourceToken := aptos.AccountAddress{} + err := sourceToken.ParseStringRelaxed(string(item.TokenID)) + if err != nil { + s.SetError(fmt.Errorf("failed to parse source token address: %w", err)) + return + } + s.Struct(&sourceToken) + s.U256(*item.Price.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { + s.U64(uint64(item.ChainSel)) + s.U256(*item.GasPrice.Int) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.BlessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize BlessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.UnblessedMerkleRoots, s, func(s *bcs.Serializer, item cciptypes.MerkleRootChain) { + s.U64(uint64(item.ChainSel)) + s.WriteBytes(item.OnRampAddress[:]) + s.U64(uint64(item.SeqNumsRange.Start())) + s.U64(uint64(item.SeqNumsRange.End())) + s.FixedBytes(item.MerkleRoot[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize UnblessedMerkleRoots: %w", s.Error()) + } + bcs.SerializeSequenceWithFunction(report.RMNSignatures, s, func(s *bcs.Serializer, item cciptypes.RMNECDSASignature) { + s.FixedBytes(item.R[:]) + s.FixedBytes(item.S[:]) + }) + if s.Error() != nil { + return nil, fmt.Errorf("failed to serialize RMNSignatures: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptypes.CommitPluginReport, error) { + des := bcs.NewDeserializer(data) + report := cciptypes.CommitPluginReport{} + + report.PriceUpdates.TokenPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.TokenPrice) { + var sourceToken aptos.AccountAddress + des.Struct(&sourceToken) + if des.Error() != nil { + return + } + item.TokenID = cciptypes.UnknownEncodedAddress(sourceToken.String()) + price := des.U256() + if des.Error() != nil { + return + } + item.Price = cciptypes.NewBigInt(&price) + }) + + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize TokenPriceUpdates: %w", des.Error()) + } + + report.PriceUpdates.GasPriceUpdates = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.GasPriceChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + gasPrice := des.U256() + if des.Error() != nil { + return + } + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) + } + + deserializeMerkleRootChain := func(des *bcs.Deserializer, item *cciptypes.MerkleRootChain) { + item.ChainSel = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return + } + onRampAddrBytes := des.ReadBytes() + if des.Error() != nil { + return + } + item.OnRampAddress = onRampAddrBytes + startSeqNum := des.U64() + if des.Error() != nil { + return + } + endSeqNum := des.U64() + if des.Error() != nil { + return + } + item.SeqNumsRange = cciptypes.NewSeqNumRange(cciptypes.SeqNum(startSeqNum), cciptypes.SeqNum(endSeqNum)) + des.ReadFixedBytesInto(item.MerkleRoot[:]) + if des.Error() != nil { + return + } + } + + report.BlessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize BlessedMerkleRoots: %w", des.Error()) + } + + report.UnblessedMerkleRoots = bcs.DeserializeSequenceWithFunction(des, deserializeMerkleRootChain) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize UnblessedMerkleRoots: %w", des.Error()) + } + + report.RMNSignatures = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RMNECDSASignature) { + des.ReadFixedBytesInto(item.R[:]) + if des.Error() != nil { + return + } + des.ReadFixedBytesInto(item.S[:]) + if des.Error() != nil { + return + } + }) + if des.Error() != nil { + return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize RMNSignatures: %w", des.Error()) + } + + if des.Remaining() > 0 { + return cciptypes.CommitPluginReport{}, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + return report, nil +} + +// Ensure CommitPluginCodec implements the CommitPluginCodec interface +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go new file mode 100644 index 00000000000..3f05cb75d52 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -0,0 +1,163 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomCommitReport = func() cciptypes.CommitPluginReport { + return cciptypes.CommitPluginReport{ + BlessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + UnblessedMerkleRoots: []cciptypes.MerkleRootChain{ + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + { + OnRampAddress: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + ChainSel: cciptypes.ChainSelector(rand.Uint64()), + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(rand.Uint64()), + cciptypes.SeqNum(rand.Uint64()), + ), + MerkleRoot: utils.RandomBytes32(), + }, + }, + PriceUpdates: cciptypes.PriceUpdates{ + TokenPriceUpdates: []cciptypes.TokenPrice{ + { + TokenID: cciptypes.UnknownEncodedAddress(generateAddressString()), + Price: cciptypes.NewBigInt(utils.RandUint256()), + }, + }, + GasPriceUpdates: []cciptypes.GasPriceChain{ + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, + }, + }, + RMNSignatures: []cciptypes.RMNECDSASignature{ + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + {R: utils.RandomBytes32(), S: utils.RandomBytes32()}, + }, + } +} + +func TestCommitPluginCodecV1(t *testing.T) { + testCases := []struct { + name string + report func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport + expErr bool + }{ + { + name: "base report", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + return report + }, + }, + { + name: "empty token address", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].TokenID = "" + return report + }, + expErr: true, + }, + { + name: "empty merkle root", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.BlessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + report.UnblessedMerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} + return report + }, + }, + { + name: "zero token price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.TokenPriceUpdates[0].Price = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + { + name: "zero gas price", + report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { + report.PriceUpdates.GasPriceUpdates[0].GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + return report + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + report := tc.report(randomCommitReport()) + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(t) + encodedReport, err := commitCodec.Encode(ctx, report) + if tc.expErr { + assert.Error(t, err) + return + } + require.NoError(t, err) + decodedReport, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(t, err) + require.Equal(t, report, decodedReport) + }) + } +} + +func BenchmarkCommitPluginCodecV1_Encode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + + rep := randomCommitReport() + for i := 0; i < b.N; i++ { + _, err := commitCodec.Encode(ctx, rep) + require.NoError(b, err) + } +} + +func BenchmarkCommitPluginCodecV1_Decode(b *testing.B) { + commitCodec := NewCommitPluginCodecV1() + ctx := testutils.Context(b) + encodedReport, err := commitCodec.Encode(ctx, randomCommitReport()) + require.NoError(b, err) + + for i := 0; i < b.N; i++ { + _, err := commitCodec.Decode(ctx, encodedReport) + require.NoError(b, err) + } +} diff --git a/core/capabilities/ccip/ccipaptos/executecodec.go b/core/capabilities/ccip/ccipaptos/executecodec.go new file mode 100644 index 00000000000..62c53e21fee --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec.go @@ -0,0 +1,343 @@ +package ccipaptos + +import ( + "context" + "fmt" + "math/big" + + "github.com/aptos-labs/aptos-go-sdk" + "github.com/aptos-labs/aptos-go-sdk/bcs" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. +// Compatible with ccip_offramp::offramp version 1.6.0 +type ExecutePluginCodecV1 struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +func NewExecutePluginCodecV1(extraDataCodec ccipcommon.ExtraDataCodec) *ExecutePluginCodecV1 { + return &ExecutePluginCodecV1{ + extraDataCodec: extraDataCodec, + } +} + +func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.ExecutePluginReport) ([]byte, error) { + if len(report.ChainReports) == 0 { + return nil, nil + } + + if len(report.ChainReports) != 1 { + return nil, fmt.Errorf("ExecutePluginCodecV1 expects exactly one ChainReport, found %d", len(report.ChainReports)) + } + + chainReport := report.ChainReports[0] + + if len(chainReport.Messages) != 1 { + return nil, fmt.Errorf("only single report message expected, got %d", len(chainReport.Messages)) + } + + if len(chainReport.OffchainTokenData) != 1 { + return nil, fmt.Errorf("only single group of offchain token data expected, got %d", len(chainReport.OffchainTokenData)) + } + + message := chainReport.Messages[0] + offchainTokenData := chainReport.OffchainTokenData[0] + + s := &bcs.Serializer{} + + // 1. source_chain_selector: u64 + s.U64(uint64(chainReport.SourceChainSelector)) + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + if len(message.Header.MessageID) != 32 { + return nil, fmt.Errorf("invalid message ID length: expected 32, got %d", len(message.Header.MessageID)) + } + s.FixedBytes(message.Header.MessageID[:]) + + // 3. header_source_chain_selector: u64 + s.U64(uint64(message.Header.SourceChainSelector)) + + // 4. dest_chain_selector: u64 + s.U64(uint64(message.Header.DestChainSelector)) + + // 5. sequence_number: u64 + s.U64(uint64(message.Header.SequenceNumber)) + + // 6. nonce: u64 + s.U64(message.Header.Nonce) + // --- End Message Header --- + + // 7. sender: vector + s.WriteBytes(message.Sender) + + // 8. data: vector + s.WriteBytes(message.Data) + + // 9. receiver: address (Aptos address, 32 bytes) + var receiverAddr aptos.AccountAddress + if err := receiverAddr.ParseStringRelaxed(message.Receiver.String()); err != nil { + return nil, fmt.Errorf("failed to parse receiver address '%s': %w", message.Receiver.String(), err) + } + s.Struct(&receiverAddr) + + // 10. gas_limit: u256 + // Extract gas limit from ExtraArgs + decodedExtraArgsMap, err := e.extraDataCodec.DecodeExtraArgs(message.ExtraArgs, chainReport.SourceChainSelector) + if err != nil { + return nil, fmt.Errorf("failed to decode ExtraArgs: %w", err) + } + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) // Use a helper to extract the gas limit + if err != nil { + return nil, fmt.Errorf("failed to extract gas limit from decoded ExtraArgs map: %w", err) + } + s.U256(*gasLimit) + + // 11. token_amounts: vector + bcs.SerializeSequenceWithFunction(message.TokenAmounts, s, func(s *bcs.Serializer, item cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + s.WriteBytes(item.SourcePoolAddress) + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + if err := destTokenAddr.ParseStringRelaxed(item.DestTokenAddress.String()); err != nil { + s.SetError(fmt.Errorf("failed to parse dest_token_address '%s': %w", item.DestTokenAddress.String(), err)) + } + s.Struct(&destTokenAddr) + + // 11c. dest_gas_amount: u32 + // Extract dest gas amount from DestExecData + destExecDataDecodedMap, err := e.extraDataCodec.DecodeTokenAmountDestExecData(item.DestExecData, chainReport.SourceChainSelector) + if err != nil { + s.SetError(fmt.Errorf("failed to decode DestExecData for token %s: %w", destTokenAddr.String(), err)) + return + } + destGasAmount, err := extractDestGasAmountFromMap(destExecDataDecodedMap) // Use a helper + if err != nil { + s.SetError(fmt.Errorf("failed to extract dest gas amount from decoded DestExecData map for token %s: %w", destTokenAddr.String(), err)) + return + } + s.U32(destGasAmount) + + // 11d. extra_data: vector + s.WriteBytes(item.ExtraData) + + // 11e. amount: u256 + if item.Amount.Int == nil { + s.SetError(fmt.Errorf("token amount is nil for token %s", destTokenAddr.String())) + return + } + s.U256(*item.Amount.Int) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during token_amounts serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize token_amounts: %w", s.Error()) + } + + // 12. offchain_token_data: vector> + bcs.SerializeSequenceWithFunction(offchainTokenData, s, func(s *bcs.Serializer, item []byte) { + s.WriteBytes(item) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during offchain_token_data serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda (though unlikely here) + return nil, fmt.Errorf("failed to serialize offchain_token_data: %w", s.Error()) + } + + // 13. proofs: vector + bcs.SerializeSequenceWithFunction(chainReport.Proofs, s, func(s *bcs.Serializer, item cciptypes.Bytes32) { + if len(item) != 32 { + s.SetError(fmt.Errorf("invalid proof length: expected 32, got %d", len(item))) + return + } + s.FixedBytes(item[:]) + }) + if err != nil { // Check error from SerializeSequenceWithFunction itself + return nil, fmt.Errorf("failed during proofs serialization: %w", err) + } + if s.Error() != nil { // Check error set within the lambda + return nil, fmt.Errorf("failed to serialize proofs: %w", s.Error()) + } + + // Final check and return + if s.Error() != nil { + return nil, fmt.Errorf("BCS serialization failed: %w", s.Error()) + } + + return s.ToBytes(), nil +} + +func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) (cciptypes.ExecutePluginReport, error) { + des := bcs.NewDeserializer(encodedReport) + report := cciptypes.ExecutePluginReport{} + var chainReport cciptypes.ExecutePluginReportSingleChain + var message cciptypes.Message + + // 1. source_chain_selector: u64 + chainReport.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize source_chain_selector: %w", des.Error()) + } + + // --- Start Message Header --- + // 2. message_id: fixed_vector_u8(32) + messageIDBytes := des.ReadFixedBytes(32) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize message_id: %w", des.Error()) + } + copy(message.Header.MessageID[:], messageIDBytes) + + // 3. header_source_chain_selector: u64 + message.Header.SourceChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize header_source_chain_selector: %w", des.Error()) + } + + // 4. dest_chain_selector: u64 + message.Header.DestChainSelector = cciptypes.ChainSelector(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize dest_chain_selector: %w", des.Error()) + } + + // 5. sequence_number: u64 + message.Header.SequenceNumber = cciptypes.SeqNum(des.U64()) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sequence_number: %w", des.Error()) + } + + // 6. nonce: u64 + message.Header.Nonce = des.U64() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize nonce: %w", des.Error()) + } + + // --- End Message Header --- + + // 7. sender: vector + message.Sender = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize sender: %w", des.Error()) + } + + // 8. data: vector + message.Data = des.ReadBytes() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize data: %w", des.Error()) + } + + // 9. receiver: address + var receiverAddr aptos.AccountAddress + des.Struct(&receiverAddr) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize receiver: %w", des.Error()) + } + message.Receiver = receiverAddr[:] + + // 10. gas_limit: u256 + _ = des.U256() + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize gas_limit: %w", des.Error()) + } + + // 11. token_amounts: vector + message.TokenAmounts = bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *cciptypes.RampTokenAmount) { + // 11a. source_pool_address: vector + item.SourcePoolAddress = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11b. dest_token_address: address + var destTokenAddr aptos.AccountAddress + des.Struct(&destTokenAddr) + if des.Error() != nil { + return // Error handled by caller + } + item.DestTokenAddress = destTokenAddr[:] + + // 11c. dest_gas_amount: u32 + destGasAmount := des.U32() + if des.Error() != nil { + return // Error handled by caller + } + // Encode dest gas amount back into DestExecData + destData, err := abiEncodeUint32(destGasAmount) + if err != nil { + des.SetError(fmt.Errorf("abi encode dest gas amount: %w", err)) + return + } + item.DestExecData = destData + + // 11d. extra_data: vector + item.ExtraData = des.ReadBytes() + if des.Error() != nil { + return // Error handled by caller + } + + // 11e. amount: u256 + amountU256 := des.U256() + if des.Error() != nil { + return // Error handled by caller + } + item.Amount = cciptypes.NewBigInt(&amountU256) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize token_amounts: %w", des.Error()) + } + + // 12. offchain_token_data: vector> + offchainTokenDataGroup := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadBytes() + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize offchain_token_data: %w", des.Error()) + } + // Wrap it in the expected [][][]byte structure + chainReport.OffchainTokenData = [][][]byte{offchainTokenDataGroup} + + // 13. proofs: vector + proofsBytes := bcs.DeserializeSequenceWithFunction(des, func(des *bcs.Deserializer, item *[]byte) { + *item = des.ReadFixedBytes(32) + }) + if des.Error() != nil { + return report, fmt.Errorf("failed to deserialize proofs: %w", des.Error()) + } + // Convert [][]byte to [][32]byte + chainReport.Proofs = make([]cciptypes.Bytes32, len(proofsBytes)) + for i, proofB := range proofsBytes { + if len(proofB) != 32 { + // This shouldn't happen if ReadFixedBytes worked correctly + return report, fmt.Errorf("internal error: deserialized proof %d has length %d, expected 32", i, len(proofB)) + } + copy(chainReport.Proofs[i][:], proofB) + } + + // Check if all bytes were consumed + if des.Remaining() > 0 { + return report, fmt.Errorf("unexpected remaining bytes after decoding: %d", des.Remaining()) + } + + // Set empty fields + message.Header.MsgHash = cciptypes.Bytes32{} + message.Header.OnRamp = cciptypes.UnknownAddress{} + message.FeeToken = cciptypes.UnknownAddress{} + message.ExtraArgs = cciptypes.Bytes{} + message.FeeTokenAmount = cciptypes.BigInt{} + + // Assemble the final report + chainReport.Messages = []cciptypes.Message{message} + // ProofFlagBits is not part of the Aptos report, initialize it empty/zero. + chainReport.ProofFlagBits = cciptypes.NewBigInt(big.NewInt(0)) + report.ChainReports = []cciptypes.ExecutePluginReportSingleChain{chainReport} + + return report, nil +} + +// Ensure ExecutePluginCodec implements the ExecutePluginCodec interface +var _ cciptypes.ExecutePluginCodec = (*ExecutePluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go new file mode 100644 index 00000000000..f4500ef679a --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -0,0 +1,179 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big.Int, destGasAmount uint32) cciptypes.ExecutePluginReport { + const numChainReports = 1 + const msgsPerReport = 1 + const numTokensPerMsg = 3 + + chainReports := make([]cciptypes.ExecutePluginReportSingleChain, numChainReports) + for i := 0; i < numChainReports; i++ { + reportMessages := make([]cciptypes.Message, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + data, err := cciptypes.NewBytesFromString(utils.RandomAddress().String()) + require.NoError(t, err) + + tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) + for z := 0; z < numTokensPerMsg; z++ { + encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + require.NoError(t, err2) + + tokenAmounts[z] = cciptypes.RampTokenAmount{ + SourcePoolAddress: utils.RandomAddress().Bytes(), + DestTokenAddress: generateAddressBytes(), + ExtraData: data, + Amount: cciptypes.NewBigInt(utils.RandUint256()), + DestExecData: encodedDestExecData, + } + } + + extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + if err != nil { + t.Fatalf("failed to pack extra args: %v", err) + } + extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + + reportMessages[j] = cciptypes.Message{ + Header: cciptypes.RampMessageHeader{ + MessageID: utils.RandomBytes32(), + SourceChainSelector: cciptypes.ChainSelector(rand.Uint64()), + DestChainSelector: cciptypes.ChainSelector(rand.Uint64()), + SequenceNumber: cciptypes.SeqNum(rand.Uint64()), + Nonce: rand.Uint64(), + MsgHash: utils.RandomBytes32(), + OnRamp: utils.RandomAddress().Bytes(), + }, + Sender: common.LeftPadBytes(utils.RandomAddress().Bytes(), 32), + Data: data, + Receiver: generateAddressBytes(), + ExtraArgs: extraArgs, + FeeToken: generateAddressBytes(), + FeeTokenAmount: cciptypes.NewBigInt(utils.RandUint256()), + TokenAmounts: tokenAmounts, + } + } + + tokenData := make([][][]byte, msgsPerReport) + for j := 0; j < msgsPerReport; j++ { + tokenData[j] = [][]byte{{0x1}, {0x2, 0x3}} + } + + chainReports[i] = cciptypes.ExecutePluginReportSingleChain{ + SourceChainSelector: cciptypes.ChainSelector(chainSelector), + Messages: reportMessages, + OffchainTokenData: tokenData, + Proofs: []cciptypes.Bytes32{utils.RandomBytes32(), utils.RandomBytes32()}, + ProofFlagBits: cciptypes.NewBigInt(big.NewInt(0)), + } + } + + return cciptypes.ExecutePluginReport{ChainReports: chainReports} +} + +func TestExecutePluginCodecV1(t *testing.T) { + ctx := testutils.Context(t) + mockExtraDataCodec := &mocks.ExtraDataCodec{} + destGasAmount := rand.Uint32() + gasLimit := utils.RandUint256() + mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ + "destgasamount": destGasAmount, + }, nil) + mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ + "gasLimit": utils.RandUint256(), + "accountIsWritableBitmap": gasLimit, + }, nil) + + testCases := []struct { + name string + report func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport + expErr bool + chainSelector uint64 + destGasAmount uint32 + gasLimit *big.Int + }{ + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "base report", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, + expErr: false, + chainSelector: 124615329519749607, // Solana mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty msgs", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].Messages = []cciptypes.Message{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + { + name: "reports have empty offchain token data", + report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { + report.ChainReports[0].OffchainTokenData = [][][]byte{} + return report + }, + expErr: true, + chainSelector: 5009297550715157269, // ETH mainnet chain selector + gasLimit: gasLimit, + destGasAmount: destGasAmount, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + codec := NewExecutePluginCodecV1(mockExtraDataCodec) + report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) + bytes, err := codec.Encode(ctx, report) + if tc.expErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + // ignore unavailable fields in comparison + for i := range report.ChainReports { + for j := range report.ChainReports[i].Messages { + report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} + report.ChainReports[i].Messages[j].Header.OnRamp = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].FeeToken = cciptypes.UnknownAddress{} + report.ChainReports[i].Messages[j].ExtraArgs = cciptypes.Bytes{} + report.ChainReports[i].Messages[j].FeeTokenAmount = cciptypes.BigInt{} + } + } + + // decode using the codec + codecDecoded, err := codec.Decode(ctx, bytes) + require.NoError(t, err) + require.Equal(t, report, codecDecoded) + }) + } +} diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go new file mode 100644 index 00000000000..5c600f266bd --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -0,0 +1,150 @@ +package ccipaptos + +import ( + "fmt" + "reflect" + + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +// ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder +// Compatible with ccip::fee_quoter version 1.6.0 +type ExtraDataDecoder struct{} + +const ( + aptosDestExecDataKey = "destGasAmount" +) + +var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) + +var ( + // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") + + // bytes4 public constant GENERIC_EXTRA_ARGS_V2_TAG = 0x181dcf10; + genericExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") + + // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba + svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") +) + +// DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data +func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { + destGasAmount, err := abiDecodeUint32(destExecData) + if err != nil { + return nil, fmt.Errorf("decode dest gas amount: %w", err) + } + + return map[string]any{ + aptosDestExecDataKey: destGasAmount, + }, nil +} + +// DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args +func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[string]any, error) { + if len(extraArgs) < 4 { + return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) + } + + var method string + var argName string + switch string(extraArgs[:4]) { + case string(evmExtraArgsV1Tag): + method = "exposeEVMExtraArgsV1" + argName = "evmExtraArgsV1" + case string(genericExtraArgsV2Tag): + method = "exposeGenericExtraArgsV2" + argName = "evmExtraArgsV2" + case string(svmExtraArgsV1Tag): + method = "exposeSVMExtraArgsV1" + argName = "svmExtraArgsV1" + default: + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + } + + output := make(map[string]any) + args := make(map[string]any) + err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + if err != nil { + return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + } + + argValue, exists := args[argName] + if !exists { + return nil, fmt.Errorf("failed to get arg value for %s", argName) + } + + val := reflect.ValueOf(argValue) + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) + } + + switch argName { + case "evmExtraArgsV1": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + case "evmExtraArgsV2": + gasLimitField := val.FieldByName("GasLimit") + if gasLimitField.IsValid() { + output["gasLimit"] = gasLimitField.Interface() + } else { + output["gasLimit"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + case "svmExtraArgsV1": + computeUnitsField := val.FieldByName("ComputeUnits") + if computeUnitsField.IsValid() { + output["computeUnits"] = computeUnitsField.Interface() + } else { + output["computeUnits"] = nil + } + + bitmapField := val.FieldByName("AccountIsWritableBitmap") + if bitmapField.IsValid() { + output["accountIsWritableBitmap"] = bitmapField.Interface() + } else { + output["accountIsWritableBitmap"] = nil + } + + allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") + if allowOutOfOrderField.IsValid() { + output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + } else { + output["allowOutOfOrderExecution"] = false + } + + tokenReceiverField := val.FieldByName("TokenReceiver") + if tokenReceiverField.IsValid() { + output["tokenReceiver"] = tokenReceiverField.Interface() + } else { + output["tokenReceiver"] = nil + } + + accountsField := val.FieldByName("Accounts") + if accountsField.IsValid() { + output["accounts"] = accountsField.Interface() + } else { + output["accounts"] = nil + } + } + return output, nil +} + +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go new file mode 100644 index 00000000000..234d2f29981 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -0,0 +1,110 @@ +package ccipaptos + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" +) + +func Test_decodeExtraData(t *testing.T) { + gasLimit := big.NewInt(rand.Int63()) + extraDataDecoder := &ExtraDataDecoder{} + + t.Run("decode extra args into map evm v1", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ + GasLimit: gasLimit, + }) + encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + }) + + t.Run("decode extra args into map evm v2", func(t *testing.T) { + encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ + GasLimit: gasLimit, + AllowOutOfOrderExecution: true, + }) + encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 2) + + gl, exist := m["gasLimit"] + require.True(t, exist) + require.Equal(t, gl, gasLimit) + + ooe, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, true, ooe) + }) + + t.Run("decode extra args into map svm", func(t *testing.T) { + key, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + cu := uint32(10000) + bitmap := uint64(4) + ooe := false + tokenReceiver := [32]byte(key.PublicKey().Bytes()) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} + encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ + ComputeUnits: cu, + AccountIsWritableBitmap: bitmap, + AllowOutOfOrderExecution: ooe, + TokenReceiver: tokenReceiver, + Accounts: accounts, + }) + encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + require.NoError(t, err) + + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 5) + + cuDecoded, exist := m["computeUnits"] + require.True(t, exist) + require.Equal(t, cuDecoded, cu) + + bitmapDecoded, exist := m["accountIsWritableBitmap"] + require.True(t, exist) + require.Equal(t, bitmapDecoded, bitmap) + + ooeDecoded, exist := m["allowOutOfOrderExecution"] + require.True(t, exist) + require.Equal(t, ooeDecoded, ooe) + + tokenReceiverDecoded, exist := m["tokenReceiver"] + require.True(t, exist) + require.Equal(t, tokenReceiverDecoded, tokenReceiver) + + accountsDecoded, exist := m["accounts"] + require.True(t, exist) + require.Equal(t, accountsDecoded, accounts) + }) + + t.Run("decode dest exec data into map", func(t *testing.T) { + destGasAmount := uint32(10000) + encoded, err := abiEncodeUint32(destGasAmount) + require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) + require.NoError(t, err) + require.Len(t, m, 1) + + decoded, exist := m[aptosDestExecDataKey] + require.True(t, exist) + require.Equal(t, destGasAmount, decoded) + }) +} diff --git a/core/capabilities/ccip/ccipaptos/gas_helpers.go b/core/capabilities/ccip/ccipaptos/gas_helpers.go new file mode 100644 index 00000000000..7f3922e5c6c --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/gas_helpers.go @@ -0,0 +1,22 @@ +package ccipaptos + +import ( + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +func NewGasEstimateProvider() EstimateProvider { + return EstimateProvider{} +} + +type EstimateProvider struct { +} + +// CalculateMerkleTreeGas is not implemented +func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { + return 0 +} + +// CalculateMessageMaxGas is not implemented. +func (gp EstimateProvider) CalculateMessageMaxGas(msg cciptypes.Message) uint64 { + return 0 +} diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go new file mode 100644 index 00000000000..995e7e0112e --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -0,0 +1,367 @@ +package ccipaptos + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/smartcontractkit/chainlink-ccip/pkg/logutil" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +var ( + // const LEAF_DOMAIN_SEPARATOR: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; + leafDomainSeparator = [32]byte{} + + // see aptos_hash::keccak256(b"Any2AptosMessageHashV1") in calculate_metadata_hash + any2AptosMessageHash = utils.Keccak256Fixed([]byte("Any2AptosMessageHashV1")) +) + +// MessageHasherV1 implements the MessageHasher interface. +// Compatible with ccip::offramp version 1.6.0 +type MessageHasherV1 struct { + lggr logger.Logger + extraDataCodec ccipcommon.ExtraDataCodec +} + +type any2AptosTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int +} + +func NewMessageHasherV1(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) *MessageHasherV1 { + return &MessageHasherV1{ + lggr: lggr, + extraDataCodec: extraDataCodec, + } +} + +// Hash implements the MessageHasher interface. +// It constructs all of the inputs to the final keccak256 hash in Internal._hash(Any2EVMRampMessage). +// The main structure of the hash is as follows: +// Fixed-size message fields are included in nested hash to reduce stack pressure. +// This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. +func (h *MessageHasherV1) Hash(ctx context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) { + lggr := logutil.WithContextValues(ctx, h.lggr) + lggr = logger.With( + lggr, + "msgID", msg.Header.MessageID.String(), + "ANY_2_APTOS_MESSAGE_HASH", hexutil.Encode(any2AptosMessageHash[:]), + "onrampAddress", msg.Header.OnRamp, + ) + lggr.Debugw("hashing message", "msg", msg) + + rampTokenAmounts := make([]any2AptosTokenTransfer, len(msg.TokenAmounts)) + for _, rta := range msg.TokenAmounts { + destGasAmount, err := abiDecodeUint32(rta.DestExecData) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest gas amount: %w", err) + } + + lggr.Debugw("decoded dest gas amount", + "destGasAmount", destGasAmount) + + destTokenAddress, err := addressBytesToBytes32(rta.DestTokenAddress) + if err != nil { + return [32]byte{}, fmt.Errorf("decode dest token address: %w", err) + } + + lggr.Debugw("abi decoded dest token address", + "destTokenAddress", destTokenAddress) + + rampTokenAmounts = append(rampTokenAmounts, any2AptosTokenTransfer{ + SourcePoolAddress: rta.SourcePoolAddress, + DestTokenAddress: destTokenAddress, + DestGasAmount: destGasAmount, + ExtraData: rta.ExtraData, + Amount: rta.Amount.Int, + }) + } + + // one difference from EVM is that we don't left pad the OnRamp to 32 bytes here, we use the source chain's canonical bytes encoding directly. + metaDataHashInput, err := computeMetadataHash(uint64(msg.Header.SourceChainSelector), uint64(msg.Header.DestChainSelector), msg.Header.OnRamp) + if err != nil { + return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) + } + + lggr.Debugw("metadata hash preimage", + "metaDataHashInput", hexutil.Encode(metaDataHashInput[:])) + + // Need to decode the extra args to get the gas limit. + // TODO: we assume that extra args is always abi-encoded for now, but we need + // to decode according to source chain selector family. We should add a family + // lookup API to the chain-selectors library. + + decodedExtraArgsMap, err := h.extraDataCodec.DecodeExtraArgs(msg.ExtraArgs, msg.Header.SourceChainSelector) + if err != nil { + return [32]byte{}, err + } + + gasLimit, err := parseExtraDataMap(decodedExtraArgsMap) + if err != nil { + return [32]byte{}, fmt.Errorf("decode extra args to get gas limit: %w", err) + } + + lggr.Debugw("decoded msg gas limit", "gasLimit", gasLimit) + + receiverAddress, err := addressBytesToBytes32(msg.Receiver) + if err != nil { + return [32]byte{}, err + } + + msgHash, err := computeMessageDataHash(metaDataHashInput, msg.Header.MessageID, receiverAddress, uint64(msg.Header.SequenceNumber), gasLimit, msg.Header.Nonce, msg.Sender, msg.Data, rampTokenAmounts) + if err != nil { + return [32]byte{}, err + } + + lggr.Debugw("final message hash result", + "msgHash", hexutil.Encode(msgHash[:]), + ) + + return msgHash, nil +} + +// This is the equivalent of offramp::calculate_message_hash. +// This is very similar to the EVM version, except for 32-byte addresses: +// +// bytes32 messageDataHash = keccak256( +// abi.encode( +// LEAF_DOMAIN_SEPARATOR, +// metadataHash, +// keccak256( +// abi.encode( +// original.header.originalId, +// original.receiver, +// original.header.sequenceNumber, +// original.gasLimit, +// original.header.nonce +// ) +// ), +// keccak256(original.sender), +// keccak256(original.data), +// keccak256(abi.encode(original.tokenAmounts)) +// ) +// ); +func computeMessageDataHash( + metadataHash [32]byte, + messageID [32]byte, + receiver [32]byte, + sequenceNumber uint64, + gasLimit *big.Int, + nonce uint64, + sender []byte, + data []byte, + tokenAmounts []any2AptosTokenTransfer, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + uint256Type, err := abi.NewType("uint256", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint256 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + headerArgs := abi.Arguments{ + {Type: bytes32Type}, // messageID + {Type: bytes32Type}, // receiver as bytes32 + {Type: uint64Type}, // sequenceNumber + {Type: uint256Type}, // gasLimit + {Type: uint64Type}, // nonce + } + headerEncoded, err := headerArgs.Pack( + messageID, + receiver, + sequenceNumber, + gasLimit, + nonce, + ) + if err != nil { + return [32]byte{}, err + } + headerHash := crypto.Keccak256Hash(headerEncoded) + + senderHash := crypto.Keccak256Hash(sender) + + dataHash := crypto.Keccak256Hash(data) + + type tokenTuple struct { + SourcePoolAddress []byte + DestTokenAddress [32]byte + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int + } + tokens := make([]tokenTuple, len(tokenAmounts)) + for i, token := range tokenAmounts { + tokens[i] = tokenTuple{ + SourcePoolAddress: token.SourcePoolAddress, + DestTokenAddress: token.DestTokenAddress, + DestGasAmount: token.DestGasAmount, + ExtraData: token.ExtraData, + Amount: token.Amount, + } + } + + // Manually encode tokens to match the Move implementation, because abi.Pack has different behavior + // for dynamic types. + var tokenHashData []byte + tokenHashData = append(tokenHashData, encodeUint256(big.NewInt(int64(len(tokens))))...) + for _, token := range tokens { + tokenHashData = append(tokenHashData, encodeBytes(token.SourcePoolAddress)...) + tokenHashData = append(tokenHashData, token.DestTokenAddress[:]...) + tokenHashData = append(tokenHashData, encodeUint32(token.DestGasAmount)...) + tokenHashData = append(tokenHashData, encodeBytes(token.ExtraData)...) + tokenHashData = append(tokenHashData, encodeUint256(token.Amount)...) + } + tokenAmountsHash := crypto.Keccak256Hash(tokenHashData) + + finalArgs := abi.Arguments{ + {Type: bytes32Type}, // LEAF_DOMAIN_SEPARATOR + {Type: bytes32Type}, // metadataHash + {Type: bytes32Type}, // headerHash + {Type: bytes32Type}, // senderHash + {Type: bytes32Type}, // dataHash + {Type: bytes32Type}, // tokenAmountsHash + } + + finalEncoded, err := finalArgs.Pack( + leafDomainSeparator, + metadataHash, + headerHash, + senderHash, + dataHash, + tokenAmountsHash, + ) + if err != nil { + return [32]byte{}, err + } + + return crypto.Keccak256Hash(finalEncoded), nil +} + +// ComputeMetadataHash calculates the metadataHash as per offramp::calculate_metadata_hash +// This is the same as the EVM version minus the separator: +// +// bytes32 metaDataHash = keccak256( +// abi.encode( +// Internal.ANY_2_APTOS_MESSAGE_HASH, +// sourceChainSelector, +// i_chainSelector, +// keccak256(_getEnabledSourceChainConfig(sourceChainSelector).onRamp) +// ) +// ); +func computeMetadataHash( + sourceChainSelector uint64, + destinationChainSelector uint64, + onRamp []byte, +) ([32]byte, error) { + uint64Type, err := abi.NewType("uint64", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create uint64 ABI type: %w", err) + } + + bytes32Type, err := abi.NewType("bytes32", "", nil) + if err != nil { + return [32]byte{}, fmt.Errorf("failed to create bytes32 ABI type: %w", err) + } + + onRampHash := crypto.Keccak256Hash(onRamp) + + args := abi.Arguments{ + {Type: bytes32Type}, // ANY_2_APTOS_MESSAGE_HASH + {Type: uint64Type}, // sourceChainSelector + {Type: uint64Type}, // destinationChainSelector (i_chainSelector) + {Type: bytes32Type}, // onRamp + } + + encoded, err := args.Pack( + any2AptosMessageHash, + sourceChainSelector, + destinationChainSelector, + onRampHash, + ) + if err != nil { + return [32]byte{}, err + } + + metadataHash := crypto.Keccak256Hash(encoded) + return metadataHash, nil +} + +func encodeUint256(n *big.Int) []byte { + return common.LeftPadBytes(n.Bytes(), 32) +} + +func encodeUint32(n uint32) []byte { + return common.LeftPadBytes(new(big.Int).SetUint64(uint64(n)).Bytes(), 32) +} + +func encodeBytes(b []byte) []byte { + encodedLength := common.LeftPadBytes(big.NewInt(int64(len(b))).Bytes(), 32) + padLen := (32 - (len(b) % 32)) % 32 + result := make([]byte, 32+len(b)+padLen) + copy(result[:32], encodedLength) + copy(result[32:], b) + return result +} + +func parseExtraDataMap(input map[string]any) (*big.Int, error) { + var outputGas *big.Int + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "gaslimit": + // Expect [][32]byte + if val, ok := fieldValue.(*big.Int); ok { + outputGas = val + return outputGas, nil + } + return nil, fmt.Errorf("unexpected type for gas limit: %T", fieldValue) + default: + // no error here, as we only need the keys to gasLimit, other keys can be skipped without like AllowOutOfOrderExecution etc. + } + } + return outputGas, errors.New("gas limit not found in extra data map") +} + +func extractDestGasAmountFromMap(input map[string]any) (uint32, error) { + // Iterate through the expected fields in the struct + for fieldName, fieldValue := range input { + lowercase := strings.ToLower(fieldName) + switch lowercase { + case "destgasamount": + // Expect uint32 + if val, ok := fieldValue.(uint32); ok { + return val, nil + } + return 0, errors.New("invalid type for destgasamount, expected uint32") + default: + } + } + + return 0, errors.New("invalid token message, dest gas amount not found in the DestExecDataDecoded map") +} + +// Interface compliance check +var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/msghasher_test.go b/core/capabilities/ccip/ccipaptos/msghasher_test.go new file mode 100644 index 00000000000..fa06a9fb2b7 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/msghasher_test.go @@ -0,0 +1,93 @@ +package ccipaptos + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_message_hash +func TestComputeMessageDataHash(t *testing.T) { + expectedHashStr := "0xc8d6cf666864a60dd6ecd89e5c294734c53b3218d3f83d2d19a3c3f9e200e00d" + + metadataHashBytes, err := hexutil.Decode("0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899") + require.NoError(t, err) + var metadataHash [32]byte + copy(metadataHash[:], metadataHashBytes) + + messageIDBytes, err := hexutil.Decode("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + require.NoError(t, err) + var messageID [32]byte + copy(messageID[:], messageIDBytes) + + receiverBytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000001234") + require.NoError(t, err) + var receiver [32]byte + copy(receiver[:], receiverBytes) + + sequenceNumber := uint64(42) + nonce := uint64(123) + gasLimit := big.NewInt(500000) + + sender, err := hexutil.Decode("0x8765432109fedcba8765432109fedcba87654321") + require.NoError(t, err) + + data := []byte("sample message data") + srcPool1, err := hexutil.Decode("0xabcdef1234567890abcdef1234567890abcdef12") + require.NoError(t, err) + destToken1Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000005678") + require.NoError(t, err) + var destToken1 [32]byte + copy(destToken1[:], destToken1Bytes) + extraData1, err := hexutil.Decode("0x00112233") + require.NoError(t, err) + token1 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool1, + DestTokenAddress: destToken1, + DestGasAmount: 10000, + ExtraData: extraData1, + Amount: big.NewInt(1000000), + } + srcPool2, err := hexutil.Decode("0x123456789abcdef123456789abcdef123456789a") + require.NoError(t, err) + destToken2Bytes, err := hexutil.Decode("0x0000000000000000000000000000000000000000000000000000000000009abc") + require.NoError(t, err) + var destToken2 [32]byte + copy(destToken2[:], destToken2Bytes) + extraData2, err := hexutil.Decode("0xffeeddcc") + require.NoError(t, err) + token2 := any2AptosTokenTransfer{ + SourcePoolAddress: srcPool2, + DestTokenAddress: destToken2, + DestGasAmount: 20000, + ExtraData: extraData2, + Amount: big.NewInt(5000000), + } + + tokens := []any2AptosTokenTransfer{token1, token2} + + computedHash, err := computeMessageDataHash(metadataHash, messageID, receiver, sequenceNumber, gasLimit, nonce, sender, data, tokens) + require.NoError(t, err) + + require.Equal(t, expectedHashStr, hexutil.Encode(computedHash[:]), "Computed hash does not match expected hash") +} + +// the equivalent test with the same values exists in the Aptos offramp.move contract, see test_calculate_metadata_hash +func TestComputeMetadataHash(t *testing.T) { + expectedHashStr := "0x812acb01df318f85be452cf6664891cf5481a69dac01e0df67102a295218dd17" + expectedHashAlternateStr := "0x6caf8756ae02ee4f12b83b38e0f21b5e43e90d203bd06729486fd4a0fc8bcc5e" + + sourceChainSelector := uint64(123456789) + destinationChainSelector := uint64(987654321) + onRamp := []byte("source-onramp-address") + + metadataHash, err := computeMetadataHash(sourceChainSelector, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashStr, hexutil.Encode(metadataHash[:]), "Computed hash does not match expected hash") + + metadataHashAlternate, err := computeMetadataHash(sourceChainSelector+1, destinationChainSelector, onRamp) + require.NoError(t, err) + require.Equal(t, expectedHashAlternateStr, hexutil.Encode(metadataHashAlternate[:]), "Alternate computed hash does not match expected alternate hash") +} diff --git a/core/capabilities/ccip/ccipaptos/rmncrypto.go b/core/capabilities/ccip/ccipaptos/rmncrypto.go new file mode 100644 index 00000000000..986ebe90f36 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/rmncrypto.go @@ -0,0 +1,20 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +// AptosRMNCrypto is the RMNCrypto implementation for Aptos chains. +type AptosRMNCrypto struct{} + +func (r *AptosRMNCrypto) VerifyReportSignatures( + _ context.Context, + _ []cciptypes.RMNECDSASignature, + _ cciptypes.RMNReport, + _ []cciptypes.UnknownAddress, +) error { + return errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/tokendata.go b/core/capabilities/ccip/ccipaptos/tokendata.go new file mode 100644 index 00000000000..4f18399c5f6 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/tokendata.go @@ -0,0 +1,18 @@ +package ccipaptos + +import ( + "context" + "errors" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" +) + +type AptosTokenDataEncoder struct{} + +func NewAptosTokenDataEncoder() AptosTokenDataEncoder { + return AptosTokenDataEncoder{} +} + +func (e AptosTokenDataEncoder) EncodeUSDC(_ context.Context, message cciptypes.Bytes, attestation cciptypes.Bytes) (cciptypes.Bytes, error) { + return nil, errors.New("not implemented") +} diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go new file mode 100644 index 00000000000..5488f3903d2 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -0,0 +1,23 @@ +package ccipaptos + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/smartcontractkit/chainlink-integrations/evm/utils" +) + +func abiEncodeUint32(data uint32) ([]byte, error) { + return utils.ABIEncode(`[{ "type": "uint32" }]`, data) +} + +func abiDecodeUint32(data []byte) (uint32, error) { + raw, err := utils.ABIDecode(`[{ "type": "uint32" }]`, data) + if err != nil { + return 0, fmt.Errorf("abi decode uint32: %w", err) + } + + val := *abi.ConvertType(raw[0], new(uint32)).(*uint32) + return val, nil +} From bb425695f58f913b90fa4caa871e2c05c4c0bf21 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 06:49:14 +0400 Subject: [PATCH 101/136] core/capabilities/ccip/common/addresscodec.go: add aptos address codec --- .../ccip/ccipaptos/addresscodec.go | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/addresscodec.go b/core/capabilities/ccip/ccipaptos/addresscodec.go index 73ee4bb79c0..6297b220279 100644 --- a/core/capabilities/ccip/ccipaptos/addresscodec.go +++ b/core/capabilities/ccip/ccipaptos/addresscodec.go @@ -1,9 +1,9 @@ package ccipaptos import ( + "encoding/hex" "fmt" - - "github.com/aptos-labs/aptos-go-sdk" + "strings" ) type AddressCodec struct{} @@ -17,30 +17,30 @@ func (a AddressCodec) AddressStringToBytes(addr string) ([]byte, error) { } func addressBytesToString(addr []byte) (string, error) { - if len(addr) != 32 { - return "", fmt.Errorf("invalid Aptos address length, expected 32, got %d", len(addr)) + if len(addr) < 1 || len(addr) > 32 { + return "", fmt.Errorf("invalid Aptos address length (%d)", len(addr)) } - accAddress := aptos.AccountAddress(addr) - return accAddress.String(), nil + return fmt.Sprintf("0x%064x", addr), nil } func addressStringToBytes(addr string) ([]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) - if err != nil { - return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + a := strings.TrimPrefix(addr, "0x") + if len(a) == 0 { + return nil, fmt.Errorf("invalid Aptos address length, expected at least 1 character: %s", addr) + } + if len(a) > 64 { + return nil, fmt.Errorf("invalid Aptos address length, expected at most 64 characters: %s", addr) + } + for len(a) < 64 { + a = "0" + a } - return accAddress[:], nil -} -func addressStringToBytes32(addr string) ([32]byte, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) + bytes, err := hex.DecodeString(a) if err != nil { - return accAddress, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return nil, fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) } - return accAddress, nil + return bytes, nil } func addressBytesToBytes32(addr []byte) ([32]byte, error) { @@ -53,14 +53,12 @@ func addressBytesToBytes32(addr []byte) ([32]byte, error) { return result, nil } -// takes a valid Aptos address string and converts it into canonical format. -func addressStringToString(addr string) (string, error) { - var accAddress aptos.AccountAddress - err := accAddress.ParseStringRelaxed(addr) +func addressStringToBytes32(addr string) ([32]byte, error) { + bytes, err := addressStringToBytes(addr) if err != nil { - return "", fmt.Errorf("failed to decode Aptos address '%s': %w", addr, err) + return [32]byte{}, err } - return accAddress.String(), nil + return addressBytesToBytes32(bytes) } func addressIsValid(addr string) bool { From d4ef87982939faa3be26edc8f43be317d4b52e5d Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:48:54 +0400 Subject: [PATCH 102/136] core/capabilities/ccip/oraclecreator/plugin.go: initialize extra data codec with Aptos decoder --- .../ccip/ccipaptos/pluginconfig.go | 21 +++++++++++++++++++ .../capabilities/ccip/oraclecreator/plugin.go | 1 + 2 files changed, 22 insertions(+) create mode 100644 core/capabilities/ccip/ccipaptos/pluginconfig.go diff --git a/core/capabilities/ccip/ccipaptos/pluginconfig.go b/core/capabilities/ccip/ccipaptos/pluginconfig.go new file mode 100644 index 00000000000..937fa3f3b3e --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/pluginconfig.go @@ -0,0 +1,21 @@ +package ccipaptos + +import ( + chainsel "github.com/smartcontractkit/chain-selectors" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// InitializePluginConfig returns a PluginConfig for EVM chains. +func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { + return ccipcommon.PluginConfig{ + CommitPluginCodec: NewCommitPluginCodecV1(), + ExecutePluginCodec: NewExecutePluginCodecV1(extraDataCodec), + MessageHasher: NewMessageHasherV1(lggr.Named(chainsel.FamilyAptos).Named("MessageHasherV1"), extraDataCodec), + TokenDataEncoder: NewAptosTokenDataEncoder(), + GasEstimateProvider: NewGasEstimateProvider(), + RMNCrypto: nil, + ContractTransmitterFactory: ocrimpls.NewAptosContractTransmitterFactory(extraDataCodec), + } +} diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 614e6b1bffd..847a0c697e1 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -27,6 +27,7 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pluginconfig" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" + _ "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" // Register Aptos plugin config factories _ "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" // Register EVM plugin config factories _ "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" // Register Solana plugin config factories "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" From c891f0ea42806880f46e8df5e44323bfbbe12f36 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 26 Feb 2025 14:49:11 +0400 Subject: [PATCH 103/136] core/capabilities/ccip/ccipevm/msghasher_test.go: initialize extra data codec with Aptos decoder --- core/capabilities/ccip/ccipevm/msghasher_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go index 77d4b726d2a..1c13ff0a71d 100644 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ b/core/capabilities/ccip/ccipevm/msghasher_test.go @@ -29,6 +29,7 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/assets" evmtestutils "github.com/smartcontractkit/chainlink-evm/pkg/testutils" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -36,6 +37,7 @@ import ( ) var extraDataCodec = ccipcommon.ExtraDataCodec(map[string]ccipcommon.SourceChainExtraDataCodec{ + chainsel.FamilyAptos: ccipaptos.ExtraDataDecoder{}, chainsel.FamilyEVM: ExtraDataDecoder{}, chainsel.FamilySolana: ccipsolana.ExtraDataDecoder{}, }) From 97e5dd300b1e52d76d33fd52db04eb9a840fc1e8 Mon Sep 17 00:00:00 2001 From: cfal Date: Thu, 27 Feb 2025 15:03:30 +0400 Subject: [PATCH 104/136] .changeset/warm-toys-give.md: add changeset --- .changeset/warm-toys-give.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/warm-toys-give.md diff --git a/.changeset/warm-toys-give.md b/.changeset/warm-toys-give.md new file mode 100644 index 00000000000..32417a44c80 --- /dev/null +++ b/.changeset/warm-toys-give.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +add support for Aptos CCIP #added + From a0e5dd0fb62ff0af178ab0742091d2894880cbe2 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 16 Apr 2025 01:24:00 +0400 Subject: [PATCH 105/136] core/capabilities/ccip/ccipaptos: update for contract changes, dont depend on generated bindings --- .../ccip/ccipaptos/commitcodec.go | 38 +++- .../ccip/ccipaptos/executecodec_test.go | 39 ++-- .../ccip/ccipaptos/extradatadecoder.go | 181 +++++++++++------- .../ccip/ccipaptos/extradatadecoder_test.go | 106 +++++++--- 4 files changed, 243 insertions(+), 121 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec.go b/core/capabilities/ccip/ccipaptos/commitcodec.go index 0fc28059a38..8dbd9f4550e 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec.go @@ -3,6 +3,7 @@ package ccipaptos import ( "context" "fmt" + "math/big" "github.com/aptos-labs/aptos-go-sdk" "github.com/aptos-labs/aptos-go-sdk/bcs" @@ -14,6 +15,8 @@ import ( // Compatible with ccip::offramp version 1.6.0 type CommitPluginCodecV1 struct{} +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) + func NewCommitPluginCodecV1() *CommitPluginCodecV1 { return &CommitPluginCodecV1{} } @@ -28,14 +31,22 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi return } s.Struct(&sourceToken) - s.U256(*item.Price.Int) + if item.Price.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.Price.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize TokenPriceUpdates: %w", s.Error()) } bcs.SerializeSequenceWithFunction(report.PriceUpdates.GasPriceUpdates, s, func(s *bcs.Serializer, item cciptypes.GasPriceChain) { s.U64(uint64(item.ChainSel)) - s.U256(*item.GasPrice.Int) + if item.GasPrice.IsEmpty() { + s.U256(*big.NewInt(0)) + } else { + s.U256(*item.GasPrice.Int) + } }) if s.Error() != nil { return nil, fmt.Errorf("failed to serialize GasPriceUpdates: %w", s.Error()) @@ -86,7 +97,19 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.Price = cciptypes.NewBigInt(&price) + + // we need this clause because the zero token price test fails otherwise: + // - abs: (big.nat) + // + abs: (big.nat) { + // + } + // the reason is because big.NewInt(0) ends up not setting the `abs` field at all, while big.NewInt().SetBytes(..) will + // set the `abs` value to 0. + // ref: https://cs.opensource.google/go/go/+/master:src/math/big/int.go;drc=432fd9c60fac4485d0473173171206f1ef558829;l=85 + if price.Sign() == 0 { + item.Price = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.Price = cciptypes.NewBigInt(&price) + } }) if des.Error() != nil { @@ -102,7 +125,11 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype if des.Error() != nil { return } - item.GasPrice = cciptypes.NewBigInt(&gasPrice) + if gasPrice.Sign() == 0 { + item.GasPrice = cciptypes.NewBigInt(big.NewInt(0)) + } else { + item.GasPrice = cciptypes.NewBigInt(&gasPrice) + } }) if des.Error() != nil { return cciptypes.CommitPluginReport{}, fmt.Errorf("failed to deserialize GasPriceUpdates: %w", des.Error()) @@ -163,6 +190,3 @@ func (c *CommitPluginCodecV1) Decode(ctx context.Context, data []byte) (cciptype return report, nil } - -// Ensure CommitPluginCodec implements the CommitPluginCodec interface -var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index f4500ef679a..0bd3b19d4bf 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -12,7 +12,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-integrations/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -30,7 +29,8 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) for z := 0; z < numTokensPerMsg; z++ { - encodedDestExecData, err2 := abiEncodeUint32(destGasAmount) + // Use the predefined ABI arguments to pack destGasAmount + encodedDestExecData, err2 := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err2) tokenAmounts[z] = cciptypes.RampTokenAmount{ @@ -42,13 +42,12 @@ var randomExecuteReport = func(t *testing.T, chainSelector uint64, gasLimit *big } } - extraArgs, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - if err != nil { - t.Fatalf("failed to pack extra args: %v", err) - } - extraArgs = append(evmExtraArgsV1Tag, extraArgs[4:]...) + // Use the predefined ABI arguments to pack EVM V1 fields + encodedExtraArgsFields, err := evmExtraArgsV1Fields.Pack(gasLimit) + require.NoError(t, err, "failed to pack extra args fields") + + // Prepend the tag + extraArgs := append(evmExtraArgsV1Tag, encodedExtraArgsFields...) reportMessages[j] = cciptypes.Message{ Header: cciptypes.RampMessageHeader{ @@ -92,12 +91,15 @@ func TestExecutePluginCodecV1(t *testing.T) { mockExtraDataCodec := &mocks.ExtraDataCodec{} destGasAmount := rand.Uint32() gasLimit := utils.RandUint256() + + // Update mock return values to use the correct keys expected by the codec + // The codec uses the ExtraDataDecoder internally, which returns maps like these. mockExtraDataCodec.On("DecodeTokenAmountDestExecData", mock.Anything, mock.Anything).Return(map[string]any{ - "destgasamount": destGasAmount, + aptosDestExecDataKey: destGasAmount, // Use the constant defined in the decoder }, nil) mockExtraDataCodec.On("DecodeExtraArgs", mock.Anything, mock.Anything).Return(map[string]any{ - "gasLimit": utils.RandUint256(), - "accountIsWritableBitmap": gasLimit, + "gasLimit": gasLimit, // Match the key used in the decoder for EVM V1/V2 gasLimit + // "allowOutOfOrderExecution": false, // Optionally mock other fields if needed by codec logic }, nil) testCases := []struct { @@ -109,7 +111,7 @@ func TestExecutePluginCodecV1(t *testing.T) { gasLimit *big.Int }{ { - name: "base report", + name: "base report EVM chain", report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 5009297550715157269, // ETH mainnet chain selector @@ -117,7 +119,7 @@ func TestExecutePluginCodecV1(t *testing.T) { destGasAmount: destGasAmount, }, { - name: "base report", + name: "base report non-EVM chain", // Name updated for clarity report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, expErr: false, chainSelector: 124615329519749607, // Solana mainnet chain selector @@ -131,7 +133,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -142,7 +144,7 @@ func TestExecutePluginCodecV1(t *testing.T) { return report }, expErr: true, - chainSelector: 5009297550715157269, // ETH mainnet chain selector + chainSelector: 5009297550715157269, gasLimit: gasLimit, destGasAmount: destGasAmount, }, @@ -151,6 +153,7 @@ func TestExecutePluginCodecV1(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { codec := NewExecutePluginCodecV1(mockExtraDataCodec) + // randomExecuteReport now uses the new encoding internally report := tc.report(randomExecuteReport(t, tc.chainSelector, tc.gasLimit, tc.destGasAmount)) bytes, err := codec.Encode(ctx, report) if tc.expErr { @@ -159,7 +162,7 @@ func TestExecutePluginCodecV1(t *testing.T) { } require.NoError(t, err) - // ignore unavailable fields in comparison + // ignore unavailable fields in comparison - This part remains the same for i := range report.ChainReports { for j := range report.ChainReports[i].Messages { report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} @@ -173,7 +176,7 @@ func TestExecutePluginCodecV1(t *testing.T) { // decode using the codec codecDecoded, err := codec.Decode(ctx, bytes) require.NoError(t, err) - require.Equal(t, report, codecDecoded) + require.Equal(t, report, codecDecoded) // Comparison should still work }) } } diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go index 5c600f266bd..2f59d9bed17 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -2,28 +2,25 @@ package ccipaptos import ( "fmt" - "reflect" + "math/big" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) // ExtraDataDecoder is a concrete implementation of ccipcommon.ExtraDataDecoder // Compatible with ccip::fee_quoter version 1.6.0 type ExtraDataDecoder struct{} +var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) + const ( aptosDestExecDataKey = "destGasAmount" ) -var aptosUtilsABI = abihelpers.MustParseABI(ccip_aptos_utils.AptosUtilsABI) - var ( // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") @@ -33,18 +30,71 @@ var ( // bytes4 public constant SVM_EXTRA_EXTRA_ARGS_V1_TAG = 0x1f3b3aba svmExtraArgsV1Tag = hexutil.MustDecode("0x1f3b3aba") + + uint32Type = mustNewType("uint32") + uint64Type = mustNewType("uint64") + uint256Type = mustNewType("uint256") + boolType = mustNewType("bool") + bytes32Type = mustNewType("bytes32") + bytes32ArrType = mustNewType("bytes32[]") + + // Arguments for decoding destGasAmount + destGasAmountArguments = abi.Arguments{ + {Name: aptosDestExecDataKey, Type: uint32Type}, + } + + // Arguments matching the fields of EVMExtraArgsV1 struct + evmExtraArgsV1Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + } + + // Arguments matching the fields of GenericExtraArgsV2 struct + genericExtraArgsV2Fields = abi.Arguments{ + {Name: "gasLimit", Type: uint256Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + } + + // Arguments matching the fields of SVMExtraArgsV1 struct + svmExtraArgsV1Fields = abi.Arguments{ + {Name: "computeUnits", Type: uint32Type}, + {Name: "accountIsWritableBitmap", Type: uint64Type}, + {Name: "allowOutOfOrderExecution", Type: boolType}, + {Name: "tokenReceiver", Type: bytes32Type}, + {Name: "accounts", Type: bytes32ArrType}, + } ) +func mustNewType(typeStr string) abi.Type { + t, err := abi.NewType(typeStr, "", nil) + if err != nil { + panic(fmt.Sprintf("failed to create ABI type %s: %v", typeStr, err)) + } + return t +} + // DecodeDestExecDataToMap reformats bytes into a chain agnostic map[string]interface{} representation for dest exec data func (d ExtraDataDecoder) DecodeDestExecDataToMap(destExecData cciptypes.Bytes) (map[string]any, error) { - destGasAmount, err := abiDecodeUint32(destExecData) + args := make(map[string]any) + err := destGasAmountArguments.UnpackIntoMap(args, destExecData) if err != nil { + if len(destExecData) != 32 { + return nil, fmt.Errorf("decode dest gas amount: expected 32 bytes for uint32, got %d: %w", len(destExecData), err) + } + + var val big.Int + val.SetBytes(destExecData) + if val.Cmp(big.NewInt(0xFFFFFFFF)) > 0 { + return nil, fmt.Errorf("decode dest gas amount: value %s exceeds uint32 max: %w", val.String(), err) + } + return nil, fmt.Errorf("decode dest gas amount: %w", err) } - return map[string]any{ - aptosDestExecDataKey: destGasAmount, - }, nil + if _, ok := args[aptosDestExecDataKey]; !ok { + return nil, fmt.Errorf("failed to unpack key '%s' for dest gas amount", aptosDestExecDataKey) + } + + return args, nil } // DecodeExtraArgsToMap reformats bytes into a chain agnostic map[string]any representation for extra args @@ -53,98 +103,99 @@ func (d ExtraDataDecoder) DecodeExtraArgsToMap(extraArgs cciptypes.Bytes) (map[s return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) } - var method string - var argName string - switch string(extraArgs[:4]) { + var decoderArgs abi.Arguments + tag := string(extraArgs[:4]) + argsData := extraArgs[4:] + + switch tag { case string(evmExtraArgsV1Tag): - method = "exposeEVMExtraArgsV1" - argName = "evmExtraArgsV1" + decoderArgs = evmExtraArgsV1Fields case string(genericExtraArgsV2Tag): - method = "exposeGenericExtraArgsV2" - argName = "evmExtraArgsV2" + decoderArgs = genericExtraArgsV2Fields case string(svmExtraArgsV1Tag): - method = "exposeSVMExtraArgsV1" - argName = "svmExtraArgsV1" + decoderArgs = svmExtraArgsV1Fields default: - return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) + return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs[:4]) } - output := make(map[string]any) - args := make(map[string]any) - err := aptosUtilsABI.Methods[method].Inputs.UnpackIntoMap(args, extraArgs[4:]) + unpackedArgs := make(map[string]any) + err := decoderArgs.UnpackIntoMap(unpackedArgs, argsData) if err != nil { - return nil, fmt.Errorf("abi decode extra args %v: %w", method, err) + return nil, fmt.Errorf("abi decode extra args (tag %x): %w", extraArgs[:4], err) } - argValue, exists := args[argName] - if !exists { - return nil, fmt.Errorf("failed to get arg value for %s", argName) - } - - val := reflect.ValueOf(argValue) - if val.Kind() != reflect.Struct { - return nil, fmt.Errorf("expected struct for %s, got %T", argName, argValue) - } + output := make(map[string]any) - switch argName { - case "evmExtraArgsV1": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + switch tag { + case string(evmExtraArgsV1Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in EVMExtraArgsV1: %T", unpackedArgs["gasLimit"]) } else { - output["gasLimit"] = nil + output["gasLimit"] = nil // Field not present or nil } - case "evmExtraArgsV2": - gasLimitField := val.FieldByName("GasLimit") - if gasLimitField.IsValid() { - output["gasLimit"] = gasLimitField.Interface() + + case string(genericExtraArgsV2Tag): + if gasLimit, ok := unpackedArgs["gasLimit"].(*big.Int); ok { + output["gasLimit"] = gasLimit + } else if unpackedArgs["gasLimit"] != nil { + return nil, fmt.Errorf("unexpected type for gasLimit in GenericExtraArgsV2: %T", unpackedArgs["gasLimit"]) } else { output["gasLimit"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in GenericExtraArgsV2: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { + // Default to false if not present, consistent with original code. + // Note: ABI decoding of bool usually doesn't result in nil, but checking doesn't hurt. output["allowOutOfOrderExecution"] = false } - case "svmExtraArgsV1": - computeUnitsField := val.FieldByName("ComputeUnits") - if computeUnitsField.IsValid() { - output["computeUnits"] = computeUnitsField.Interface() + + case string(svmExtraArgsV1Tag): + if computeUnits, ok := unpackedArgs["computeUnits"].(uint32); ok { + output["computeUnits"] = computeUnits + } else if unpackedArgs["computeUnits"] != nil { + return nil, fmt.Errorf("unexpected type for computeUnits in SVMExtraArgsV1: %T", unpackedArgs["computeUnits"]) } else { output["computeUnits"] = nil } - bitmapField := val.FieldByName("AccountIsWritableBitmap") - if bitmapField.IsValid() { - output["accountIsWritableBitmap"] = bitmapField.Interface() + if bitmap, ok := unpackedArgs["accountIsWritableBitmap"].(uint64); ok { + output["accountIsWritableBitmap"] = bitmap + } else if unpackedArgs["accountIsWritableBitmap"] != nil { + return nil, fmt.Errorf("unexpected type for accountIsWritableBitmap in SVMExtraArgsV1: %T", unpackedArgs["accountIsWritableBitmap"]) } else { output["accountIsWritableBitmap"] = nil } - allowOutOfOrderField := val.FieldByName("AllowOutOfOrderExecution") - if allowOutOfOrderField.IsValid() { - output["allowOutOfOrderExecution"] = allowOutOfOrderField.Interface() + if allow, ok := unpackedArgs["allowOutOfOrderExecution"].(bool); ok { + output["allowOutOfOrderExecution"] = allow + } else if unpackedArgs["allowOutOfOrderExecution"] != nil { + return nil, fmt.Errorf("unexpected type for allowOutOfOrderExecution in SVMExtraArgsV1: %T", unpackedArgs["allowOutOfOrderExecution"]) } else { output["allowOutOfOrderExecution"] = false } - tokenReceiverField := val.FieldByName("TokenReceiver") - if tokenReceiverField.IsValid() { - output["tokenReceiver"] = tokenReceiverField.Interface() + if tokenReceiver, ok := unpackedArgs["tokenReceiver"].([32]byte); ok { + output["tokenReceiver"] = tokenReceiver + } else if unpackedArgs["tokenReceiver"] != nil { + return nil, fmt.Errorf("unexpected type for tokenReceiver in SVMExtraArgsV1: %T", unpackedArgs["tokenReceiver"]) } else { output["tokenReceiver"] = nil } - accountsField := val.FieldByName("Accounts") - if accountsField.IsValid() { - output["accounts"] = accountsField.Interface() + if accounts, ok := unpackedArgs["accounts"].([][32]byte); ok { + output["accounts"] = accounts + } else if unpackedArgs["accounts"] != nil { + return nil, fmt.Errorf("unexpected type for accounts in SVMExtraArgsV1: %T", unpackedArgs["accounts"]) } else { output["accounts"] = nil } } + return output, nil } - -var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go index 234d2f29981..d8188010362 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder_test.go @@ -5,10 +5,9 @@ import ( "math/rand" "testing" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/v1_6_0/ccip_aptos_utils" ) func Test_decodeExtraData(t *testing.T) { @@ -16,40 +15,38 @@ func Test_decodeExtraData(t *testing.T) { extraDataDecoder := &ExtraDataDecoder{} t.Run("decode extra args into map evm v1", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeEVMExtraArgsV1", ccip_aptos_utils.AptosUtilsEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - encoded = append(evmExtraArgsV1Tag, encoded[4:]...) + encodedFields, err := evmExtraArgsV1Fields.Pack(gasLimit) require.NoError(t, err) + encoded := append(evmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp for big.Int comparison }) t.Run("decode extra args into map evm v2", func(t *testing.T) { - encoded, err := aptosUtilsABI.Pack("exposeGenericExtraArgsV2", ccip_aptos_utils.AptosUtilsGenericExtraArgsV2{ - GasLimit: gasLimit, - AllowOutOfOrderExecution: true, - }) - encoded = append(genericExtraArgsV2Tag, encoded[4:]...) + allowOoe := true + encodedFields, err := genericExtraArgsV2Fields.Pack(gasLimit, allowOoe) require.NoError(t, err) + encoded := append(genericExtraArgsV2Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 2) gl, exist := m["gasLimit"] require.True(t, exist) - require.Equal(t, gl, gasLimit) + require.Equal(t, 0, gl.(*big.Int).Cmp(gasLimit), "Expected %s, got %s", gasLimit.String(), gl.(*big.Int).String()) // Use Cmp - ooe, exist := m["allowOutOfOrderExecution"] + ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, true, ooe) + require.Equal(t, allowOoe, ooeDecoded) // Check boolean directly }) t.Run("decode extra args into map svm", func(t *testing.T) { @@ -59,52 +56,99 @@ func Test_decodeExtraData(t *testing.T) { bitmap := uint64(4) ooe := false tokenReceiver := [32]byte(key.PublicKey().Bytes()) - accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} - encoded, err := aptosUtilsABI.Pack("exposeSVMExtraArgsV1", ccip_aptos_utils.AptosUtilsSVMExtraArgsV1{ - ComputeUnits: cu, - AccountIsWritableBitmap: bitmap, - AllowOutOfOrderExecution: ooe, - TokenReceiver: tokenReceiver, - Accounts: accounts, - }) - encoded = append(svmExtraArgsV1Tag, encoded[4:]...) + accounts := [][32]byte{[32]byte(key.PublicKey().Bytes())} // Example with one account + + encodedFields, err := svmExtraArgsV1Fields.Pack( + cu, + bitmap, + ooe, + tokenReceiver, + accounts, + ) require.NoError(t, err) + encoded := append(svmExtraArgsV1Tag, encodedFields...) + m, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) require.NoError(t, err) require.Len(t, m, 5) cuDecoded, exist := m["computeUnits"] require.True(t, exist) - require.Equal(t, cuDecoded, cu) + require.Equal(t, cu, cuDecoded) bitmapDecoded, exist := m["accountIsWritableBitmap"] require.True(t, exist) - require.Equal(t, bitmapDecoded, bitmap) + require.Equal(t, bitmap, bitmapDecoded) ooeDecoded, exist := m["allowOutOfOrderExecution"] require.True(t, exist) - require.Equal(t, ooeDecoded, ooe) + require.Equal(t, ooe, ooeDecoded) tokenReceiverDecoded, exist := m["tokenReceiver"] require.True(t, exist) - require.Equal(t, tokenReceiverDecoded, tokenReceiver) + require.Equal(t, tokenReceiver, tokenReceiverDecoded.([32]byte)) accountsDecoded, exist := m["accounts"] require.True(t, exist) - require.Equal(t, accountsDecoded, accounts) + require.Equal(t, accounts, accountsDecoded.([][32]byte)) }) t.Run("decode dest exec data into map", func(t *testing.T) { destGasAmount := uint32(10000) - encoded, err := abiEncodeUint32(destGasAmount) + encoded, err := destGasAmountArguments.Pack(destGasAmount) require.NoError(t, err) + m, err := extraDataDecoder.DecodeDestExecDataToMap(encoded) require.NoError(t, err) require.Len(t, m, 1) decoded, exist := m[aptosDestExecDataKey] require.True(t, exist) - require.Equal(t, destGasAmount, decoded) + require.Equal(t, destGasAmount, decoded.(uint32)) // Type assert and compare uint32 + }) + + t.Run("error on short extra args", func(t *testing.T) { + shortData := evmExtraArgsV1Tag[:2] // Less than 4 bytes + _, err := extraDataDecoder.DecodeExtraArgsToMap(shortData) + require.Error(t, err) + require.Contains(t, err.Error(), "extra args too short") + }) + + t.Run("error on unknown tag", func(t *testing.T) { + unknownTag := []byte{0xde, 0xad, 0xbe, 0xef} + dummyData, err := evmExtraArgsV1Fields.Pack(big.NewInt(1)) + require.NoError(t, err) + dataWithUnknownTag := append(unknownTag, dummyData...) + _, err = extraDataDecoder.DecodeExtraArgsToMap(dataWithUnknownTag) + require.Error(t, err) + require.Contains(t, err.Error(), "unknown extra args tag") + }) + + t.Run("error on malformed evm v1 data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint256 + encoded := append(evmExtraArgsV1Tag, malformedData...) + _, err := extraDataDecoder.DecodeExtraArgsToMap(encoded) + require.Error(t, err) + require.Contains(t, err.Error(), "abi decode extra args") + }) + + t.Run("error on malformed dest exec data", func(t *testing.T) { + malformedData := []byte{0x01, 0x02, 0x03} // Too short for uint32 (expects 32 bytes) + _, err := extraDataDecoder.DecodeDestExecDataToMap(malformedData) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "expected 32 bytes for uint32") + }) + + t.Run("error on dest exec data exceeding uint32 max", func(t *testing.T) { + tooLargeValue := new(big.Int).Lsh(big.NewInt(1), 32) + encodedTooLarge, err := abi.Arguments{{Type: uint256Type}}.Pack(tooLargeValue) // Pack as uint256 + require.NoError(t, err) + + _, err = extraDataDecoder.DecodeDestExecDataToMap(encodedTooLarge) + require.Error(t, err) + require.Contains(t, err.Error(), "decode dest gas amount") + require.Contains(t, err.Error(), "exceeds uint32 max") }) } From 9525feb7f32284f163e08e132359f22476d58d0c Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:19:21 +0400 Subject: [PATCH 106/136] core/capabilities/ccip/configs/aptos: add ccip CW/CR configs --- .../ccip/configs/aptos/chain_writer.go | 70 ++++++ .../ccip/configs/aptos/contract_reader.go | 231 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 core/capabilities/ccip/configs/aptos/chain_writer.go create mode 100644 core/capabilities/ccip/configs/aptos/contract_reader.go diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go new file mode 100644 index 00000000000..061672baac9 --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -0,0 +1,70 @@ +package aptosconfig + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-aptos/relayer/chainwriter" + "github.com/smartcontractkit/chainlink-aptos/relayer/utils" +) + +func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, error) { + fromAddress, err := utils.HexPublicKeyToAddress(publicKeyStr) + if err != nil { + return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) + } + + fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) + + return chainwriter.ChainWriterConfig{ + Modules: map[string]*chainwriter.ChainWriterModule{ + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainwriter.ChainWriterFunction{ + consts.MethodCommit: { + Name: "commit", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + { + Name: "Signatures", + Type: "vector>", + Required: true, + }, + }, + }, + consts.MethodExecute: { + Name: "execute", + PublicKey: publicKeyStr, + FromAddress: fromAddress.String(), + Params: []chainreader.AptosFunctionParam{ + { + Name: "ReportContext", + Type: "vector>", + Required: true, + }, + { + Name: "Report", + Type: "vector", + Required: true, + }, + }, + }, + }, + }, + }, + FeeStrategy: chainwriter.DefaultFeeStrategy, + }, nil +} diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go new file mode 100644 index 00000000000..016d593239d --- /dev/null +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -0,0 +1,231 @@ +package aptosconfig + +import ( + "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" +) + +func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { + return chainreader.ChainReaderConfig{ + IsLoopPlugin: true, + Modules: map[string]*chainreader.ChainReaderModule{ + // TODO: more offramp config and other modules + consts.ContractNameRMNRemote: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetReportDigestHeader: { + Name: "get_report_digest_header", + }, + consts.MethodNameGetVersionedConfig: { + Name: "get_versioned_config", + // ref: https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L1440 + ResultTupleToStruct: []string{"version", "config"}, + }, + consts.MethodNameGetCursedSubjects: { + Name: "get_cursed_subjects", + }, + }, + }, + + consts.ContractNameRMNProxy: { + Name: "rmn_remote", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetARM: { + Name: "get_arm", + }, + }, + }, + + consts.ContractNameFeeQuoter: { + Name: "fee_quoter", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameFeeQuoterGetTokenPrice: { + Name: "get_token_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "token", + Type: "address", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetTokenPrices: { + Name: "get_token_prices", + Params: []chainreader.AptosFunctionParam{ + { + Name: "tokens", + Type: "vector
", + Required: true, + }, + }, + }, + consts.MethodNameFeeQuoterGetStaticConfig: { + Name: "get_static_config", + }, + }, + }, + consts.ContractNameOffRamp: { + Name: "offramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameGetExecutionState: { + Name: "get_execution_state", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + { + Name: "sequenceNumber", + Type: "u64", + Required: true, + }, + }, + }, + consts.MethodNameGetMerkleRoot: { + Name: "get_merkle_root", + Params: []chainreader.AptosFunctionParam{ + { + Name: "root", + Type: "vector", + Required: true, + }, + }, + }, + consts.MethodNameOffRampLatestConfigDetails: { + Name: "latest_config_details", + Params: []chainreader.AptosFunctionParam{ + { + Name: "ocrPluginType", + Type: "u8", + Required: true, + }, + }, + // wrap the returned OCR config + // https://github.com/smartcontractkit/chainlink-ccip/blob/bee7c32c71cf0aec594c051fef328b4a7281a1fc/pkg/reader/ccip.go#L141 + ResultTupleToStruct: []string{"ocr_config"}, + }, + consts.MethodNameGetLatestPriceSequenceNumber: { + Name: "get_latest_price_sequence_number", + }, + consts.MethodNameOffRampGetStaticConfig: { + Name: "get_static_config", + // TODO: field renames + }, + consts.MethodNameOffRampGetDynamicConfig: { + Name: "get_dynamic_config", + // TODO: field renames + }, + consts.MethodNameGetSourceChainConfig: { + Name: "get_source_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "sourceChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameExecutionStateChanged: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "execution_state_changed_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageId", + }, + "message_hash": { + NewName: "MessageHash", + }, + "state": { + NewName: "State", + }, + }, + }, + consts.EventNameCommitReportAccepted: { + EventHandleStructName: "OffRampState", + EventHandleFieldName: "commit_report_accepted_events", + EventAccountAddress: "offramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "blessed_merkle_roots": { + NewName: "BlessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "unblessed_merkle_roots": { + NewName: "UnblessedMerkleRoots", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "on_ramp_address": { + NewName: "OnRampAddress", + }, + "min_seq_nr": { + NewName: "MinSeqNr", + }, + "max_seq_nr": { + NewName: "MaxSeqNr", + }, + "merkle_root": { + NewName: "MerkleRoot", + }, + }, + }, + "price_updates": { + NewName: "PriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "token_price_updates": { + NewName: "TokenPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_token": { + NewName: "SourceToken", + }, + "usd_per_token": { + NewName: "UsdPerToken", + }, + }, + }, + "gas_price_updates": { + NewName: "GasPriceUpdates", + SubFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "usd_per_unit_gas": { + NewName: "UsdPerUnitGas", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, nil +} From 9e2f502deb8e02891691fc07efec7babd45acf3f Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:21:50 +0400 Subject: [PATCH 107/136] core/services/keystore/keys/ocr2key/aptos_keyring.go: implement Sign3 and Verify3 --- .../keystore/keys/ocr2key/aptos_keyring.go | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/services/keystore/keys/ocr2key/aptos_keyring.go b/core/services/keystore/keys/ocr2key/aptos_keyring.go index 154f6ea3d2a..393ddd4eb5a 100644 --- a/core/services/keystore/keys/ocr2key/aptos_keyring.go +++ b/core/services/keystore/keys/ocr2key/aptos_keyring.go @@ -56,8 +56,24 @@ func (akr *aptosKeyring) Sign(reportCtx ocrtypes.ReportContext, report ocrtypes. return akr.SignBlob(sigData) } +func (ekr *aptosKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) ([]byte, error) { + rawReportContext := RawReportContext3(digest, seqNr) + h, err := blake2b.New256(nil) + if err != nil { + return nil, err + } + h.Write(r) + h.Write(rawReportContext[0][:]) + h.Write(rawReportContext[1][:]) + return h.Sum(nil), nil +} + func (akr *aptosKeyring) Sign3(digest types.ConfigDigest, seqNr uint64, r ocrtypes.Report) (signature []byte, err error) { - return nil, errors.New("not implemented") + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return nil, err + } + return akr.SignBlob(sigData) } func (akr *aptosKeyring) SignBlob(b []byte) ([]byte, error) { @@ -74,8 +90,12 @@ func (akr *aptosKeyring) Verify(publicKey ocrtypes.OnchainPublicKey, reportCtx o return akr.VerifyBlob(publicKey, hash, signature) } -func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { - return false +func (akr *aptosKeyring) Verify3(publicKey ocrtypes.OnchainPublicKey, digest ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool { + sigData, err := akr.reportToSigData3(digest, seqNr, r) + if err != nil { + return false + } + return akr.VerifyBlob(publicKey, sigData, signature) } func (akr *aptosKeyring) VerifyBlob(pubkey ocrtypes.OnchainPublicKey, b, sig []byte) bool { From 20c0b0a1999201220c71114176df6006236cbeef Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:30:05 +0400 Subject: [PATCH 108/136] core/capabilities/ccip/ocrimpls/config_tracker.go: dont use address codec for Aptos --- core/capabilities/ccip/ocrimpls/config_tracker.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/config_tracker.go b/core/capabilities/ccip/ocrimpls/config_tracker.go index 9619b0824cd..0500eb05a46 100644 --- a/core/capabilities/ccip/ocrimpls/config_tracker.go +++ b/core/capabilities/ccip/ocrimpls/config_tracker.go @@ -2,9 +2,11 @@ package ocrimpls import ( "context" + "encoding/hex" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -77,6 +79,13 @@ func toOnchainPublicKeys(signers [][]byte) []types.OnchainPublicKey { func toOCRAccounts(transmitters [][]byte, addressCodec ccipocr3.AddressCodec, chainSelector ccipocr3.ChainSelector) []types.Account { accounts := make([]types.Account, len(transmitters)) for i, transmitter := range transmitters { + family, _ := chainsel.GetSelectorFamily(uint64(chainSelector)) + // Aptos transmitter accounts do not go through the address codec, because they are ed25519 public keys. + if family == chainsel.FamilyAptos { + s := hex.EncodeToString(transmitter) + accounts[i] = types.Account(s) + continue + } address, _ := addressCodec.AddressBytesToString(transmitter, chainSelector) accounts[i] = types.Account(address) } From 5c189ad98f75e764ba868b971359dc3eac95ddf9 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:43:57 +0400 Subject: [PATCH 109/136] core/capabilities/ccip/ocrimpls/contract_transmitter.go: support ed25519 signatures --- .../ccip/ocrimpls/contract_transmitter.go | 79 +++++++++++++------ 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 8dda409f3f3..24e9de74e38 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -31,15 +31,22 @@ type ToCalldataFunc func( codec ccipcommon.ExtraDataCodec, ) (contract string, method string, args any, err error) +type ToEd25519CalldataFunc func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + codec ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) + var _ ocr3types.ContractTransmitter[[]byte] = &ccipTransmitter{} type ccipTransmitter struct { - cw commontypes.ContractWriter - fromAccount ocrtypes.Account - offrampAddress string - toCalldataFn ToCalldataFunc - extraDataCodec ccipcommon.ExtraDataCodec - lggr logger.Logger + cw commontypes.ContractWriter + fromAccount ocrtypes.Account + offrampAddress string + toCalldataFn ToCalldataFunc + toEd25519CalldataFn ToEd25519CalldataFunc + extraDataCodec ccipcommon.ExtraDataCodec } func XXXNewContractTransmitterTestsOnly( @@ -81,35 +88,57 @@ func (c *ccipTransmitter) Transmit( reportWithInfo ocr3types.ReportWithInfo[[]byte], sigs []ocrtypes.AttributedOnchainSignature, ) error { - var rs [][32]byte - var ss [][32]byte - var vs [32]byte if len(sigs) > 32 { return errors.New("too many signatures, maximum is 32") } - for i, as := range sigs { - r, s, v, err := evmutil.SplitSignature(as.Signature) - if err != nil { - return fmt.Errorf("failed to split signature: %w", err) - } - rs = append(rs, r) - ss = append(ss, s) - vs[i] = v - } // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) - if c.toCalldataFn == nil { - return errors.New("toCalldataFn is nil") - } + var contract string + var method string + var args any + var err error + + if c.toCalldataFn != nil { + var rs [][32]byte + var ss [][32]byte + var vs [32]byte + for i, as := range sigs { + r, s, v, err := evmutil.SplitSignature(as.Signature) + if err != nil { + return fmt.Errorf("failed to split signature: %w", err) + } + rs = append(rs, r) + ss = append(ss, s) + vs[i] = v + } - // chain writer takes in the raw calldata and packs it on its own. - contract, method, args, err := c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) - if err != nil { - return fmt.Errorf("failed to generate call data: %w", err) + // chain writer takes in the raw calldata and packs it on its own. + contract, method, args, err = c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ecdsa call data: %w", err) + } + } else if c.toEd25519CalldataFn != nil { + var signatures [][96]byte + for _, as := range sigs { + sig := as.Signature + if len(sig) != 96 { + return fmt.Errorf("invalid ed25519 signature length, expected 96, got %d", len(sig)) + } + var sigBytes [96]byte + copy(sigBytes[:], sig) + signatures = append(signatures, sigBytes) + } + + contract, method, args, err = c.toEd25519CalldataFn(rawReportCtx, reportWithInfo, signatures, c.extraDataCodec) + if err != nil { + return fmt.Errorf("failed to generate ed25519 call data: %w", err) + } + } else { + return errors.New("no calldata function") } // TODO: no meta fields yet, what should we add? From 4b42abbfbe8068fdee61400e35377d7ece6d8310 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:50:36 +0400 Subject: [PATCH 110/136] core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go: add --- .../aptos_contract_transmitter_factory.go | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go new file mode 100644 index 00000000000..f6c2e729263 --- /dev/null +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -0,0 +1,96 @@ +package ocrimpls + +import ( + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" +) + +// AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. +type AptosCommitCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` + Signatures [][96]byte `mapstructure:"Signatures"` +} + +// AptosExecCallArgs defines the calldata structure for an Aptos execute transaction. +type AptosExecCallArgs struct { + ReportContext [2][32]byte `mapstructure:"ReportContext"` + Report []byte `mapstructure:"Report"` +} + +// AptosContractTransmitterFactory implements the transmitter factory for Aptos chains. +type AptosContractTransmitterFactory struct{} + +// NewAptosCommitCalldataFunc returns a ToCalldataFunc for Aptos commits that omits any Info object. +func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { + return func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, + ) (string, string, any, error) { + return consts.ContractNameOffRamp, + commitMethod, + AptosCommitCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + Signatures: signatures, + }, + nil + } +} + +// NewCommitTransmitter constructs an Aptos commit transmitter. +func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, + commitMethod, _ string, // priceOnlyMethod is ignored for Aptos +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: NewAptosCommitCalldataFunc(commitMethod), + } +} + +// AptosExecCallDataFunc builds the execute call data for Aptos +var AptosExecCallDataFunc = func( + rawReportCtx [2][32]byte, + report ocr3types.ReportWithInfo[[]byte], + signatures [][96]byte, + _ ccipcommon.ExtraDataCodec, +) (contract string, method string, args any, err error) { + return consts.ContractNameOffRamp, + consts.MethodExecute, + AptosExecCallArgs{ + ReportContext: rawReportCtx, + Report: report.Report, + }, nil +} + +// NewExecTransmitter constructs an Aptos execute transmitter. +func (f *AptosContractTransmitterFactory) NewExecTransmitter( + cw types.ContractWriter, + fromAccount ocrtypes.Account, + offrampAddress string, +) ocr3types.ContractTransmitter[[]byte] { + return &ccipTransmitter{ + cw: cw, + fromAccount: fromAccount, + offrampAddress: offrampAddress, + toEd25519CalldataFn: AptosExecCallDataFunc, + extraDataCodec: ccipcommon.NewExtraDataCodec( + ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), + ), + } +} From e3749d2460879ee3e812bcb0d41744ff8a888b45 Mon Sep 17 00:00:00 2001 From: cfal Date: Fri, 18 Apr 2025 02:53:01 +0400 Subject: [PATCH 111/136] core/capabilities/ccip/oraclecreator/plugin.go: support Aptos --- .../capabilities/ccip/ccipaptos/crcwconfig.go | 56 +++++++++++++++++++ .../capabilities/ccip/oraclecreator/plugin.go | 5 ++ 2 files changed, 61 insertions(+) create mode 100644 core/capabilities/ccip/ccipaptos/crcwconfig.go diff --git a/core/capabilities/ccip/ccipaptos/crcwconfig.go b/core/capabilities/ccip/ccipaptos/crcwconfig.go new file mode 100644 index 00000000000..0548e4add39 --- /dev/null +++ b/core/capabilities/ccip/ccipaptos/crcwconfig.go @@ -0,0 +1,56 @@ +package ccipaptos + +import ( + "context" + "encoding/json" + "fmt" + + aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + aptosconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/aptos" +) + +// ChainCWProvider is a struct that implements the ChainRWProvider interface for EVM chains. +type ChainCWProvider struct{} + +// GetChainReader returns a new ContractReader for EVM chains. +func (g ChainCWProvider) GetChainReader(ctx context.Context, params ccipcommon.ChainReaderProviderOpts) (types.ContractReader, error) { + cfg, err := aptosconfig.GetChainReaderConfig() + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain reader config: %w", err) + } + marshaledConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain reader config: %w", err) + } + + cr, err := params.Relayer.NewContractReader(ctx, marshaledConfig) + if err != nil { + return nil, err + } + + cr = aptosloop.NewLoopChainReader(params.Lggr, cr) + + return cr, nil +} + +// GetChainWriter returns a new ContractWriter for EVM chains. +func (g ChainCWProvider) GetChainWriter(ctx context.Context, params ccipcommon.ChainWriterProviderOpts) (types.ContractWriter, error) { + transmitter := params.Transmitters[types.NewRelayID(params.ChainFamily, params.ChainID)] + cfg, err := aptosconfig.GetChainWriterConfig(transmitter[0]) + if err != nil { + return nil, fmt.Errorf("failed to get Aptos chain writer config: %w", err) + } + chainWriterConfig, err := json.Marshal(cfg) + if err != nil { + return nil, fmt.Errorf("failed to marshal Aptos chain writer config: %w", err) + } + + cw, err := params.Relayer.NewContractWriter(ctx, chainWriterConfig) + if err != nil { + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", params.ChainID, err) + } + + return cw, nil +} diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 847a0c697e1..5abf6d0c7db 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -18,6 +18,7 @@ import ( ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" @@ -397,6 +398,10 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } + if relayChainFamily == relay.NetworkAptos { + cr = aptosloop.NewLoopChainReader(i.lggr, cr) + } + if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ From 9c286d9eb50ae338b72c54693a9f4b568cc64000 Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 22 Apr 2025 19:12:49 +0400 Subject: [PATCH 112/136] core/capabilities/ccip/ccipaptos: update chainlink-integrations refs --- core/capabilities/ccip/ccipaptos/commitcodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/executecodec_test.go | 2 +- core/capabilities/ccip/ccipaptos/msghasher.go | 2 +- core/capabilities/ccip/ccipaptos/utils.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/commitcodec_test.go b/core/capabilities/ccip/ccipaptos/commitcodec_test.go index 3f05cb75d52..ccc24d18a22 100644 --- a/core/capabilities/ccip/ccipaptos/commitcodec_test.go +++ b/core/capabilities/ccip/ccipaptos/commitcodec_test.go @@ -11,7 +11,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/executecodec_test.go b/core/capabilities/ccip/ccipaptos/executecodec_test.go index 0bd3b19d4bf..5773e707a4c 100644 --- a/core/capabilities/ccip/ccipaptos/executecodec_test.go +++ b/core/capabilities/ccip/ccipaptos/executecodec_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go index 995e7e0112e..73f18d4e6dc 100644 --- a/core/capabilities/ccip/ccipaptos/msghasher.go +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) var ( diff --git a/core/capabilities/ccip/ccipaptos/utils.go b/core/capabilities/ccip/ccipaptos/utils.go index 5488f3903d2..f9610cb75c3 100644 --- a/core/capabilities/ccip/ccipaptos/utils.go +++ b/core/capabilities/ccip/ccipaptos/utils.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/smartcontractkit/chainlink-integrations/evm/utils" + "github.com/smartcontractkit/chainlink-evm/pkg/utils" ) func abiEncodeUint32(data uint32) ([]byte, error) { From 8b89094f51f1490503ec86b4eaceccaaf64e6c10 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 19:46:07 +0400 Subject: [PATCH 113/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add CCIPMessageSent --- core/capabilities/ccip/configs/aptos/contract_reader.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 016d593239d..58fc435fd1c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -128,6 +128,11 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", From 8eabba179721042be90ceabad7e538223cb253a1 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 30 Apr 2025 20:22:13 +0400 Subject: [PATCH 114/136] core/capabilities/ccip/configs/aptos/contract_reader.go: add get_dest_chain_gas_price --- .../capabilities/ccip/configs/aptos/contract_reader.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 58fc435fd1c..e6a97e2171d 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -62,6 +62,16 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { consts.MethodNameFeeQuoterGetStaticConfig: { Name: "get_static_config", }, + consts.MethodNameGetFeePriceUpdate: { + Name: "get_dest_chain_gas_price", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, }, }, consts.ContractNameOffRamp: { From a78f1cfd3b1b9ef5d88aa256528810d695d53b55 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:46:10 +0200 Subject: [PATCH 115/136] Upading aptos plugin ref --- plugins/plugins.private.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index dc1048fbc68..cf37667eac7 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,9 +9,9 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer" - gitRef: "2.21.0-beta16-aptos" - installPath: "github.com/smartcontractkit/chainlink-internal-integrations/aptos/relayer/cmd/chainlink-aptos" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" gitRef: "86191e815fb879118fb303bfd974a120c1945daa" From f4ca06d2b98e473ffd05e3defc2c9f3b02aafe5e Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 23 Apr 2025 14:58:17 +0200 Subject: [PATCH 116/136] Adjusting aptos plugin ref to point to the chainlink-aptos as a whole --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index cf37667eac7..7ceb9a49f3e 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -9,7 +9,7 @@ defaults: plugins: aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-aptos/relayer" + - moduleURI: "github.com/smartcontractkit/chainlink-aptos" gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: From e31abb392f4e33036b497dfbc646f8a055c7efbd Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 30 Apr 2025 19:50:32 +0200 Subject: [PATCH 117/136] Fixing merge conflict resolution (logger-related) --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 3 +++ core/capabilities/ccip/ocrimpls/contract_transmitter.go | 1 + 2 files changed, 4 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index f6c2e729263..1db95ffe7ab 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) // AptosCommitCallArgs defines the calldata structure for an Aptos commit transaction. @@ -50,6 +51,7 @@ func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { // NewCommitTransmitter constructs an Aptos commit transmitter. func (f *AptosContractTransmitterFactory) NewCommitTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, @@ -80,6 +82,7 @@ var AptosExecCallDataFunc = func( // NewExecTransmitter constructs an Aptos execute transmitter. func (f *AptosContractTransmitterFactory) NewExecTransmitter( + lggr logger.Logger, cw types.ContractWriter, fromAccount ocrtypes.Account, offrampAddress string, diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 24e9de74e38..09e79744290 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -47,6 +47,7 @@ type ccipTransmitter struct { toCalldataFn ToCalldataFunc toEd25519CalldataFn ToEd25519CalldataFunc extraDataCodec ccipcommon.ExtraDataCodec + lggr logger.Logger } func XXXNewContractTransmitterTestsOnly( From f9cee8b29017cd61c6ca1ecb4e124ac2486e82d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:30:51 +0200 Subject: [PATCH 118/136] Add OnRamp config --- .../ccip/configs/aptos/contract_reader.go | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index e6a97e2171d..4aa84dacf29 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -26,7 +26,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameRMNProxy: { Name: "rmn_remote", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -35,7 +34,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, - consts.ContractNameFeeQuoter: { Name: "fee_quoter", Functions: map[string]*chainreader.ChainReaderFunction{ @@ -138,11 +136,6 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, Events: map[string]*chainreader.ChainReaderEvent{ - consts.EventNameCCIPMessageSent: { - EventHandleStructName: "OnRampState", - EventHandleFieldName: "ccip_message_sent_events", - EventAccountAddress: "onramp::get_state_address", - }, consts.EventNameExecutionStateChanged: { EventHandleStructName: "OffRampState", EventHandleFieldName: "execution_state_changed_events", @@ -241,6 +234,45 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, + consts.ContractNameOnRamp: { + Name: "onramp", + Functions: map[string]*chainreader.ChainReaderFunction{ + consts.MethodNameOnRampGetDynamicConfig: { + Name: "get_dynamic_config", + }, + consts.MethodNameOnRampGetStaticConfig: { + Name: "get_static_config", + }, + consts.MethodNameOnRampGetDestChainConfig: { + Name: "get_dest_chain_config", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + ResultTupleToStruct: []string{"sequenceNumber", "allowListEnabled", "router"}, + }, + consts.MethodNameGetExpectedNextSequenceNumber: { + Name: "get_expected_next_sequence_number", + Params: []chainreader.AptosFunctionParam{ + { + Name: "destChainSelector", + Type: "u64", + Required: true, + }, + }, + }, + }, + Events: map[string]*chainreader.ChainReaderEvent{ + consts.EventNameCCIPMessageSent: { + EventHandleStructName: "OnRampState", + EventHandleFieldName: "ccip_message_sent_events", + EventAccountAddress: "onramp::get_state_address", + }, + }, + }, }, }, nil } From 2dc1e8c406471d0a8b25c4f6129c513951fe0224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 13:43:54 +0200 Subject: [PATCH 119/136] Fix NewExtraDataCodecParams --- core/capabilities/ccip/ccipsolana/msghasher_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/ccipsolana/msghasher_test.go b/core/capabilities/ccip/ccipsolana/msghasher_test.go index 0e5c0280e1e..4b8ff7e0f4a 100644 --- a/core/capabilities/ccip/ccipsolana/msghasher_test.go +++ b/core/capabilities/ccip/ccipsolana/msghasher_test.go @@ -17,6 +17,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-evm/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common/mocks" @@ -25,6 +26,7 @@ import ( func TestMessageHasher_EVM2SVM(t *testing.T) { registeredExtraDataCodecMap := map[string]ccipcommon.SourceChainExtraDataCodec{ + chainsel.FamilyAptos: ccipaptos.ExtraDataDecoder{}, chainsel.FamilyEVM: ccipevm.ExtraDataDecoder{}, chainsel.FamilySolana: ExtraDataDecoder{}, } From 71ff7cbf12f974d431fea1a2ff8ef915315f10d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 1 May 2025 15:17:03 +0200 Subject: [PATCH 120/136] Generate --- core/internal/mocks/flags.go | 2 +- core/internal/mocks/flux_aggregator.go | 2 +- .../ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go | 2 +- .../ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go | 2 +- go.md | 4 ++++ 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/core/internal/mocks/flags.go b/core/internal/mocks/flags.go index 26c791eccfc..558c5d0c4b9 100644 --- a/core/internal/mocks/flags.go +++ b/core/internal/mocks/flags.go @@ -3,7 +3,7 @@ package mocks import ( - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/internal/mocks/flux_aggregator.go b/core/internal/mocks/flux_aggregator.go index d2c7ea3e216..5b61d7a34c6 100644 --- a/core/internal/mocks/flux_aggregator.go +++ b/core/internal/mocks/flux_aggregator.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go index 1c12e1eba81..daa676e23e3 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/contracts/evm2_evm_off_ramp_interface.go @@ -5,7 +5,7 @@ package mock_contracts import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" common "github.com/ethereum/go-ethereum/common" event "github.com/ethereum/go-ethereum/event" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go index 2329746de1f..23fee609a78 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go index 7ff63e78229..1a80a1b8bc4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mocks/registry.go @@ -5,7 +5,7 @@ package mocks import ( big "math/big" - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bind "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" generated "github.com/smartcontractkit/chainlink-evm/gethwrappers/generated" diff --git a/go.md b/go.md index b8e62b5712f..77b34bfbdd6 100644 --- a/go.md +++ b/go.md @@ -24,6 +24,8 @@ flowchart LR chain-selectors click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" + chainlink-aptos --> chainlink-common + click chainlink-aptos href "https://github.com/smartcontractkit/chainlink-aptos" chainlink-automation --> chainlink-common click chainlink-automation href "https://github.com/smartcontractkit/chainlink-automation" chainlink-ccip --> chain-selectors @@ -70,6 +72,7 @@ flowchart LR click chainlink-solana href "https://github.com/smartcontractkit/chainlink-solana" chainlink-tron/relayer --> chainlink-evm click chainlink-tron/relayer href "https://github.com/smartcontractkit/chainlink-tron" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds @@ -249,6 +252,7 @@ flowchart LR chainlink/system-tests/tests --> chainlink-testing-framework/wasp chainlink/system-tests/tests --> chainlink/system-tests/lib click chainlink/system-tests/tests href "https://github.com/smartcontractkit/chainlink" + chainlink/v2 --> chainlink-aptos chainlink/v2 --> chainlink-automation chainlink/v2 --> chainlink-data-streams chainlink/v2 --> chainlink-feeds From d239f280b3c7c5642a435de15239ded2aa136fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 17:34:53 +0200 Subject: [PATCH 121/136] Fix logger --- .../ccip/ocrimpls/aptos_contract_transmitter_factory.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index 1db95ffe7ab..855cc3a47f9 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -58,6 +58,7 @@ func (f *AptosContractTransmitterFactory) NewCommitTransmitter( commitMethod, _ string, // priceOnlyMethod is ignored for Aptos ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, @@ -88,6 +89,7 @@ func (f *AptosContractTransmitterFactory) NewExecTransmitter( offrampAddress string, ) ocr3types.ContractTransmitter[[]byte] { return &ccipTransmitter{ + lggr: lggr, cw: cw, fromAccount: fromAccount, offrampAddress: offrampAddress, From c2dfd7335d56f62776bafb7cf4be0decdc6aca3b Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Thu, 1 May 2025 21:14:32 +0200 Subject: [PATCH 122/136] Bumping up chainlink-aptos plugin gitRef --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 7ceb9a49f3e..5a889536e68 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "29f3af22b874e733fc5abb74a930d02bf44ef6e5" + gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From ff23bc1733bd225aef6a013f74f83be979a118cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 2 May 2025 20:19:33 +0200 Subject: [PATCH 123/136] Add field renames to CCIPMessageSent event --- .../ccip/configs/aptos/chain_writer.go | 1 + .../ccip/configs/aptos/contract_reader.go | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/chain_writer.go b/core/capabilities/ccip/configs/aptos/chain_writer.go index 061672baac9..6594f0878a1 100644 --- a/core/capabilities/ccip/configs/aptos/chain_writer.go +++ b/core/capabilities/ccip/configs/aptos/chain_writer.go @@ -16,6 +16,7 @@ func GetChainWriterConfig(publicKeyStr string) (chainwriter.ChainWriterConfig, e return chainwriter.ChainWriterConfig{}, fmt.Errorf("failed to parse Aptos address from public key %s: %w", publicKeyStr, err) } + // TODO REMOVE fmt.Printf("DEBUG: Aptos GetChainWriterConfig: fromAddressStr=%s, pubKeyStr=%s\n", fromAddress.String(), publicKeyStr) return chainwriter.ChainWriterConfig{ diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 4aa84dacf29..853b38aed3c 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -270,6 +270,49 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { EventHandleStructName: "OnRampState", EventHandleFieldName: "ccip_message_sent_events", EventAccountAddress: "onramp::get_state_address", + EventFieldRenames: map[string]chainreader.RenamedField{ + "dest_chain_selector": { + NewName: "DestChainSelector", + SubFieldRenames: nil, + }, + "sequence_number": { + NewName: "SequenceNumber", + SubFieldRenames: nil, + }, + "message": { + NewName: "Message", + SubFieldRenames: map[string]chainreader.RenamedField{ + "header": { + NewName: "Header", + }, + "sender": { + NewName: "Sender", + }, + "data": { + NewName: "Data", + }, + "receiver": { + NewName: "Receiver", + }, + "extra_args": { + NewName: "ExtraArgs", + }, + "fee_token": { + NewName: "FeeToken", + }, + "fee_token_amount": { + NewName: "FeeTokenAmount", + }, + "fee_value_juels": { + NewName: "FeeValueJuels", + }, + "token_amounts": { + NewName: "TokenAmounts", + SubFieldRenames: nil, // TODO + }, + }, + }, + }, }, }, }, From effa0cb2748b434902d5a40997c6eb502dcb146f Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:21:26 +0200 Subject: [PATCH 124/136] Temp chainlink-aptos version --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index 5a889536e68..d9ddaedd16f 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "023cbbe11507b88efc758ed3c49bffb476a487b0" + gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From 3012a5d04fd067a3bc2b19e4ef1fb967bd2d89f5 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:29:44 +0200 Subject: [PATCH 125/136] Fixing CCIPMessageSent event renamings --- .../ccip/configs/aptos/contract_reader.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 853b38aed3c..e4b89ca4ca2 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -284,6 +284,23 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { SubFieldRenames: map[string]chainreader.RenamedField{ "header": { NewName: "Header", + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_chain_selector": { + NewName: "SourceChainSelector", + }, + "dest_chain_selector": { + NewName: "DestChainSelector", + }, + "sequence_number": { + NewName: "SequenceNumber", + }, + "message_id": { + NewName: "MessageID", + }, + "nonce": { + NewName: "Nonce", + }, + }, }, "sender": { NewName: "Sender", From 1baa3d57f9aa578b3471b43f9741a0027e7ef327 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Fri, 2 May 2025 20:43:05 +0200 Subject: [PATCH 126/136] Fixing plugin build --- plugins/plugins.private.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index d9ddaedd16f..e640ec5e77b 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "83794c91aa457dd65c229d1d6bf579747d7bba96" + gitRef: "808b080f471d054ff623164b3a316759a8f18758" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" From ad9a64049712cf25f2ead5a596d49c179cff7f11 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Tue, 13 May 2025 17:49:51 +0200 Subject: [PATCH 127/136] TokenAmount field of CCIPMessageSent renaming CR config --- .../ccip/configs/aptos/contract_reader.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index e4b89ca4ca2..6a22ca30df0 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -325,7 +325,23 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, "token_amounts": { NewName: "TokenAmounts", - SubFieldRenames: nil, // TODO + SubFieldRenames: map[string]chainreader.RenamedField{ + "source_pool_address": { + NewName: "SourcePoolAddress", + }, + "dest_token_address": { + NewName: "DestTokenAddress", + }, + "extra_data": { + NewName: "ExtraData", + }, + "amount": { + NewName: "Amount", + }, + "dest_exec_data": { + NewName: "DestExecData", + }, + }, }, }, }, From b7f293c87339e4e4ba3ec94b52b997f44248b8c1 Mon Sep 17 00:00:00 2001 From: cfal Date: Thu, 15 May 2025 12:27:58 +0400 Subject: [PATCH 128/136] core/capabilities/ccip: resolve issues from develop branch refactors --- .../ccip/ccipaptos/extradatadecoder.go | 2 +- .../capabilities/ccip/ccipaptos/pluginconfig.go | 12 ++++++++++-- .../aptos_contract_transmitter_factory.go | 17 ++++++++++------- core/capabilities/ccip/oraclecreator/plugin.go | 5 ----- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/extradatadecoder.go b/core/capabilities/ccip/ccipaptos/extradatadecoder.go index 2f59d9bed17..577583e3db0 100644 --- a/core/capabilities/ccip/ccipaptos/extradatadecoder.go +++ b/core/capabilities/ccip/ccipaptos/extradatadecoder.go @@ -15,7 +15,7 @@ import ( // Compatible with ccip::fee_quoter version 1.6.0 type ExtraDataDecoder struct{} -var _ ccipcommon.ExtraDataDecoder = (*ExtraDataDecoder)(nil) +var _ ccipcommon.SourceChainExtraDataCodec = ExtraDataDecoder{} const ( aptosDestExecDataKey = "destGasAmount" diff --git a/core/capabilities/ccip/ccipaptos/pluginconfig.go b/core/capabilities/ccip/ccipaptos/pluginconfig.go index 937fa3f3b3e..64d4711094d 100644 --- a/core/capabilities/ccip/ccipaptos/pluginconfig.go +++ b/core/capabilities/ccip/ccipaptos/pluginconfig.go @@ -7,8 +7,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) -// InitializePluginConfig returns a PluginConfig for EVM chains. -func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { +// initializePluginConfig returns a PluginConfig for Aptos chains. +func initializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraDataCodec) ccipcommon.PluginConfig { return ccipcommon.PluginConfig{ CommitPluginCodec: NewCommitPluginCodecV1(), ExecutePluginCodec: NewExecutePluginCodecV1(extraDataCodec), @@ -17,5 +17,13 @@ func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipcommon.ExtraD GasEstimateProvider: NewGasEstimateProvider(), RMNCrypto: nil, ContractTransmitterFactory: ocrimpls.NewAptosContractTransmitterFactory(extraDataCodec), + ChainRW: ChainCWProvider{}, + ExtraDataCodec: ExtraDataDecoder{}, + AddressCodec: AddressCodec{}, } } + +func init() { + // Register the Aptos plugin config factory + ccipcommon.RegisterPluginConfig(chainsel.FamilyAptos, initializePluginConfig) +} diff --git a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go index 855cc3a47f9..6d9a8421003 100644 --- a/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go +++ b/core/capabilities/ccip/ocrimpls/aptos_contract_transmitter_factory.go @@ -7,9 +7,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/consts" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipaptos" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana" ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -28,7 +25,15 @@ type AptosExecCallArgs struct { } // AptosContractTransmitterFactory implements the transmitter factory for Aptos chains. -type AptosContractTransmitterFactory struct{} +type AptosContractTransmitterFactory struct { + extraDataCodec ccipcommon.ExtraDataCodec +} + +func NewAptosContractTransmitterFactory(extraDataCodec ccipcommon.ExtraDataCodec) *AptosContractTransmitterFactory { + return &AptosContractTransmitterFactory{ + extraDataCodec: extraDataCodec, + } +} // NewAptosCommitCalldataFunc returns a ToCalldataFunc for Aptos commits that omits any Info object. func NewAptosCommitCalldataFunc(commitMethod string) ToEd25519CalldataFunc { @@ -94,8 +99,6 @@ func (f *AptosContractTransmitterFactory) NewExecTransmitter( fromAccount: fromAccount, offrampAddress: offrampAddress, toEd25519CalldataFn: AptosExecCallDataFunc, - extraDataCodec: ccipcommon.NewExtraDataCodec( - ccipcommon.NewExtraDataCodecParams(ccipevm.ExtraDataDecoder{}, ccipsolana.ExtraDataDecoder{}, ccipaptos.ExtraDataDecoder{}), - ), + extraDataCodec: f.extraDataCodec, } } diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index 5abf6d0c7db..847a0c697e1 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -18,7 +18,6 @@ import ( ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - aptosloop "github.com/smartcontractkit/chainlink-aptos/relayer/chainreader/loop" commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" @@ -398,10 +397,6 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } - if relayChainFamily == relay.NetworkAptos { - cr = aptosloop.NewLoopChainReader(i.lggr, cr) - } - if chainID == destChainID && destChainFamily == relayChainFamily { offrampAddress := destAddrStr err2 := cr.Bind(ctx, []types.BoundContract{ From 3104873413f54eb2fda0131baf8aef08a4403ad1 Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 21 May 2025 14:15:09 +0400 Subject: [PATCH 129/136] add and update chainlink-aptos and aptos-go-sdk --- core/scripts/go.mod | 4 +-- core/scripts/go.sum | 8 +++--- deployment/go.mod | 4 +-- deployment/go.sum | 8 +++--- go.mod | 10 +++++--- go.sum | 48 +++++++++++++++++++++++++++++------ integration-tests/go.mod | 4 +-- integration-tests/go.sum | 8 +++--- integration-tests/load/go.mod | 4 +-- integration-tests/load/go.sum | 8 +++--- system-tests/lib/go.mod | 4 +-- system-tests/lib/go.sum | 8 +++--- system-tests/tests/go.mod | 4 +-- system-tests/tests/go.sum | 8 +++--- 14 files changed, 83 insertions(+), 47 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 7c1cc75e395..66393e71707 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -83,7 +83,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect @@ -383,7 +383,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.57 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 633c53d7fcd..cd7dce91374 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -125,8 +125,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1257,8 +1257,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/deployment/go.mod b/deployment/go.mod index 0852235e4e0..ece31267316 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -13,7 +13,7 @@ require ( dario.cat/mergo v1.0.1 github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.3.1 - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/aws/aws-sdk-go v1.55.6 github.com/deckarep/golang-set/v2 v2.6.0 github.com/ethereum/go-ethereum v1.15.7 @@ -32,7 +32,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.57 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a github.com/smartcontractkit/chainlink-common v0.7.1-0.20250519161208-80bc8b13c0e7 diff --git a/deployment/go.sum b/deployment/go.sum index 7c2dabc059f..7359f05aecb 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -127,8 +127,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1235,8 +1235,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/go.mod b/go.mod index 1c6f3bc22da..ecaac69a241 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/NethermindEth/juno v0.12.5 github.com/NethermindEth/starknet.go v0.8.0 github.com/andybalholm/brotli v1.1.1 + github.com/aptos-labs/aptos-go-sdk v1.7.0 github.com/avast/retry-go/v4 v4.6.1 github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/cosmos/cosmos-sdk v0.50.13 @@ -16,7 +17,7 @@ require ( github.com/dominikbraun/graph v0.23.0 github.com/doyensec/safeurl v0.2.1 github.com/esote/minmaxheap v1.0.0 - github.com/ethereum/go-ethereum v1.15.3 + github.com/ethereum/go-ethereum v1.15.7 github.com/fatih/color v1.18.0 github.com/fbsobreira/gotron-sdk v0.0.0-20250403083053-2943ce8c759b github.com/fxamacker/cbor/v2 v2.7.0 @@ -74,6 +75,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.57 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e @@ -177,6 +179,7 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.38.17 // indirect github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/consensys/bavard v0.1.22 // indirect @@ -194,7 +197,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/dgraph-io/badger/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto v0.1.2-0.20240116140435-c67e07994f91 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -252,6 +255,7 @@ require ( github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hasura/go-graphql-client v0.13.1 // indirect github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.2 // indirect @@ -335,7 +339,7 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/urfave/cli/v2 v2.27.5 // indirect - github.com/valyala/fastjson v1.4.1 // indirect + github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/go.sum b/go.sum index c3d34e02a62..9516253f6f5 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -225,6 +227,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/cometbft/cometbft v0.38.17 h1:FkrQNbAjiFqXydeAO81FUzriL4Bz0abYxN/eOHrQGOk= github.com/cometbft/cometbft v0.38.17/go.mod h1:5l0SkgeLRXi6bBfQuevXjKqML1jjfJJlvI1Ulp02/o4= github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= @@ -273,6 +277,12 @@ github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHH github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= +github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= +github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= +github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -286,12 +296,14 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= @@ -325,8 +337,8 @@ github.com/esote/minmaxheap v1.0.0 h1:rgA7StnXXpZG6qlM0S7pUmEv1KpWe32rYT4x8J8nta github.com/esote/minmaxheap v1.0.0/go.mod h1:Ln8+i7fS1k3PLgZI2JAo0iA1as95QnIYiGCrqSJ5FZk= github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.15.3 h1:OeTWAq6r8iR89bfJDjmmOemE74ywArl9DUViFsVj3Y8= -github.com/ethereum/go-ethereum v1.15.3/go.mod h1:jMXlpZXfSar1mGs/5sB0aEpEnPsiE1Jn6/3anlueqz8= +github.com/ethereum/go-ethereum v1.15.7 h1:vm1XXruZVnqtODBgqFaTclzP0xAvCvQIDKyFNUA1JpY= +github.com/ethereum/go-ethereum v1.15.7/go.mod h1:+S9k+jFzlyVTNcYGvqFhzN/SFhI6vA+aOY4T5tLSPL0= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -335,6 +347,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -359,6 +373,8 @@ github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdF github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 h1:Uc+IZ7gYqAf/rSGFplbWBSHaGolEQlNLgMgSE3ccnIQ= github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9yhSRvsmYyZsshflcR6ePWYLql6UU1amW13IM= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= @@ -608,6 +624,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYSucoNE= github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -639,6 +657,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hasura/go-graphql-client v0.13.1 h1:kKbjhxhpwz58usVl+Xvgah/TDha5K2akNTRQdsEHN6U= +github.com/hasura/go-graphql-client v0.13.1/go.mod h1:k7FF7h53C+hSNFRG3++DdVZWIuHdCaTbI7siTJ//zGQ= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -663,6 +683,12 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -831,6 +857,8 @@ github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8D github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -922,6 +950,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -1050,6 +1080,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= @@ -1202,8 +1234,8 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= -github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 7c781e61127..f43ff6a99c2 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -113,7 +113,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -452,7 +452,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 9ee084b7e9a..8b620dada5e 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -159,8 +159,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a h1:2/4CQPSQ5LAAJHR5ONx+TwtfPDyG5tv2M2mJ2aw/8Kk= github.com/archseer/binary v0.0.0-20250226104222-b87d7f4fd58a/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -1466,8 +1466,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index f8ff877cfa6..9be393c30c9 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -86,7 +86,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -440,7 +440,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index b47315ce163..b939a2fe864 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -163,8 +163,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1448,8 +1448,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 1a9fe072998..ce89b479818 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -64,7 +64,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect @@ -356,7 +356,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index ca4e8c4ae22..a3da840195e 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -121,8 +121,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -1222,8 +1222,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 5ac6414e7fc..71c6b651c1e 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -80,7 +80,7 @@ require ( github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect - github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -429,7 +429,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.57 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index cba3b066a4d..253deadd86c 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -157,8 +157,8 @@ github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d h1:VsrpaOlsWs+XaofivnfP9gU5aSBmRudoJEMZvXGvrok= -github.com/aptos-labs/aptos-go-sdk v1.6.3-0.20250331001805-0680b714db6d/go.mod h1:BgddSKFtfWFLK+no8l+AwCcb/Lh1lv74ybYLzeonloo= +github.com/aptos-labs/aptos-go-sdk v1.7.0 h1:4FSjePHenTWMf/285tS/Im3Xb+rXy01j4IHl6KdJGXw= +github.com/aptos-labs/aptos-go-sdk v1.7.0/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -1422,8 +1422,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf h1:zzG5D68tGbDBW3mQW6sa50ga0kGRQp9S7F4vqZO0ZrU= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250502091650-484cfa7ccddf/go.mod h1:yj4d1XS6lBOXM1sDMP1ULCbRJgOuBYf2V7VtQ6Qgev8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= From 4b7e272bac53d1fe46fdc0079edba7056b5d2a65 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 21 May 2025 18:54:00 +0200 Subject: [PATCH 130/136] Bumping up the chainlink-aptos version --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 2 ++ deployment/go.mod | 2 +- deployment/go.sum | 2 ++ go.mod | 2 +- go.sum | 2 ++ integration-tests/go.mod | 2 +- integration-tests/go.sum | 2 ++ integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 2 ++ plugins/plugins.private.yaml | 2 +- system-tests/tests/go.mod | 2 +- system-tests/tests/go.sum | 2 ++ 13 files changed, 19 insertions(+), 7 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 66393e71707..8d33f29dded 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -383,7 +383,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.57 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index cd7dce91374..19a01a873d0 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1259,6 +1259,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/deployment/go.mod b/deployment/go.mod index ece31267316..f8f4e619bd2 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -32,7 +32,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.57 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a github.com/smartcontractkit/chainlink-common v0.7.1-0.20250519161208-80bc8b13c0e7 diff --git a/deployment/go.sum b/deployment/go.sum index 7359f05aecb..ef7233af240 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1237,6 +1237,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/go.mod b/go.mod index ecaac69a241..bc10a2ddab8 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.57 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e diff --git a/go.sum b/go.sum index 9516253f6f5..a9dde294140 100644 --- a/go.sum +++ b/go.sum @@ -1082,6 +1082,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f43ff6a99c2..d063973c46c 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -452,7 +452,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 8b620dada5e..8c4f16de525 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1468,6 +1468,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 9be393c30c9..14626342e9e 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -440,7 +440,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index b939a2fe864..bfc1c895690 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1450,6 +1450,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= diff --git a/plugins/plugins.private.yaml b/plugins/plugins.private.yaml index e640ec5e77b..fb66ecb3010 100644 --- a/plugins/plugins.private.yaml +++ b/plugins/plugins.private.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "808b080f471d054ff623164b3a316759a8f18758" + gitRef: "a9a1f1d5d3e26adeae13e223496fee83886be85b" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cron: - moduleURI: "github.com/smartcontractkit/capabilities/cron" diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 71c6b651c1e..d4ff9cd5836 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -429,7 +429,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.57 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 253deadd86c..fbd3ef642d1 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1424,6 +1424,8 @@ github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3m github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= From 577cffe12721cebc90ae7216de17ff05325b1789 Mon Sep 17 00:00:00 2001 From: Sergei Drugalev Date: Wed, 21 May 2025 19:01:51 +0200 Subject: [PATCH 131/136] Adding EventFilter config to CCIPMessageSent --- core/capabilities/ccip/configs/aptos/contract_reader.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/capabilities/ccip/configs/aptos/contract_reader.go b/core/capabilities/ccip/configs/aptos/contract_reader.go index 6a22ca30df0..fa67a79b42d 100644 --- a/core/capabilities/ccip/configs/aptos/contract_reader.go +++ b/core/capabilities/ccip/configs/aptos/contract_reader.go @@ -346,6 +346,9 @@ func GetChainReaderConfig() (chainreader.ChainReaderConfig, error) { }, }, }, + EventFilterRenames: map[string]string{ + "DestChain": "DestChainSelector", + }, }, }, }, From 00ca917c5bde4bf80ee0b02a9419c2553b93f8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Wed, 21 May 2025 22:15:33 +0000 Subject: [PATCH 132/136] Fix msghasher append --- core/capabilities/ccip/ccipaptos/msghasher.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/capabilities/ccip/ccipaptos/msghasher.go b/core/capabilities/ccip/ccipaptos/msghasher.go index 73f18d4e6dc..c3f3a57f03e 100644 --- a/core/capabilities/ccip/ccipaptos/msghasher.go +++ b/core/capabilities/ccip/ccipaptos/msghasher.go @@ -66,7 +66,7 @@ func (h *MessageHasherV1) Hash(ctx context.Context, msg cciptypes.Message) (ccip lggr.Debugw("hashing message", "msg", msg) rampTokenAmounts := make([]any2AptosTokenTransfer, len(msg.TokenAmounts)) - for _, rta := range msg.TokenAmounts { + for i, rta := range msg.TokenAmounts { destGasAmount, err := abiDecodeUint32(rta.DestExecData) if err != nil { return [32]byte{}, fmt.Errorf("decode dest gas amount: %w", err) @@ -83,13 +83,13 @@ func (h *MessageHasherV1) Hash(ctx context.Context, msg cciptypes.Message) (ccip lggr.Debugw("abi decoded dest token address", "destTokenAddress", destTokenAddress) - rampTokenAmounts = append(rampTokenAmounts, any2AptosTokenTransfer{ + rampTokenAmounts[i] = any2AptosTokenTransfer{ SourcePoolAddress: rta.SourcePoolAddress, DestTokenAddress: destTokenAddress, DestGasAmount: destGasAmount, ExtraData: rta.ExtraData, Amount: rta.Amount.Int, - }) + } } // one difference from EVM is that we don't left pad the OnRamp to 32 bytes here, we use the source chain's canonical bytes encoding directly. From 201e6ccb92af9d62a1aa353276deaf3467566b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 22 May 2025 11:08:36 +0200 Subject: [PATCH 133/136] Add Aptos2EVM support --- core/scripts/go.mod | 4 +- core/scripts/go.sum | 8 +- .../changeset/aptos/operation/fee_quoter.go | 23 +++ .../changeset/aptos/sequence/update_lane.go | 7 + .../changeset/testhelpers/feestest/helpers.go | 8 +- .../messagelimitationstest/helpers.go | 3 +- .../testhelpers/messagingtest/helpers.go | 18 +- .../changeset/testhelpers/test_environment.go | 13 +- .../changeset/testhelpers/test_helpers.go | 170 ++++++++++++++---- deployment/environment/memory/aptos_chains.go | 34 +++- deployment/go.mod | 4 +- deployment/go.sum | 3 + go.mod | 4 +- go.sum | 8 +- integration-tests/go.mod | 4 +- integration-tests/go.sum | 8 +- integration-tests/load/go.mod | 4 +- integration-tests/load/go.sum | 8 +- .../smoke/ccip/ccip_aptos_messaging_test.go | 77 +++++++- .../smoke/ccip/ccip_disable_lane_test.go | 6 +- .../smoke/ccip/ccip_messaging_test.go | 6 +- .../ccip/ccip_migration_to_v_1_6_test.go | 8 +- .../smoke/ccip/ccip_reader_test.go | 6 +- .../smoke/ccip/ccip_reorg_test.go | 9 +- system-tests/lib/go.mod | 4 +- system-tests/lib/go.sum | 8 +- system-tests/tests/go.mod | 4 +- system-tests/tests/go.sum | 8 +- 28 files changed, 364 insertions(+), 103 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 30cb5c9d4ef..154ce3aa434 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -32,7 +32,7 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 github.com/smartcontractkit/chainlink-deployments-framework v0.1.1 @@ -383,7 +383,7 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 6046315cf62..6e4deb62c27 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1257,12 +1257,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/deployment/ccip/changeset/aptos/operation/fee_quoter.go b/deployment/ccip/changeset/aptos/operation/fee_quoter.go index 4e699935110..9b76ccf0d85 100644 --- a/deployment/ccip/changeset/aptos/operation/fee_quoter.go +++ b/deployment/ccip/changeset/aptos/operation/fee_quoter.go @@ -204,6 +204,29 @@ func updateFeeQuoterPrices(b operations.Bundle, deps AptosDeps, in UpdateFeeQuot "gasPriceCount", len(gasDestChainSelectors), ) + // TODO + multipliers := make([]uint64, len(sourceTokens)) + for i := range multipliers { + multipliers[i] = uint64(1) + } + moduleInfo, function, _, args, err = ccipBind.FeeQuoter().Encoder().ApplyPremiumMultiplierWeiPerEthUpdates(sourceTokens, multipliers) + if err != nil { + return nil, fmt.Errorf("failed to encode ApplyPremiumMultiplierWeiPerEth: %w", err) + } + tx, err := aptosmcms.NewTransaction( + moduleInfo.PackageName, + moduleInfo.ModuleName, + function, + ccipAddress, + aptosmcms.ArgsToData(args), + "FeeQuoter", + nil, + ) + if err != nil { + return nil, fmt.Errorf("failed to generate transaction: %w", err) + } + txs = append(txs, tx) + return txs, nil } diff --git a/deployment/ccip/changeset/aptos/sequence/update_lane.go b/deployment/ccip/changeset/aptos/sequence/update_lane.go index 9cad5a2b3e2..cbac53cc9e8 100644 --- a/deployment/ccip/changeset/aptos/sequence/update_lane.go +++ b/deployment/ccip/changeset/aptos/sequence/update_lane.go @@ -146,6 +146,13 @@ func setAptosSourceUpdates(lane config.LaneConfig, updateInputsByAptosChain map[ } input.UpdateFeeQuoterPricesConfig.Prices.GasPrices[dest.Selector] = dest.GasPrice + if input.UpdateFeeQuoterPricesConfig.Prices.TokenPrices == nil { + input.UpdateFeeQuoterPricesConfig.Prices.TokenPrices = make(map[string]*big.Int) + } + aptUSDPrice28Decimals := big.NewInt(5) + aptUSDPrice28Decimals.Mul(aptUSDPrice28Decimals, big.NewInt(0).Exp(big.NewInt(10), big.NewInt(28), nil)) + input.UpdateFeeQuoterPricesConfig.Prices.TokenPrices["0xa"] = aptUSDPrice28Decimals + // Setting the fee quoter destination on the source chain input.UpdateFeeQuoterDestsConfig.MCMSAddress = mcmsAddress if input.UpdateFeeQuoterDestsConfig.Updates == nil { diff --git a/deployment/ccip/changeset/testhelpers/feestest/helpers.go b/deployment/ccip/changeset/testhelpers/feestest/helpers.go index 769245c4265..f8674986559 100644 --- a/deployment/ccip/changeset/testhelpers/feestest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/feestest/helpers.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" @@ -144,7 +145,7 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { tc.t.Logf("fee token balance before: %s, fee token enabled: %s", feeTokenBalanceBefore.String(), tc.feeToken.String()) - msgSentEvent := testhelpers.TestSendRequest( + out := testhelpers.TestSendRequest( tc.t, tc.env, state, @@ -159,15 +160,16 @@ func RunFeeTokenTestCase(tc FeeTokenTestCase) { ExtraArgs: nil, }, ) + msgSentEvent := out.RawEvent.(*onramp.OnRampCCIPMessageSent) expectedSeqNum[testhelpers.SourceDestPair{ SourceChainSelector: tc.src, DestChainSelector: tc.dst, - }] = msgSentEvent.SequenceNumber + }] = out.SequenceNumber expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: tc.src, DestChainSelector: tc.dst, - }] = []uint64{msgSentEvent.SequenceNumber} + }] = []uint64{out.SequenceNumber} // Check the fee token balance after the request and ensure fee tokens were spent var feeTokenBalanceAfter *big.Int diff --git a/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go b/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go index 7a5df7621f4..b144d51a149 100644 --- a/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/messagelimitationstest/helpers.go @@ -99,7 +99,7 @@ func Run(tc TestCase) TestCaseOutput { require.NoError(tc.T, err) } - msgSentEvent, err := testhelpers.SendRequest( + out, err := testhelpers.SendRequest( tc.Env, tc.OnchainState, testhelpers.WithSourceChain(tc.SrcChain), testhelpers.WithDestChain(tc.DestChain), @@ -113,6 +113,7 @@ func Run(tc TestCase) TestCaseOutput { return TestCaseOutput{} } require.NoError(tc.T, err) + msgSentEvent := out.RawEvent.(*onramp.OnRampCCIPMessageSent) tc.T.Logf("Message not reverted as expected") diff --git a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go index 1fbc3aeb32f..6c9ea84662a 100644 --- a/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go +++ b/deployment/ccip/changeset/testhelpers/messagingtest/helpers.go @@ -4,9 +4,11 @@ import ( "testing" "time" + "github.com/aptos-labs/aptos-go-sdk" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" + module_onramp "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp/onramp" "github.com/stretchr/testify/require" solconfig "github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/config" @@ -16,7 +18,6 @@ import ( chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_2_0/router" - "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -103,7 +104,7 @@ const ( type TestCaseOutput struct { Replayed bool Nonce uint64 - MsgSentEvent *onramp.OnRampCCIPMessageSent + MsgSentEvent *testhelpers.AnyMsgSentEvent } func sleepAndReplay(t *testing.T, e testhelpers.DeployedEnv, chainSelectors ...uint64) { @@ -180,7 +181,18 @@ func Run(t *testing.T, tc TestCase) (out TestCaseOutput) { FeeToken: feeToken, ExtraArgs: tc.ExtraArgs, } - + case chain_selectors.FamilyAptos: + feeToken := aptos.AccountAddress{} + if len(tc.FeeToken) > 0 { + feeToken.ParseStringRelaxed(tc.FeeToken) + } + msg = module_onramp.Aptos2AnyRampMessage{ + Data: tc.MsgData, + Receiver: common.LeftPadBytes(tc.Receiver, 32), + ExtraArgs: tc.ExtraArgs, + FeeToken: feeToken, + TokenAmounts: nil, + } default: tc.T.Errorf("unsupported source chain: %v", family) } diff --git a/deployment/ccip/changeset/testhelpers/test_environment.go b/deployment/ccip/changeset/testhelpers/test_environment.go index 707b589ae8d..05470327d8c 100644 --- a/deployment/ccip/changeset/testhelpers/test_environment.go +++ b/deployment/ccip/changeset/testhelpers/test_environment.go @@ -697,22 +697,16 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn var apps []commonchangeset.ConfiguredChangeSet evmContractParams := make(map[uint64]v1_6.ChainContractParams) - evmChains := []uint64{} + var ( + evmChains, solChains, aptosChains []uint64 + ) for _, chain := range allChains { if _, ok := e.Env.Chains[chain]; ok { evmChains = append(evmChains, chain) } - } - - solChains := []uint64{} - for _, chain := range allChains { if _, ok := e.Env.SolChains[chain]; ok { solChains = append(solChains, chain) } - } - - aptosChains := []uint64{} - for _, chain := range allChains { if _, ok := e.Env.AptosChains[chain]; ok { aptosChains = append(aptosChains, chain) } @@ -876,6 +870,7 @@ func AddCCIPContractsToEnvironment(t *testing.T, allChains []uint64, tEnv TestEn // TODO(aptos): update this for token transfers tokenInfo := map[cciptypes.UnknownEncodedAddress]pluginconfig.TokenInfo{} linkTokenAddress := state.AptosChains[chain].LinkTokenAddress + linkTokenAddress.ParseStringRelaxed("0xa") tokenInfo[cciptypes.UnknownEncodedAddress(linkTokenAddress.String())] = tokenConfig.TokenSymbolToInfo[shared.LinkSymbol] ocrOverride := tc.OCRConfigOverride diff --git a/deployment/ccip/changeset/testhelpers/test_helpers.go b/deployment/ccip/changeset/testhelpers/test_helpers.go index 0098a96d3aa..4a77f4a781b 100644 --- a/deployment/ccip/changeset/testhelpers/test_helpers.go +++ b/deployment/ccip/changeset/testhelpers/test_helpers.go @@ -14,8 +14,13 @@ import ( "testing" "time" + "github.com/aptos-labs/aptos-go-sdk" + aptosBind "github.com/smartcontractkit/chainlink-aptos/bindings/bind" aptos_fee_quoter "github.com/smartcontractkit/chainlink-aptos/bindings/ccip/fee_quoter" "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_dummy_receiver" + module_onramp "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_onramp/onramp" + aptos_router "github.com/smartcontractkit/chainlink-aptos/bindings/ccip_router" + "github.com/smartcontractkit/chainlink-aptos/relayer/codec" mcmstypes "github.com/smartcontractkit/mcms/types" "golang.org/x/sync/errgroup" @@ -393,6 +398,14 @@ func CCIPSendCalldata( return calldata, nil } +type AnyMsgSentEvent struct { + SequenceNumber uint64 + // RawEvent contains the raw event depending on the chain: + // EVM: *onramp.OnRampCCIPMessageSent + // Aptos: module_onramp.CCIPMessageSent + RawEvent any +} + // testhelpers.SendRequest(t, e, state, src, dest, msg, opts...) // opts being testRouter, sender // always return error @@ -406,7 +419,7 @@ func TestSendRequest( testRouter bool, msg any, opts ...SendReqOpts, -) (msgSentEvent *onramp.OnRampCCIPMessageSent) { +) (msgSentEvent *AnyMsgSentEvent) { baseOpts := []SendReqOpts{ WithSourceChain(src), WithDestChain(dest), @@ -480,7 +493,7 @@ func SendRequest( e cldf.Environment, state stateview.CCIPOnChainState, opts ...SendReqOpts, -) (*onramp.OnRampCCIPMessageSent, error) { +) (*AnyMsgSentEvent, error) { cfg := &CCIPSendReqConfig{} for _, opt := range opts { opt(cfg) @@ -496,7 +509,7 @@ func SendRequest( case chainsel.FamilySolana: return SendRequestSol(e, state, cfg) case chainsel.FamilyAptos: - panic("Aptos - not implemented") + return SendRequestAptos(e, state, cfg) default: return nil, fmt.Errorf("send request: unsupported chain family: %v", family) } @@ -506,7 +519,7 @@ func SendRequestEVM( e cldf.Environment, state stateview.CCIPOnChainState, cfg *CCIPSendReqConfig, -) (*onramp.OnRampCCIPMessageSent, error) { +) (*AnyMsgSentEvent, error) { // Set default sender if not provided if cfg.Sender == nil { cfg.Sender = e.Chains[cfg.SourceChain].DeployerKey @@ -543,14 +556,17 @@ func SendRequestEVM( it.Event.Message.Sender.String(), cfg.IsTestRouter, ) - return it.Event, nil + return &AnyMsgSentEvent{ + SequenceNumber: it.Event.SequenceNumber, + RawEvent: it.Event, + }, nil } func SendRequestSol( e cldf.Environment, state stateview.CCIPOnChainState, cfg *CCIPSendReqConfig, -) (*onramp.OnRampCCIPMessageSent, error) { // TODO: chain independent return value +) (*AnyMsgSentEvent, error) { // TODO: chain independent return value ctx := e.GetContext() s := state.SolChains[cfg.SourceChain] @@ -775,34 +791,126 @@ func SendRequestSol( cfg.IsTestRouter, ) - return &onramp.OnRampCCIPMessageSent{ - DestChainSelector: ccipMessageSentEvent.DestinationChainSelector, - SequenceNumber: ccipMessageSentEvent.SequenceNumber, - Message: onramp.InternalEVM2AnyRampMessage{ - Header: onramp.InternalRampMessageHeader{ - SourceChainSelector: ccipMessageSentEvent.Message.Header.SourceChainSelector, - DestChainSelector: ccipMessageSentEvent.Message.Header.DestChainSelector, - MessageId: ccipMessageSentEvent.Message.Header.MessageId, - SequenceNumber: ccipMessageSentEvent.SequenceNumber, - Nonce: ccipMessageSentEvent.Message.Header.Nonce, + return &AnyMsgSentEvent{ + SequenceNumber: ccipMessageSentEvent.SequenceNumber, + RawEvent: &onramp.OnRampCCIPMessageSent{ + DestChainSelector: ccipMessageSentEvent.DestinationChainSelector, + SequenceNumber: ccipMessageSentEvent.SequenceNumber, + Message: onramp.InternalEVM2AnyRampMessage{ + Header: onramp.InternalRampMessageHeader{ + SourceChainSelector: ccipMessageSentEvent.Message.Header.SourceChainSelector, + DestChainSelector: ccipMessageSentEvent.Message.Header.DestChainSelector, + MessageId: ccipMessageSentEvent.Message.Header.MessageId, + SequenceNumber: ccipMessageSentEvent.SequenceNumber, + Nonce: ccipMessageSentEvent.Message.Header.Nonce, + }, + FeeTokenAmount: ConvertSolanaCrossChainAmountToBigInt(ccipMessageSentEvent.Message.FeeTokenAmount), + FeeValueJuels: ConvertSolanaCrossChainAmountToBigInt(ccipMessageSentEvent.Message.FeeValueJuels), + ExtraArgs: ccipMessageSentEvent.Message.ExtraArgs, + Receiver: ccipMessageSentEvent.Message.Receiver, + Data: ccipMessageSentEvent.Message.Data, + + // TODO: these fields are EVM specific - need to revisit for Solana + FeeToken: common.Address{}, // ccipMessageSentEvent.Message.FeeToken + Sender: common.Address{}, // ccipMessageSentEvent.Message.Sender + TokenAmounts: []onramp.InternalEVM2AnyTokenTransfer{}, }, - FeeTokenAmount: ConvertSolanaCrossChainAmountToBigInt(ccipMessageSentEvent.Message.FeeTokenAmount), - FeeValueJuels: ConvertSolanaCrossChainAmountToBigInt(ccipMessageSentEvent.Message.FeeValueJuels), - ExtraArgs: ccipMessageSentEvent.Message.ExtraArgs, - Receiver: ccipMessageSentEvent.Message.Receiver, - Data: ccipMessageSentEvent.Message.Data, - - // TODO: these fields are EVM specific - need to revisit for Solana - FeeToken: common.Address{}, // ccipMessageSentEvent.Message.FeeToken - Sender: common.Address{}, // ccipMessageSentEvent.Message.Sender - TokenAmounts: []onramp.InternalEVM2AnyTokenTransfer{}, - }, - // TODO: EVM specific - need to revisit for Solana - Raw: types.Log{}, + // TODO: EVM specific - need to revisit for Solana + Raw: types.Log{}, + }, }, nil } +func SendRequestAptos( + e cldf.Environment, + state stateview.CCIPOnChainState, + cfg *CCIPSendReqConfig, +) (*AnyMsgSentEvent, error) { + sender := e.AptosChains[cfg.SourceChain].DeployerSigner + senderAddress := sender.AccountAddress() + client := e.AptosChains[cfg.SourceChain].Client + + e.Logger.Infof("(Aptos) Sending CCIP request from chain selector %d to chain selector %d from sender %s", + cfg.SourceChain, cfg.DestChain, senderAddress.StringLong()) + + msg := cfg.Message.(module_onramp.Aptos2AnyRampMessage) + r := state.AptosChains[cfg.SourceChain].CCIPAddress + if cfg.IsTestRouter { + r = state.AptosChains[cfg.DestChain].TestRouterAddress + } + + tokenAddresses := make([]aptos.AccountAddress, len(msg.TokenAmounts)) + tokenAmounts := make([]uint64, len(msg.TokenAmounts)) + tokenStoreAddresses := make([]aptos.AccountAddress, len(msg.TokenAmounts)) + for i, v := range msg.TokenAmounts { + // TODO - struct missing input data + tokenAddresses[i] = v.SourcePoolAddress + tokenAmounts[i] = v.Amount + tokenStoreAddresses[i] = v.SourcePoolAddress + } + + router := aptos_router.Bind(r, client) + fee, err := router.Router().GetFee( + nil, + cfg.DestChain, + msg.Receiver, + msg.Data, + tokenAddresses, + tokenAmounts, + tokenStoreAddresses, + msg.FeeToken, + aptos.AccountAddress{}, // TODO missing parameter + msg.ExtraArgs, + ) + if err != nil { + e.Logger.Errorf("Estimating fee: %v", err) + } + e.Logger.Infof("Estimated fee: %v", fee) + + opts := &aptosBind.TransactOpts{ + Signer: sender, + } + tx, err := router.Router().CCIPSend( + opts, + cfg.DestChain, + msg.Receiver, + msg.Data, + tokenAddresses, + tokenAmounts, + tokenStoreAddresses, + msg.FeeToken, + aptos.AccountAddress{}, // TODO missing parameter + msg.ExtraArgs, + ) + if err != nil { + return nil, fmt.Errorf("failed to send fee: %w", err) + } + data, err := client.WaitForTransaction(tx.Hash) + if err != nil { + return nil, fmt.Errorf("failed to wait for transaction: %w", err) + } + if !data.Success { + return nil, fmt.Errorf("transaction reverted: %v", data.VmStatus) + } + e.Logger.Infof("(Aptos) CCIP message sent (tx %s) from chain selector %d to chain selector %d", tx.Hash, cfg.SourceChain, cfg.DestChain) + for _, event := range data.Events { + e.Logger.Infof("Event type: %v", event.Type) + if event.Type == fmt.Sprintf("%s::onramp::CCIPMessageSent", r.StringLong()) { + var msgSentEvent module_onramp.CCIPMessageSent + if err := codec.DecodeAptosJsonValue(event.Data, &msgSentEvent); err != nil { + return nil, fmt.Errorf("failed to decode CCIPMessageSentEvent: %w", err) + } + e.Logger.Debugf("CCIPMessageSentEvent: %v", msgSentEvent) + return &AnyMsgSentEvent{ + SequenceNumber: msgSentEvent.SequenceNumber, + RawEvent: msgSentEvent, + }, nil + } + } + return nil, errors.New("failed to send CCIPMessageSentEvent") +} + func ConvertSolanaCrossChainAmountToBigInt(amount ccip_router.CrossChainAmount) *big.Int { bytes := amount.LeBytes[:] slices.Reverse(bytes) // convert to big-endian @@ -1085,7 +1193,7 @@ func addLaneAptosChangesets(t *testing.T, srcChainSelector, destChainSelector ui AllowListEnabled: false, }, Selector: destChainSelector, - GasPrice: big.NewInt(1e17), + GasPrice: big.NewInt(1e9), TokenPrices: nil, FeeQuoterDestChainConfig: fee_quoter.FeeQuoterDestChainConfig{ IsEnabled: true, @@ -1902,7 +2010,7 @@ func Transfer( useTestRouter bool, data, extraArgs []byte, feeToken string, -) (*onramp.OnRampCCIPMessageSent, map[uint64]*uint64) { +) (*AnyMsgSentEvent, map[uint64]*uint64) { startBlocks := make(map[uint64]*uint64) block, err := LatestBlock(ctx, env, destChain) diff --git a/deployment/environment/memory/aptos_chains.go b/deployment/environment/memory/aptos_chains.go index 074186e7fca..2765a702ef3 100644 --- a/deployment/environment/memory/aptos_chains.go +++ b/deployment/environment/memory/aptos_chains.go @@ -67,7 +67,7 @@ func GenerateChainsAptos(t *testing.T, numChains int) map[uint64]cldf.AptosChain require.NoError(t, err) account := createAptosAccount(t, true) - url, nodeClient := aptosChain(t, chainID, account.Address) + url, nodeClient := aptosChain(t, chainID, account) chains[selector] = cldf.AptosChain{ Selector: selector, Client: nodeClient, @@ -89,7 +89,7 @@ func GenerateChainsAptos(t *testing.T, numChains int) map[uint64]cldf.AptosChain return chains } -func aptosChain(t *testing.T, chainID string, adminAddress aptos.AccountAddress) (string, *aptos.NodeClient) { +func aptosChain(t *testing.T, chainID string, account *aptos.Account) (string, *aptos.NodeClient) { t.Helper() // initialize the docker network used by CTF @@ -110,7 +110,7 @@ func aptosChain(t *testing.T, chainID string, adminAddress aptos.AccountAddress) Image: "", // filled out by defaultAptos function Type: "aptos", ChainID: chainID, - PublicKey: adminAddress.String(), + PublicKey: account.Address.StringLong(), CustomPorts: []string{fmt.Sprintf("%d:8080", ports[0]), fmt.Sprintf("%d:8081", ports[1])}, } output, err := blockchain.NewBlockchainNetwork(bcInput) @@ -148,9 +148,35 @@ func aptosChain(t *testing.T, chainID string, adminAddress aptos.AccountAddress) dc, err := framework.NewDockerClient() require.NoError(t, err) // incase we didn't use the default account above - _, err = dc.ExecContainer(containerName, []string{"aptos", "account", "fund-with-faucet", "--account", adminAddress.String(), "--amount", "100000000000"}) + _, err = dc.ExecContainer(containerName, []string{"aptos", "account", "fund-with-faucet", "--account", account.Address.StringLong(), "--amount", "100000000000"}) require.NoError(t, err) + // Migrate APT Coin to FA, required for CCIP + payload := aptos.TransactionPayload{ + Payload: &aptos.EntryFunction{ + Module: aptos.ModuleId{ + Address: aptos.AccountOne, + Name: "coin", + }, + Function: "migrate_to_fungible_store", + ArgTypes: []aptos.TypeTag{ + { + Value: &aptos.StructTag{ + Address: aptos.AccountOne, + Module: "aptos_coin", + Name: "AptosCoin", + }, + }, + }, + Args: nil, + }, + } + res, err := client.BuildSignAndSubmitTransaction(account, payload) + require.NoError(t, err) + tx, err := client.WaitForTransaction(res.Hash) + require.NoError(t, err) + require.Truef(t, tx.Success, "Migrating APT to FungibleAsset failed: %v", tx.VmStatus) + return url, client } diff --git a/deployment/go.mod b/deployment/go.mod index 23a1a99583f..7989f4a7ce0 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -32,8 +32,8 @@ require ( github.com/sethvargo/go-retry v0.2.4 github.com/smartcontractkit/ccip-owner-contracts v0.1.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 github.com/smartcontractkit/chainlink-deployments-framework v0.1.1 diff --git a/deployment/go.sum b/deployment/go.sum index 12be9c4423d..9452c0fdd1e 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1237,10 +1237,13 @@ github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/go.mod b/go.mod index cc84fcbc868..fd2aed9f000 100644 --- a/go.mod +++ b/go.mod @@ -74,9 +74,9 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 diff --git a/go.sum b/go.sum index 9ef5f181f12..d3a9a5f0252 100644 --- a/go.sum +++ b/go.sum @@ -1076,12 +1076,12 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 0fdd9a8d641..9d5772304de 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -45,7 +45,7 @@ require ( github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 github.com/smartcontractkit/chainlink-deployments-framework v0.1.1 @@ -452,7 +452,7 @@ require ( github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index db50fdf7f44..d3336c0dd5f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,12 +1466,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index a53ffd5a1f1..b8921285200 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -27,7 +27,7 @@ require ( github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 github.com/smartcontractkit/chain-selectors v1.0.55 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 github.com/smartcontractkit/chainlink-deployments-framework v0.1.1 @@ -440,7 +440,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 792d0db7e5c..271bc5f4f60 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1448,12 +1448,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go index a336b37311d..0f5d8ff68df 100644 --- a/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_aptos_messaging_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/ethereum/go-ethereum/accounts/abi/bind/v2" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" @@ -75,7 +76,7 @@ func Test_CCIP_Messaging_EVM2Aptos(t *testing.T) { func(t *testing.T) { // TODO: check dummy receiver events // dummyReceiver := state.AptosChains[destChain].ReceiverAddress - // events, err := e.Env.AptosChains[destChain].Client.EventsByHandle(dummyReceiver, fmt.Sprintf("%s::dummy_receiver::ReceivedMessage", dummyReceiver), "received_message_events", nil, nil) + // events, err := e.Env.AptosChains[destChain].Client.EventsByHandle(dummyReceiver, fmt.Sprintf("%s::dummy_receiver::CCIPReceiverState", dummyReceiver), "received_message_events", nil, nil) // require.NoError(t, err) // require.Len(t, events, 1) // var receivedMessage module_dummy_receiver.ReceivedMessage @@ -90,3 +91,77 @@ func Test_CCIP_Messaging_EVM2Aptos(t *testing.T) { fmt.Printf("out: %v\n", out) } + +func Test_CCIP_Messaging_Aptos2EVM(t *testing.T) { + ctx := testhelpers.Context(t) + e, _, _ := testsetups.NewIntegrationEnvironment( + t, + testhelpers.WithNumOfChains(2), + testhelpers.WithAptosChains(1), + ) + + evmChainSelectors := maps.Keys(e.Env.Chains) + aptosChainSelectors := maps.Keys(e.Env.AptosChains) + + fmt.Println("EVM: ", evmChainSelectors) + fmt.Println("Aptos: ", aptosChainSelectors) + + state, err := stateview.LoadOnchainState(e.Env) + require.NoError(t, err) + + sourceChain := aptosChainSelectors[0] + destChain := evmChainSelectors[0] + + t.Log("Source chain (Aptos): ", sourceChain, "Dest chain (EVM): ", destChain) + + testhelpers.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain, destChain, false) + + var ( + replayed bool + nonce uint64 + senderAddress = e.Env.AptosChains[sourceChain].DeployerSigner.AccountAddress() + sender = common.LeftPadBytes(senderAddress[:], 32) + out messagingtest.TestCaseOutput + setup = messagingtest.NewTestSetupWithDeployedEnv( + t, + e, + state, + sourceChain, + destChain, + sender, + false, // testRouter + ) + ) + + t.Run("Message to Aptos", func(t *testing.T) { + latestHead, err := testhelpers.LatestBlock(ctx, e.Env, destChain) + require.NoError(t, err) + message := []byte("Hello EVM, from Aptos!") + out = messagingtest.Run(t, + messagingtest.TestCase{ + TestSetup: setup, + Replayed: replayed, + Nonce: &nonce, + ValidationType: messagingtest.ValidationTypeExec, + FeeToken: "0xa", + Receiver: state.Chains[destChain].Receiver.Address().Bytes(), + MsgData: message, + ExtraArgs: nil, + ExpectedExecutionState: testhelpers.EXECUTION_STATE_SUCCESS, + ExtraAssertions: []func(t *testing.T){ + func(t *testing.T) { + iter, err := state.Chains[destChain].Receiver.FilterMessageReceived(&bind.FilterOpts{ + Context: ctx, + Start: latestHead, + }) + require.NoError(t, err) + require.True(t, iter.Next()) + // MessageReceived doesn't emit the data unfortunately, so can't check that. + }, + }, + }, + ) + }) + + fmt.Printf("out: %v\n", out) +} diff --git a/integration-tests/smoke/ccip/ccip_disable_lane_test.go b/integration-tests/smoke/ccip/ccip_disable_lane_test.go index c921aa87b46..3695601c8cb 100644 --- a/integration-tests/smoke/ccip/ccip_disable_lane_test.go +++ b/integration-tests/smoke/ccip/ccip_disable_lane_test.go @@ -47,7 +47,7 @@ func TestDisableLane(t *testing.T) { wethPrice = deployment.E18Mult(4000) noOfRequests = 3 sendmessage = func(src, dest uint64, deployer *bind.TransactOpts) (*onramp.OnRampCCIPMessageSent, error) { - return testhelpers.SendRequest( + out, err := testhelpers.SendRequest( e, state, testhelpers.WithSender(deployer), @@ -61,6 +61,10 @@ func TestDisableLane(t *testing.T) { FeeToken: common.HexToAddress("0x0"), ExtraArgs: nil, })) + if err != nil { + return nil, err + } + return out.RawEvent.(*onramp.OnRampCCIPMessageSent), nil } assertSendRequestReverted = func(src, dest uint64, deployer *bind.TransactOpts) { diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip/ccip_messaging_test.go index 2254ddb017b..d495e8d8cfb 100644 --- a/integration-tests/smoke/ccip/ccip_messaging_test.go +++ b/integration-tests/smoke/ccip/ccip_messaging_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink-ccip/chains/evm/gobindings/generated/v1_6_0/onramp" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" @@ -178,6 +179,7 @@ func Test_CCIPMessaging_EVM2EVM(t *testing.T) { ExpectedExecutionState: testhelpers.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas }, ) + msgSentEvent := out.MsgSentEvent.RawEvent.(*onramp.OnRampCCIPMessageSent) err := manualexechelpers.ManuallyExecuteAll( ctx, @@ -187,7 +189,7 @@ func Test_CCIPMessaging_EVM2EVM(t *testing.T) { sourceChain, destChain, []int64{ - int64(out.MsgSentEvent.Message.Header.SequenceNumber), //nolint:gosec // seqNr fits in int64 + int64(msgSentEvent.Message.Header.SequenceNumber), //nolint:gosec // seqNr fits in int64 }, 24*time.Hour, // lookbackDurationMsgs 24*time.Hour, // lookbackDurationCommitReport @@ -197,7 +199,7 @@ func Test_CCIPMessaging_EVM2EVM(t *testing.T) { require.NoError(t, err) t.Logf("successfully manually executed message %x", - out.MsgSentEvent.Message.Header.MessageId) + msgSentEvent.Message.Header.MessageId) }) monitorCancel() diff --git a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go index 7b43b0f8be8..215126f86c7 100644 --- a/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go +++ b/integration-tests/smoke/ccip/ccip_migration_to_v_1_6_test.go @@ -700,7 +700,7 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { startBlocks[dest] = &block expectedSeqNumExec := make(map[testhelpers.SourceDestPair][]uint64) expectedSeqNums := make(map[testhelpers.SourceDestPair]uint64) - msgSentEvent, err := testhelpers.SendRequest( + out, err := testhelpers.SendRequest( e.Env, state, testhelpers.WithSourceChain(src1), testhelpers.WithDestChain(dest), @@ -717,14 +717,16 @@ func TestMigrateFromV1_5ToV1_6(t *testing.T) { })) require.NoError(t, err) + msgSentEvent := out.RawEvent.(*onramp.OnRampCCIPMessageSent) + expectedSeqNumExec[testhelpers.SourceDestPair{ SourceChainSelector: src1, DestChainSelector: dest, - }] = []uint64{msgSentEvent.SequenceNumber} + }] = []uint64{out.SequenceNumber} expectedSeqNums[testhelpers.SourceDestPair{ SourceChainSelector: src1, DestChainSelector: dest, - }] = msgSentEvent.SequenceNumber + }] = out.SequenceNumber // This sleep is needed so that plugins come up and start indexing logs. // Otherwise test will flake. diff --git a/integration-tests/smoke/ccip/ccip_reader_test.go b/integration-tests/smoke/ccip/ccip_reader_test.go index 90a481fb3c3..a89c73b0953 100644 --- a/integration-tests/smoke/ccip/ccip_reader_test.go +++ b/integration-tests/smoke/ccip/ccip_reader_test.go @@ -855,7 +855,7 @@ func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { msg := testhelpers.DefaultRouterMessage(state.Chains[destChain].Receiver.Address()) msgSentEvent := testhelpers.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg) require.Equal(t, uint64(i), msgSentEvent.SequenceNumber) - require.Equal(t, uint64(i), msgSentEvent.Message.Header.Nonce) // check outbound nonce incremented + require.Equal(t, uint64(i), msgSentEvent.RawEvent.(*onramp.OnRampCCIPMessageSent).Message.Header.Nonce) // check outbound nonce incremented seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain)) require.NoError(t, err2) require.Equal(t, cciptypes.SeqNum(i+1), seqNum) @@ -1014,7 +1014,7 @@ func TestCCIPReader_DiscoverContracts(t *testing.T) { ctx := tests.Context(t) sb, auth := setupSimulatedBackendAndAuth(t) - //--------------------------------Setup--------------------------------// + // --------------------------------Setup--------------------------------// onRampS1StaticConfig := onramp.OnRampStaticConfig{ ChainSelector: uint64(chainS1), RmnRemote: utils.RandomAddress(), @@ -1134,7 +1134,7 @@ func TestCCIPReader_DiscoverContracts(t *testing.T) { assert.NoError(t, crD.Close()) assert.NoError(t, lpD.Close()) }) - //--------------------------------Setup done--------------------------------// + // --------------------------------Setup done--------------------------------// // Call the ccip chain reader with DiscoverContracts for test contractAddresses, err := reader.DiscoverContracts(ctx, []cciptypes.ChainSelector{chainS1, chainD}) diff --git a/integration-tests/smoke/ccip/ccip_reorg_test.go b/integration-tests/smoke/ccip/ccip_reorg_test.go index 4c841477362..5958875cded 100644 --- a/integration-tests/smoke/ccip/ccip_reorg_test.go +++ b/integration-tests/smoke/ccip/ccip_reorg_test.go @@ -392,14 +392,15 @@ func sendCCIPMessage( FeeToken: common.HexToAddress("0x0"), ExtraArgs: nil, }) + msgSentEvent := msgEvent.RawEvent.(*onramp.OnRampCCIPMessageSent) l.Info(). - Str("messageID", hexutil.Encode(msgEvent.Message.Header.MessageId[:])). - Uint64("blockNumber", msgEvent.Raw.BlockNumber). - Str("blockHash", msgEvent.Raw.BlockHash.String()). + Str("messageID", hexutil.Encode(msgSentEvent.Message.Header.MessageId[:])). + Uint64("blockNumber", msgSentEvent.Raw.BlockNumber). + Str("blockHash", msgSentEvent.Raw.BlockHash.String()). Msg("Sent CCIP message") - return msgEvent + return msgSentEvent } // Check finality violations helper diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index e2f6ceb4c53..2220396a962 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -356,9 +356,9 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20250417193446-eeb0a7d1e049 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index abbd28fcccd..d126b051faf 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1222,12 +1222,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index 95df3c4cf03..61d84e8b947 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -429,9 +429,9 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect github.com/smartcontractkit/chain-selectors v1.0.55 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20250514200342-5169fbe9e28d // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index c3787b2c59e..d77fb29c287 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,12 +1422,12 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.55 h1:jn8cwTBEzAi/eQRDO7EbFpZFn60yxygnSSPP2HPbYs0= github.com/smartcontractkit/chain-selectors v1.0.55/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820 h1:We9ORnHO9T7cyiwWtB1+nogzIANFfzyp5yf0vlL5Odw= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250514143050-3ff5479ce820/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57 h1:I9H4qOLd/C2OzWmjAUsxsEBKQWR6HduWMNOa0E3XYfE= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250520180119-ca1d871d8b57/go.mod h1:+nE9h84c7s1KnpdtWxZu64aafZt/lQ/RtTs7zRknxrY= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e h1:4Hx+m9MovqsayvKdYjnj6OQ5pxXkpU2LDz0UNRuqoA8= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250515132731-ad40fab9b75e/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= github.com/smartcontractkit/chainlink-common v0.7.1-0.20250515101002-90b1d1b66ce4 h1:kWAHWz0JFWzJ9pw5mFGRWSeudqHJOy1ttDTv72WsdG4= From 4c8070b33974b16015d79d78bce6dee4af8fdfab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 22 May 2025 11:40:00 +0200 Subject: [PATCH 134/136] Update action --- .github/workflows/integration-in-memory-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml index b86e4273e0e..4f3ee4ff72d 100644 --- a/.github/workflows/integration-in-memory-tests.yml +++ b/.github/workflows/integration-in-memory-tests.yml @@ -74,7 +74,7 @@ jobs: contents: read needs: changes if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@a17a745159d7537f85956899a38262ece7408e6e + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@50a6cb250423d2a1d8edfd8e42c53f63135043e0 with: workflow_name: Run CCIP Integration Tests For PR chainlink_version: ${{ inputs.cl_ref || github.sha }} @@ -102,7 +102,7 @@ jobs: contents: read needs: changes if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@a17a745159d7537f85956899a38262ece7408e6e + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@50a6cb250423d2a1d8edfd8e42c53f63135043e0 with: workflow_name: Run CCIP Integration Tests For Merge Queue chainlink_version: ${{ inputs.cl_ref || github.sha }} From f9742e9d5da3b1f1379fe7ac9865264aeae6befd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 22 May 2025 11:46:03 +0200 Subject: [PATCH 135/136] gomodtidy --- core/scripts/go.sum | 2 -- deployment/go.sum | 5 +---- go.sum | 2 -- integration-tests/go.sum | 2 -- integration-tests/load/go.sum | 2 -- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 4 ++-- system-tests/tests/go.sum | 2 -- 8 files changed, 4 insertions(+), 17 deletions(-) diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 292bc89715b..197a80a8d4a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1257,8 +1257,6 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= diff --git a/deployment/go.sum b/deployment/go.sum index 0bc914b865e..52bcf9f7264 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1235,14 +1235,11 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab h1:O8NTsAlJYAVRBOD69zlHnEmNvLkQQ3Nnzl0VAsgtFBs= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20250515091132-6c08936b29ab/go.mod h1:Jb05WL6lj5H89XGcaaOinxTf4Gdj+vXO4TcUhqTgqIM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6/go.mod h1:Pw1pSK/XqEKELzGbZ5ht/xzja1iXpODqMqISQNlaZ9w= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a h1:BVhdDkwltth3sw9MeFS3ItQlyPat8M4NUwp86QX2j9U= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a/go.mod h1:k3/Z6AvwurPUlfuDFEonRbkkiTSgNSrtVNhJEWNlUZA= diff --git a/go.sum b/go.sum index 4f559ddfb37..c9b9566da01 100644 --- a/go.sum +++ b/go.sum @@ -1080,8 +1080,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b8431605d8e..25126181368 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1466,8 +1466,6 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index aad71e8c532..eef22daa521 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1448,8 +1448,6 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 32dcc92afa7..8f57128e088 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -356,7 +356,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/ccip-owner-contracts v0.1.0 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250520123946-6aaf88e0848a // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 8677ab8a40d..3b27417ecb8 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1222,8 +1222,8 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20250520151840-9225ee08ced6 h1:o/EafkQLS1pU6dFIyayyYfLTVQlm6EBfNV9YXM1OrvU= diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 2e0e85940c5..95ab0004484 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1422,8 +1422,6 @@ github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9L github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= github.com/smartcontractkit/chain-selectors v1.0.57 h1:KApvb/Kpn15YalY7khFQaHH3mb7teX7JF/gwvq3ti7M= github.com/smartcontractkit/chain-selectors v1.0.57/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575 h1:XxacRSsKHYcr4UR/2HyPES3sZeESHyzOA0JqPFXXitk= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521104113-54f9407e4575/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2 h1:NdkSyuX+sydkdFNqZYQg3Dyz8d1DaFh0hh0xFBl6OSg= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250521134619-a9a1f1d5d3e2/go.mod h1:ITBdddHYp2ocxNjTgBXDGqzWop2qGXenzFK6Oek+uqc= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= From b957364795950efe8ed454067502d93792eafb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 22 May 2025 11:53:22 +0200 Subject: [PATCH 136/136] Update Aptos LOOP plugin --- plugins/plugins.public.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index 5ede15f0bea..46f6b758bbb 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -10,7 +10,7 @@ defaults: plugins: aptos: - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "a9a1f1d5d3e26adeae13e223496fee83886be85b" + gitRef: "223d75c942913b3fc09b2a54f946069798438ed0" installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" cosmos: - moduleURI: "github.com/smartcontractkit/chainlink-cosmos" @@ -32,11 +32,6 @@ plugins: gitRef: "v1.1.2-0.20250519165144-2167692b318c" installPath: "github.com/smartcontractkit/chainlink-solana/pkg/solana/cmd/chainlink-solana" - aptos: - - moduleURI: "github.com/smartcontractkit/chainlink-aptos" - gitRef: "808b080f471d054ff623164b3a316759a8f18758" - installPath: "github.com/smartcontractkit/chainlink-aptos/cmd/chainlink-aptos" - starknet: - moduleURI: "github.com/smartcontractkit/chainlink-starknet/relayer" gitRef: "7e854bab99ef4a9cdbaa8dc2cac1fdf059238682" # 2025-05-15