WithdrawalConfig
The WithdrawalConfig struct is passed to the Application constructor to enable foreclosure and emergency withdrawal. It defines who may foreclose the application (the guardian), the geometry of the accounts drive (the in-app balance ledger held inside the machine state), and the contract that builds withdrawal outputs.
A zero-valued WithdrawalConfig is valid and deploys an application without the feature.
Struct
struct WithdrawalConfig {
address guardian;
uint8 log2LeavesPerAccount;
uint8 log2MaxNumOfAccounts;
uint64 accountsDriveStartIndex;
IWithdrawalOutputBuilder withdrawalOutputBuilder;
}
| Field | Type | Description |
|---|---|---|
guardian | address | The account allowed to call foreclose(). |
log2LeavesPerAccount | uint8 | Log2 of the machine-state-tree leaves reserved per account. Each account record occupies 2^(5 + log2LeavesPerAccount) bytes. |
log2MaxNumOfAccounts | uint8 | Log2 of the maximum number of accounts. This is the depth of the accounts-drive tree. |
accountsDriveStartIndex | uint64 | Start-index factor that positions the accounts drive in machine memory (see Drive geometry). |
withdrawalOutputBuilder | IWithdrawalOutputBuilder | The contract that builds the withdrawal output for an account. See IWithdrawalOutputBuilder. |
Drive geometry
Let a = log2LeavesPerAccount, b = log2MaxNumOfAccounts, and c = accountsDriveStartIndex. The accounts drive:
- has a size of
2^(a + b + 5)bytes (the+5is the log2 of the 32-byte data block,CanonicalMachine.LOG2_DATA_BLOCK_SIZE); - starts at machine memory address
c * 2^(a + b + 5); - holds up to
2^baccounts, each occupying2^(a + 5)bytes.
These same three values are returned on-chain by getLog2LeavesPerAccount(), getLog2MaxNumOfAccounts(), and getAccountsDriveStartIndex(), and must match the layout the guest application actually writes.
Validation
function isValid(WithdrawalConfig memory withdrawalConfig) internal pure returns (bool)
The Application constructor calls isValid() and reverts with InvalidWithdrawalConfig (see ApplicationFactory) if it returns false. isValid() enforces that the accounts drive fits inside the machine memory:
log2(driveSize) = 5 + log2MaxNumOfAccounts + log2LeavesPerAccountmust not exceed64(the machine memory is2^64bytes); and- the drive's end address
(accountsDriveStartIndex + 1) << log2(driveSize)must not overflow and must not exceed2^64.
isValid() checks only the drive geometry. It does not reject a zero guardian or a zero withdrawalOutputBuilder. A config with those set to zero still passes the constructor, as long as its geometry is valid. Deployment tools such as the Cartesi Rollups CLI go further and refuse a zero guardian or builder for an enabled config, but a direct factory call would not.