2

there is a game account created by the contract. the contract is the creator of this account, but it is not authorized to make transactions. why?

...
#[derive(Accounts)]
pub struct ResultGameMatchContext<'info> {
    #[account(mut)]
    pub game: Account<'info, Game>,

    #[account(mut)]
    pub game_match: Account<'info, GameMatch>,

    /// CHECK: we will check this in the instruction
    #[account(mut)]
    pub player: AccountInfo<'info>,

    /// CHECK: we will check this in the instruction
    #[account(mut)]
    pub admin: Signer<'info>,

    /// CHECK: sysvar address check is hardcoded, we want to avoid the default deserialization
    #[account(address = sysvar::recent_blockhashes::ID)]
    pub recent_blockhashes: UncheckedAccount<'info>,
    pub system_program: Program<'info, System>,
}
...
        if ctx.accounts.game_match.won {
            msg!("you won!");
            ctx.accounts.game_match.status = GameMatchStatus::Won;

            ctx.accounts.game.win_count += 1;
            ctx.accounts.game_match.won_amount = (ctx.accounts.game_match.bet_amount
                * ctx.accounts.game.multiplier as u64)
                / 1000 as u64;

            msg!("won_amount: {}", ctx.accounts.game_match.won_amount);

            // Error
            let transfer_to_player = solana_program::system_instruction::transfer(
                &ctx.accounts.game.key(),
                &ctx.accounts.player.key(),
                ctx.accounts.game_match.won_amount,
            );
            solana_program::program::invoke(
                &transfer_to_player,
                &[
                    ctx.accounts.game.to_account_info(),
                    ctx.accounts.player.to_account_info(),
                    ctx.accounts.system_program.to_account_info(),
                ],
            )?;
        }
...

2 Answers 2

1

You should have to init your vault function first.

pub fn init_vault( 
    ctx: Context<InitValut>, 
    _bump: u8,
) -> ProgramResult {
    msg!("Init Vault");
    let vault = &mut ctx.accounts.vault;
    vault.owner = *ctx.accounts.owner.key;
    vault.rand = *ctx.accounts.rand.key;
    vault.bump = _bump;
    Ok(())
}

This will be used for PDA sign. The game account should be created with a nonce account like this

let vec_instructions = system_instruction::create_nonce_account(
        owner.key,
        nonce_account.key,
        vault.key,
        10_000_000, // you have to transfer some solana to the nonce account.
    );

    for instruction in vec_instructions {
        invoke(
            &instruction,
            &[
                owner.clone(),
                nonce_account.clone(),
                system_program.to_account_info(),
                rent.clone(),
                recent_blockhash.clone(),
            ]
        )?;
    }
0

As you know, the Only system accounts can transfer the Sol to each other. The Game account is owned by your contract not owned by the system program. So if you want to send Solana from game account to user account, you should have to create a nonce-account to manage the solana.

    let vault_seeds = &[
            vault.rand.as_ref(),
            &[vault.bump],
        ];
        invoke_signed(
            &system_instruction::withdraw_nonce_account(
                nonce_account.key,
                vault.to_account_info().key,
                owner.key,
                bid_data.bid_amount - _bid_amount,
            ),
            &[
                nonce_account.clone(),
                owner.clone(),
                system_program.to_account_info(),
                rent.clone(),
                recent_blockhash.clone(),
                vault.to_account_info(),
            ],
            &[vault_seeds],
        )?;
2
  • How can we describe successfully completing the transfer of funds from the user's account to the game account on Solana?
    – tolgaandx
    Commented Mar 13, 2023 at 17:55
  • After create the nonce account, you can run the transfer function to transfer of funds from user account to game account. But withdrawing from the game account, you should use the withdraw_nonce_account function Commented Mar 13, 2023 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.