Skip to content

Commit

Permalink
add donate in authorized token mints
Browse files Browse the repository at this point in the history
  • Loading branch information
makarychev committed Jun 10, 2024
1 parent 4c547d2 commit 60e939f
Show file tree
Hide file tree
Showing 16 changed files with 686 additions and 27 deletions.
4 changes: 3 additions & 1 deletion programs/donaproto/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ pub enum DonationError {
#[msg("Ipfs hash too long")]
IpfsHashTooLong,
#[msg("Donation amount too low")]
DonationAmountTooLow,
DonationAmountTooLow,
#[msg("Invalid donation mint")]
InvalidDonationMint,
}
2 changes: 1 addition & 1 deletion programs/donaproto/src/instructions/authorize_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn authorize_clmm_pool(ctx: Context<AuthorizeClmmPool>) -> Result<()> {
let authorized_clmm_pool = &mut ctx.accounts.authorized_clmm_pool;
authorized_clmm_pool.pool_state = ctx.accounts.pool_state.key();
authorized_clmm_pool.program_id = ctx.accounts.authorized_clmm.program_id;
authorized_clmm_pool.token = ctx.accounts.donation_amm_mint.key();
authorized_clmm_pool.mint = ctx.accounts.donation_amm_mint.key();
authorized_clmm_pool.donation_protocol = ctx.accounts.donation_protocol.key();

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions programs/donaproto/src/instructions/create_donation_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ pub struct CreateDonationV2<'info> {
bump,
)]
pub creator_data: Account<'info, CreatorData>,
#[account(
constraint = authorized_clmm_pool.mint == donation_mint.key(),
)]
pub donation_mint: Account<'info, Mint>,
pub default_donation_mint: Account<'info, Mint>,
#[account(
Expand Down
4 changes: 4 additions & 0 deletions programs/donaproto/src/instructions/donate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ pub fn donate(ctx: Context<Donate>, amount: u64) -> Result<()> {
return Err(DonationError::DonationAmountZero.into());
}

if ctx.accounts.donation_mint.key() != ctx.accounts.donation_protocol.donation_mint {
return Err(DonationError::InvalidDonationMint.into());
}

// Transfer amount from user to donation holding wallet
token::transfer(
CpiContext::new(
Expand Down
190 changes: 190 additions & 0 deletions programs/donaproto/src/instructions/donate_v2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Mint, TokenAccount, Transfer};
use raydium_amm_v3::states::PoolState;

use crate::{
errors::DonationError,
states::{AuthorizedClmmPool, ContributorData, DonationData, DonationProtocolData},
utils::calculate_amount,
AUTHORIZED_CLMM_POOL_PREFIX, CONTRIBUTOR_PREFIX, TREASURY_PREFIX,
};

#[derive(Accounts)]
pub struct DonateV2<'info> {
#[account(mut,
constraint = donation_data.donation_protocol == donation_protocol.key(),
constraint = donation_data.holding_wallet == holding_wallet.key(),
)]
pub donation_data: Account<'info, DonationData>,
#[account(mut,
constraint = contributor_data.donation_protocol == donation_protocol.key(),
seeds = [
CONTRIBUTOR_PREFIX.as_bytes(),
donation_protocol.to_account_info().key.as_ref(),
user_wallet.to_account_info().key.as_ref(),
],
bump = contributor_data.bump,
)]
pub contributor_data: Account<'info, ContributorData>,
#[account(
constraint = donation_protocol.donation_mint == default_donation_mint.key(),
)]
pub donation_protocol: Account<'info, DonationProtocolData>,

#[account(mut,
constraint = user_token_wallet.owner == *user_wallet.key,
constraint = user_token_wallet.mint == donation_mint.key(),
)]
pub user_token_wallet: Account<'info, TokenAccount>,
#[account(mut,
constraint = user_reward_token_wallet.owner == *user_wallet.key,
constraint = user_reward_token_wallet.mint == reward_mint.key(),
)]
pub user_reward_token_wallet: Account<'info, TokenAccount>,
#[account(mut,
constraint = donation_protocol.treasury_mint.key() == reward_mint.key(),
constraint = reward_treasury.key() == donation_protocol.treasury.key(),
)]
pub reward_treasury: Account<'info, TokenAccount>,
#[account(
seeds = [TREASURY_PREFIX.as_bytes(), donation_protocol.key().as_ref()],
bump = donation_protocol.treasury_owner_bump,
)]
/// CHECK: pda account ["treasury", donation_protocol_data]
pub reward_treasury_owner: AccountInfo<'info>,

#[account(mut,
constraint = holding_wallet.mint == donation_mint.key(),
constraint = holding_wallet.key() == donation_data.holding_wallet,
)]
pub holding_wallet: Account<'info, TokenAccount>,
#[account(
constraint = authorized_clmm_pool.mint == donation_mint.key(),
)]
pub donation_mint: Account<'info, Mint>,
#[account(
constraint = donation_protocol.treasury_mint.key() == reward_mint.key(),
)]
pub reward_mint: Account<'info, Mint>,

pub default_donation_mint: Account<'info, Mint>,
#[account(
seeds = [
AUTHORIZED_CLMM_POOL_PREFIX.as_bytes(),
donation_protocol.key().as_ref(),
pool_state.key().as_ref(),
],
bump,
constraint = authorized_clmm_pool.donation_protocol == donation_protocol.key(),
constraint = authorized_clmm_pool.pool_state == pool_state.key(),
)]
pub authorized_clmm_pool: Account<'info, AuthorizedClmmPool>,
#[account(
constraint = (pool_state.load()?.token_mint_0 == donation_protocol.donation_mint && pool_state.load()?.token_mint_1 == donation_mint.key())
|| (pool_state.load()?.token_mint_1 == donation_protocol.donation_mint && pool_state.load()?.token_mint_0 == donation_mint.key()),
)]
pub pool_state: AccountLoader<'info, PoolState>,

#[account(mut)]
pub user_wallet: Signer<'info>,
pub token_program: Program<'info, anchor_spl::token::Token>,
}

pub fn donate_v2(ctx: Context<DonateV2>, amount: u64) -> Result<()> {
let donation_data = &mut ctx.accounts.donation_data;

if donation_data.is_closed {
return Err(DonationError::DonationClosed.into());
}

if amount == 0 {
return Err(DonationError::DonationAmountZero.into());
}

if ctx.accounts.donation_protocol.donation_mint == ctx.accounts.donation_mint.key() {
return Err(DonationError::InvalidDonationMint.into());
}

let default_donation_mint = &ctx.accounts.default_donation_mint;
let donation_mint = &ctx.accounts.donation_mint;
let is_default_token_mint_0 = ctx.accounts.pool_state.load()?.token_mint_0
== ctx.accounts.donation_protocol.donation_mint;
let default_amount = calculate_amount(
default_donation_mint.decimals,
donation_mint.decimals,
amount,
ctx.accounts.pool_state.load()?.sqrt_price_x64,
is_default_token_mint_0,
);

// Transfer amount from user to donation holding wallet in specific token mints
token::transfer(
CpiContext::new(
ctx.accounts.token_program.to_account_info().clone(),
Transfer {
from: ctx.accounts.user_token_wallet.to_account_info().clone(),
to: ctx.accounts.holding_wallet.to_account_info().clone(),
authority: ctx.accounts.user_wallet.to_account_info().clone(),
},
),
amount,
)?;

let contributor_data = &mut ctx.accounts.contributor_data;
donation_data.total_amount_received = donation_data
.total_amount_received
.checked_add(amount)
.unwrap();
contributor_data.total_amount_donated = contributor_data
.total_amount_donated
.checked_add(default_amount)
.unwrap();
contributor_data.donations_count = contributor_data.donations_count.checked_add(1).unwrap();
let donation_protocol = &ctx.accounts.donation_protocol;

if default_amount >= donation_protocol.min_amount_to_earn {
// TODO: add calculation for reward amount
let reward_treasury_balance = ctx.accounts.reward_treasury.amount;
let mut reward_amount = default_amount;
if reward_amount > reward_treasury_balance {
reward_amount = reward_treasury_balance.checked_div(100).unwrap();
}
// END

// Transfer amount of tokens from reward treasury wallet to user
let seeds = &[
TREASURY_PREFIX.as_bytes(),
ctx.accounts
.donation_protocol
.to_account_info()
.key
.as_ref(),
&[ctx.accounts.donation_protocol.treasury_owner_bump],
];
let signer = &[&seeds[..]];
if reward_amount > 0 {
token::transfer(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info().clone(),
Transfer {
from: ctx.accounts.reward_treasury.to_account_info().clone(),
to: ctx
.accounts
.user_reward_token_wallet
.to_account_info()
.clone(),
authority: ctx.accounts.reward_treasury_owner.to_account_info().clone(),
},
signer,
),
reward_amount,
)?;
contributor_data.total_amount_earned = contributor_data
.total_amount_earned
.checked_add(reward_amount)
.unwrap();
}
}

Ok(())
}
2 changes: 2 additions & 0 deletions programs/donaproto/src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ pub mod authorize_clmm;
pub use authorize_clmm::*;
pub mod create_donation_v2;
pub use create_donation_v2::*;
pub mod donate_v2;
pub use donate_v2::*;
4 changes: 4 additions & 0 deletions programs/donaproto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,8 @@ pub mod donaproto {
) -> Result<()> {
instructions::create_donation_v2(ctx, amount, ipfs_hash, ending_timestamp, holding_bump)
}

pub fn donate_v2(ctx: Context<DonateV2>, amount: u64) -> Result<()> {
instructions::donate_v2(ctx, amount)
}
}
2 changes: 1 addition & 1 deletion programs/donaproto/src/states/authorized_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ use anchor_lang::prelude::*;
pub struct AuthorizedClmmPool {
pub pool_state: Pubkey,
pub program_id: Pubkey,
pub token: Pubkey,
pub mint: Pubkey,
pub donation_protocol: Pubkey,
}
6 changes: 3 additions & 3 deletions tests/authorizeClmm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("Authorize CLMM program", () => {
const clmmProgramId = new anchor.web3.PublicKey("devi51mZmdwUJGU9hjN27vEz64Gps7uUefqxg27EAtH");
const minAmountToEarn = new anchor.BN(1000);
const donationProtocolData = anchor.web3.Keypair.generate();
const [treasuryOwnerPK, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
const [treasuryOwnerPubkey, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from(TREASURY_PREFIX),
donationProtocolData.publicKey.toBuffer(),
Expand Down Expand Up @@ -70,7 +70,7 @@ describe("Authorize CLMM program", () => {
connection,
payer,
rewardsMintPubKey,
treasuryOwnerPK,
treasuryOwnerPubkey,
allowOwnerOffCurve = true
)
console.log(`treasuryPK: ${treasuryTokenAccount.address}`);
Expand All @@ -83,7 +83,7 @@ describe("Authorize CLMM program", () => {
accounts: {
donationProtocolData: donationProtocolData.publicKey,
treasury: treasuryTokenAccount.address,
treasuryOwner: treasuryOwnerPK,
treasuryOwner: treasuryOwnerPubkey,
treasuryMint: rewardsMintPubKey,
donationMint: donationMintPubKey,
payer: payer.publicKey,
Expand Down
8 changes: 4 additions & 4 deletions tests/authorizeClmmPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe("Authorize CLMM pool", () => {
const minAmountToCollect = new anchor.BN(1_000_000);
const minAmountToEarn = new anchor.BN(1000);
const donationProtocolData = anchor.web3.Keypair.generate();
const [treasuryOwnerPK, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
const [treasuryOwnerPubkey, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from(TREASURY_PREFIX),
donationProtocolData.publicKey.toBuffer(),
Expand Down Expand Up @@ -82,7 +82,7 @@ describe("Authorize CLMM pool", () => {
connection,
payer,
rewardsMintPubKey,
treasuryOwnerPK,
treasuryOwnerPubkey,
allowOwnerOffCurve = true
)

Expand All @@ -94,7 +94,7 @@ describe("Authorize CLMM pool", () => {
accounts: {
donationProtocolData: donationProtocolData.publicKey,
treasury: treasuryTokenAccount.address,
treasuryOwner: treasuryOwnerPK,
treasuryOwner: treasuryOwnerPubkey,
treasuryMint: rewardsMintPubKey,
donationMint: donationMintPubKey,
payer: payer.publicKey,
Expand Down Expand Up @@ -194,6 +194,6 @@ describe("Authorize CLMM pool", () => {
assert.deepEqual(onchainAuthorizedClmmPool.donationProtocol, donationProtocolData.publicKey);
assert.deepEqual(onchainAuthorizedClmmPool.poolState, poolStateResult.poolId);
assert.deepEqual(onchainAuthorizedClmmPool.programId, clmmProgramId);
assert.deepEqual(onchainAuthorizedClmmPool.token, newDonationMintPubKey);
assert.deepEqual(onchainAuthorizedClmmPool.mint, newDonationMintPubKey);
});
});
6 changes: 3 additions & 3 deletions tests/createDonation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe("donaproto", () => {
rewardMintDecimals
)

const [treasuryOwnerPK, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
const [treasuryOwnerPubkey, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from(TREASURY_PREFIX),
donationProtocolData.publicKey.toBuffer(),
Expand All @@ -63,7 +63,7 @@ describe("donaproto", () => {
connection,
payer,
rewardsMintPubKey,
treasuryOwnerPK,
treasuryOwnerPubkey,
allowOwnerOffCurve = true
)

Expand All @@ -75,7 +75,7 @@ describe("donaproto", () => {
accounts: {
donationProtocolData: donationProtocolData.publicKey,
treasury: treasuryTokenAccount.address,
treasuryOwner: treasuryOwnerPK,
treasuryOwner: treasuryOwnerPubkey,
treasuryMint: rewardsMintPubKey,
donationMint: donationMintPubKey,
payer: payer.publicKey,
Expand Down
10 changes: 5 additions & 5 deletions tests/createDonationV2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("Create donation V2", () => {
const minAmountToCollect = new anchor.BN(1_000_000);
const minAmountToEarn = new anchor.BN(1000);
const donationProtocolData = anchor.web3.Keypair.generate();
const [treasuryOwnerPK, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
const [treasuryOwnerPubkey, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from(TREASURY_PREFIX),
donationProtocolData.publicKey.toBuffer(),
Expand Down Expand Up @@ -93,7 +93,7 @@ describe("Create donation V2", () => {
newMintDecimals
);

const [treasuryOwnerPK, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
const [treasuryOwnerPubkey, treasuryOwnerBump] = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from(TREASURY_PREFIX),
donationProtocolData.publicKey.toBuffer(),
Expand All @@ -105,7 +105,7 @@ describe("Create donation V2", () => {
connection,
payer,
rewardsMintPubKey,
treasuryOwnerPK,
treasuryOwnerPubkey,
allowOwnerOffCurve = true
)

Expand All @@ -117,7 +117,7 @@ describe("Create donation V2", () => {
accounts: {
donationProtocolData: donationProtocolData.publicKey,
treasury: treasuryTokenAccount.address,
treasuryOwner: treasuryOwnerPK,
treasuryOwner: treasuryOwnerPubkey,
treasuryMint: rewardsMintPubKey,
donationMint: donationMintPubKey,
payer: payer.publicKey,
Expand Down Expand Up @@ -252,7 +252,7 @@ describe("Create donation V2", () => {
assert.deepEqual(onchainAuthorizedClmmPool.donationProtocol, donationProtocolData.publicKey);
assert.deepEqual(onchainAuthorizedClmmPool.poolState, poolStateResult.poolId);
assert.deepEqual(onchainAuthorizedClmmPool.programId, clmmProgramId);
assert.deepEqual(onchainAuthorizedClmmPool.token, newDonationMintPubKey);
assert.deepEqual(onchainAuthorizedClmmPool.mint, newDonationMintPubKey);
});

it("creates a donation", async () => {
Expand Down
Loading

0 comments on commit 60e939f

Please sign in to comment.