Skip to content

Commit

Permalink
fix tests with/without mcms
Browse files Browse the repository at this point in the history
  • Loading branch information
tt-cll committed Feb 26, 2025
1 parent 44c532f commit c97da70
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 115 deletions.
114 changes: 61 additions & 53 deletions deployment/ccip/changeset/solana/cs_chain_contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,9 @@ func TestTokenAdminRegistry(t *testing.T) {
state, err := ccipChangeset.LoadOnchainStateSolana(e)
require.NoError(t, err)
linkTokenAddress := state.SolChains[solChain].LinkToken
newAdminNonTimelock, _ := solana.NewRandomPrivateKey()
newAdmin := newAdminNonTimelock.PublicKey()
newTokenAdmin := e.SolChains[solChain].DeployerKey.PublicKey()

var mcmsConfig *ccipChangesetSolana.MCMSConfigSolana
if test.Mcms {
Expand All @@ -508,18 +511,22 @@ func TestTokenAdminRegistry(t *testing.T) {
FeeQuoterOwnedByTimelock: true,
OffRampOwnedByTimelock: true,
}
timelockSignerPDA, err := ccipChangesetSolana.FetchTimelockSigner(e, solChain)
require.NoError(t, err)
newAdmin = timelockSignerPDA
newTokenAdmin = timelockSignerPDA
}
timelockSignerPDA, err := ccipChangesetSolana.FetchTimelockSigner(e, solChain)
require.NoError(t, err)

e, err = commonchangeset.Apply(t, e, nil,
e, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{
commonchangeset.Configure(
// register token admin registry for tokenAddress via admin instruction
deployment.CreateLegacyChangeSet(ccipChangesetSolana.RegisterTokenAdminRegistry),
ccipChangesetSolana.RegisterTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
TokenAdminRegistryAdmin: timelockSignerPDA.String(),
TokenAdminRegistryAdmin: newAdmin.String(),
RegisterType: ccipChangesetSolana.ViaGetCcipAdminInstruction,
MCMSSolana: mcmsConfig,
},
Expand All @@ -530,7 +537,7 @@ func TestTokenAdminRegistry(t *testing.T) {
ChainSelector: solChain,
TokenPubkey: linkTokenAddress,
TokenProgram: ccipChangeset.SPL2022Tokens,
NewAuthority: timelockSignerPDA,
NewAuthority: newTokenAdmin,
},
),
commonchangeset.Configure(
Expand All @@ -539,11 +546,12 @@ func TestTokenAdminRegistry(t *testing.T) {
ccipChangesetSolana.RegisterTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: linkTokenAddress.String(),
TokenAdminRegistryAdmin: timelockSignerPDA.String(),
TokenAdminRegistryAdmin: newAdmin.String(),
RegisterType: ccipChangesetSolana.ViaOwnerInstruction,
MCMSSolana: mcmsConfig,
},
),
},
)
require.NoError(t, err)

Expand All @@ -553,51 +561,52 @@ func TestTokenAdminRegistry(t *testing.T) {
require.NoError(t, err)
require.Equal(t, solana.PublicKey{}, tokenAdminRegistryAccount.Administrator)
// pending administrator should be the proposed admin key
require.Equal(t, timelockSignerPDA, tokenAdminRegistryAccount.PendingAdministrator)
require.Equal(t, newAdmin, tokenAdminRegistryAccount.PendingAdministrator)

linkTokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(linkTokenAddress, state.SolChains[solChain].Router)
var linkTokenAdminRegistryAccount solRouter.TokenAdminRegistry
err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, linkTokenAdminRegistryPDA, &linkTokenAdminRegistryAccount)
require.NoError(t, err)
require.Equal(t, timelockSignerPDA, linkTokenAdminRegistryAccount.PendingAdministrator)
require.Equal(t, newAdmin, linkTokenAdminRegistryAccount.PendingAdministrator)

e, err = commonchangeset.Apply(t, e, nil,
commonchangeset.Configure(
// accept admin role for tokenAddress
deployment.CreateLegacyChangeSet(ccipChangesetSolana.AcceptAdminRoleTokenAdminRegistry),
ccipChangesetSolana.AcceptAdminRoleTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
// NewRegistryAdminPrivateKey: tokenAdminRegistryAdminPrivKey.String(),
MCMSSolana: mcmsConfig,
},
),
)
require.NoError(t, err)
err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
require.NoError(t, err)
// confirm that the administrator is the deployer key
require.Equal(t, timelockSignerPDA, tokenAdminRegistryAccount.Administrator)
require.Equal(t, solana.PublicKey{}, tokenAdminRegistryAccount.PendingAdministrator)

newTokenAdminRegistryAdminPrivKey, _ := solana.NewRandomPrivateKey()
e, err = commonchangeset.Apply(t, e, nil,
commonchangeset.Configure(
// transfer admin role for tokenAddress
deployment.CreateLegacyChangeSet(ccipChangesetSolana.TransferAdminRoleTokenAdminRegistry),
ccipChangesetSolana.TransferAdminRoleTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
NewRegistryAdminPublicKey: newTokenAdminRegistryAdminPrivKey.PublicKey().String(),
// CurrentRegistryAdminPrivateKey: tokenAdminRegistryAdminPrivKey.String(),
MCMSSolana: mcmsConfig,
},
),
)
require.NoError(t, err)
err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
require.NoError(t, err)
require.Equal(t, newTokenAdminRegistryAdminPrivKey.PublicKey(), tokenAdminRegistryAccount.PendingAdministrator)
// While we can assign the admin role arbitrarily regardless of mcms, we can only accept it as timelock
if test.Mcms {
e, err = commonchangeset.Apply(t, e, nil,
commonchangeset.Configure(
// accept admin role for tokenAddress
deployment.CreateLegacyChangeSet(ccipChangesetSolana.AcceptAdminRoleTokenAdminRegistry),
ccipChangesetSolana.AcceptAdminRoleTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
MCMSSolana: mcmsConfig,
},
),
)
require.NoError(t, err)
err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
require.NoError(t, err)
// confirm that the administrator is the deployer key
require.Equal(t, timelockSignerPDA, tokenAdminRegistryAccount.Administrator)
require.Equal(t, solana.PublicKey{}, tokenAdminRegistryAccount.PendingAdministrator)

e, err = commonchangeset.ApplyChangesetsV2(t, e, []commonchangeset.ConfiguredChangeSet{
commonchangeset.Configure(
// transfer admin role for tokenAddress
deployment.CreateLegacyChangeSet(ccipChangesetSolana.TransferAdminRoleTokenAdminRegistry),
ccipChangesetSolana.TransferAdminRoleTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
NewRegistryAdminPublicKey: newAdminNonTimelock.PublicKey().String(),
MCMSSolana: mcmsConfig,
},
),
},
)
require.NoError(t, err)
err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, tokenAdminRegistryPDA, &tokenAdminRegistryAccount)
require.NoError(t, err)
require.Equal(t, newAdminNonTimelock.PublicKey(), tokenAdminRegistryAccount.PendingAdministrator)
}
})
}
}
Expand Down Expand Up @@ -625,6 +634,7 @@ func TestPoolLookupTable(t *testing.T) {
solChain := tenv.Env.AllChainSelectorsSolana()[0]

var mcmsConfig *ccipChangesetSolana.MCMSConfigSolana
newAdmin := tenv.Env.SolChains[solChain].DeployerKey.PublicKey()
if test.Mcms {
_, _ = testhelpers.TransferOwnershipSolana(t, &tenv.Env, solChain, true, true, true, true)
mcmsConfig = &ccipChangesetSolana.MCMSConfigSolana{
Expand All @@ -635,6 +645,9 @@ func TestPoolLookupTable(t *testing.T) {
FeeQuoterOwnedByTimelock: true,
OffRampOwnedByTimelock: true,
}
timelockSignerPDA, err := ccipChangesetSolana.FetchTimelockSigner(tenv.Env, solChain)
require.NoError(t, err)
newAdmin = timelockSignerPDA
}

e, tokenAddress, err := deployToken(t, tenv.Env, solChain)
Expand All @@ -659,17 +672,14 @@ func TestPoolLookupTable(t *testing.T) {
require.Equal(t, lookupTablePubKey, lookupTableEntries0[0])
require.Equal(t, tokenAddress, lookupTableEntries0[7])

timelockSignerPDA, err := ccipChangesetSolana.FetchTimelockSigner(e, solChain)
require.NoError(t, err)

e, err = commonchangeset.Apply(t, e, nil,
commonchangeset.Configure(
// register token admin registry for linkToken via owner instruction
deployment.CreateLegacyChangeSet(ccipChangesetSolana.RegisterTokenAdminRegistry),
ccipChangesetSolana.RegisterTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
TokenAdminRegistryAdmin: timelockSignerPDA.String(),
TokenAdminRegistryAdmin: newAdmin.String(),
RegisterType: ccipChangesetSolana.ViaGetCcipAdminInstruction,
MCMSSolana: mcmsConfig,
},
Expand All @@ -680,17 +690,15 @@ func TestPoolLookupTable(t *testing.T) {
ccipChangesetSolana.AcceptAdminRoleTokenAdminRegistryConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
// NewRegistryAdminPrivateKey: tokenAdminRegistryAdminPrivKey.String(),
MCMSSolana: mcmsConfig,
MCMSSolana: mcmsConfig,
},
),
commonchangeset.Configure(
// set pool -> this updates tokenAdminRegistryPDA, hence above changeset is required
deployment.CreateLegacyChangeSet(ccipChangesetSolana.SetPool),
ccipChangesetSolana.SetPoolConfig{
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
// TokenAdminRegistryAdminPrivateKey: tokenAdminRegistryAdminPrivKey.String(),
ChainSelector: solChain,
TokenPubKey: tokenAddress.String(),
WritableIndexes: []uint8{3, 4, 7},
MCMSSolana: mcmsConfig,
},
Expand All @@ -702,7 +710,7 @@ func TestPoolLookupTable(t *testing.T) {

err = e.SolChains[solChain].GetAccountDataBorshInto(ctx, tokenAdminRegistryPDA, &tokenAdminRegistry)
require.NoError(t, err)
require.Equal(t, timelockSignerPDA, tokenAdminRegistry.Administrator)
require.Equal(t, newAdmin, tokenAdminRegistry.Administrator)
require.Equal(t, lookupTablePubKey, tokenAdminRegistry.LookupTable)
})
}
Expand Down
2 changes: 1 addition & 1 deletion deployment/ccip/changeset/solana/cs_set_ocr3.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func SetOCR3ConfigSolana(e deployment.Environment, cfg v1_6.SetOCR3OffRampConfig
}
if cfg.MCMS != nil {
proposal, err := proposalutils.BuildProposalFromBatchesV2(
e.GetContext(),
e,
timelocks,
proposers,
inspectors,
Expand Down
80 changes: 33 additions & 47 deletions deployment/ccip/changeset/solana/cs_token_admin_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,25 +122,6 @@ func RegisterTokenAdminRegistry(e deployment.Environment, cfg RegisterTokenAdmin
}
}
if routerUsingMCMS {
// ixn := instruction
// programID := chainState.Router.String()
// contractType := ccipChangeset.Router
// data, err := ixn.Data()
// if err != nil {
// return deployment.ChangesetOutput{}, fmt.Errorf("failed to extract data: %w", err)
// }
// tx, err := mcmsSolana.NewTransaction(
// programID,
// data,
// big.NewInt(0), // e.g. value
// ixn.Accounts(), // pass along needed accounts
// string(contractType), // some string identifying the target
// []string{}, // any relevant metadata
// )
// if err != nil {
// return deployment.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err)
// }

tx, err := BuildMCMSTxn(instruction, chainState.Router.String(), ccipChangeset.Router)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err)
Expand Down Expand Up @@ -168,8 +149,7 @@ type TransferAdminRoleTokenAdminRegistryConfig struct {
ChainSelector uint64
TokenPubKey string
NewRegistryAdminPublicKey string
// CurrentRegistryAdminPrivateKey string
MCMSSolana *MCMSConfigSolana
MCMSSolana *MCMSConfigSolana
}

func (cfg TransferAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error {
Expand Down Expand Up @@ -264,20 +244,19 @@ func TransferAdminRoleTokenAdminRegistry(e deployment.Environment, cfg TransferA
MCMSTimelockProposals: []mcms.TimelockProposal{*proposal},
}, nil
}
// instructions := []solana.Instruction{ix1}
// // the existing authority will have to sign the transfer
// if err := chain.Confirm(instructions, solCommonUtil.AddSigners(currentRegistryAdminPrivateKey)); err != nil {
// return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
// }
// the existing authority will have to sign the transfer
chain := e.SolChains[cfg.ChainSelector]
if err := chain.Confirm([]solana.Instruction{ix1}); err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
}
return deployment.ChangesetOutput{}, nil
}

// ACCEPT TOKEN ADMIN REGISTRY
type AcceptAdminRoleTokenAdminRegistryConfig struct {
ChainSelector uint64
TokenPubKey string
// NewRegistryAdminPrivateKey string
MCMSSolana *MCMSConfigSolana
MCMSSolana *MCMSConfigSolana
}

func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environment) error {
Expand All @@ -295,6 +274,14 @@ func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environ
return err
}
routerUsingMcms := cfg.MCMSSolana != nil && cfg.MCMSSolana.RouterOwnedByTimelock
newAdmin := chain.DeployerKey.PublicKey()
var err error
if routerUsingMcms {
newAdmin, err = FetchTimelockSigner(e, cfg.ChainSelector)
if err != nil {
return fmt.Errorf("failed to fetch timelock signer: %w", err)
}
}
if err := ccipChangeset.ValidateOwnershipSolana(&e, chain, routerUsingMcms, chainState.Router, ccipChangeset.Router); err != nil {
return fmt.Errorf("failed to validate ownership: %w", err)
}
Expand All @@ -306,14 +293,9 @@ func (cfg AcceptAdminRoleTokenAdminRegistryConfig) Validate(e deployment.Environ
if err := chain.GetAccountDataBorshInto(context.Background(), tokenAdminRegistryPDA, &tokenAdminRegistryAccount); err != nil {
return fmt.Errorf("token admin registry not found for (mint: %s, router: %s), cannot accept admin role", tokenPubKey.String(), chainState.Router.String())
}
// check if accepting admin is the pending admin
newRegistryAdminPublicKey, err := FetchTimelockSigner(e, cfg.ChainSelector)
if err != nil {
return fmt.Errorf("failed to fetch timelock signer: %w", err)
}
if !tokenAdminRegistryAccount.PendingAdministrator.Equals(newRegistryAdminPublicKey) {
if !tokenAdminRegistryAccount.PendingAdministrator.Equals(newAdmin) {
return fmt.Errorf("new admin public key (%s) does not match pending registry admin role (%s) for token %s",
newRegistryAdminPublicKey.String(),
newAdmin.String(),
tokenAdminRegistryAccount.PendingAdministrator.String(),
tokenPubKey.String(),
)
Expand All @@ -325,29 +307,36 @@ func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdmin
if err := cfg.Validate(e); err != nil {
return deployment.ChangesetOutput{}, err
}
// chain := e.SolChains[cfg.ChainSelector]
chain := e.SolChains[cfg.ChainSelector]
state, _ := ccipChangeset.LoadOnchainState(e)
chainState := state.SolChains[cfg.ChainSelector]
tokenPubKey := solana.MustPublicKeyFromBase58(cfg.TokenPubKey)

// verified
tokenAdminRegistryPDA, _, _ := solState.FindTokenAdminRegistryPDA(tokenPubKey, chainState.Router)
newRegistryAdminPublicKey, err := FetchTimelockSigner(e, cfg.ChainSelector)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch timelock signer: %w", err)
}

routerUsingMCMS := cfg.MCMSSolana != nil && cfg.MCMSSolana.RouterOwnedByTimelock
var authority solana.PublicKey
var err error
if routerUsingMCMS {
authority, err = FetchTimelockSigner(e, cfg.ChainSelector)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to fetch timelock signer: %w", err)
}
} else {
authority = chain.DeployerKey.PublicKey()
}
ix1, err := solRouter.NewAcceptAdminRoleTokenAdminRegistryInstruction(
chainState.RouterConfigPDA,
tokenAdminRegistryPDA,
tokenPubKey,
newRegistryAdminPublicKey,
authority,
).ValidateAndBuild()
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate instructions: %w", err)
}
if routerUsingMCMS {
// We will only be able to accept the admin role if the pending admin is the timelock signer
tx, err := BuildMCMSTxn(ix1, chainState.Router.String(), ccipChangeset.Router)
if err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to create transaction: %w", err)
Expand All @@ -361,11 +350,8 @@ func AcceptAdminRoleTokenAdminRegistry(e deployment.Environment, cfg AcceptAdmin
MCMSTimelockProposals: []mcms.TimelockProposal{*proposal},
}, nil
}

// instructions := []solana.Instruction{ix1}
// // the new authority will have to sign the acceptance
// if err := chain.Confirm(instructions, solCommonUtil.AddSigners(newRegistryAdminPrivateKey)); err != nil {
// return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
// }
if err := chain.Confirm([]solana.Instruction{ix1}); err != nil {
return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm instructions: %w", err)
}
return deployment.ChangesetOutput{}, nil
}
Loading

0 comments on commit c97da70

Please sign in to comment.