I have two methods in my program, one to initialize a PDA and set some state variables the other to transfer SOL from one to another account
pub fn initialize(ctx: Context<Initialize>, max_participation_amount: u64) -> Result<()> {
let state_account: &mut Account<State> = &mut ctx.accounts.auction_instance;
state_account.vault_public_key = ctx.accounts.vault.key().clone();
state_account.max_participation_amount = max_participation_amount;
Ok(())
}
pub fn fund_vault(ctx: Context<FundVault>) -> Result<()> {
let payer = &mut ctx.accounts.payer;
let receiver = &mut ctx.accounts.receiver;
let amount: u64 = 1_000_000_000;
if payer.lamports() < amount {
return Err(error!(ErrorCode::NotEnoughSol));
}
let instruction = transfer(&payer.key(), &receiver.key(), amount);
let account_infos = [
payer.to_account_info().clone(),
receiver.to_account_info().clone(),
ctx.accounts.system_program.to_account_info().clone(),
];
invoke(&instruction, &account_infos)?;
Ok(())
}
#[derive(Accounts)]
pub struct FundVault<'info> {
/// CHECK:
#[account(mut)]
pub receiver: AccountInfo<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = user, seeds = [b"vault"], bump, space = Vault::LEN)]
pub vault: Account<'info, Vault>,
#[account(init, payer = user, space = State::LEN)]
pub auction_instance: Account<'info, State>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
my typescript test code looks like this
it("Is initialized!", async () => {
const a = await provider.connection.getAccountInfo(
provider.wallet.publicKey,
);
console.log(pdaVaultPublicKey);
console.log(a.owner);
const tx = await program.methods
.initialize(new anchor.BN(maxParticipationAmount))
.accounts({ vault: pdaVaultPublicKey, user: provider.publicKey })
.rpc();
const b = await provider.connection.getAccountInfo(
provider.wallet.publicKey,
);
console.log(b.owner);
});
it("it is funded", async () => {
const newUser = anchor.web3.Keypair.generate();
let airdropSig = await provider.connection.requestAirdrop(
newUser.publicKey,
5 * anchor.web3.LAMPORTS_PER_SOL,
);
const latestBlockHash = await provider.connection.getLatestBlockhash();
await provider.connection.confirmTransaction({
blockhash: latestBlockHash.blockhash,
lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
signature: airdropSig,
});
const tx = await program.methods
.fundVault()
.accounts({
payer: newUser.publicKey,
receiver: provider.wallet.publicKey,
})
.signers([newUser])
.rpc();
});
so while running each of the test one by one no errors occur. running the test in the order posted I am getting this error while the second test is being run.
Error: failed to send transaction: Transaction simulation failed: This account may not be used to pay transaction fees
at Connection.sendEncodedTransaction (node_modules/@solana/web3.js/src/connection.ts:4546:13)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at Connection.sendRawTransaction (node_modules/@solana/web3.js/src/connection.ts:4505:20)
at sendAndConfirmRawTransaction (node_modules/@project-serum/anchor/src/provider.ts:288:21)
at AnchorProvider.sendAndConfirm (node_modules/@project-serum/anchor/src/provider.ts:148:14)
at MethodsBuilder.rpc [as _rpcFn] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:29:16)
my assumption is that the owner of the wallet provider while calling first instruction (initialize) is changed and for some reason calling the second instruction (fundVault) fails.
fundVault is in this example just a transfer of SOL from some newly generated keypair to the provider wallet
I have console logged the owner in my tests and indeed the owner does change in initialize instruction. But I am not sure why it changes and why it might have any influence on the second instruction call.
anybody having any ideas?
initialize
when it requires 4? I suspect Anchor is taking your 2nd account (user) asauction_instance
and initializing it as aState
account, but I don't know enough about how Anchor behaves when you pass the wrong number of accounts to know for sure. I asked about the same error message here, so I know you definitely can init a user wallet and break it like this: solana.stackexchange.com/questions/378/…