Skip to content

Commit

Permalink
Permissioned mint-authority (#328)
Browse files Browse the repository at this point in the history
* permissioned mint-authority

* take mint authority on create mint manager

* update tests

* fix build
  • Loading branch information
Giannis Chatziveroglou authored Oct 19, 2022
1 parent 6ec9cd1 commit b477f1e
Show file tree
Hide file tree
Showing 35 changed files with 426 additions and 439 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cardinal/token-manager",
"version": "1.7.2",
"version": "1.7.2-beta.2",
"description": "Cardinal token manager SDK",
"keywords": [
"solana",
Expand Down
2 changes: 2 additions & 0 deletions programs/cardinal-token-manager/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ pub enum ErrorCode {
InstructionsDisallowed,
#[msg("Invalidation type is not allowed with this token manager kind")]
InvalidInvalidationTypeKindMatch,
#[msg("Invalid Mint Authority")]
InvalidMintAuthority,
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,19 @@ pub fn handler(ctx: Context<CreateMintManagerCtx>) -> Result<()> {
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::set_authority(cpi_context, AuthorityType::FreezeAccount, Some(ctx.accounts.mint_manager.key()))?;

if ctx.accounts.mint.mint_authority.is_none() || ctx.accounts.mint.mint_authority.unwrap() != ctx.accounts.freeze_authority.key() {
return Err(error!(ErrorCode::InvalidMintAuthority));
}

// set freeze authority of mint to mint manager
let cpi_accounts = SetAuthority {
account_or_mint: ctx.accounts.mint.to_account_info(),
current_authority: ctx.accounts.freeze_authority.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
token::set_authority(cpi_context, AuthorityType::MintTokens, Some(ctx.accounts.mint_manager.key()))?;

Ok(())
}
13 changes: 13 additions & 0 deletions programs/cardinal-token-manager/src/instructions/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ pub fn handler(ctx: Context<InitCtx>, ix: InitIx) -> Result<()> {
return Err(error!(ErrorCode::InvalidInvalidationType));
}

if ix.kind == TokenManagerKind::Permissioned as u8 {
let mint = &ctx.accounts.mint;
let mint_key = mint.key();
let path = &[MINT_MANAGER_SEED.as_bytes(), mint_key.as_ref()];
let (mint_manager_key, _bump) = Pubkey::find_program_address(path, ctx.program_id);
if mint.mint_authority.is_none() || mint.mint_authority.unwrap() != mint_manager_key {
return Err(error!(ErrorCode::InvalidMintAuthority));
}
if mint.freeze_authority.is_none() || mint.freeze_authority.unwrap() != mint_manager_key {
return Err(error!(ErrorCode::InvalidFreezeAuthority));
}
}

// Unamanged must use invalidate
if ix.kind == TokenManagerKind::Unmanaged as u8 && ix.invalidation_type != InvalidationType::Invalidate as u8 {
return Err(error!(ErrorCode::InvalidInvalidationType));
Expand Down
10 changes: 10 additions & 0 deletions src/idl/cardinal_token_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,11 @@ export type CardinalTokenManager = {
code: 6033;
name: "InvalidInvalidationTypeKindMatch";
msg: "Invalidation type is not allowed with this token manager kind";
},
{
code: 6034;
name: "InvalidMintAuthority";
msg: "Invalid Mint Authority";
}
];
};
Expand Down Expand Up @@ -2447,5 +2452,10 @@ export const IDL: CardinalTokenManager = {
name: "InvalidInvalidationTypeKindMatch",
msg: "Invalidation type is not allowed with this token manager kind",
},
{
code: 6034,
name: "InvalidMintAuthority",
msg: "Invalid Mint Authority",
},
],
};
41 changes: 21 additions & 20 deletions src/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,27 @@ export const withIssueToken = async (
}: IssueParameters,
payer = wallet.publicKey
): Promise<[Transaction, PublicKey, Keypair | undefined]> => {
// create mint manager
if (
kind === TokenManagerKind.Managed ||
kind === TokenManagerKind.Permissioned
) {
const [mintManagerIx, mintManagerId] =
await tokenManager.instruction.creatMintManager(
connection,
wallet,
mint,
payer
);

const mintManagerData = await tryGetAccount(() =>
tokenManager.accounts.getMintManager(connection, mintManagerId)
);
if (!mintManagerData) {
transaction.add(mintManagerIx);
}
}

// init token manager
const numInvalidator =
(customInvalidators ? customInvalidators.length : 0) +
Expand Down Expand Up @@ -289,26 +310,6 @@ export const withIssueToken = async (
}
}

if (
kind === TokenManagerKind.Managed ||
kind === TokenManagerKind.Permissioned
) {
const [mintManagerIx, mintManagerId] =
await tokenManager.instruction.creatMintManager(
connection,
wallet,
mint,
payer
);

const mintManagerData = await tryGetAccount(() =>
tokenManager.accounts.getMintManager(connection, mintManagerId)
);
if (!mintManagerData) {
transaction.add(mintManagerIx);
}
}

// issuer
const tokenManagerTokenAccountId = await withFindOrInitAssociatedTokenAccount(
transaction,
Expand Down
18 changes: 8 additions & 10 deletions tests/claimLinks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { getProvider } from "./workspace";

describe("Claim links", () => {
const recipient = Keypair.generate();
const tokenCreator = Keypair.generate();
const user = Keypair.generate();
let issuerTokenAccountId: PublicKey;
let rentalMint: Token;
let claimLink: string;
Expand All @@ -41,7 +41,7 @@ describe("Claim links", () => {
before(async () => {
const provider = getProvider();
const airdropCreator = await provider.connection.requestAirdrop(
tokenCreator.publicKey,
user.publicKey,
LAMPORTS_PER_SOL
);
await provider.connection.confirmTransaction(airdropCreator);
Expand All @@ -55,10 +55,10 @@ describe("Claim links", () => {
// create rental mint
[issuerTokenAccountId, rentalMint] = await createMint(
provider.connection,
tokenCreator,
provider.wallet.publicKey,
user,
user.publicKey,
1,
provider.wallet.publicKey
user.publicKey
);
});

Expand All @@ -67,7 +67,7 @@ describe("Claim links", () => {
const [transaction, tokenManagerId, otp] = await withIssueToken(
new Transaction(),
provider.connection,
provider.wallet,
new SignerWallet(user),
{
mint: rentalMint.publicKey,
issuerTokenAccountId,
Expand All @@ -80,7 +80,7 @@ describe("Claim links", () => {
const txEnvelope = new TransactionEnvelope(
SolanaProvider.init({
connection: provider.connection,
wallet: provider.wallet,
wallet: new SignerWallet(user),
opts: provider.opts,
}),
[...transaction.instructions]
Expand All @@ -100,9 +100,7 @@ describe("Claim links", () => {
expect(tokenManagerData.parsed.amount.toNumber()).to.eq(1);
expect(tokenManagerData.parsed.mint).to.eqAddress(rentalMint.publicKey);
expect(tokenManagerData.parsed.invalidators).length.greaterThanOrEqual(0);
expect(tokenManagerData.parsed.issuer).to.eqAddress(
provider.wallet.publicKey
);
expect(tokenManagerData.parsed.issuer).to.eqAddress(user.publicKey);
expect(tokenManagerData.parsed.claimApprover).to.eqAddress(otp!.publicKey);

const checkIssuerTokenAccount = await rentalMint.getAccountInfo(
Expand Down
18 changes: 8 additions & 10 deletions tests/claimLinksInvalidate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { getProvider } from "./workspace";

describe("Claim links invalidate", () => {
const recipient = Keypair.generate();
const tokenCreator = Keypair.generate();
const user = Keypair.generate();
let issuerTokenAccountId: PublicKey;
let rentalMint: Token;
let claimLink: string;
Expand All @@ -36,7 +36,7 @@ describe("Claim links invalidate", () => {
before(async () => {
const provider = getProvider();
const airdropCreator = await provider.connection.requestAirdrop(
tokenCreator.publicKey,
user.publicKey,
LAMPORTS_PER_SOL
);
await provider.connection.confirmTransaction(airdropCreator);
Expand All @@ -50,18 +50,18 @@ describe("Claim links invalidate", () => {
// create rental mint
[issuerTokenAccountId, rentalMint] = await createMint(
provider.connection,
tokenCreator,
provider.wallet.publicKey,
user,
user.publicKey,
1,
provider.wallet.publicKey
user.publicKey
);
});

it("Create link", async () => {
const provider = getProvider();
const [transaction, tokenManagerId, otp] = await claimLinks.issueToken(
provider.connection,
provider.wallet,
new SignerWallet(user),
{
mint: rentalMint.publicKey,
issuerTokenAccountId,
Expand All @@ -74,7 +74,7 @@ describe("Claim links invalidate", () => {
const txEnvelope = new TransactionEnvelope(
SolanaProvider.init({
connection: provider.connection,
wallet: provider.wallet,
wallet: new SignerWallet(user),
opts: provider.opts,
}),
[...transaction.instructions]
Expand All @@ -94,9 +94,7 @@ describe("Claim links invalidate", () => {
expect(tokenManagerData.parsed.amount.toNumber()).to.eq(1);
expect(tokenManagerData.parsed.mint).to.eqAddress(rentalMint.publicKey);
expect(tokenManagerData.parsed.invalidators).length.greaterThanOrEqual(0);
expect(tokenManagerData.parsed.issuer).to.eqAddress(
provider.wallet.publicKey
);
expect(tokenManagerData.parsed.issuer).to.eqAddress(user.publicKey);
expect(tokenManagerData.parsed.claimApprover).to.eqAddress(otp.publicKey);

const checkIssuerTokenAccount = await rentalMint.getAccountInfo(
Expand Down
22 changes: 10 additions & 12 deletions tests/createAndExtendPartialRental.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("Create and Extend Rental", () => {
const EXTENSION_DURATION = 1000;
const RENTAL_PAYMENT_AMONT = 10;
const recipient = Keypair.generate();
const tokenCreator = Keypair.generate();
const user = Keypair.generate();
let recipientPaymentTokenAccountId: PublicKey;
let issuerTokenAccountId: PublicKey;
let paymentMint: Token;
Expand All @@ -32,7 +32,7 @@ describe("Create and Extend Rental", () => {
before(async () => {
const provider = getProvider();
const airdropCreator = await provider.connection.requestAirdrop(
tokenCreator.publicKey,
user.publicKey,
LAMPORTS_PER_SOL
);
await provider.connection.confirmTransaction(airdropCreator);
Expand All @@ -46,26 +46,26 @@ describe("Create and Extend Rental", () => {
// create payment mint
[recipientPaymentTokenAccountId, paymentMint] = await createMint(
provider.connection,
tokenCreator,
user,
recipient.publicKey,
RECIPIENT_START_PAYMENT_AMOUNT
);

// create rental mint
[issuerTokenAccountId, rentalMint] = await createMint(
provider.connection,
tokenCreator,
provider.wallet.publicKey,
user,
user.publicKey,
1,
provider.wallet.publicKey
user.publicKey
);
});

it("Create rental", async () => {
const provider = getProvider();
const [transaction, tokenManagerId] = await rentals.createRental(
provider.connection,
provider.wallet,
new SignerWallet(user),
{
claimPayment: {
paymentAmount: RENTAL_PAYMENT_AMONT,
Expand All @@ -88,7 +88,7 @@ describe("Create and Extend Rental", () => {
const txEnvelope = new TransactionEnvelope(
SolanaProvider.init({
connection: provider.connection,
wallet: provider.wallet,
wallet: new SignerWallet(user),
opts: provider.opts,
}),
[...transaction.instructions]
Expand All @@ -106,9 +106,7 @@ describe("Create and Extend Rental", () => {
expect(tokenManagerData.parsed.amount.toNumber()).to.eq(1);
expect(tokenManagerData.parsed.mint).to.eqAddress(rentalMint.publicKey);
expect(tokenManagerData.parsed.invalidators).length.greaterThanOrEqual(1);
expect(tokenManagerData.parsed.issuer).to.eqAddress(
provider.wallet.publicKey
);
expect(tokenManagerData.parsed.issuer).to.eqAddress(user.publicKey);

const checkIssuerTokenAccount = await rentalMint.getAccountInfo(
issuerTokenAccountId
Expand All @@ -118,7 +116,7 @@ describe("Create and Extend Rental", () => {
// check receipt-index
const tokenManagers = await tokenManager.accounts.getTokenManagersForIssuer(
provider.connection,
provider.wallet.publicKey
user.publicKey
);
expect(tokenManagers.map((i) => i.pubkey.toString())).to.include(
tokenManagerId.toString()
Expand Down
Loading

0 comments on commit b477f1e

Please sign in to comment.