I have a program that use to store configuration, as show bellow.
All work well except that, 'set_fee' function throw error:
> Program logged: "Instruction: SetFee"
> Program logged: "Error: memory allocation failed, out of memory"
> Program consumed: 1796 of 200000 compute units
> Program returned error: "SBF program panicked"
Can someone spot out where I have possibly done wrong?
#[program]
pub mod MyConf {
use super::*;
pub fn add_domain(ctx: Context<DomainAdd>, domain: u32, name: String ) -> Result<()> {
// ...
let domain_account: &mut Account<'_, DomainData> = &mut ctx.accounts.domain_account;
domain_account.name = name;
Ok(())
}
pub fn get_domain(ctx: Context<DomainGet>, domain: u32) -> Result<String> {
let _domain_account: & Account<'_, DomainData> = & ctx.accounts.domain_account;
Ok(String::from("tester"))
// Ok(_domain_account.name) // TODO: This also a issue that I unable to let it compile. It complains "cannot move out of dereference of"
}
pub fn set_fee(ctx: Context<FeeSet>, fee: u64, name: String ) -> Result<()> { // <== THIS failed! Error: "memory allocation failed, out of memory"
msg!("admin_board::set fee to {} for user: {}", fee, name);
msg!("admin_board::set_fee() ctx.accounts.admin is: {:?}", ctx.accounts.admin.key());
require!(ctx.accounts.admin_roles_account.admins.contains(ctx.accounts.admin.key), Errors::NotAnOwner);
let fee_account: &mut Account<'_, FeeData> = &mut ctx.accounts.fee_account;
fee_account.fee = fee;
Ok(())
}
pub fn get_fee(ctx: Context<FeeGet>, domain: u32, name: String ) -> Result<u64> {
let fee_account : &Account<'_, FeeData> = &ctx.accounts.fee_account;
msg!("admin_board::get_fee() return fee value: {}", fee_account.fee);
Ok(fee_account.fee)
}
}
...
// =========================== Account and Data Struct Begin ======================
#[derive(Accounts)]
#[instruction(name: String)]
pub struct FeeSet<'info> {
#[account(mut)] // mut is must in order to pay init gas fee
pub admin: Signer<'info>,
#[account(
init_if_needed,
space = 8 + FeeData::INIT_SPACE + 8, // This is slightly more space than FeeData struct actually need.
payer = admin,
seeds=[ b"FeeData", name.as_bytes().as_ref()],
bump,
)]
pub fee_account: Account<'info, FeeData>,
#[account(
seeds = [ b"admin_roles"], // ensure no other fake PDA can call this function
bump,
)]
pub admin_roles_account: Account<'info, AdminRoleSet>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
#[instruction(domain: u32, name: String)]
pub struct FeeGet<'info> {
#[account(
constraint = name == domain_account.name,
seeds=[ b"DomainData", domain.to_le_bytes().as_ref()],
bump,
)]
pub domain_account: Account<'info, DomainData>,
#[account(
seeds=[ b"FeeData", name.as_bytes().as_ref()],
bump,
)]
pub fee_account: Account<'info, FeeData>,
}
#[account]
#[derive(InitSpace)]
pub struct DomainData {
#[max_len(256)]
pub name: String, // 4 bytes + 256 bytes
}
#[account]
#[derive(InitSpace)]
pub struct FeeData {
pub fee: u64,
}
#[account]
#[derive(InitSpace)]
pub struct AdminRoleSet {
admins: [Pubkey;3], // 32 bytes * N
}