2

It seems that Anchor isn't using default values on enums.

I create an account containing an enum with a Default, and don't set a value on that enum. Example lib.rs:

#![feature(derive_default_enum)]
use anchor_lang::prelude::*;

// This is your program's public key and it will update
// automatically when you build the project.
declare_id!("HENtWdUyz7yv1rkopkt4jsd1A6tgZt8QPkKuk7KtqFb7");

#[program]
mod hello_anchor {
    use super::*;
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        msg!("Initialized!");
        Ok(())
    }
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)]
pub enum Hello {
    X,
    #[default]
    Y,
}

#[account]
pub struct HelloAccount {
    data: Hello
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = signer, space = 100)]
    pub hello_account: Account<'info, HelloAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

Playground link: https://beta.solpg.io/630dd93888a7fca897ad7d0a

If I call the initialize method, and then fetch the created account it has this structure:

{
  "data": {
    "x": {}
  }
}

I'd have expected it to have the y value since that's the default in the enum and I didn't set it.

Similarly if I create an account containing an array of these enums. Example lib.rs:

#![feature(derive_default_enum)]
use anchor_lang::prelude::*;

// This is your program's public key and it will update
// automatically when you build the project.
declare_id!("995YWZuGkLpcC6Q8itToMhJrnaYwwLTzUViWdui8eJU2");

#[program]
mod hello_anchor {
    use super::*;
    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        msg!("Initialized!");
        Ok(())
    }
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, Default)]
pub enum Hello {
    X,
    #[default]
    Y,
}

#[account]
pub struct HelloAccount {
    data: [Hello; 3]
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = signer, space = 100)]
    pub hello_account: Account<'info, HelloAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

Playground link: beta.solpg.io/630dda3c88a7fca897ad7d0b

Again I call initialize and fetch the created account. It looks like this:

{
  "data": [
    {
      "x": {}
    },
    {
      "x": {}
    },
    {
      "x": {}
    }
  ]
}

Again the array is initialized with all x values when the default is y.

Is there a way to get Anchor to initialize using the default value?

Also note that in the second case (with the array), there's a rust compile error if Default is not derived for the enum, which is fixed when I derive it. There's also a rust compile error if I have the Default derive and don't include the #[default]. So I'm not sure what I'm missing here.

Edit: I've also opened a bug in the Anchor repo: https://github.com/coral-xyz/anchor/issues/2159

1 Answer 1

1

I believe you have to implement (impl) default for each enum you want to use default values for.

#[account]
#[derive(Default)]
pub struct HelloAccount {
    data: Hello
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy)]
pub enum Hello {
    X,
    Y,
}

impl Default for Hello {
  fn default() -> Self {
    Hello::Y
  }
}
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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