diff --git a/accumulator_updater/programs/accumulator_updater/src/instructions/put_all.rs b/accumulator_updater/programs/accumulator_updater/src/instructions/put_all.rs index 4adb7a49..d51d4fb1 100644 --- a/accumulator_updater/programs/accumulator_updater/src/instructions/put_all.rs +++ b/accumulator_updater/programs/accumulator_updater/src/instructions/put_all.rs @@ -14,6 +14,7 @@ use { pub const ACCUMULATOR: &[u8; 11] = b"accumulator"; +pub const FUND: &[u8; 4] = b"fund"; pub fn put_all<'info>( ctx: Context<'_, '_, '_, 'info, PutAll<'info>>, @@ -39,17 +40,23 @@ pub fn put_all<'info>( &crate::ID, ); require_keys_eq!(accumulator_input_ai.key(), pda); - let signer_seeds = &[ + let signer_seeds = [ cpi_caller.as_ref(), ACCUMULATOR.as_ref(), base_account_key.as_ref(), &[bump], ]; + let fund_pda_bump = *ctx + .bumps + .get("fund") + .ok_or(AccumulatorUpdaterError::FundBumpNotFound)?; + let fund_signer_seeds = [ACCUMULATOR.as_ref(), FUND.as_ref(), &[fund_pda_bump]]; PutAll::create_account( accumulator_input_ai, 8 + AccumulatorInput::INIT_SPACE, - &ctx.accounts.payer, - signer_seeds, + &ctx.accounts.fund, + // seeds, + &[signer_seeds.as_slice(), fund_signer_seeds.as_slice()], &ctx.accounts.system_program, )?; loader = AccountLoader::::try_from_unchecked( @@ -86,22 +93,35 @@ pub fn is_uninitialized_account(ai: &AccountInfo) -> bool { ai.data_is_empty() && ai.owner == &system_program::ID } + #[derive(Accounts)] #[instruction( base_account_key: Pubkey)] pub struct PutAll<'info> { - #[account(mut)] - pub payer: Signer<'info>, + /// `Fund` is a system account that holds + /// the lamports that will be used to fund + /// `AccumulatorInput` account initialization + #[account( + mut, + seeds = [ + b"accumulator".as_ref(), + b"fund".as_ref(), + ], + owner = system_program::System::id(), + bump, + )] + pub fund: SystemAccount<'info>, pub whitelist_verifier: WhitelistVerifier<'info>, pub system_program: Program<'info, System>, // remaining_accounts: - [AccumulatorInput PDA] } + impl<'info> PutAll<'info> { fn create_account<'a>( account_info: &AccountInfo<'a>, space: usize, payer: &AccountInfo<'a>, - seeds: &[&[u8]], + seeds: &[&[&[u8]]], system_program: &AccountInfo<'a>, ) -> Result<()> { let lamports = Rent::get()?.minimum_balance(space); @@ -113,7 +133,7 @@ impl<'info> PutAll<'info> { from: payer.to_account_info(), to: account_info.to_account_info(), }, - &[seeds], + seeds, ), lamports, space.try_into().unwrap(), diff --git a/accumulator_updater/programs/accumulator_updater/src/lib.rs b/accumulator_updater/programs/accumulator_updater/src/lib.rs index 4fe3cd9e..88ad4e76 100644 --- a/accumulator_updater/programs/accumulator_updater/src/lib.rs +++ b/accumulator_updater/programs/accumulator_updater/src/lib.rs @@ -88,8 +88,7 @@ pub mod accumulator_updater { #[derive(Accounts)] pub struct Initialize<'info> { #[account(mut)] - pub payer: Signer<'info>, - + pub payer: Signer<'info>, #[account( init, payer = payer, @@ -142,4 +141,6 @@ pub enum AccumulatorUpdaterError { AccumulatorInputNotWritable, #[msg("Accumulator Input not provided")] AccumulatorInputNotProvided, + #[msg("Fund Bump not found")] + FundBumpNotFound, } diff --git a/accumulator_updater/programs/accumulator_updater/src/state/accumulator_input.rs b/accumulator_updater/programs/accumulator_updater/src/state/accumulator_input.rs index dcaf3956..afd7079a 100644 --- a/accumulator_updater/programs/accumulator_updater/src/state/accumulator_input.rs +++ b/accumulator_updater/programs/accumulator_updater/src/state/accumulator_input.rs @@ -6,6 +6,7 @@ use { anchor_lang::prelude::*, }; + /// `AccumulatorInput` is an arbitrary set of bytes /// that will be included in the AccumulatorSysvar /// @@ -42,6 +43,7 @@ pub struct AccumulatorHeader { pub end_offsets: [u16; 255], // 510 } + impl AccumulatorHeader { // HEADER_LEN allows for append-only forward-compatibility for the header. // this is the number of bytes from the beginning of the account_info.data diff --git a/accumulator_updater/programs/mock-cpi-caller/src/instructions/add_price.rs b/accumulator_updater/programs/mock-cpi-caller/src/instructions/add_price.rs index d6713ee0..dd5b9e5b 100644 --- a/accumulator_updater/programs/mock-cpi-caller/src/instructions/add_price.rs +++ b/accumulator_updater/programs/mock-cpi-caller/src/instructions/add_price.rs @@ -61,7 +61,7 @@ impl<'info> AddPrice<'info> { inputs: Vec>, ) -> anchor_lang::Result<()> { let mut accounts = vec![ - AccountMeta::new(ctx.accounts.payer.key(), true), + AccountMeta::new(ctx.accounts.fund.key(), false), AccountMeta::new_readonly(ctx.accounts.accumulator_whitelist.key(), false), AccountMeta::new_readonly(ctx.accounts.ixs_sysvar.key(), false), AccountMeta::new_readonly(ctx.accounts.system_program.key(), false), @@ -113,6 +113,8 @@ pub struct AddPrice<'info> { pub pyth_price_account: AccountLoader<'info, PriceAccount>, #[account(mut)] pub payer: Signer<'info>, + #[account(mut)] + pub fund: SystemAccount<'info>, /// also needed for accumulator_updater pub system_program: Program<'info, System>, /// CHECK: whitelist diff --git a/accumulator_updater/programs/mock-cpi-caller/src/instructions/update_price.rs b/accumulator_updater/programs/mock-cpi-caller/src/instructions/update_price.rs index 608ca707..efd6146d 100644 --- a/accumulator_updater/programs/mock-cpi-caller/src/instructions/update_price.rs +++ b/accumulator_updater/programs/mock-cpi-caller/src/instructions/update_price.rs @@ -45,8 +45,10 @@ pub struct UpdatePrice<'info> { bump, )] pub pyth_price_account: AccountLoader<'info, PriceAccount>, + // #[account(mut)] + // pub payer: Signer<'info>, #[account(mut)] - pub payer: Signer<'info>, + pub fund: SystemAccount<'info>, /// Needed for accumulator_updater pub system_program: Program<'info, System>, /// CHECK: whitelist @@ -91,7 +93,7 @@ impl<'info> UpdatePrice<'info> { values: Vec>, ) -> anchor_lang::Result<()> { let mut accounts = vec![ - AccountMeta::new(ctx.accounts.payer.key(), true), + AccountMeta::new(ctx.accounts.fund.key(), false), AccountMeta::new_readonly(ctx.accounts.accumulator_whitelist.key(), false), AccountMeta::new_readonly(ctx.accounts.ixs_sysvar.key(), false), AccountMeta::new_readonly(ctx.accounts.system_program.key(), false), diff --git a/accumulator_updater/tests/accumulator_updater.ts b/accumulator_updater/tests/accumulator_updater.ts index e096c1af..486b1e83 100644 --- a/accumulator_updater/tests/accumulator_updater.ts +++ b/accumulator_updater/tests/accumulator_updater.ts @@ -15,6 +15,10 @@ const accumulatorUpdaterProgram = anchor.workspace .AccumulatorUpdater as Program; const mockCpiProg = anchor.workspace.MockCpiCaller as Program; let whitelistAuthority = anchor.web3.Keypair.generate(); +const [fundPda] = anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from("accumulator"), Buffer.from("fund")], + accumulatorUpdaterProgram.programId +); const pythPriceAccountId = new anchor.BN(1); const addPriceParams = { @@ -33,6 +37,7 @@ const [pythPriceAccountPk] = anchor.web3.PublicKey.findProgramAddressSync( mockCpiProg.programId ); +let fundBalance = 100 * anchor.web3.LAMPORTS_PER_SOL; describe("accumulator_updater", () => { // Configure the client to use the local cluster. let provider = anchor.AnchorProvider.env(); @@ -44,6 +49,10 @@ describe("accumulator_updater", () => { accumulatorUpdaterProgram.programId ); + before("transfer lamports to the fund", async () => { + await provider.connection.requestAirdrop(fundPda, fundBalance); + }); + it("Is initialized!", async () => { // Add your test here. const tx = await accumulatorUpdaterProgram.methods @@ -104,6 +113,7 @@ describe("accumulator_updater", () => { const mockCpiCallerAddPriceTxPubkeys = await mockCpiProg.methods .addPrice(addPriceParams) .accounts({ + fund: fundPda, systemProgram: anchor.web3.SystemProgram.programId, ixsSysvar: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, accumulatorWhitelist: whitelistPubkey, @@ -219,6 +229,9 @@ describe("accumulator_updater", () => { accumulatorAccounts .map((a) => a.toString()) .includes(accumulatorPdaKey.toString()); + + const fundBalanceAfter = await provider.connection.getBalance(fundPda); + assert.isTrue(fundBalance > fundBalanceAfter); }); it("Mock CPI Program - UpdatePrice", async () => { @@ -233,6 +246,7 @@ describe("accumulator_updater", () => { await mockCpiProg.methods .updatePrice(updatePriceParams) .accounts({ + fund: fundPda, pythPriceAccount: pythPriceAccountPk, ixsSysvar: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY, accumulatorWhitelist: whitelistPubkey,