Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ yarn-error.log*
next-env.d.ts

# Anchor
/anchor/target/
/anchor/target/
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The allow/block list is then consumed by a transfer-hook.

The list is managed by a single authority and can be used by several token mints. This enables a separation of concerns between token management and allow/block list management, ideal for scenarios where an issuer wants a 3rd party managed allow/block list or wants to share the same list across a group of assets.


Initializes new tokens with several configuration options:
- Permanent delegate
- Allow list
Expand All @@ -30,7 +31,7 @@ This repo includes a UI to manage the allow/block list based on the `legacy-next
Install dependencies:
`yarn install`

Compile the program:
Compile the program (make sure to replace your program ID):
`anchor build`

Compile the UI:
Expand All @@ -43,8 +44,8 @@ Serve the UI:

There are a couple scripts to manage the local validator and deployment.

To start the local validator and deploy the program:
To start the local validator and deploy the program (uses the anchor CLI and default anchor keypair):
`./scripts/start.sh`

To stop the local validator:
`./scripts/stop.sh`
`./scripts/stop.sh`
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ resolution = true
skip-lint = false

[programs.localnet]
abl-token = "LtkoMwPSKxAE714EY3V1oAEQ5LciqJcRwQQuQnzEhQQ"
abl-token = "EYBRvArz4kb5YLtzjD4TW6DbWhS8qjcMYqBU4wHLW3qj"

[registry]
url = "https://api.apr.dev"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

pub const META_LIST_ACCOUNT_SEED: &[u8] = b"extra-account-metas";
pub const CONFIG_SEED: &[u8] = b"config";
pub const AB_WALLET_SEED: &[u8] = b"ab_wallet";
pub const AB_WALLET_SEED: &[u8] = b"ab_wallet";
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ pub enum ABListError {

#[msg("Wallet blocked")]
WalletBlocked,
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
use anchor_lang::{prelude::*, solana_program::program::invoke, solana_program::system_instruction::transfer};
use anchor_lang::prelude::*;
use anchor_spl::{
token_2022::{spl_token_2022::{extension::{BaseStateWithExtensions, StateWithExtensions}, state::Mint as Mint2022}, Token2022},
token_interface::{spl_token_metadata_interface::state::{Field, TokenMetadata}, token_metadata_initialize, token_metadata_update_field, Mint, TokenMetadataInitialize, TokenMetadataUpdateField},
token_2022::Token2022,
token_interface::{transfer_hook_update, Mint, TransferHookUpdate},
};

use spl_tlv_account_resolution::{
state::ExtraAccountMetaList,
};
use spl_tlv_account_resolution::state::ExtraAccountMetaList;
use spl_transfer_hook_interface::instruction::ExecuteInstruction;

use crate::{Mode, META_LIST_ACCOUNT_SEED, get_extra_account_metas, get_meta_list_size};

use crate::{get_extra_account_metas, get_meta_list_size, META_LIST_ACCOUNT_SEED};

#[derive(Accounts)]
#[instruction(args: AttachToMintArgs)]
pub struct AttachToMint<'info> {
#[account(mut)]
pub payer: Signer<'info>,

pub mint_authority: Signer<'info>,

pub metadata_authority: Signer<'info>,

#[account(
mut,
mint::token_program = token_program,
Expand All @@ -44,78 +36,16 @@ pub struct AttachToMint<'info> {
}

impl AttachToMint<'_> {
pub fn attach_to_mint(&mut self, args: AttachToMintArgs) -> Result<()> {
let mint_info = self.mint.to_account_info();
let mint_data = mint_info.data.borrow();
let mint = StateWithExtensions::<Mint2022>::unpack(&mint_data)?;

let metadata = mint.get_variable_len_extension::<TokenMetadata>();

if metadata.is_err() {
// assume metadata is not initialized, so we need to initialize it

let cpi_accounts = TokenMetadataInitialize {
program_id: self.token_program.to_account_info(),
mint: self.mint.to_account_info(),
metadata: self.mint.to_account_info(), // metadata account is the mint, since data is stored in mint
mint_authority: self.mint_authority.to_account_info(),
update_authority: self.metadata_authority.to_account_info(),
};
let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);
token_metadata_initialize(cpi_ctx, args.name.unwrap(), args.symbol.unwrap(), args.uri.unwrap())?;
}

let cpi_accounts = TokenMetadataUpdateField {
metadata: self.mint.to_account_info(),
update_authority: self.metadata_authority.to_account_info(),
program_id: self.token_program.to_account_info(),
pub fn attach_to_mint(&mut self) -> Result<()> {
let tx_hook_accs = TransferHookUpdate {
token_program_id: self.token_program.to_account_info(),
mint: self.mint.to_account_info(),
authority: self.payer.to_account_info(),
};

let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);
let ctx = CpiContext::new(self.token_program.to_account_info(), tx_hook_accs);

token_metadata_update_field(cpi_ctx, Field::Key("AB".to_string()), args.mode.to_string())?;

if args.mode == Mode::Mixed {
let cpi_accounts = TokenMetadataUpdateField {
metadata: self.mint.to_account_info(),
update_authority: self.metadata_authority.to_account_info(),
program_id: self.token_program.to_account_info(),
};
let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);

token_metadata_update_field(
cpi_ctx,
Field::Key("threshold".to_string()),
args.threshold.to_string(),
)?;
}


let data = self.mint.to_account_info().data_len();
let min_balance = Rent::get()?.minimum_balance(data);
if min_balance > self.mint.to_account_info().get_lamports() {
invoke(
&transfer(
&self.payer.key(),
&self.mint.to_account_info().key(),
min_balance - self.mint.to_account_info().get_lamports(),
),
&[
self.payer.to_account_info(),
self.mint.to_account_info(),
self.system_program.to_account_info(),
],
)?;
}
transfer_hook_update(ctx, Some(crate::ID_CONST))?;

// initialize the extra metas account
let extra_metas_account = &self.extra_metas_account;
Expand All @@ -124,16 +54,5 @@ impl AttachToMint<'_> {
ExtraAccountMetaList::init::<ExecuteInstruction>(&mut data, &metas)?;

Ok(())

}
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct AttachToMintArgs {
pub name: Option<String>,
pub symbol: Option<String>,
pub uri: Option<String>,
pub mode: Mode,
pub threshold: u64,
}

Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
use anchor_lang::{prelude::*, solana_program::system_instruction::transfer };
use anchor_lang::solana_program::program::invoke;
use anchor_lang::{prelude::*, solana_program::system_instruction::transfer};
use anchor_spl::token_interface::spl_token_metadata_interface::state::TokenMetadata;
use anchor_spl::{
token_2022::{
spl_token_2022::extension::{BaseStateWithExtensions, StateWithExtensions},
spl_token_2022::state::Mint,
Token2022,

},
token_interface::{
Mint as MintAccount,
spl_token_metadata_interface::state::Field, token_metadata_update_field,
TokenMetadataUpdateField,
Mint as MintAccount, TokenMetadataUpdateField,
},
};

Expand All @@ -21,7 +19,7 @@ use crate::Mode;
pub struct ChangeMode<'info> {
#[account(mut)]
pub authority: Signer<'info>,

#[account(
mut,
mint::token_program = token_program,
Expand Down Expand Up @@ -73,8 +71,6 @@ impl ChangeMode<'_> {
)?;
}



let data = self.mint.to_account_info().data_len();
let min_balance = Rent::get()?.minimum_balance(data);
if min_balance > self.mint.to_account_info().get_lamports() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use anchor_lang::prelude::*;
use crate::{Config, CONFIG_SEED};

use anchor_lang::prelude::*;

#[derive(Accounts)]
pub struct InitConfig<'info> {
Expand All @@ -21,7 +20,6 @@ pub struct InitConfig<'info> {

impl InitConfig<'_> {
pub fn init_config(&mut self, config_bump: u8) -> Result<()> {

self.config.set_inner(Config {
authority: self.payer.key(),
bump: config_bump,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@ use anchor_spl::{
},
};

use spl_tlv_account_resolution::
state::ExtraAccountMetaList
;
use spl_tlv_account_resolution::state::ExtraAccountMetaList;
use spl_transfer_hook_interface::instruction::ExecuteInstruction;

use crate::{get_extra_account_metas, get_meta_list_size, Mode, META_LIST_ACCOUNT_SEED};


#[derive(Accounts)]
#[instruction(args: InitMintArgs)]
pub struct InitMint<'info> {
Expand Down Expand Up @@ -62,10 +59,7 @@ impl InitMint<'_> {
mint_authority: self.payer.to_account_info(),
update_authority: self.payer.to_account_info(),
};
let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);
let cpi_ctx = CpiContext::new(self.token_program.to_account_info(), cpi_accounts);
token_metadata_initialize(cpi_ctx, args.name, args.symbol, args.uri)?;

let cpi_accounts = TokenMetadataUpdateField {
Expand All @@ -74,10 +68,7 @@ impl InitMint<'_> {
program_id: self.token_program.to_account_info(),
};

let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);
let cpi_ctx = CpiContext::new(self.token_program.to_account_info(), cpi_accounts);

token_metadata_update_field(cpi_ctx, Field::Key("AB".to_string()), args.mode.to_string())?;

Expand All @@ -87,10 +78,7 @@ impl InitMint<'_> {
update_authority: self.payer.to_account_info(),
program_id: self.token_program.to_account_info(),
};
let cpi_ctx = CpiContext::new(
self.token_program.to_account_info(),
cpi_accounts,
);
let cpi_ctx = CpiContext::new(self.token_program.to_account_info(), cpi_accounts);

token_metadata_update_field(
cpi_ctx,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
pub mod attach_to_mint;
pub mod change_mode;
pub mod init_config;
pub mod init_mint;
pub mod init_wallet;
pub mod tx_hook;
pub mod remove_wallet;
pub mod change_mode;
pub mod init_config;
pub mod attach_to_mint;
pub mod tx_hook;

pub use attach_to_mint::*;
pub use change_mode::*;
pub use init_config::*;
pub use init_mint::*;
pub use init_wallet::*;
pub use tx_hook::*;
pub use remove_wallet::*;
pub use change_mode::*;
pub use init_config::*;
pub use attach_to_mint::*;

pub use tx_hook::*;
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use anchor_lang::prelude::*;
use spl_discriminator::SplDiscriminate;
use spl_transfer_hook_interface::instruction::ExecuteInstruction;

pub mod constants;
pub mod errors;
pub mod instructions;
pub mod state;
pub mod constants;
pub mod utils;
pub use constants::*;
pub use errors::*;
pub use instructions::*;
pub use state::*;
pub use constants::*;
pub use utils::*;

declare_id!("LtkoMwPSKxAE714EY3V1oAEQ5LciqJcRwQQuQnzEhQQ");
declare_id!("3ku1ZEGvBEEfhaYsAzBZuecTPEa58ZRhoVqHVGpGxVGi");

#[program]
pub mod abl_token {
Expand All @@ -28,8 +28,8 @@ pub mod abl_token {
ctx.accounts.init_config(ctx.bumps.config)
}

pub fn attach_to_mint(ctx: Context<AttachToMint>, args: AttachToMintArgs) -> Result<()> {
ctx.accounts.attach_to_mint(args)
pub fn attach_to_mint(ctx: Context<AttachToMint>) -> Result<()> {
ctx.accounts.attach_to_mint()
}

#[instruction(discriminator = ExecuteInstruction::SPL_DISCRIMINATOR_SLICE)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{fmt::{self, Display}, str::FromStr};
use std::{
fmt::{self, Display},
str::FromStr,
};

use anchor_lang::prelude::*;

Expand All @@ -20,7 +23,7 @@ pub struct Config {
pub enum Mode {
Allow,
Block,
Mixed
Mixed,
}

impl FromStr for Mode {
Expand All @@ -45,4 +48,3 @@ impl Display for Mode {
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ use spl_tlv_account_resolution::{

use crate::AB_WALLET_SEED;




pub fn get_meta_list_size() -> Result<usize> {
Ok(ExtraAccountMetaList::size_of(1).unwrap())
}
Expand Down
Loading
Loading