Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix audit findings #5

Merged
merged 2 commits into from
Oct 31, 2024
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
12 changes: 8 additions & 4 deletions programs/minter-controller/src/instructions/add_minter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ pub struct AddMinter<'info> {
#[account(mut)]
pub payer: Signer<'info>,

//The admin signature prevents a minter from being accidentally created with an incorrect admin
#[account(mut)]
pub admin: Signer<'info>,

#[account()]
pub minter_authority: Signer<'info>,

Expand All @@ -19,19 +23,19 @@ pub struct AddMinter<'info> {
#[account(
init,
payer = payer,
space = 8 + 32 + 32 + 32 + 33 + 8 + 8 + 8 + 8 + 1, //8 discriminator + 32 minter_authority + 32 mint account + 32 admin + 33 optional pending admin + 8 capacity + 8 tokens + 8 refill_per_second + 8 last_refill_time + 1 bump
space = 8 + Minter::INIT_SPACE,
seeds = [b"minter", minter_authority.key().as_ref(), mint_account.key().as_ref()],
bump
)]
pub minter: Account<'info, Minter>,
pub system_program: Program<'info, System>,
}

pub fn add_minter(ctx: Context<AddMinter>, capacity: u64, refill_per_second: u64, admin: Pubkey) -> Result<()> {
pub fn add_minter(ctx: Context<AddMinter>, capacity: u64, refill_per_second: u64) -> Result<()> {
ctx.accounts.minter.minter_authority = ctx.accounts.minter_authority.key();
ctx.accounts.minter.mint_account = ctx.accounts.mint_account.key();
ctx.accounts.minter.bump = ctx.bumps.minter;
ctx.accounts.minter.admin = admin;
ctx.accounts.minter.admin = ctx.accounts.admin.key();
ctx.accounts.minter.pending_admin = None;
ctx.accounts.minter.rate_limit.capacity = capacity;
ctx.accounts.minter.rate_limit.refill_per_second = refill_per_second;
Expand All @@ -40,7 +44,7 @@ pub fn add_minter(ctx: Context<AddMinter>, capacity: u64, refill_per_second: u64
mint_account: ctx.accounts.minter.mint_account,
capacity: capacity,
refill_per_second: refill_per_second,
admin: admin
admin: ctx.accounts.minter.admin
});
Ok(())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct AddWhitelistedAddress<'info> {
#[account(
init,
payer = payer,
space = 8 + 32 + 32 + 32 + 1, ////8 discriminator + 32 minter_authority + 32 mint account + 32 to address + 1 bump
space = 8 + WhitelistedAddress::INIT_SPACE,
seeds = [b"mint-whitelist", minter_authority.key().as_ref(), mint_account.key().as_ref(), to_address.key().as_ref()],
bump
)]
Expand Down
4 changes: 2 additions & 2 deletions programs/minter-controller/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pub mod minter_controller {
accept_admin_transfer::accept_admin_transfer(ctx)
}

pub fn add_minter(ctx: Context<AddMinter>, capacity: u64, refill_per_second: u64, admin: Pubkey) -> Result<()> {
add_minter::add_minter(ctx, capacity, refill_per_second, admin)
pub fn add_minter(ctx: Context<AddMinter>, capacity: u64, refill_per_second: u64) -> Result<()> {
add_minter::add_minter(ctx, capacity, refill_per_second)
}

pub fn add_whitelisted_address(ctx: Context<AddWhitelistedAddress>) -> Result<()> {
Expand Down
2 changes: 2 additions & 0 deletions programs/minter-controller/src/state/minter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use {
};

#[account]
#[derive(InitSpace)]
pub struct Minter {
pub minter_authority: Pubkey,
pub mint_account: Pubkey,
Expand All @@ -13,6 +14,7 @@ pub struct Minter {
}

#[account]
#[derive(InitSpace)]
pub struct RateLimit {
pub capacity: u64,
pub remaining_amount: u64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use {
};

#[account]
#[derive(InitSpace)]
pub struct WhitelistedAddress{
pub minter_authority: Pubkey,
pub mint_account: Pubkey,
Expand Down
64 changes: 45 additions & 19 deletions tests/minter_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,15 @@ describe('minter_controller', () => {
let foundEvent = false
try {
const tx = await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
.addMinter(capacity, refillPerSecond)
.accounts({
minter: minterPDA,
payer: provider.wallet.publicKey,
minterAuthority: minterAuthorityKeypair.publicKey,
mintAccount: mintPDA
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([minterAuthorityKeypair])
.signers([minterAuthorityKeypair, adminKeypair])
.rpc()

const events = await getEvents(provider, minterControllerProgram, tx)
Expand All @@ -208,14 +209,15 @@ describe('minter_controller', () => {

it('Can add second minter', async () => {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
.addMinter(capacity, refillPerSecond)
.accounts({
minter: minterPDA2,
payer: provider.wallet.publicKey,
minterAuthority: minterAuthorityKeypair2.publicKey,
mintAccount: mintPDA
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([minterAuthorityKeypair2])
.signers([minterAuthorityKeypair2, adminKeypair])
.rpc()

expect(
Expand All @@ -234,14 +236,15 @@ describe('minter_controller', () => {

it('Can add minter for second token', async () => {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
.addMinter(capacity, refillPerSecond)
.accounts({
minter: minterPDAToken2,
payer: provider.wallet.publicKey,
minterAuthority: minterAuthorityKeypair.publicKey,
mintAccount: mintPDAToken2
mintAccount: mintPDAToken2,
admin: adminKeypair.publicKey
})
.signers([minterAuthorityKeypair])
.signers([minterAuthorityKeypair, adminKeypair])
.rpc()

expect(
Expand All @@ -254,14 +257,15 @@ describe('minter_controller', () => {
it('Cannot add duplicate minter', async () => {
try {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
.addMinter(capacity, refillPerSecond)
.accounts({
minter: minterPDA,
payer: provider.wallet.publicKey,
minterAuthority: minterAuthorityKeypair.publicKey,
mintAccount: mintPDA
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([minterAuthorityKeypair])
.signers([minterAuthorityKeypair, adminKeypair])
.rpc()
assert.fail('Expected adding duplicate minter to fail')

Expand All @@ -270,36 +274,58 @@ describe('minter_controller', () => {
}
})

it('Cannot add minter without signature', async () => {
it('Cannot add minter without minterAuthority signature', async () => {
try {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
const tx = await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond)
.accounts({
minter: badMinterPDA,
payer: provider.wallet.publicKey,
minterAuthority: badMinterAuthorityKeypair.publicKey,
mintAccount: mintPDA
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([adminKeypair])
.rpc();

assert.fail('Should throw an error')
} catch (err) {
assert.isTrue(err.toString().includes('Missing signature for public key'))
}
})

it('Cannot add minter without admin signature', async () => {
try {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond)
.accounts({
minter: badMinterPDA,
payer: provider.wallet.publicKey,
minterAuthority: badMinterAuthorityKeypair.publicKey,
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([badMinterAuthorityKeypair])
.rpc();

assert.fail('Should throw an error')
} catch (err) {
assert.isTrue(err.toString().includes('Missing signature for public key'))
}
})

it('Cannot add minter with mismatched signature', async () => {
try {
await minterControllerProgram.methods
.addMinter(capacity, refillPerSecond, adminKeypair.publicKey)
.addMinter(capacity, refillPerSecond)
.accounts({
minter: badMinterPDA,
payer: provider.wallet.publicKey,
minterAuthority: badMinterAuthorityKeypair.publicKey,
mintAccount: mintPDA
mintAccount: mintPDA,
admin: adminKeypair.publicKey
})
.signers([minterAuthorityKeypair])
.signers([minterAuthorityKeypair, adminKeypair])
.rpc()
assert.fail('Expected adding duplicate minter to fail')
} catch (err) {
Expand Down