# Z-Imburse Docs: EntitlementNote
[Entitlement Notes](https://github.com/Mach-34/z-imburse/blob/main/contracts/z_imburse_escrow/src/types/entitlement_note.nr) are how an admin gives an organization participant the ability to self-reimburse for expenses. The data is defined below:
## Note Definition
```rust
pub struct EntitlementNote {
// the user that is allowed to use this entitlement
recipient: AztecAddress,
// the type of receipt verifier that this entitlement can be used for
verifier_id: u8,
// the maximum value that can be withdrawn from the escrow using this entitlement
max_value: U128,
// date range that verified emails can be used for
date_start: u32, // SPOT ONLY
date_end: u32, // SPOT ONLY
// destination if used for travel
destination: Field, // SPOT ONLY (not used in hosting)
// whether or not the entitlement is a spot entitlement
spot: bool,
// blinding factor & nullifier secret for the note
randomness: Field,
}
```
Breaking this down:
* An `EntitlementNote` is owned by `EntitlementNote.recipient` - a `context.msg_sender()` cannot use this note unless it is the receipient
* The `EntitlementNote.verifier_id` ensures that the note is being used with the right email verification circuit. It additionally is used in the `ZImburseRegistry` to prevent the use of unauthorized signatures.
* The `EntitlementNote.max_value` is the maximum amount of payment tokens that a participant can claim. For instance, if `max_value` is 10 but a receipt billing 12 is produced, the claimant can only withdraw 10 tokens.
* The `Entitlement.date_start` and `Entitlement.date_end` are optional values that are included only for SPOT entitlements. One-time use entitlements will likely want to constrain a time range of a valid receipt. For instance, if an admin wants to reimburse the cost of flights to DevCon 2024, they may choose to only allow flight receipts that show flights taken from November 1 - November 12
* The `EntitlementNote.destination` is an optional value that is only included for travel receipts. For instance, if an admin wants to reimburse the cost of flights to DevCon 2024, they may choose to only allow flight receipts that fly into the airport code "BKK"
* The `EntitlementNote.spot` boolean allows granular searching of entitlement notes and one of each entitlement type to exist for any user (rather than one spot OR recurring entitlement per verifier id per user).
* The `EntitlementNote.randomness` value is a blinding factor that makes it impossible to perform a partial preimage attack against the note hash. Additionally, since entitlement notes are known to both recipients and the admin, the randomness value is used as a nullifier secret over the traditional `nsk_app`
:::info
It would be ideal to get an exploration of the deficiencies/ risk of using `EntitlementNote.randomness` as the nullifier secret over the standard method of `get_nsk_app`
:::
## Recurring Nullification
If an `EntitlementNote` is recurring, it means the recipient can use the entitlement for as many satisfying emails as they can produce. The verifier circuit for the given entitlement should handle parsing the timestamp. [EntitlementNote::check_and_emit_recurring_nullifier](https://github.com/Mach-34/z-imburse/blob/main/contracts/z_imburse_escrow/src/types/entitlement_note.nr#L296-L311) is used to constrain this action:
1. [derive the recurring nullifier](https://github.com/Mach-34/z-imburse/blob/main/contracts/z_imburse_escrow/src/types/entitlement_note.nr#L259-L272)
2. emit the nullifier through the kernel
Technically, there is an unsafe oracle call performed to check if the nullifier exists. This has minimal costs and is done to provide better error messaging to honest users. However, if a malicous user attempts to lie about the return value of `check_nullifier_exists`, the kernel circuit will still fail as it is trying to insert a nullifier that already exists.
Through this mechanism, we are able to ensure that for a specific entitlement a claimant is only able to claim once per period (functionally always month in Z-Imburse V1).
:::info
`start_date` and `end_date` are not currently used in recurring entitlements. This means that a participant could potentially claim reimbursements from before the start of business conducted between the admin and receipient. `start_date` needs to be included to prevent this, and `end_date` could be a nice tool for the admin to cap the obligation without manual intervention in the future.
:::
## Entitlement Nullification
Entitlements are issued by Admins to participants, but they may choose to revoke the participant's right to use the entitlement in the future. Because of this, every `EntitlementNote` created is actually duplicated and sent to both the admin and the claimant. The admin cannot reimburse themselves with the entitlement as they are not the receipient, however, they *can* revoke the entitlement from the holder.
To accomodate this, there also exists a special entitlement nullifier for the note itself. Originally we attempted to just use `pop_notes` to emit the nullifier, however there is siloing of the notes that prevents the nullifier from the admin's note affecting the participant's note (and vice versa). For this reason, we have a slightly more complex method [for emitting entitlement nullifiers](https://github.com/Mach-34/z-imburse/blob/main/contracts/z_imburse_escrow/src/types/entitlement_note.nr#L284-L294).
The nullifier computed by `check_nullifier` will be the same for both the admin and the recipient's notes, meaning that either can emit it to prevent the other from doing something with it.
On the admin side, they will call `ZImburseEscrow::revoke_entitlement` on any existing entitlement (spot or recurring). On the participant side, claiming a spot entitlement will intrinsically consume it and also emit the nullifier. In either case, when the nullifier is emitted by one party, the other party can no longer use the note for their intended purpose as they will fail the nullifier non-inclusion check.
:::info
Unit tests for the `ZImburseEscrow` contract use the Aztec TXE which does not support `prove_nullifier_non_inclusion`. For this reason, we have the very hacky practice of commenting out `EntitlementNote::check_nullifier` for [EntitlementNote::check_nullifier_txe](https://github.com/Mach-34/z-imburse/tree/main/contracts/z_imburse_escrow/src/types#L277-L282)
:::
As mentioned above, the nullifier emission by one party will not intrinsically remove the note from the PXE of the other party. Therefore, the nullifying party must also [emit the `randomness` of the in a nullifier event](https://github.com/Mach-34/z-imburse/blob/main/contracts/z_imburse_escrow/src/types/entitlement_note.nr#L359-L378). All participant's PXE's must scan for nullified notes and prune them if they find these events during sync/ live watching. Unless there are critical issues with how this is done, this can be overlooked for auditing as we will seek a way to automatically nullify without additional work scanning for events.