Reputation: 645
I need a program that distributes SOLs owned by PDA
to another account.
Defined the context for distribute
instruction as below.
#[derive(Accounts)]
pub struct Pool<'info> {
#[account(
mut,
seeds = [
b"pool_account".as_ref()],
bump = pool_account.pool_account_bump
)
]
pool_account: Account<'info, PoolState>,
#[account()]
soho_account: Account<'info, PoolState>
}
The distribute
instruction is
pub fn distribute(ctx: Context<Pool>) -> ProgramResult {
let pool_account = &ctx.accounts.pool_account;
let pool_account_balance = pool_account.to_account_info().lamports();
let soho_account = &ctx.accounts.soho_account;
println!("Distributing {:?} lamports ", pool_account_balance,);
let from_pub_key = pool_account.to_account_info().key;
let to_pub_key = soho_account.to_account_info().key;
let ix = system_instruction::transfer(from_pub_key, to_pub_key, pool_account_balance);
anchor_lang::solana_program::program::invoke(
&ix,
&[
ctx.accounts.pool_account.to_account_info(),
soho_account.to_account_info()
],
)?;
Ok(())
}
The test
it(`Distrubutes funds to shareholders`, async () => {
let [poolAccount, poolAccountBump] = await web3.PublicKey.findProgramAddress(
[Buffer.from("pool_account")],
program.programId
)
// Airdrop SOL to pool account PDA
const connection = await anchor.getProvider().connection;
let signature = await connection.requestAirdrop(poolAccount, LAMPORTS_PER_SOL)
await connection.confirmTransaction(signature);
balance = await connection.getBalance(poolAccount);
console.log(`Pool Account: ${poolAccount} balance: ${balance}`)
assert.ok(balance == 1000953520, `Program account has ${balance}`)
const sohoAccount = anchor.web3.Keypair.generate();
signature = await connection.requestAirdrop(sohoAccount.publicKey, LAMPORTS_PER_SOL)
await connection.confirmTransaction(signature);
await program.rpc.distribute({
accounts: {
poolAccount: poolAccount,
sohoAccount: sohoAccount.publicKey,
// soho2: soho2.publicKey,
}
})
})
When I run the test for the distribute
instruction, the test fails w/
Error: 3007: The given account is owned by a different program than expected
message.
Basically, it expects the soho_account
to be owned by the program. however it should be an external account.
Upvotes: 1
Views: 2487
Reputation: 8098
The system
transfer requires that, at a minimum, the from
account is a System Owned account. Not a PDA and not a Program Owned account.
If the PDA is owned
by your program then your program can transfer from it to ANY account without invoking the system transfer.
See the cookbook: https://solanacookbook.com/references/programs.html#transferring-lamports
Upvotes: 2