Skip to content

Commit

Permalink
Migrate v2 (#426)
Browse files Browse the repository at this point in the history
* Migrate v2

* Allow collector

* Fix ci

* Close token manager token account during migrate
  • Loading branch information
jpbogle authored Jul 7, 2023
1 parent 97bb7c3 commit 433926e
Show file tree
Hide file tree
Showing 14 changed files with 752 additions and 297 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ env:
CARGO_TERM_COLOR: always
RUST_TOOLCHAIN: nightly
NPM_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
SOLANA_VERSION: 1.10.41
SOLANA_VERSION: 1.14.15
ANCHOR_GIT: https://github.com/project-serum/anchor
ANCHOR_VERSION: 0.26.0

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ permissions:

env:
CARGO_TERM_COLOR: always
SOLANA_VERSION: 1.10.41
RUST_TOOLCHAIN: nightly
SOLANA_VERSION: 1.14.15
RUST_TOOLCHAIN: 1.69.0
SOTERIA_VERSION: 0.0.0
ANCHOR_GIT: https://github.com/project-serum/anchor
ANCHOR_VERSION: 0.26.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,109 +1,110 @@
use std::str::FromStr;

use crate::errors::ErrorCode;
use crate::state::MintManager;
use crate::state::TokenManager;
use crate::state::MINT_MANAGER_SEED;
use crate::state::*;
use anchor_lang::prelude::*;
use anchor_spl::token::CloseAccount;
use anchor_spl::token::Mint;
use anchor_spl::token::ThawAccount;
use anchor_spl::token::Token;
use anchor_spl::token::TokenAccount;
use anchor_spl::token::{self};
use cardinal_creator_standard::instructions::init_mint_manager;
use mpl_token_metadata::instruction::create_master_edition_v3;
use solana_program::program::invoke_signed;

use anchor_lang::prelude::*;
use anchor_lang::AccountsClose;

#[derive(Accounts)]

pub struct MigrateCtx<'info> {
current_mint_manager: Box<Account<'info, MintManager>>,
/// CHECK: no checks required
#[account(mut)]
mint_manager: UncheckedAccount<'info>,
#[account(mut, close = collector, constraint = token_manager.kind == TokenManagerKind::Permissioned as u8 && token_manager.state == TokenManagerState::Claimed as u8 @ ErrorCode::InvalidTokenManagerState)]
mint_manager: Box<Account<'info, MintManager>>,
#[account(mut, close = collector)]
token_manager: Box<Account<'info, TokenManager>>,
#[account(mut, constraint =
token_manager_token_account.owner == token_manager.key()
&& token_manager_token_account.mint == token_manager.mint
@ ErrorCode::InvalidTokenManagerTokenAccount
)]
token_manager_token_account: Box<Account<'info, TokenAccount>>,
#[account(mut, constraint = token_manager.mint == mint.key() @ ErrorCode::InvalidMint )]
mint: Box<Account<'info, Mint>>,
/// CHECK: no checks required
#[account(mut)]
mint_metadata: UncheckedAccount<'info>,

/// CHECK: no checks required
ruleset: UncheckedAccount<'info>,

#[account(mut)]
token_manager: Box<Account<'info, TokenManager>>,
mint_edition: UncheckedAccount<'info>,

#[account(mut)]
holder_token_account: Box<Account<'info, TokenAccount>>,
/// CHECK: no checks required
token_authority: UncheckedAccount<'info>,

/// CHECK: no checks required
authority: UncheckedAccount<'info>,
#[account(constraint = token_manager.invalidators.contains(&invalidator.key()) @ ErrorCode::InvalidInvalidator)]
invalidator: Signer<'info>,

#[account(mut)]
payer: Signer<'info>,
rent: Sysvar<'info, Rent>,
/// CHECK: no checks required
#[account(mut)]
collector: UncheckedAccount<'info>,
token_program: Program<'info, Token>,
system_program: Program<'info, System>,
/// CHECK: This is not dangerous because the ID is checked with instructions sysvar
#[account(address = cardinal_creator_standard::id())]
cardinal_creator_standard: UncheckedAccount<'info>,
#[account(address = mpl_token_metadata::id())]
mpl_token_metadata: UncheckedAccount<'info>,
}

pub fn handler(ctx: Context<MigrateCtx>) -> Result<()> {
if ctx.accounts.payer.key() != Pubkey::from_str("gmdS6fDgVbeCCYwwvTPJRKM9bFbAgSZh6MTDUT2DcgV").unwrap() {
return Err(error!(ErrorCode::InvalidMigrateAuthority));
}

if ctx.accounts.holder_token_account.delegate.is_some() {
return Err(error!(ErrorCode::CannotMigrateDelegatedToken));
}

let mint_manager_key = ctx.accounts.mint.key();
let current_mint_manager_seeds = &[MINT_MANAGER_SEED.as_bytes(), mint_manager_key.as_ref(), &[ctx.accounts.current_mint_manager.bump]];
let current_mint_manager_signer = &[&current_mint_manager_seeds[..]];
let mint_manager_seeds = &[MINT_MANAGER_SEED.as_bytes(), mint_manager_key.as_ref(), &[ctx.accounts.mint_manager.bump]];
let mint_manager_signer = &[&mint_manager_seeds[..]];

// thaw recipient account
let cpi_accounts = ThawAccount {
account: ctx.accounts.holder_token_account.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
authority: ctx.accounts.current_mint_manager.to_account_info(),
authority: ctx.accounts.mint_manager.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts).with_signer(current_mint_manager_signer);
let cpi_context = CpiContext::new(cpi_program, cpi_accounts).with_signer(mint_manager_signer);
token::thaw_account(cpi_context)?;

invoke_signed(
&init_mint_manager(
ctx.accounts.cardinal_creator_standard.key(),
ctx.accounts.mint_manager.key(),
&create_master_edition_v3(
ctx.accounts.mpl_token_metadata.key(),
ctx.accounts.mint_edition.key(),
ctx.accounts.mint.key(),
ctx.accounts.invalidator.key(),
ctx.accounts.mint_manager.key(),
ctx.accounts.mint_metadata.key(),
ctx.accounts.ruleset.key(),
ctx.accounts.holder_token_account.key(),
ctx.accounts.token_authority.key(),
ctx.accounts.authority.key(),
ctx.accounts.payer.key(),
)?,
Some(0),
),
&[
ctx.accounts.mint_manager.to_account_info(),
ctx.accounts.mpl_token_metadata.to_account_info(),
ctx.accounts.mint_edition.to_account_info(),
ctx.accounts.mint.to_account_info(),
ctx.accounts.invalidator.to_account_info(),
ctx.accounts.mint_manager.to_account_info(),
ctx.accounts.mint_metadata.to_account_info(),
ctx.accounts.ruleset.to_account_info(),
ctx.accounts.holder_token_account.to_account_info(),
ctx.accounts.token_authority.to_account_info(),
ctx.accounts.authority.to_account_info(),
ctx.accounts.payer.to_account_info(),
ctx.accounts.rent.to_account_info(),
ctx.accounts.token_program.to_account_info(),
ctx.accounts.system_program.to_account_info(),
ctx.accounts.cardinal_creator_standard.to_account_info(),
ctx.accounts.mpl_token_metadata.to_account_info(),
],
current_mint_manager_signer,
mint_manager_signer,
)?;

ctx.accounts.token_manager.close(ctx.accounts.payer.to_account_info())?;
let mint = ctx.accounts.token_manager.mint;
let token_manager_seeds = &[TOKEN_MANAGER_SEED.as_bytes(), mint.as_ref(), &[ctx.accounts.token_manager.bump]];
let token_manager_signer = &[&token_manager_seeds[..]];

// close token_manager_token_account
let cpi_accounts = CloseAccount {
account: ctx.accounts.token_manager_token_account.to_account_info(),
destination: ctx.accounts.collector.to_account_info(),
authority: ctx.accounts.token_manager.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts).with_signer(token_manager_signer);
token::close_account(cpi_context)?;

Ok(())
}
66 changes: 28 additions & 38 deletions src/idl/cardinal_token_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,59 +810,54 @@ export type CardinalTokenManager = {
{
name: "migrate";
accounts: [
{
name: "currentMintManager";
isMut: false;
isSigner: false;
},
{
name: "mintManager";
isMut: true;
isSigner: false;
},
{
name: "mint";
name: "tokenManager";
isMut: true;
isSigner: false;
},
{
name: "mintMetadata";
isMut: false;
name: "tokenManagerTokenAccount";
isMut: true;
isSigner: false;
},
{
name: "ruleset";
isMut: false;
name: "mint";
isMut: true;
isSigner: false;
},
{
name: "tokenManager";
name: "mintMetadata";
isMut: true;
isSigner: false;
},
{
name: "holderTokenAccount";
name: "mintEdition";
isMut: true;
isSigner: false;
},
{
name: "tokenAuthority";
isMut: false;
name: "holderTokenAccount";
isMut: true;
isSigner: false;
},
{
name: "authority";
name: "invalidator";
isMut: false;
isSigner: false;
isSigner: true;
},
{
name: "payer";
isMut: true;
isSigner: true;
},
{
name: "rent";
isMut: false;
name: "collector";
isMut: true;
isSigner: false;
},
{
Expand All @@ -876,7 +871,7 @@ export type CardinalTokenManager = {
isSigner: false;
},
{
name: "cardinalCreatorStandard";
name: "mplTokenMetadata";
isMut: false;
isSigner: false;
}
Expand Down Expand Up @@ -2166,59 +2161,54 @@ export const IDL: CardinalTokenManager = {
{
name: "migrate",
accounts: [
{
name: "currentMintManager",
isMut: false,
isSigner: false,
},
{
name: "mintManager",
isMut: true,
isSigner: false,
},
{
name: "mint",
name: "tokenManager",
isMut: true,
isSigner: false,
},
{
name: "mintMetadata",
isMut: false,
name: "tokenManagerTokenAccount",
isMut: true,
isSigner: false,
},
{
name: "ruleset",
isMut: false,
name: "mint",
isMut: true,
isSigner: false,
},
{
name: "tokenManager",
name: "mintMetadata",
isMut: true,
isSigner: false,
},
{
name: "holderTokenAccount",
name: "mintEdition",
isMut: true,
isSigner: false,
},
{
name: "tokenAuthority",
isMut: false,
name: "holderTokenAccount",
isMut: true,
isSigner: false,
},
{
name: "authority",
name: "invalidator",
isMut: false,
isSigner: false,
isSigner: true,
},
{
name: "payer",
isMut: true,
isSigner: true,
},
{
name: "rent",
isMut: false,
name: "collector",
isMut: true,
isSigner: false,
},
{
Expand All @@ -2232,7 +2222,7 @@ export const IDL: CardinalTokenManager = {
isSigner: false,
},
{
name: "cardinalCreatorStandard",
name: "mplTokenMetadata",
isMut: false,
isSigner: false,
},
Expand Down
Loading

0 comments on commit 433926e

Please sign in to comment.