feat(accumulator-updater): add funding account for AccumulatorInput creation (#771)
This commit is contained in:
parent
0ac771266c
commit
9fea461174
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue