Skip to content

Commit

Permalink
Use invalidator
Browse files Browse the repository at this point in the history
  • Loading branch information
jpbogle committed Feb 4, 2022
1 parent 3e05231 commit a384f73
Show file tree
Hide file tree
Showing 18 changed files with 227 additions and 8 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion programs/cardinal-rent-receipt/src/instructions/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn handler(ctx: Context<ClaimCtx>, bump: u8, receipt_token_manager_bump: u8)
system_program: ctx.accounts.system_program.to_account_info(),
};
let issue_ctx = CpiContext::new(ctx.accounts.cardinal_token_manager.to_account_info(), cpi_accounts).with_signer(rent_receipt_signer);
cardinal_token_manager::cpi::issue(issue_ctx, IssueIx{amount: 1, kind: TokenManagerKind::Managed as u8})?;
cardinal_token_manager::cpi::issue(issue_ctx, IssueIx{amount: 1, kind: TokenManagerKind::Authority as u8})?;

let cpi_accounts = cardinal_token_manager::cpi::accounts::ClaimCtx {
token_manager: ctx.accounts.receipt_token_manager.to_account_info(),
Expand Down
2 changes: 1 addition & 1 deletion programs/cardinal-time-invalidator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cardinal-time-invalidator"
version = "0.0.3"
description = "Cardinal paid claim approver"
description = "Program for a invalidating token managers based on time"
edition = "2021"
homepage = "https://cardinal.so"
repository = "https://github.com/cardinal-labs/cardinal-token-manager/tree/main/programs/cardinal-time-invalidator"
Expand Down
4 changes: 3 additions & 1 deletion programs/cardinal-token-manager/src/instructions/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub fn handler(ctx: Context<ClaimCtx>) -> ProgramResult {
token::transfer(cpi_context, token_manager.amount)?;

// if this is a managed token, this means we will revoke it at the end of life, so we need to delegate and freeze
if token_manager.kind == TokenManagerKind::Managed as u8 {
if token_manager.kind == TokenManagerKind::Authority as u8 {
// set account delegate of recipient token account to certificate PDA
let cpi_accounts = Approve {
to: ctx.accounts.recipient_token_account.to_account_info(),
Expand All @@ -86,6 +86,8 @@ pub fn handler(ctx: Context<ClaimCtx>) -> ProgramResult {
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::freeze_account(cpi_context)?;
} else if token_manager.kind == TokenManagerKind::Edition as u8 {

}
return Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn handler(ctx: Context<InvalidateCtx>) -> ProgramResult {
let token_manager_seeds = &[TOKEN_MANAGER_SEED.as_bytes(), mint.as_ref(), &[token_manager.bump]];
let token_manager_signer = &[&token_manager_seeds[..]];

if token_manager.kind == TokenManagerKind::Managed as u8 {
if token_manager.kind == TokenManagerKind::Authority as u8 {
// if claimed we need to thaw
if token_manager.state == TokenManagerState::Claimed as u8 {
// thaw recipient account
Expand All @@ -67,6 +67,8 @@ pub fn handler(ctx: Context<InvalidateCtx>) -> ProgramResult {
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::transfer(cpi_context, token_manager.amount)?;
} else if token_manager.kind == TokenManagerKind::Edition as u8 {

}

token_manager.state = TokenManagerState::Invalidated as u8;
Expand Down
4 changes: 3 additions & 1 deletion programs/cardinal-token-manager/src/instructions/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ pub struct IssueCtx<'info> {
}

pub fn handler(ctx: Context<IssueCtx>, ix: IssueIx) -> ProgramResult {
if ix.kind != TokenManagerKind::Managed as u8 && ix.kind != TokenManagerKind::Unmanaged as u8{
if ix.kind != TokenManagerKind::Authority as u8
&& ix.kind != TokenManagerKind::Unmanaged as u8
&& ix.kind != TokenManagerKind::Edition as u8 {
return Err(ErrorCode::InvalidTokenManagerKind.into());
}
// set token manager data
Expand Down
6 changes: 4 additions & 2 deletions programs/cardinal-token-manager/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ pub enum TokenManagerState {
#[derive(Clone, Debug, PartialEq, AnchorSerialize, AnchorDeserialize)]
#[repr(u8)]
pub enum TokenManagerKind {
/// Token a managed rental and will be returned to issuer
Managed = 1,
/// Token a managed rental and will use freeze authority to manage the token
Authority = 1,
/// Token is unmanaged and can be traded freely until expiration
Unmanaged = 2,
/// Token is a metaplex edition and so it uses metaplex program to freeze
Edition = 3,
}

pub fn token_manager_size(num_invalidators: usize) -> usize {
Expand Down
31 changes: 31 additions & 0 deletions programs/cardinal-use-invalidator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "cardinal-use-invalidator"
version = "0.0.3"
description = "Cardinal usage invalidator and counter"
edition = "2021"
homepage = "https://cardinal.so"
repository = "https://github.com/cardinal-labs/cardinal-token-manager/tree/main/programs/cardinal-time-invalidator"
authors = ["Jeremy Bogle <[email protected]>"]
license = "AGPL-3.0"
keywords = ["solana", "cardinal"]

[lib]
crate-type = ["cdylib", "lib"]
name = "cardinal_use_invalidator"

[features]
no-entrypoint = []
no-idl = []
cpi = ["no-entrypoint"]
default = []

[dependencies]
anchor-lang = "0.20.1"
anchor-spl = "0.20.1"
spl-associated-token-account = "1.0.2"
spl-token = { version = "3.1.1", features = ["no-entrypoint"] }
solana-program = "1.8.1"
cardinal-token-manager = { version = "^0.0.3", path = "../cardinal-token-manager", features = ["cpi"] }

[dev-dependencies]
proptest = { version = "1.0" }
5 changes: 5 additions & 0 deletions programs/cardinal-use-invalidator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Use invalidator

Program for a invalidating token managers based on usages

More in-depth documentation pending.
2 changes: 2 additions & 0 deletions programs/cardinal-use-invalidator/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
13 changes: 13 additions & 0 deletions programs/cardinal-use-invalidator/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use anchor_lang::prelude::*;

#[error]
pub enum ErrorCode {
#[msg("Token account not owned by the claim approver")]
InvalidPaymentTokenAccount,
#[msg("Token account not owned by the issuer")]
InvalidIssuerTokenAccount,
#[msg("Invalid token manager for this claim approver")]
InvalidTokenManager,
#[msg("Usages not at the maximum")]
InvalidUsages
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use {
crate::{state::*, errors::*},
anchor_lang::{prelude::*},
cardinal_token_manager::{state::TokenManager},
};

#[derive(Accounts)]
#[instruction(num_usages: u64)]
pub struct IncrementUsagesCtx<'info> {
token_manager: Box<Account<'info, TokenManager>>,

#[account(mut, constraint = use_invalidator.usages + num_usages <= use_invalidator.max_usages @ ErrorCode::InvalidUsages)]
use_invalidator: Box<Account<'info, UseInvalidator>>,

#[account(mut)]
payer: Signer<'info>,
system_program: Program<'info, System>,
}

pub fn handler(ctx: Context<IncrementUsagesCtx>, num_usages: u64) -> ProgramResult {
let use_invalidator = &mut ctx.accounts.use_invalidator;
use_invalidator.usages += num_usages;
return Ok(())
}
30 changes: 30 additions & 0 deletions programs/cardinal-use-invalidator/src/instructions/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use {
crate::{state::*},
anchor_lang::{prelude::*},
cardinal_token_manager::{state::TokenManager},
};

#[derive(Accounts)]
#[instruction(bump: u8, _max_usages: u64)]
pub struct InitCtx<'info> {
token_manager: Box<Account<'info, TokenManager>>,

#[account(
init,
payer = payer,
space = USE_INVALIDATOR_SIZE,
seeds = [USE_INVALIDATOR_SEED.as_bytes(), token_manager.key().as_ref()], bump = bump,
)]
use_invalidator: Box<Account<'info, UseInvalidator>>,

#[account(mut)]
payer: Signer<'info>,
system_program: Program<'info, System>,
}

pub fn handler(ctx: Context<InitCtx>, bump: u8, max_usages: u64) -> ProgramResult {
let use_invalidator = &mut ctx.accounts.use_invalidator;
use_invalidator.bump = bump;
use_invalidator.max_usages = max_usages;
return Ok(())
}
50 changes: 50 additions & 0 deletions programs/cardinal-use-invalidator/src/instructions/invalidate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use {
crate::{state::*, errors::*},
anchor_lang::{prelude::*},
cardinal_token_manager::{program::CardinalTokenManager, state::{TokenManager}},
};

#[derive(Accounts)]
pub struct InvalidateCtx<'info> {
#[account(mut)]
token_manager: Box<Account<'info, TokenManager>>,

#[account(mut,
constraint = use_invalidator.usages >= use_invalidator.max_usages @ ErrorCode::InvalidUsages,
close = invalidator
)]
use_invalidator: Box<Account<'info, UseInvalidator>>,

#[account(mut)]
invalidator: Signer<'info>,

cardinal_token_manager: Program<'info, CardinalTokenManager>,

// cpi accounts
token_manager_token_account: UncheckedAccount<'info>,
token_program: UncheckedAccount<'info>,
mint: UncheckedAccount<'info>,
recipient_token_account: UncheckedAccount<'info>,
issuer_token_account: UncheckedAccount<'info>,
}

pub fn handler(ctx: Context<InvalidateCtx>) -> ProgramResult {
let token_manager_key = ctx.accounts.token_manager.key();
let use_invalidator_seeds = &[USE_INVALIDATOR_SEED.as_bytes(), token_manager_key.as_ref(), &[ctx.accounts.use_invalidator.bump]];
let use_invalidator_signer = &[&use_invalidator_seeds[..]];

// invalidate
let cpi_accounts = cardinal_token_manager::cpi::accounts::InvalidateCtx {
token_manager: ctx.accounts.token_manager.to_account_info(),
token_manager_token_account: ctx.accounts.token_manager_token_account.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
recipient_token_account: ctx.accounts.recipient_token_account.to_account_info(),
issuer_token_account: ctx.accounts.issuer_token_account.to_account_info(),
invalidator: ctx.accounts.invalidator.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
};
let cpi_ctx = CpiContext::new(ctx.accounts.cardinal_token_manager.to_account_info(), cpi_accounts).with_signer(use_invalidator_signer);
cardinal_token_manager::cpi::invalidate(cpi_ctx)?;

return Ok(())
}
7 changes: 7 additions & 0 deletions programs/cardinal-use-invalidator/src/instructions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod init;
pub mod increment_usages;
pub mod invalidate;

pub use init::*;
pub use increment_usages::*;
pub use invalidate::*;
24 changes: 24 additions & 0 deletions programs/cardinal-use-invalidator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pub mod instructions;
pub mod state;
pub mod errors;

use {anchor_lang::prelude::*, instructions::*};

declare_id!("useB5qbYZgjE14qXxWx17Zm4JS5bzWrDcWXt3uBq62L");

#[program]
pub mod cardinal_use_invalidator {
use super::*;

pub fn init(ctx: Context<InitCtx>, bump: u8, max_usages: u64) -> ProgramResult {
init::handler(ctx, bump, max_usages)
}

pub fn increment_usages(ctx: Context<IncrementUsagesCtx>, num_usages: u64) -> ProgramResult {
increment_usages::handler(ctx, num_usages)
}

pub fn invalidate(ctx: Context<InvalidateCtx>) -> ProgramResult {
invalidate::handler(ctx)
}
}
11 changes: 11 additions & 0 deletions programs/cardinal-use-invalidator/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use anchor_lang::prelude::*;

pub const USE_INVALIDATOR_SEED: &str = "use-invalidator";
pub const USE_INVALIDATOR_SIZE: usize = 8 + std::mem::size_of::<UseInvalidator>();
#[account]
pub struct UseInvalidator {
pub bump: u8,
pub usages: u64,
pub max_usages: u64,
pub use_authority: Pubkey,
}
3 changes: 2 additions & 1 deletion src/programs/tokenManager/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ type Accounts = TokenManagerTypes["Accounts"];
export type TokenManagerData = Accounts["tokenManager"];

export enum TokenManagerKind {
Managed = 1,
Authority = 1,
Edition = 2,
Unmanaged = 2,
}

Expand Down

0 comments on commit a384f73

Please sign in to comment.