@@ -113,6 +113,7 @@ type TokenPoolConfigWithMCM struct {
113113 TokenPubKey solana.PublicKey
114114 Metadata string
115115 MCMS * proposalutils.TimelockConfig
116+ UpgradeConfig UpgradeConfig
116117}
117118
118119func (cfg TokenPoolConfigWithMCM ) Validate (e cldf.Environment , chainState solanastateview.CCIPChainState ) error {
@@ -126,6 +127,20 @@ func (cfg TokenPoolConfigWithMCM) Validate(e cldf.Environment, chainState solana
126127 return chainState .ValidatePoolDeployment (& e , * cfg .PoolType , cfg .ChainSelector , cfg .TokenPubKey , false , cfg .Metadata )
127128}
128129
130+ func (cfg TokenPoolConfigWithMCM ) ValidateForGlobalInit () error {
131+ if cfg .ChainSelector == 0 {
132+ return errors .New ("chain selector must be defined" )
133+ }
134+ if cfg .PoolType == nil {
135+ return errors .New ("pool type must be defined" )
136+ }
137+ if cfg .Metadata == "" {
138+ return errors .New ("metadata must be defined" )
139+ }
140+
141+ return nil
142+ }
143+
129144type NewMintTokenPoolConfig struct {
130145 ChainSelector uint64
131146 PoolType * solTestTokenPool.PoolType
@@ -197,7 +212,7 @@ func AddTokenPoolAndLookupTable(e cldf.Environment, cfg AddTokenPoolAndLookupTab
197212
198213 var configPDA solana.PublicKey
199214 // Global Configuration
200- configPDA , err = tokenPoolGlobalConfigPDA (tokenPool )
215+ configPDA , err = TokenPoolGlobalConfigPDA (tokenPool )
201216 if err != nil {
202217 return cldf.ChangesetOutput {}, fmt .Errorf ("failed to get solana token pool global config PDA: %w" , err )
203218 }
@@ -438,19 +453,18 @@ func InitGlobalConfigTokenPoolProgram(e cldf.Environment, cfg TokenPoolConfigWit
438453 return cldf.ChangesetOutput {}, err
439454 }
440455 solChainState := state .SolChains [cfg .ChainSelector ]
441- if err := cfg .Validate ( e , solChainState ); err != nil {
456+ if err := cfg .ValidateForGlobalInit ( ); err != nil {
442457 return cldf.ChangesetOutput {}, err
443458 }
444459 chain := e .BlockChains .SolanaChains ()[cfg .ChainSelector ]
445- tokenPubKey := cfg .TokenPubKey
446460 tokenPool , contractType := solChainState .GetActiveTokenPool (* cfg .PoolType , cfg .Metadata )
447461 chainState := state .SolChains [cfg .ChainSelector ]
448462 routerProgramAddress , _ , _ := chainState .GetRouterInfo ()
449463 rmnRemoteAddress := chainState .RMNRemote
450464
451465 var configPDA solana.PublicKey
452466 // Global Configuration
453- configPDA , err = tokenPoolGlobalConfigPDA (tokenPool )
467+ configPDA , err = TokenPoolGlobalConfigPDA (tokenPool )
454468 if err != nil {
455469 return cldf.ChangesetOutput {}, fmt .Errorf ("failed to get solana token pool global config PDA: %w" , err )
456470 }
@@ -475,26 +489,112 @@ func InitGlobalConfigTokenPoolProgram(e cldf.Environment, cfg TokenPoolConfigWit
475489 solLockReleaseTokenPool .SetProgramID (tokenPool )
476490 initGlobalConfigIx , err = solLockReleaseTokenPool .NewInitGlobalConfigInstruction (routerProgramAddress , rmnRemoteAddress , configPDA , chain .DeployerKey .PublicKey (), solana .SystemProgramID , tokenPool , programData .Address ).ValidateAndBuild ()
477491 default :
478- panic ( "unhandled default case" )
492+ return cldf. ChangesetOutput {}, fmt . Errorf ( "invalid token pool type: %w" , err )
479493 }
480494 if err != nil {
481495 return cldf.ChangesetOutput {}, fmt .Errorf ("failed to build ix to init global config: %w" , err )
482496 }
483497
484498 var txns []mcmsTypes.Transaction
485499
486- useMcms := solanastateview .IsSolanaProgramOwnedByTimelock (
487- & e ,
488- chain ,
489- solChainState ,
490- contractType ,
491- tokenPubKey ,
492- cfg .Metadata ,
493- )
500+ instructions := []solana.Instruction {initGlobalConfigIx }
501+
502+ timelockSignerPDA , err := FetchTimelockSigner (e , cfg .ChainSelector )
503+ if err != nil {
504+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to fetch timelock signer: %w" , err )
505+ }
506+ if cfg .UpgradeConfig .UpgradeAuthority == timelockSignerPDA {
507+ err := appendTxs (instructions , tokenPool , contractType , & txns )
508+ if err != nil {
509+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to generate mcms txn: %w" , err )
510+ }
511+ } else {
512+ if err := chain .Confirm (instructions ); err != nil {
513+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to confirm instructions: %w" , err )
514+ }
515+ }
516+
517+ if len (txns ) > 0 {
518+ proposal , err := BuildProposalsForTxns (
519+ e , cfg .ChainSelector , "proposal to init global config in Solana Token Pool" , cfg .MCMS .MinDelay , txns )
520+ if err != nil {
521+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to build proposal: %w" , err )
522+ }
523+ return cldf.ChangesetOutput {
524+ MCMSTimelockProposals : []mcms.TimelockProposal {* proposal },
525+ }, nil
526+ }
527+
528+ return cldf.ChangesetOutput {}, nil
529+ }
530+
531+ func EnableSelfServedInTokenPoolProgram (e cldf.Environment , cfg TokenPoolConfigWithMCM ) (cldf.ChangesetOutput , error ) {
532+ e .Logger .Infow ("Enable self served token pool" , "cfg" , cfg )
533+
534+ return modifySelfServedConfig (e , cfg , true )
535+ }
536+
537+ func DisableSelfServedInTokenPoolProgram (e cldf.Environment , cfg TokenPoolConfigWithMCM ) (cldf.ChangesetOutput , error ) {
538+ e .Logger .Infow ("Disable self served token pool" , "cfg" , cfg )
539+
540+ return modifySelfServedConfig (e , cfg , false )
541+ }
542+
543+ func modifySelfServedConfig (e cldf.Environment , cfg TokenPoolConfigWithMCM , enabled bool ) (cldf.ChangesetOutput , error ) {
544+ state , err := stateview .LoadOnchainState (e )
545+ if err != nil {
546+ return cldf.ChangesetOutput {}, err
547+ }
548+ solChainState := state .SolChains [cfg .ChainSelector ]
549+ if err := cfg .ValidateForGlobalInit (); err != nil {
550+ return cldf.ChangesetOutput {}, err
551+ }
552+ chain := e .BlockChains .SolanaChains ()[cfg .ChainSelector ]
553+ tokenPool , contractType := solChainState .GetActiveTokenPool (* cfg .PoolType , cfg .Metadata )
554+
555+ var configPDA solana.PublicKey
556+ // Global Configuration
557+ configPDA , err = TokenPoolGlobalConfigPDA (tokenPool )
558+ if err != nil {
559+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to get solana token pool global config PDA: %w" , err )
560+ }
561+
562+ // Checking that configPDA exists, so the update method will not fail
563+ _ , err = chain .Client .GetAccountInfo (context .Background (), configPDA )
564+ if err != nil {
565+ e .Logger .Infow ("Global config not initialized" , "configPDA" , configPDA .String ())
566+ return cldf.ChangesetOutput {}, nil
567+ }
568+
569+ programData , err := getSolProgramData (e , chain , tokenPool )
570+ if err != nil {
571+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to get solana token pool program data: %w" , err )
572+ }
573+
574+ var initGlobalConfigIx solana.Instruction
575+ switch * cfg .PoolType {
576+ case solTestTokenPool .BurnAndMint_PoolType :
577+ solBurnMintTokenPool .SetProgramID (tokenPool )
578+ initGlobalConfigIx , err = solBurnMintTokenPool .NewUpdateSelfServedAllowedInstruction (enabled , configPDA , chain .DeployerKey .PublicKey (), tokenPool , programData .Address ).ValidateAndBuild ()
579+ case solTestTokenPool .LockAndRelease_PoolType :
580+ solLockReleaseTokenPool .SetProgramID (tokenPool )
581+ initGlobalConfigIx , err = solLockReleaseTokenPool .NewUpdateSelfServedAllowedInstruction (enabled , configPDA , chain .DeployerKey .PublicKey (), tokenPool , programData .Address ).ValidateAndBuild ()
582+ default :
583+ return cldf.ChangesetOutput {}, fmt .Errorf ("invalid token pool type: %w" , err )
584+ }
585+ if err != nil {
586+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to build ix to init global config: %w" , err )
587+ }
494588
495589 instructions := []solana.Instruction {initGlobalConfigIx }
496590
497- if useMcms {
591+ var txns []mcmsTypes.Transaction
592+
593+ timelockSignerPDA , err := FetchTimelockSigner (e , cfg .ChainSelector )
594+ if err != nil {
595+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to fetch timelock signer: %w" , err )
596+ }
597+ if cfg .UpgradeConfig .UpgradeAuthority == timelockSignerPDA {
498598 err := appendTxs (instructions , tokenPool , contractType , & txns )
499599 if err != nil {
500600 return cldf.ChangesetOutput {}, fmt .Errorf ("failed to generate mcms txn: %w" , err )
@@ -540,15 +640,15 @@ func ModifyMintAuthority(e cldf.Environment, cfg NewMintTokenPoolConfig) (cldf.C
540640 case solTestTokenPool .LockAndRelease_PoolType :
541641 return cldf.ChangesetOutput {}, nil
542642 default :
543- panic ( "unhandled default case" )
643+ return cldf. ChangesetOutput {}, fmt . Errorf ( "invalid token pool type: %w" , err )
544644 }
545645
546646 newMintAuthority := cfg .NewMintAuthority
547647 tokenPoolSigner , _ := solTokenUtil .TokenPoolSignerAddress (tokenPubKey , tokenPool )
548648
549649 poolConfig , err := solTokenUtil .TokenPoolConfigAddress (tokenPubKey , tokenPool )
550650 if err != nil {
551- return cldf.ChangesetOutput {}, fmt .Errorf ("failed to calculate the pool configg : %w" , err )
651+ return cldf.ChangesetOutput {}, fmt .Errorf ("failed to calculate the pool config : %w" , err )
552652 }
553653 programData , err := getSolProgramData (e , chain , tokenPool )
554654 if err != nil {
@@ -1870,7 +1970,7 @@ func InitializeStateVersion(e cldf.Environment, cfg TokenPoolConfigWithMCM) (cld
18701970 tokenPubKey ,
18711971 poolConfig ).ValidateAndBuild ()
18721972 default :
1873- panic ( "unhandled default case" )
1973+ return cldf. ChangesetOutput {}, fmt . Errorf ( "invalid token pool type: %w" , err )
18741974 }
18751975 if err != nil {
18761976 return cldf.ChangesetOutput {}, fmt .Errorf ("failed to build ix to init global config: %w" , err )
@@ -1914,7 +2014,7 @@ func InitializeStateVersion(e cldf.Environment, cfg TokenPoolConfigWithMCM) (cld
19142014 return cldf.ChangesetOutput {}, nil
19152015}
19162016
1917- func tokenPoolGlobalConfigPDA (programID solana.PublicKey ) (solana.PublicKey , error ) {
2017+ func TokenPoolGlobalConfigPDA (programID solana.PublicKey ) (solana.PublicKey , error ) {
19182018 addr , _ , err := solana .FindProgramAddress ([][]byte {[]byte ("config" )}, programID )
19192019 return addr , err
19202020}
0 commit comments