You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 15:45:06