Assertions

Assert Upgradeable Loader Account

AssertUpgradeableLoaderAccount Instruction

The AssertUpgradeableLoaderAccount instruction is for making assertions on the states and fields of an upgradeable loader account.

This could also be accomplished by using the AssertAccountData instruction, but this instruction is a convenience instruction for stake accounts which checks that the account is owned by the stake program and maps enums to offset / type deserialization.

The upgradeable loader account is an enum that looks like

pub enum UpgradeableLoaderState {
    /// Account is not initialized.
    Uninitialized,
    /// A Buffer account.
    Buffer {
        /// Authority address
        authority_address: Option<Pubkey>,
        // The raw program data follows this serialized structure in the
        // account's data.
    },
    /// An Program account.
    Program {
        /// Address of the ProgramData account.
        programdata_address: Pubkey,
    },
    // A ProgramData account.
    ProgramData {
        /// Slot that the program was last modified.
        slot: u64,
        /// Address of the Program's upgrade authority.
        upgrade_authority_address: Option<Pubkey>,
        // The raw program data follows this serialized structure in the
        // account's data.
    },
}

The assertion enum consists of the following

pub enum UpgradeableLoaderStateAssertion {
    State {
        value: UpgradeableLoaderStateType,
        operator: EquatableOperator,
    },
    Buffer(UpgradableBufferAssertion),
    Program(UpgradeableProgramAssertion),
    ProgramData(UpgradeableProgramDataAssertion),
}

You can make assertions about the State, Buffer, Program, and ProgramData structs of the upgradeable loader account. UpgradeableLoaderStateType is an enum that represents the state of the upgradeable loader account.

The UpgradableBufferAssertion struct is as follows:

pub enum UpgradableBufferAssertion {
    Authority {
        value: Option<Pubkey>,
        operator: EquatableOperator,
    },
}

The UpgradeableProgramAssertion struct is as follows:

pub enum UpgradeableProgramAssertion {
    ProgramDataAddress {
        value: Pubkey,
        operator: EquatableOperator,
    },
}

The UpgradeableProgramDataAssertion struct is as follows:

pub enum UpgradeableProgramDataAssertion {
    UpgradeAuthority {
        value: Option<Pubkey>,
        operator: EquatableOperator,
    },
    Slot {
        value: u64,
        operator: IntegerOperator,
    },
}

Example: Asserting on the state of an upgradeable loader account

In this example, we assert that the upgradeable loader account is in the Buffer state.

Assert state transaction

const tx = await pipe(
  createTransaction({ version: 0 }),
  (tx) =>
    appendTransactionInstructions(
      [
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: upgradeableLoaderAccount,
          assertion: upgradeableLoaderStateAssertion('State', {
            value: UpgradeableLoaderStateType.Buffer,
            operator: EquatableOperator.Equal,
          }),
        }),
      ],
      tx
    ),
  (tx) => setTransactionFeePayer(userKey, tx),
  (tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
  (tx) => signTransaction([userKeyPair], tx)
)

Example: Asserting on the buffer of an upgradeable loader account

In this example, we assert that the authority of the buffer of the upgradeable loader account is equal to a specific pubkey.

Assert state + assert buffer transaction

const tx = await pipe(
  createTransaction({ version: 0 }),
  (tx) =>
    appendTransactionInstructions(
      [
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programKey,
          assertion: upgradeableLoaderStateAssertion('State', {
            value: UpgradeableLoaderStateType.Buffer,
            operator: EquatableOperator.Equal,
          }),
        }),
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programKey,
          assertion: upgradeableLoaderStateAssertion('Buffer', {
            __kind: 'Authority',
            value: authorityKey,
            operator: EquatableOperator.Equal,
          }),
        }),
      ],
      tx
    ),
  (tx) => setTransactionFeePayer(userKey, tx),
  (tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
  (tx) => signTransaction([userKeyPair], tx)
)

Example: Asserting on the program of an upgradeable loader account

In this example, we assert that the program data address of the upgradeable loader account is equal to a specific pubkey.

Assert state + assert program transaction

const tx = await pipe(
  createTransaction({ version: 0 }),
  (tx) =>
    appendTransactionInstructions(
      [
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programKey,
          assertion: upgradeableLoaderStateAssertion('State', {
            value: UpgradeableLoaderStateType.Program,
            operator: EquatableOperator.Equal,
          }),
        }),
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programKey,
          assertion: upgradeableLoaderStateAssertion('Program', {
            __kind: 'ProgramDataAddress',
            value: programDataKey,
            operator: EquatableOperator.Equal,
          }),
        }),
      ],
      tx
    ),
  (tx) => setTransactionFeePayer(userKey, tx),
  (tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
  (tx) => signTransaction([userKeyPair], tx)
)

Example: Asserting on the program data of an upgradeable loader account

In this example, we assert that the upgrade authority of the program data of the upgradeable loader account is equal to a specific pubkey and that the slot of the upgrade matches a specific slot.

Assert state + assert program data transaction

const tx = await pipe(
  createTransaction({ version: 0 }),
  (tx) =>
    appendTransactionInstructions(
      [
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programDataKey,
          assertion: upgradeableLoaderStateAssertion('State', {
            value: UpgradeableLoaderStateType.ProgramData,
            operator: EquatableOperator.Equal,
          }),
        }),
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programDataKey,
          assertion: upgradeableLoaderStateAssertion('ProgramData', {
            __kind: 'UpgradeAuthority',
            value: upgradeAuthority,
            operator: EquatableOperator.Equal,
          }),
        }),
        getAssertUpgradeableLoaderAccountInstruction({
          targetAccount: programDataKey,
          assertion: upgradeableLoaderStateAssertion('ProgramData', {
            __kind: 'Slot',
            value: expectedSlot,
            operator: IntegerOperator.Equal,
          }),
        }),
      ],
      tx
    ),
  (tx) => setTransactionFeePayer(userKey, tx),
  (tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
  (tx) => signTransaction([userKeyPair], tx)
)
Previous
Stake Account