Skip to content

Commit dc68689

Browse files
authored
Enable self served token pools (#961)
1 parent 7f07ce3 commit dc68689

28 files changed

+1676
-44
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@
2626
.idea
2727

2828
vendor/
29+
30+
.vscode
31+
chains/solana/tsclient/src/staging.ts
32+
*node_modules

chains/solana/contracts/programs/base-token-pool/src/common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub const POOL_SIGNER_SEED: &[u8] = b"ccip_tokenpool_signer";
1616
pub const EXTERNAL_TOKEN_POOLS_SIGNER: &[u8] = b"external_token_pools_signer";
1717
pub const ALLOWED_OFFRAMP: &[u8] = b"allowed_offramp";
1818

19+
pub const CONFIG_SEED: &[u8] = b"config";
20+
1921
pub const fn valid_version(v: u8, max_version: u8) -> bool {
2022
!uninitialized(v) && v <= max_version
2123
}
@@ -329,6 +331,11 @@ pub struct ReleaseOrMintOutV1 {
329331
pub destination_amount: u64, // token amounts local to solana
330332
}
331333

334+
#[event]
335+
pub struct GlobalConfigUpdated {
336+
pub self_served_allowed: bool,
337+
}
338+
332339
#[event]
333340
pub struct Burned {
334341
pub sender: Pubkey,

chains/solana/contracts/programs/burnmint-token-pool/src/context.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,43 @@ use crate::{program::BurnmintTokenPool, ChainConfig, State};
1010

1111
const MAX_POOL_STATE_V: u8 = 1;
1212

13+
#[derive(Accounts)]
14+
pub struct InitGlobalConfig<'info> {
15+
#[account(
16+
init,
17+
seeds = [CONFIG_SEED],
18+
bump,
19+
payer = authority,
20+
space = ANCHOR_DISCRIMINATOR + PoolConfig::INIT_SPACE,
21+
)]
22+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
23+
24+
#[account(mut)]
25+
pub authority: Signer<'info>,
26+
pub system_program: Program<'info, System>,
27+
28+
// Global Config updates only allowed by program upgrade authority
29+
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
30+
pub program_data: Account<'info, ProgramData>,
31+
}
32+
33+
#[derive(Accounts)]
34+
pub struct UpdateGlobalConfig<'info> {
35+
#[account(
36+
mut,
37+
seeds = [CONFIG_SEED],
38+
bump,
39+
)]
40+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
41+
42+
pub authority: Signer<'info>,
43+
pub system_program: Program<'info, System>,
44+
45+
// Global Config updates only allowed by program upgrade authority
46+
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
47+
pub program_data: Account<'info, ProgramData>,
48+
}
49+
1350
#[derive(Accounts)]
1451
pub struct InitializeTokenPool<'info> {
1552
#[account(
@@ -31,8 +68,14 @@ pub struct InitializeTokenPool<'info> {
3168

3269
// Token pool initialization only allowed by program upgrade authority. Initializing token pools managed
3370
// by the CLL deployment of this program is limited to CLL. Users must deploy their own instance of this program.
34-
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
71+
#[account(constraint = allowed_to_initialize_token_pool(&program_data, &authority, &config, &mint) @ CcipTokenPoolError::Unauthorized)]
3572
pub program_data: Account<'info, ProgramData>,
73+
74+
#[account(
75+
seeds = [CONFIG_SEED],
76+
bump,
77+
)]
78+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
3679
}
3780

3881
#[derive(Accounts)]
@@ -367,3 +410,22 @@ pub struct DeleteChainConfig<'info> {
367410
#[account(mut, address = state.config.owner)]
368411
pub authority: Signer<'info>,
369412
}
413+
414+
// This account can not be declared in the common crate, the program ID for that Account would be incorrect.
415+
#[account]
416+
#[derive(InitSpace)]
417+
pub struct PoolConfig {
418+
pub self_served_allowed: bool,
419+
}
420+
421+
/// Checks if the given authority is allowed to initialize the token pool.
422+
pub fn allowed_to_initialize_token_pool(
423+
program_data: &Account<ProgramData>,
424+
authority: &Signer,
425+
config: &Account<PoolConfig>,
426+
mint: &InterfaceAccount<Mint>,
427+
) -> bool {
428+
program_data.upgrade_authority_address == Some(authority.key()) || // The upgrade authority of the token pool program can initialize a token pool
429+
(config.self_served_allowed && Some(authority.key()) == mint.mint_authority.into() )
430+
// or the mint authority of the token
431+
}

chains/solana/contracts/programs/burnmint-token-pool/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,29 @@ use crate::context::*;
1515
pub mod burnmint_token_pool {
1616
use super::*;
1717

18+
pub fn init_global_config(ctx: Context<InitGlobalConfig>) -> Result<()> {
19+
ctx.accounts.config.self_served_allowed = false;
20+
21+
emit!(GlobalConfigUpdated {
22+
self_served_allowed: ctx.accounts.config.self_served_allowed,
23+
});
24+
25+
Ok(())
26+
}
27+
28+
pub fn update_global_config(
29+
ctx: Context<UpdateGlobalConfig>,
30+
self_served_allowed: bool,
31+
) -> Result<()> {
32+
ctx.accounts.config.self_served_allowed = self_served_allowed;
33+
34+
emit!(GlobalConfigUpdated {
35+
self_served_allowed: ctx.accounts.config.self_served_allowed,
36+
});
37+
38+
Ok(())
39+
}
40+
1841
pub fn initialize(
1942
ctx: Context<InitializeTokenPool>,
2043
router: Pubkey,

chains/solana/contracts/programs/lockrelease-token-pool/src/context.rs

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,50 @@ use anchor_spl::{
33
associated_token::get_associated_token_address_with_program_id,
44
token_interface::{Mint, TokenAccount},
55
};
6-
use base_token_pool::common::{
7-
uninitialized, valid_version, CcipTokenPoolError, LockOrBurnInV1, ReleaseOrMintInV1,
8-
RemoteAddress, RemoteConfig, ALLOWED_OFFRAMP, ANCHOR_DISCRIMINATOR,
9-
EXTERNAL_TOKEN_POOLS_SIGNER, POOL_CHAINCONFIG_SEED, POOL_SIGNER_SEED, POOL_STATE_SEED,
10-
};
6+
use base_token_pool::common::*;
117
use ccip_common::seed;
128

139
use crate::{program::LockreleaseTokenPool, ChainConfig, State};
1410

1511
const MAX_POOL_STATE_V: u8 = 1;
1612

13+
#[derive(Accounts)]
14+
pub struct InitGlobalConfig<'info> {
15+
#[account(
16+
init,
17+
seeds = [CONFIG_SEED],
18+
bump,
19+
payer = authority,
20+
space = ANCHOR_DISCRIMINATOR + PoolConfig::INIT_SPACE,
21+
)]
22+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
23+
24+
#[account(mut)]
25+
pub authority: Signer<'info>,
26+
pub system_program: Program<'info, System>,
27+
28+
// Global Config updates only allowed by program upgrade authority
29+
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
30+
pub program_data: Account<'info, ProgramData>,
31+
}
32+
33+
#[derive(Accounts)]
34+
pub struct UpdateGlobalConfig<'info> {
35+
#[account(
36+
mut,
37+
seeds = [CONFIG_SEED],
38+
bump,
39+
)]
40+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
41+
42+
pub authority: Signer<'info>,
43+
pub system_program: Program<'info, System>,
44+
45+
// Global Config updates only allowed by program upgrade authority
46+
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
47+
pub program_data: Account<'info, ProgramData>,
48+
}
49+
1750
#[derive(Accounts)]
1851
pub struct InitializeTokenPool<'info> {
1952
#[account(
@@ -25,6 +58,7 @@ pub struct InitializeTokenPool<'info> {
2558
)]
2659
pub state: Account<'info, State>, // config PDA for token pool
2760
pub mint: InterfaceAccount<'info, Mint>, // underlying token that the pool wraps
61+
2862
#[account(mut)]
2963
pub authority: Signer<'info>,
3064
pub system_program: Program<'info, System>,
@@ -34,8 +68,14 @@ pub struct InitializeTokenPool<'info> {
3468

3569
// Token pool initialization only allowed by program upgrade authority. Initializing token pools managed
3670
// by the CLL deployment of this program is limited to CLL. Users must deploy their own instance of this program.
37-
#[account(constraint = program_data.upgrade_authority_address == Some(authority.key()) @ CcipTokenPoolError::Unauthorized)]
71+
#[account(constraint = allowed_to_initialize_token_pool(&program_data, &authority, &config, &mint) @ CcipTokenPoolError::Unauthorized)]
3872
pub program_data: Account<'info, ProgramData>,
73+
74+
#[account(
75+
seeds = [CONFIG_SEED],
76+
bump,
77+
)]
78+
pub config: Account<'info, PoolConfig>, // Global Config PDA of the Token Pool
3979
}
4080

4181
#[derive(Accounts)]
@@ -400,3 +440,22 @@ pub struct TokenTransfer<'info> {
400440
#[account(constraint = authority.key() == state.config.owner || authority.key() == state.config.rebalancer @ CcipTokenPoolError::Unauthorized)]
401441
pub authority: Signer<'info>,
402442
}
443+
444+
// This account can not be declared in the common crate, the program ID for that Account would be incorrect.
445+
#[account]
446+
#[derive(InitSpace)]
447+
pub struct PoolConfig {
448+
pub self_served_allowed: bool,
449+
}
450+
451+
/// Checks if the given authority is allowed to initialize the token pool.
452+
pub fn allowed_to_initialize_token_pool(
453+
program_data: &Account<ProgramData>,
454+
authority: &Signer,
455+
config: &Account<PoolConfig>,
456+
mint: &InterfaceAccount<Mint>,
457+
) -> bool {
458+
program_data.upgrade_authority_address == Some(authority.key()) || // The upgrade authority of the token pool program can initialize a token pool
459+
(config.self_served_allowed && Some(authority.key()) == mint.mint_authority.into() )
460+
// or the mint authority of the token
461+
}

chains/solana/contracts/programs/lockrelease-token-pool/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ pub mod lockrelease_token_pool {
1313

1414
use super::*;
1515

16+
pub fn init_global_config(ctx: Context<InitGlobalConfig>) -> Result<()> {
17+
ctx.accounts.config.self_served_allowed = false;
18+
Ok(())
19+
}
20+
21+
pub fn update_global_config(
22+
ctx: Context<UpdateGlobalConfig>,
23+
self_served_allowed: bool,
24+
) -> Result<()> {
25+
ctx.accounts.config.self_served_allowed = self_served_allowed;
26+
Ok(())
27+
}
28+
1629
pub fn initialize(
1730
ctx: Context<InitializeTokenPool>,
1831
router: Pubkey,

chains/solana/contracts/target/idl/base_token_pool.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@
295295
}
296296
],
297297
"events": [
298+
{
299+
"name": "GlobalConfigUpdated",
300+
"fields": [
301+
{
302+
"name": "selfServedAllowed",
303+
"type": "bool",
304+
"index": false
305+
}
306+
]
307+
},
298308
{
299309
"name": "Burned",
300310
"fields": [

chains/solana/contracts/target/idl/burnmint_token_pool.json

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,63 @@
22
"version": "0.1.0-dev",
33
"name": "burnmint_token_pool",
44
"instructions": [
5+
{
6+
"name": "initGlobalConfig",
7+
"accounts": [
8+
{
9+
"name": "config",
10+
"isMut": true,
11+
"isSigner": false
12+
},
13+
{
14+
"name": "authority",
15+
"isMut": true,
16+
"isSigner": true
17+
},
18+
{
19+
"name": "systemProgram",
20+
"isMut": false,
21+
"isSigner": false
22+
},
23+
{
24+
"name": "programData",
25+
"isMut": false,
26+
"isSigner": false
27+
}
28+
],
29+
"args": []
30+
},
31+
{
32+
"name": "updateGlobalConfig",
33+
"accounts": [
34+
{
35+
"name": "config",
36+
"isMut": true,
37+
"isSigner": false
38+
},
39+
{
40+
"name": "authority",
41+
"isMut": false,
42+
"isSigner": true
43+
},
44+
{
45+
"name": "systemProgram",
46+
"isMut": false,
47+
"isSigner": false
48+
},
49+
{
50+
"name": "programData",
51+
"isMut": false,
52+
"isSigner": false
53+
}
54+
],
55+
"args": [
56+
{
57+
"name": "selfServedAllowed",
58+
"type": "bool"
59+
}
60+
]
61+
},
562
{
663
"name": "initialize",
764
"accounts": [
@@ -34,6 +91,11 @@
3491
"name": "programData",
3592
"isMut": false,
3693
"isSigner": false
94+
},
95+
{
96+
"name": "config",
97+
"isMut": false,
98+
"isSigner": false
3799
}
38100
],
39101
"args": [
@@ -579,6 +641,18 @@
579641
}
580642
],
581643
"accounts": [
644+
{
645+
"name": "PoolConfig",
646+
"type": {
647+
"kind": "struct",
648+
"fields": [
649+
{
650+
"name": "selfServedAllowed",
651+
"type": "bool"
652+
}
653+
]
654+
}
655+
},
582656
{
583657
"name": "State",
584658
"type": {

0 commit comments

Comments
 (0)