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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 90 additions & 75 deletions deployment/ccip/changeset/solana_v0_1_1/cs_deploy_chain_test.go

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/gagliardetto/solana-go"
chainselectors "github.com/smartcontractkit/chain-selectors"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"

"github.com/smartcontractkit/chainlink-ccip/chains/solana/contracts/tests/testutils"
burnmint "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/v0_1_1/burnmint_token_pool"
Expand Down Expand Up @@ -38,7 +37,7 @@ import (
commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset"
"github.com/smartcontractkit/chainlink/deployment/common/proposalutils"
commontypes "github.com/smartcontractkit/chainlink/deployment/common/types"
"github.com/smartcontractkit/chainlink/deployment/environment/memory"
"github.com/smartcontractkit/chainlink/deployment/internal/soltestutils"
)

func TestValidateContracts(t *testing.T) {
Expand Down Expand Up @@ -193,26 +192,33 @@ func TestValidate(t *testing.T) {
// the transfer ownership changeset.
func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, stateview.CCIPOnChainState) {
t.Helper()
lggr := logger.Test(t)
e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{
Bootstraps: 1,
Chains: 2,
SolChains: 1,
Nodes: 4,
CCIPSolanaContractVersion: memory.SolanaContractV0_1_1,
})
evmSelectors := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilyEVM))
homeChainSel := evmSelectors[0]
solChainSelectors := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilySolana))
solChain1 := solChainSelectors[0]
solChain := e.BlockChains.SolanaChains()[solChain1]
nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain)

homeChainSel := chainselectors.TEST_90000001.Selector
solChainSel := chainselectors.TEST_22222222222222222222222222222222222222222222.Selector

programsPath := t.TempDir()
progIDs := soltestutils.LoadCCIPPrograms(t, programsPath)
env, err := environment.New(t.Context(),
environment.WithEVMSimulated(t, []uint64{homeChainSel}),
environment.WithSolanaContainer(t, []uint64{solChainSel}, programsPath, progIDs),
environment.WithLogger(logger.Test(t)),
)
require.NoError(t, err)

testhelpers.RegisterNodes(t, env, 4, homeChainSel)

solChain := env.BlockChains.SolanaChains()[solChainSel]
nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain)
require.NoError(t, err)

// Fund account for fees
testutils.FundAccounts(e.GetContext(), []solana.PrivateKey{*solChain.DeployerKey}, solChain.Client, t)
err = testhelpers.SavePreloadedSolAddresses(e, solChainSelectors[0])
testutils.FundAccounts(env.GetContext(), []solana.PrivateKey{*solChain.DeployerKey}, solChain.Client, t)
err = testhelpers.SavePreloadedSolAddresses(*env, solChainSel)
require.NoError(t, err)
solLinkTokenPrivKey, _ := solana.NewRandomPrivateKey()

e := *env

e, _, err = commonchangeset.ApplyChangesets(t, e, []commonchangeset.ConfiguredChangeSet{
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(v1_6.DeployHomeChainChangeset),
Expand All @@ -229,7 +235,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(commonchangeset.DeploySolanaLinkToken),
commonchangeset.DeploySolanaLinkTokenConfig{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenPrivKey: solLinkTokenPrivKey,
TokenDecimals: 9,
},
Expand All @@ -238,7 +244,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
cldf.CreateLegacyChangeSet(ccipChangesetSolana.DeployChainContractsChangeset),
ccipChangesetSolana.DeployChainContractsConfig{
HomeChainSelector: homeChainSel,
ChainSelector: solChain1,
ChainSelector: solChainSel,
ContractParamsPerChain: ccipChangesetSolana.ChainContractParams{
FeeQuoterParams: ccipChangesetSolana.FeeQuoterParams{
DefaultMaxFeeJuelsPerMsg: solBinary.Uint128{Lo: 300000000, Hi: 0, Endianness: nil},
Expand All @@ -252,23 +258,23 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(ccipChangesetSolana.DeploySolanaToken),
ccipChangesetSolana.DeploySolanaTokenConfig{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenProgramName: shared.SPL2022Tokens,
TokenDecimals: 9,
},
),
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(ccipChangesetSolana.DeploySolanaToken),
ccipChangesetSolana.DeploySolanaTokenConfig{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenProgramName: shared.SPLTokens,
TokenDecimals: 9,
},
),
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(commonchangeset.DeployMCMSWithTimelockV2),
map[uint64]commontypes.MCMSWithTimelockConfigV2{
solChain1: {
solChainSel: {
Canceller: proposalutils.SingleGroupMCMSV2(t),
Proposer: proposalutils.SingleGroupMCMSV2(t),
Bypasser: proposalutils.SingleGroupMCMSV2(t),
Expand All @@ -280,18 +286,18 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
require.NoError(t, err)

// solana verification
err = testhelpers.ValidateSolanaState(e, solChainSelectors)
err = testhelpers.ValidateSolanaState(e, []uint64{solChainSel})
require.NoError(t, err)
state, err := stateview.LoadOnchainStateSolana(e)
require.NoError(t, err)
tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0]
tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0]
tokenAddressLockRelease := state.SolChains[solChainSel].SPL2022Tokens[0]
tokenAddressBurnMint := state.SolChains[solChainSel].SPLTokens[0]

e, _, err = commonchangeset.ApplyChangesets(t, e, []commonchangeset.ConfiguredChangeSet{
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(ccipChangesetSolana.InitGlobalConfigTokenPoolProgram),
ccipChangesetSolana.TokenPoolConfigWithMCM{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenPoolConfigs: []ccipChangesetSolana.TokenPoolConfig{
{
TokenPubKey: tokenAddressLockRelease,
Expand All @@ -309,7 +315,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(ccipChangesetSolana.AddTokenPoolAndLookupTable),
ccipChangesetSolana.AddTokenPoolAndLookupTableConfig{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenPoolConfigs: []ccipChangesetSolana.TokenPoolConfig{
{
TokenPubKey: tokenAddressLockRelease,
Expand All @@ -322,7 +328,7 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
commonchangeset.Configure(
cldf.CreateLegacyChangeSet(ccipChangesetSolana.AddTokenPoolAndLookupTable),
ccipChangesetSolana.AddTokenPoolAndLookupTableConfig{
ChainSelector: solChain1,
ChainSelector: solChainSel,
TokenPoolConfigs: []ccipChangesetSolana.TokenPoolConfig{
{
TokenPubKey: tokenAddressBurnMint,
Expand All @@ -340,19 +346,21 @@ func prepareEnvironmentForOwnershipTransfer(t *testing.T) (cldf.Environment, sta
func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {
t.Parallel()
skipInCI(t)

e, state := prepareEnvironmentForOwnershipTransfer(t)
solChain1 := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilySolana))[0]
solChain := e.BlockChains.SolanaChains()[solChain1]
solSelector := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilySolana))[0]
solChain := e.BlockChains.SolanaChains()[solSelector]
solState := state.SolChains[solSelector]

tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0]
tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0]
tokenAddressLockRelease := solState.SPL2022Tokens[0]
tokenAddressBurnMint := solState.SPLTokens[0]

burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, state.SolChains[solChain1].BurnMintTokenPools[shared.CLLMetadata])
lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, state.SolChains[solChain1].LockReleaseTokenPools[shared.CLLMetadata])
burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, solState.BurnMintTokenPools[shared.CLLMetadata])
lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, solState.LockReleaseTokenPools[shared.CLLMetadata])
timelockSignerPDA, _ := testhelpers.TransferOwnershipSolanaV0_1_1(
t,
&e,
solChain1,
solSelector,
false,
ccipChangesetSolana.CCIPContractsToTransfer{
Router: true,
Expand All @@ -370,7 +378,7 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {

// (A) Check Router ownership - we need to add retries as the ownership transfer commitment is confirmed and not finalized.
require.Eventually(t, func() bool {
routerConfigPDA := state.SolChains[solChain1].RouterConfigPDA
routerConfigPDA := solState.RouterConfigPDA
t.Logf("Checking Router Config PDA ownership data configPDA: %s", routerConfigPDA.String())
programData := ccip_router.Config{}
err := solChain.GetAccountDataBorshInto(ctx, routerConfigPDA, &programData)
Expand All @@ -380,7 +388,7 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {

// (B) Check FeeQuoter ownership
require.Eventually(t, func() bool {
feeQuoterConfigPDA := state.SolChains[solChain1].FeeQuoterConfigPDA
feeQuoterConfigPDA := solState.FeeQuoterConfigPDA
t.Logf("Checking Fee Quoter PDA ownership data configPDA: %s", feeQuoterConfigPDA.String())
programData := fee_quoter.Config{}
err := solChain.GetAccountDataBorshInto(ctx, feeQuoterConfigPDA, &programData)
Expand All @@ -390,7 +398,7 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {

// (C) Check OffRamp:
require.Eventually(t, func() bool {
offRampConfigPDA := state.SolChains[solChain1].OffRampConfigPDA
offRampConfigPDA := solState.OffRampConfigPDA
programData := ccip_offramp.Config{}
t.Logf("Checking Off Ramp PDA ownership data configPDA: %s", offRampConfigPDA.String())
err := solChain.GetAccountDataBorshInto(ctx, offRampConfigPDA, &programData)
Expand Down Expand Up @@ -418,7 +426,7 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {

// (F) Check RMNRemote ownership
require.Eventually(t, func() bool {
rmnRemoteConfigPDA := state.SolChains[solChain1].RMNRemoteConfigPDA
rmnRemoteConfigPDA := solState.RMNRemoteConfigPDA
t.Logf("Checking RMNRemote PDA ownership data configPDA: %s", rmnRemoteConfigPDA.String())
programData := rmn_remote.Config{}
err := solChain.GetAccountDataBorshInto(ctx, rmnRemoteConfigPDA, &programData)
Expand All @@ -430,19 +438,21 @@ func TestTransferCCIPToMCMSWithTimelockSolana(t *testing.T) {
func TestTransferCCIPFromMCMSWithTimelockSolana(t *testing.T) {
t.Parallel()
skipInCI(t)

e, state := prepareEnvironmentForOwnershipTransfer(t)
solChain1 := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilySolana))[0]
solChain := e.BlockChains.SolanaChains()[solChain1]
solSelector := e.BlockChains.ListChainSelectors(cldf_chain.WithFamily(chainselectors.FamilySolana))[0]
solChain := e.BlockChains.SolanaChains()[solSelector]
solState := state.SolChains[solSelector]

tokenAddressLockRelease := state.SolChains[solChain1].SPL2022Tokens[0]
tokenAddressBurnMint := state.SolChains[solChain1].SPLTokens[0]
tokenAddressLockRelease := solState.SPL2022Tokens[0]
tokenAddressBurnMint := solState.SPLTokens[0]

burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, state.SolChains[solChain1].BurnMintTokenPools[shared.CLLMetadata])
lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, state.SolChains[solChain1].LockReleaseTokenPools[shared.CLLMetadata])
burnMintPoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressBurnMint, solState.BurnMintTokenPools[shared.CLLMetadata])
lockReleasePoolConfigPDA, _ := solTokenUtil.TokenPoolConfigAddress(tokenAddressLockRelease, solState.LockReleaseTokenPools[shared.CLLMetadata])
timelockSignerPDA, _ := testhelpers.TransferOwnershipSolanaV0_1_1(
t,
&e,
solChain1,
solSelector,
false,
ccipChangesetSolana.CCIPContractsToTransfer{
Router: true,
Expand All @@ -461,7 +471,7 @@ func TestTransferCCIPFromMCMSWithTimelockSolana(t *testing.T) {
CurrentOwner: timelockSignerPDA,
ProposedOwner: solChain.DeployerKey.PublicKey(),
ContractsByChain: map[uint64]ccipChangesetSolana.CCIPContractsToTransfer{
solChain1: {
solSelector: {
Router: true,
FeeQuoter: true,
OffRamp: true,
Expand All @@ -476,7 +486,7 @@ func TestTransferCCIPFromMCMSWithTimelockSolana(t *testing.T) {
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
config := state.SolChains[solSelector].RouterConfigPDA
ix, err := ccip_router.NewAcceptOwnershipInstruction(
config, solChain.DeployerKey.PublicKey(),
).ValidateAndBuild()
Expand Down
Loading
Loading