IApplication
Inherits: IOwnable, AddressErrors, BinaryMerkleTreeErrors, IRefundOutputBuilderErrors, IWithdrawalOutputBuilderErrors, IVersionGetter
The base layer incarnation of an application running on the execution layer.
The state of the application advances through inputs sent to an IInputBox contract.
These inputs can be sent either directly, or indirectly through portals.
Reader nodes can retrieve inputs sent to the IInputBox contract through events, and feed them into the machine.
Validator nodes can also submit claims to the IOutputsMerkleRootValidator contract (see the getOutputsMerkleRootValidator function).
Once accepted, claims can be used to validate outputs generated by the machine.
Some outputs are executable, which means they can have on-chain side effects.
Every application is subscribed to some outputs Merkle root validator, and may be governed by some owner. The outputs Merkle root validator has the power to accept claims, which, in turn, are used to validate outputs. Meanwhile, the owner can replace the outputs Merkle root validator at any time. Therefore, the users of an application must trust both the outputs Merkle root validator and the application owner.
There are several ownership models to choose from:
- no owner (address zero)
- individual signer (externally-owned account)
- multiple signers (multi-sig)
- DAO (decentralized autonomous organization)
- self-owned application (off-chain governance logic)
Functions
migrateToOutputsMerkleRootValidator
Migrate the application to a new outputs Merkle root validator.
Can only be called by the application owner.
May raise OwnableUnauthorizedAccount or Foreclosed.
function migrateToOutputsMerkleRootValidator(IOutputsMerkleRootValidator newOutputsMerkleRootValidator)
external;
Parameters
| Name | Type | Description |
|---|---|---|
newOutputsMerkleRootValidator | IOutputsMerkleRootValidator | The new outputs Merkle root validator |
foreclose
Forecloses the application, allowing users to withdraw their funds by providing Merkle proofs of their in-app accounts.
Can only be called by the application guardian.
May raise NotGuardian or Foreclosed.
function foreclose() external;
executeOutput
Execute an output.
On a successful execution, emits a OutputExecuted event.
May raise any of the errors raised by validateOutput,
as well as OutputNotExecutable and OutputNotReexecutable.
function executeOutput(bytes calldata output, OutputValidityProof calldata proof)
external;
Parameters
| Name | Type | Description |
|---|---|---|
output | bytes | The output |
proof | OutputValidityProof | The proof used to validate the output against a claim accepted to the current outputs Merkle root validator contract |
issueRefund
Issue a refund for an unprocessed input.
May raise CannotRefundFinalizedInput, RefundAlreadyIssued,
UnknownInputSender, as well as any of the errors raised by validateInput.
On success, marks the input as refunded, and emits a RefundIssued event.
function issueRefund(uint256 inputIndex, bytes calldata input) external;
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The index of the input in the application's input box. |
input | bytes | The input that was sent to the application |
proveAccountsDriveMerkleRoot
Prove the accounts drive Merkle root in the last-finalized machine state provided by the application's outputs Merkle root validator or in the initial machine Merkle root (template hash) if no machine Merkle root has been finalized yet. This function can be called by anyone after the app is foreclosed so that accounts can be validated and their funds can be withdrawn.
May raise NotForeclosed, AccountsDriveMerkleRootAlreadyProved,
InvalidAccountsDriveMerkleRootProofSize or InvalidMachineMerkleRoot.
On success, stores the proved accounts drive Merkle root and emits an
AccountsDriveMerkleRootProved event.
function proveAccountsDriveMerkleRoot(
bytes32 accountsDriveMerkleRoot,
bytes32[] calldata proof
) external;
Parameters
| Name | Type | Description |
|---|---|---|
accountsDriveMerkleRoot | bytes32 | The accounts drive Merkle root |
proof | bytes32[] | Siblings of the accounts drive Merkle root in the machine |
withdraw
Withdraw the funds of an account from the foreclosed application. First, the account is validated against the proved accounts drive Merkle root. Then, a withdrawal output is built from the account, and executed.
May raise NotForeclosed, AccountFundsAlreadyWithdrawn,
as well as any of the errors raised by validateAccount.
On success, marks the account funds as withdrawn, and emits a Withdrawal event.
function withdraw(bytes calldata account, AccountValidityProof calldata proof)
external;
Parameters
| Name | Type | Description |
|---|---|---|
account | bytes | The account |
proof | AccountValidityProof | The proof used to validate the account |
wasOutputExecuted
Check whether an output has been executed.
function wasOutputExecuted(uint256 outputIndex) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
outputIndex | uint256 | The index of output |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Whether the output has been executed before or is currently being executed (in the current transaction) |
validateOutput
Validate an output.
May raise any of the errors raised by validateOutputHash.
function validateOutput(bytes calldata output, OutputValidityProof calldata proof)
external
view;
Parameters
| Name | Type | Description |
|---|---|---|
output | bytes | The output |
proof | OutputValidityProof | The proof used to validate the output against a claim accepted to the current outputs Merkle root validator contract |
validateOutputHash
Validate an output hash.
May raise InvalidOutputHashesSiblingsArrayLength
or InvalidOutputsMerkleRoot.
function validateOutputHash(bytes32 outputHash, OutputValidityProof calldata proof)
external
view;
Parameters
| Name | Type | Description |
|---|---|---|
outputHash | bytes32 | The output hash |
proof | OutputValidityProof | The proof used to validate the output against a claim accepted to the current outputs Merkle root validator contract |
getTemplateHash
Get the application's template hash.
function getTemplateHash() external view returns (bytes32);
Returns
| Name | Type | Description |
|---|---|---|
<none> | bytes32 | The application's template hash |
getOutputsMerkleRootValidator
Get the current outputs Merkle root validator.
function getOutputsMerkleRootValidator()
external
view
returns (IOutputsMerkleRootValidator);
Returns
| Name | Type | Description |
|---|---|---|
<none> | IOutputsMerkleRootValidator | The current outputs Merkle root validator |
getInputBox
Get the input box contract used by application.
function getInputBox() external view returns (IInputBox);
getDeploymentBlockNumber
Get number of block in which contract was deployed
function getDeploymentBlockNumber() external view returns (uint256);
getNumberOfExecutedOutputs
Get number of outputs executed by the application.
function getNumberOfExecutedOutputs() external view returns (uint256);
isForeclosed
Check whether the application has been foreclosed. An application that has been foreclosed will remain so.
function isForeclosed() external view returns (bool);
getGuardian
Get the address of the guardian, which has the power to foreclose the application.
function getGuardian() external view returns (address);
getWithdrawalConfig
Get the withdrawal configuration set upon construction.
function getWithdrawalConfig()
external
view
returns (WithdrawalConfig memory withdrawalConfig);
Returns
| Name | Type | Description |
|---|---|---|
withdrawalConfig | WithdrawalConfig | The withdrawal configuration |
getNumberOfIssuedRefunds
Get the number of issued refunds.
Useful for fast-syncing RefundIssued events.
function getNumberOfIssuedRefunds() external view returns (uint256);
wasRefundForInputIssued
Check whether a refund had been issued for an input.
function wasRefundForInputIssued(uint256 inputIndex) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The index of the input in the application's input box |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Whether a refund for the input has been issued before or is currently being issued (in the current transaction) |
getAccountsDriveMerkleRoot
Check whether the accounts drive Merkle root was proved and its value.
function getAccountsDriveMerkleRoot()
external
view
returns (bool wasAccountsDriveMerkleRootProved, bytes32 accountsDriveMerkleRoot);
Returns
| Name | Type | Description |
|---|---|---|
wasAccountsDriveMerkleRootProved | bool | Whether the accounts drive Merkle root was proved |
accountsDriveMerkleRoot | bytes32 | The accounts drive Merkle root (if proved) |
getNumberOfWithdrawals
Get the number of withdrawals.
Useful for fast-syncing Withdrawal events.
function getNumberOfWithdrawals() external view returns (uint256);
wereAccountFundsWithdrawn
Check whether an account had its funds withdrawn.
function wereAccountFundsWithdrawn(uint256 accountIndex) external view returns (bool);
Parameters
| Name | Type | Description |
|---|---|---|
accountIndex | uint256 | The index of the account in the accounts drive. |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | Whether the account funds have been withdrawn before or are currently being withdrawn (in the current transaction) |
getLog2LeavesPerAccount
Get the log (base 2) of the number of leaves in the machine state tree that are reserved for each account in the accounts drive.
function getLog2LeavesPerAccount() external view returns (uint8);
getLog2MaxNumOfAccounts
Get the log (base 2) of the maximum number of accounts that can be stored in the accounts drive.
This is equivalent to the depth of the accounts drive tree whose leaves are the account roots.
function getLog2MaxNumOfAccounts() external view returns (uint8);
getAccountsDriveStartIndex
Get the factor that, when multiplied by the size of the accounts drive, yields the start memory address of the accounts drive.
If a = getLog2LeavesPerAccount() b = getLog2MaxNumOfAccounts(),
and c = getAccountsDriveStartIndex(), then the accounts drive starts
at memory address c*2^{a+b+5} and has 2^{a+b+5} bytes in size.
function getAccountsDriveStartIndex() external view returns (uint64);
getRefundOutputBuilder
Get the refund output builder, which gets static-called whenever a deposit is to be refunded to the original depositor.
function getRefundOutputBuilder() external view returns (IRefundOutputBuilder);
validateInput
Validates an input that was sent to the application.
May raise IllFormedInput as well as any of the errors raised by validateInputHash.
function validateInput(uint256 inputIndex, bytes calldata input)
external
view
returns (uint256 blockNumber, address inputSender, bytes memory inputPayload);
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The index of the input in the application's input box. |
input | bytes | The input that was sent to the application |
Returns
| Name | Type | Description |
|---|---|---|
blockNumber | uint256 | The number of the base-layer block in which the input was added |
inputSender | address | The input sender |
inputPayload | bytes | The input payload |
validateInputHash
Validates an input that was sent to the application.
May raise InvalidInputIndex or InvalidInputHash.
function validateInputHash(uint256 inputIndex, bytes32 inputHash) external view;
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The index of the input in the application's input box. |
inputHash | bytes32 | The hash of the input that was sent to the application |
getWithdrawalOutputBuilder
Get the withdrawal output builder, which gets static-called whenever the funds of an account are to be withdrawn.
function getWithdrawalOutputBuilder() external view returns (IWithdrawalOutputBuilder);
validateAccount
Validate the existence of an account at a given index
on the accounts drive given a Merkle proof of the account root,
according to the accounts drive Merkle root proved through the
proveAccountsDriveMerkleRoot function.
May raise any of the errors raised by validateAccountMerkleRoot,
as well as DriveSmallerThanData (if the provided account is too large).
function validateAccount(bytes calldata account, AccountValidityProof calldata proof)
external
view;
Parameters
| Name | Type | Description |
|---|---|---|
account | bytes | The account |
proof | AccountValidityProof | The proof used to validate the account |
validateAccountMerkleRoot
Validate the existence of an account at a given index
on the accounts drive given a Merkle proof of the account root,
according to the accounts drive Merkle root proved through the
proveAccountsDriveMerkleRoot function.
May raise InvalidAccountRootSiblingsArrayLength, InvalidNodeIndex
(if the account index is outside the boundaries of the accounts drive),
AccountsDriveMerkleRootNotProved or InvalidAccountsDriveMerkleRoot.
function validateAccountMerkleRoot(
bytes32 accountMerkleRoot,
AccountValidityProof calldata proof
) external view;
Parameters
| Name | Type | Description |
|---|---|---|
accountMerkleRoot | bytes32 | The account Merkle root |
proof | AccountValidityProof | The proof used to validate the account |
Events
OutputsMerkleRootValidatorChanged
MUST trigger when a new outputs Merkle root validator is chosen.
event OutputsMerkleRootValidatorChanged(IOutputsMerkleRootValidator newOutputsMerkleRootValidator);
Parameters
| Name | Type | Description |
|---|---|---|
newOutputsMerkleRootValidator | IOutputsMerkleRootValidator | The new outputs Merkle root validator |
OutputExecuted
MUST trigger when an output is executed.
event OutputExecuted(uint64 indexed outputIndex, bytes output);
Parameters
| Name | Type | Description |
|---|---|---|
outputIndex | uint64 | The index of the output |
output | bytes | The output |
Foreclosure
MUST trigger when the application is foreclosed.
event Foreclosure();
RefundIssued
MUST trigger when a refund for an input is issued.
event RefundIssued(uint256 indexed inputIndex, bytes input, bytes output);
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The index of the input |
input | bytes | The input |
output | bytes | The refund output |
AccountsDriveMerkleRootProved
MUST trigger when the accounts drive Merkle root is proved.
event AccountsDriveMerkleRootProved(bytes32 accountsDriveMerkleRoot);
Parameters
| Name | Type | Description |
|---|---|---|
accountsDriveMerkleRoot | bytes32 | The accounts drive Merkle root |
Withdrawal
MUST trigger when the funds of an account are withdrawn.
event Withdrawal(uint64 indexed accountIndex, bytes account, bytes output);
Parameters
| Name | Type | Description |
|---|---|---|
accountIndex | uint64 | The account index in the accounts drive |
account | bytes | The account as encoded in the accounts drive |
output | bytes | The withdrawal output |
Errors
OutputNotExecutable
Could not execute an output, because the application contract doesn't know how to.
error OutputNotExecutable(bytes output);
Parameters
| Name | Type | Description |
|---|---|---|
output | bytes | The output |
OutputNotReexecutable
Could not execute an output, because it was already executed.
error OutputNotReexecutable(bytes output);
Parameters
| Name | Type | Description |
|---|---|---|
output | bytes | The output |
InvalidOutputHashesSiblingsArrayLength
Raised when the output hashes siblings array has an invalid size.
Please consult CanonicalMachine for the maximum number of outputs.
error InvalidOutputHashesSiblingsArrayLength();
InvalidOutputsMerkleRoot
Raised when the computed outputs Merkle root is invalid, according to the current outputs Merkle root validator.
error InvalidOutputsMerkleRoot(bytes32 outputsMerkleRoot);
NotGuardian
Raised when a function that can only be called by the application guardian is called by some other account.
error NotGuardian();
NotForeclosed
Raised when the application has not yet been foreclosed and therefore withdrawal-related actions cannot be performed yet.
error NotForeclosed();
Foreclosed
Raised when the application has been foreclosed and therefore some actions cannot be performed anymore.
error Foreclosed();
InvalidInputIndex
Raised when trying to validate an input with an invalid index.
This error is raised when invalidInputIndex >= numOfInputs.
error InvalidInputIndex(uint256 invalidInputIndex, uint256 numOfInputs);
Parameters
| Name | Type | Description |
|---|---|---|
invalidInputIndex | uint256 | The invalid input index provided for validation |
numOfInputs | uint256 | The actual number of inputs to the application |
InvalidInputHash
Raised when trying to validate an input with an invalid hash.
This error is raised when storedInputHash != invalidInputHash.
error InvalidInputHash(bytes32 storedInputHash, bytes32 invalidInputHash);
Parameters
| Name | Type | Description |
|---|---|---|
storedInputHash | bytes32 | The hash of the input stored in the input box |
invalidInputHash | bytes32 | The invalid input hash provided for validation |
IllFormedInput
Raised when decoding an ill-formed input.
This error should never be raised if the application uses the canonical input box contract.
error IllFormedInput();
CannotRefundFinalizedInput
Raised when trying to issue a refund for a finalized input.
error CannotRefundFinalizedInput(uint256 inputIndex);
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The input index |
RefundAlreadyIssued
Raised when trying to re-issue a refund for the same input.
error RefundAlreadyIssued(uint256 inputIndex);
Parameters
| Name | Type | Description |
|---|---|---|
inputIndex | uint256 | The input index |
InvalidAccountsDriveMerkleRootProofSize
Raised when the accounts drive Merkle root proof size is invalid.
The array length should be log2 of the machine memory size - log2 of the
accounts drive size. See the CanonicalMachine library and the
getLog2MaxNumOfAccounts and getLog2LeavesPerAccount functions.
error InvalidAccountsDriveMerkleRootProofSize();
AccountsDriveMerkleRootAlreadyProved
Raised when someone tries to prove the accounts drive Merkle root but it
has already been proved. This error adds an extra layer of protection against
consensus-takeover attacks in which getLastFinalizedMachineMerkleRoot returns
a different value after the application is foreclosed.
error AccountsDriveMerkleRootAlreadyProved();
AccountsDriveMerkleRootNotProved
Raised when someone tries to validate an accounts Merkle root but the
accounts drive Merkle root has not yet been proved through the
proveAccountsDriveMerkleRoot function.
error AccountsDriveMerkleRootNotProved();
InvalidAccountRootSiblingsArrayLength
Raised when the account root siblings array has an invalid length.
The array length should be log2 of the maximum number of accounts. See the
getLog2MaxNumOfAccounts function.
error InvalidAccountRootSiblingsArrayLength();
InvalidMachineMerkleRoot
Raised when the computed machine Merkle root differs from the last-finalized machine Merkle root provided by the outputs Merkle root validator or from the initial machine Merkle root (template hash) if no machine Merkle root has been finalized yet.
error InvalidMachineMerkleRoot(bytes32 machineMerkleRoot);
Parameters
| Name | Type | Description |
|---|---|---|
machineMerkleRoot | bytes32 | The computed machine Merkle root |
InvalidAccountsDriveMerkleRoot
Raised when the computed accounts drive Merkle root differs
from the one proved through the proveAccountsDriveMerkleRoot function.
error InvalidAccountsDriveMerkleRoot(bytes32 accountsDriveMerkleRoot);
Parameters
| Name | Type | Description |
|---|---|---|
accountsDriveMerkleRoot | bytes32 | The computed accounts drive Merkle root |
AccountFundsAlreadyWithdrawn
Raised when trying to withdraw funds of an account whose funds have already been withdrawn.
error AccountFundsAlreadyWithdrawn(uint64 accountIndex);
Parameters
| Name | Type | Description |
|---|---|---|
accountIndex | uint64 | The account index |
NotDeploymentBlock
Raised when the application owner tries to migrate the application to another outputs Merkle root validator in a block that is not the deployment block.
This restriction protects users from malicious application owners that, by swapping the outputs Merkle root validator, can take control of user funds locked in the application contract. Rather, the application owner serves merely as an implementation detail that enables application-consensus factory contracts to deploy application-consensus pairs in the same transaction.
error NotDeploymentBlock();