feat(accumulator-updater): add funding account for AccumulatorInput creation (#771)

This commit is contained in:
swimricky 2023-04-19 09:51:27 -07:00 committed by GitHub
parent 0ac771266c
commit 9fea461174
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 12 deletions

View File

@ -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::<AccumulatorInput>::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(),

View File

@ -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,
}

View File

@ -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

View File

@ -61,7 +61,7 @@ impl<'info> AddPrice<'info> {
inputs: Vec<Vec<u8>>,
) -> 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

View File

@ -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<Vec<u8>>,
) -> 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),

View File

@ -15,6 +15,10 @@ const accumulatorUpdaterProgram = anchor.workspace
.AccumulatorUpdater as Program<AccumulatorUpdater>;
const mockCpiProg = anchor.workspace.MockCpiCaller as Program<MockCpiCaller>;
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,