Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Removing overcomplicated withdraw.
  • Loading branch information
blockiosaurus committed Aug 18, 2024
commit 226e8692a7e6873b49c23ca55298d5d5e7ce697d
102 changes: 8 additions & 94 deletions clients/js/test/plugins/collection/treasury.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from 'ava';

import { generateSigner } from '@metaplex-foundation/umi';
import { generateSigner, lamports } from '@metaplex-foundation/umi';
import {
pluginAuthorityPair,
updatePluginAuthority,
Expand Down Expand Up @@ -153,74 +153,6 @@ test('it cannot create asset with treasury', async (t) => {
});
});

test('it can deposit SOL to treasury', async (t) => {
const umi = await createUmi();

const collection = await createCollection(umi, {
plugins: [
pluginAuthorityPair({
type: 'Treasury',
data: {
withdrawn: 0,
},
authority: updatePluginAuthority(),
}),
],
});

await assertCollection(t, umi, {
...DEFAULT_COLLECTION,
collection: collection.publicKey,
updateAuthority: umi.identity.publicKey,
treasury: {
authority: {
type: 'UpdateAuthority',
},
withdrawn: 0,
},
});

const identityBeforeBalance = await umi.rpc.getBalance(
umi.identity.publicKey
);
const collectionBeforeBalance = await umi.rpc.getBalance(
collection.publicKey
);

await updateCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: -1_000_000,
},
}).sendAndConfirm(umi);

const identityAfterBalance = await umi.rpc.getBalance(umi.identity.publicKey);
const collectionAfterBalance = await umi.rpc.getBalance(collection.publicKey);

const identityExpected =
identityBeforeBalance.basisPoints -
1_000_000n - // Deposited
5_000n; // Transaction fee
t.is(identityExpected, identityAfterBalance.basisPoints);
t.is(
collectionBeforeBalance.basisPoints + 1_000_000n,
collectionAfterBalance.basisPoints
);

await assertCollection(t, umi, {
...DEFAULT_COLLECTION,
collection: collection.publicKey,
updateAuthority: umi.identity.publicKey,
treasury: {
authority: {
type: 'UpdateAuthority',
},
withdrawn: -1_000_000,
},
});
});

test('it can withdraw SOL from treasury', async (t) => {
const umi = await createUmi();

Expand Down Expand Up @@ -248,13 +180,7 @@ test('it can withdraw SOL from treasury', async (t) => {
},
});

await updateCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: -1_000_000,
},
}).sendAndConfirm(umi);
await umi.rpc.airdrop(collection.publicKey, lamports(1_000_000));

const identityBeforeBalance = await umi.rpc.getBalance(
umi.identity.publicKey
Expand All @@ -267,7 +193,7 @@ test('it can withdraw SOL from treasury', async (t) => {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: 0,
withdrawn: 1_000_000,
},
}).sendAndConfirm(umi);

Expand All @@ -292,7 +218,7 @@ test('it can withdraw SOL from treasury', async (t) => {
authority: {
type: 'UpdateAuthority',
},
withdrawn: 0,
withdrawn: 1_000_000,
},
});
});
Expand Down Expand Up @@ -325,20 +251,14 @@ test('it cannot withdraw SOL from treasury if not the authority', async (t) => {
},
});

await updateCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: -1_000_000,
},
}).sendAndConfirm(umi);
await umi.rpc.airdrop(collection.publicKey, lamports(1_000_000));

const result = updateCollectionPlugin(umi, {
collection: collection.publicKey,
authority,
plugin: {
type: 'Treasury',
withdrawn: 0,
withdrawn: 1_000_000,
},
}).sendAndConfirm(umi);

Expand Down Expand Up @@ -372,19 +292,13 @@ test('it cannot withdraw more than excess rent from treasury', async (t) => {
},
});

await updateCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: -1_000_000,
},
}).sendAndConfirm(umi);
await umi.rpc.airdrop(collection.publicKey, lamports(1_000_000));

const result = updateCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'Treasury',
withdrawn: 1,
withdrawn: 1_000_001,
},
}).sendAndConfirm(umi);

Expand Down
70 changes: 26 additions & 44 deletions programs/mpl-core/src/plugins/treasury.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl PluginValidation for Treasury {
else if target_plugin.withdrawn > 0 {
Err(MplCoreError::InvalidTreasuryWithdrawn.into())
} else {
Ok(ValidationResult::Pass)
abstain!()
}
} else {
abstain!()
Expand Down Expand Up @@ -70,56 +70,38 @@ impl PluginValidation for Treasury {
if PluginType::from(target_plugin) == PluginType::Treasury {
if let Plugin::Treasury(treasury) = target_plugin {
let collection = ctx.collection_info.ok_or(MplCoreError::MissingCollection)?;
solana_program::msg!("Current Withdrawn: {:?}", treasury.withdrawn);
solana_program::msg!("New Withdrawn: {:?}", self.withdrawn);
match treasury.withdrawn.cmp(&self.withdrawn) {
// Depositing SOL into the treasury
std::cmp::Ordering::Less => {
solana_program::msg!("Treasury: Depositing SOL into the treasury");
let diff: u64 = self
.withdrawn
.checked_sub(treasury.withdrawn)
.ok_or(MplCoreError::NumericalOverflow)?
.try_into()
.map_err(|_| MplCoreError::NumericalOverflow)?;
invoke(
&system_instruction::transfer(ctx.payer.key, collection.key, diff),
&[ctx.payer.clone(), collection.clone()],
)?;
}
// Withdrawing SOL from the treasury
std::cmp::Ordering::Greater => {
solana_program::msg!("Treasury: Withdrawing SOL from the treasury");
let excess_rent = collection
.lamports()
.checked_sub(Rent::get()?.minimum_balance(collection.data_len()))
.ok_or(MplCoreError::NumericalOverflow)?;
let diff: u64 = treasury
.withdrawn
.checked_sub(self.withdrawn)
.ok_or(MplCoreError::NumericalOverflow)?
.try_into()
.map_err(|_| MplCoreError::NumericalOverflow)?;
// Withdrawing SOL from the treasury
if treasury.withdrawn > self.withdrawn {
let excess_rent = collection
.lamports()
.checked_sub(Rent::get()?.minimum_balance(collection.data_len()))
.ok_or(MplCoreError::NumericalOverflow)?;
let diff: u64 = treasury
.withdrawn
.checked_sub(self.withdrawn)
.ok_or(MplCoreError::NumericalOverflow)?
.try_into()
.map_err(|_| MplCoreError::NumericalOverflow)?;

if diff > excess_rent {
return Err(MplCoreError::CannotOverdraw.into());
}

let auth_starting_lamports = ctx.payer.lamports();
**ctx.payer.lamports.borrow_mut() =
auth_starting_lamports.checked_add(diff).unwrap();
**collection.lamports.borrow_mut() = collection
.lamports()
.checked_sub(diff)
.ok_or(MplCoreError::NumericalOverflow)?;
if diff > excess_rent {
return Err(MplCoreError::CannotOverdraw.into());
}
std::cmp::Ordering::Equal => {}

let auth_starting_lamports = ctx.payer.lamports();
**ctx.payer.lamports.borrow_mut() =
auth_starting_lamports.checked_add(diff).unwrap();
**collection.lamports.borrow_mut() = collection
.lamports()
.checked_sub(diff)
.ok_or(MplCoreError::NumericalOverflow)?;
} else {
return Err(MplCoreError::InvalidPluginOperation.into());
}
} else {
return Err(MplCoreError::InvalidPlugin.into());
}
}
}
Ok(ValidationResult::Pass)
abstain!()
}
}