Assertions

Assert Account Delta

AssertAccountDelta Instruction

The AssertAccountDelta instruction is similar to AssertAccountData and AssertAccountInfo instructions but with the key difference of allowing you to compare one account's data with another account's data or AccountInfo.

Example: Storing lamports into a memory account and asserting on the delta.

You may want to assert on the lamport delta of an account during a transaction. To do this we can use the memory account and delta assertion instructions that lighthouse offers. This involves writing the lamports of user's account into a memory account and asserting on the delta change.

Memory write + delta assertion transaction

const [memory, memoryBump] = await findMemoryPda({
  memoryId: 0,
  payer: userPubkey,
})

const tx = await pipe(
  createTransaction({ version: 0 }),
  (tx) =>
    appendTransactionInstructions(
      [
        getMemoryWriteInstruction({
          memory,
          payer: userPubkey,
          sourceAccount: userPubkey,
          writeType: writeType('AccountInfoField', {
            fields: ['Lamports'],
          }),
          memoryId: 0,
          writeOffset: 0,
          memoryBump,
        }),
        SystemProgram.transfer({
          fromPubkey: userPubkey,
          toPubkey: destinationPubkey,
          lamports: 1e9,
        }),
        getAssertAccountDeltaInstruction({
          accountA: memory,
          accountB: userPubkey,
          assertion: {
            __kind: 'AccountInfo',
            aOffset: 0,
            assertion: {
              __kind: 'Lamports',
              value: -1e9,
              operator: IntegerOperator.Equal,
            },
          },
        }),
      ],
      tx
    ),
  (tx) => setTransactionFeePayer(userPubkey, tx),
  (tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
  (tx) => signTransaction([userKeyPair], tx)
)

The first instruction writes the lamports of the user's account into the memory account.

The second instruction transfers 1e9 lamports (1 SOL) from the user's account to another account.

The third instruction asserts that the lamport delta of the user's account is -1e9 (1 SOL), which is what we expect.

Example: Asserting on delta of values stored in two different accounts.

Imagine a account struct with the following layout:

pub struct TestAccount {
    pub account_discriminator: [u8; 8], // bytes 0 to 7
    pub vault_balance: u64,             // bytes 8 to 16
}

Say we wanted to assert about the difference between two test accounts' vault balance.

Instruction building example for account data delta assertion

const ix = getAssertAccountDeltaInstruction({
  accountA: testAccountA,
  accountB: testAccountB,
  assertion: {
    __kind: 'Data',
    aOffset: 8, // The byte offset in account A to deserialize into a u64 (vault_balance).
    bOffset: 8, // The byte offset in account B to deserialize into a u64 (vault_balance).
    assertion: {
      __kind: 'U64',
      value: expectedDiffBound, // b.vault_balance - a.vault_balance
      operator: IntegerOperator.LessThan,
    },
  },
})

This would typically be used after storing account data into memory so you can assert on the delta changes of account data.

Previous
Account Info