如何将deposit_sol_collateral_account所有权转移至非mint类PDA
结论
你找到的示例是SPL代币账户的操作流程,不能直接照搬,但PDA作为程序签名者的核心逻辑是通用的,你需要适配原生SOL账户的操作规则即可,不需要用到mint相关的功能。
核心差异说明
你找到的示例是操作SPL代币账户,调用的是Token程序的transfer、set_authority等CPI指令,而你的deposit_sol_collateral_account是原生SOL账户,由系统程序管理,不需要和Token程序交互,两种场景的PDA签名逻辑一致,只是调用的底层程序和指令不同。
两种实现方案
根据你的需求可以选择以下任意一种方案:
方案1:直接用PDA作为SOL抵押账户(推荐,更简洁)
原生PDA本身就可以直接持有SOL,不需要额外创建中间账户,你可以在初始化阶段就将抵押账户绑定到PDA,省去后续转移所有权的步骤:
#[derive(Accounts)] pub struct InitializeObligation<'info> { #[account(signer)] authority: AccountInfo<'info>, #[account(zero)] obligation: Account<'info, Obligation>, // 直接将抵押账户初始化为程序PDA #[account( init, payer = authority, space = 0, // 仅存SOL不需要额外存储数据时space设为0即可 seeds = [b"sol_collateral", obligation.key().as_ref()], bump )] deposit_sol_collateral_account: AccountInfo<'info>, pub system_program: Program<'info, System>, }
你现有的depositcollateral存款逻辑不需要改动,后续需要取出抵押SOL时,用PDA种子作为签名即可直接操作账户内的SOL:
// 抵押SOL取出示例 pub fn withdraw_collateral(ctx: Context<WithdrawCollateral>, amount: u64) -> ProgramResult { let lamports = sol_to_lamports(amount as f64); // 构造PDA签名种子 let obligation_key = ctx.accounts.obligation.key(); let bump = *ctx.bumps.get("deposit_sol_collateral_account").unwrap(); let seeds = &[b"sol_collateral", obligation_key.as_ref(), &[bump]]; // 直接调整账户lamports余额完成SOL转移 **ctx.accounts.deposit_sol_collateral_account.try_borrow_mut_lamports()? -= lamports; **ctx.accounts.owner.try_borrow_mut_lamports()? += lamports; // 对应业务状态更新 ctx.accounts.obligation.deposited_sol -= amount; ctx.accounts.global_state.deposited_sol -= amount; Ok(()) }
方案2:将现有SOL账户所有权转移给PDA
如果你需要保留已经创建的deposit_sol_collateral_account账户,可以调用系统程序的assign指令将账户所有权转移给你的PDA:
pub fn transfer_account_to_pda(ctx: Context<TransferAccount>) -> ProgramResult { // 生成PDA地址 let (pda, _bump) = Pubkey::find_program_address(&[b"sol_collateral"], ctx.program_id); // 调用系统程序assign指令转移账户所有权 let ix = system_instruction::assign( &ctx.accounts.deposit_sol_collateral_account.key(), &pda ); // 当前账户所有者签名完成转移 anchor_lang::solana_program::program::invoke( &ix, &[ ctx.accounts.deposit_sol_collateral_account.clone(), ctx.accounts.current_owner.clone(), ctx.accounts.system_program.clone() ] )?; Ok(()) }
转移完成后你就可以用PDA的种子签名来操作这个账户内的SOL,操作逻辑和方案1的取出逻辑一致。
内容的提问来源于stack exchange,提问作者Muhammad Ismaila
相关产品推荐
相关产品推荐

