Smart Contracts for Cartesi Rollups
This repository contains the on-chain part of Cartesi Rollups.
If you are interested in taking a look at the off-chain part, please, head over to cartesi/rollups-node
.
🧩 Dependencies
💡 Basic setup
This repository contains git submodules. In order to properly initialize them, please, run the following command.
git submodule update --init --recursive
This repository uses pnpm to manage JavaScript dependencies. In order to install them, please, run the following command.
pnpm i
🚀 Local deployment
If you want to run a Hardhat node and deploy the contracts, please run the following command.
pnpm start
If, instead, you wish to deploy the contracts to an already running node (e.g. Anvil), you can do so by running the following command.
pnpm deploy:development
If the node is not listening to http://localhost:8545/
, please set the RPC_URL
environment variable accordingly.
🧪 Tests
If you want to run the tests, please run the following command.
forge test -vvv
📚 Documentation
🚀 Smart contract documentation is kept up-to-date and deployed here.
ℹ️ You may also want to check the official Cartesi Rollups documentation website.
🔎 For an in-depth view of the on-chain architecture, we invite you to take a look at the CONTRACTS.md
file.
🎨 Experimenting
To get a taste of how to use Cartesi to develop your DApp, check the following resources: See Cartesi Rollups in action with the Simple Echo Examples in C++, JavaScript, Lua, Rust and Python. To have a glimpse of how to develop your DApp locally using your favorite IDE and tools check our Host Environment in the Rollups Examples repository.
💬 Talk with us
If you're interested in developing with Cartesi, working with the team, or hanging out in our community, don't forget to join us on Discord and follow along.
Want to stay up to date? Make sure to join our announcements channel on Telegram or follow our Twitter.
🤝 Contributing
Thank you for your interest in Cartesi! Head over to our Contributing Guidelines for instructions on how to sign our Contributors Agreement and get started with Cartesi!
Please note we have a Code of Conduct, please follow it in all your interactions with the project.
📜 License
Note: This component currently has dependencies that are licensed under the GNU GPL, version 3, and so you should treat this component as a whole as being under the GPL version 3. But all Cartesi-written code in this component is licensed under the Apache License, version 2, or a compatible permissive license, and can be used independently under the Apache v2 license. After this component is rewritten, the entire component will be released under the Apache v2 license. The arbitration d-lib repository and all contributions are licensed under GPL 3. Please review our COPYING file.
Contents
CanonicalMachine
Defines several constants related to the reference implementation of the RISC-V machine that runs Linux, also known as the "Cartesi Machine".
State Variables
INPUT_MAX_SIZE
Maximum input size (2 megabytes).
uint256 constant INPUT_MAX_SIZE = 1 << 21;
LOG2_MAX_OUTPUTS
Log2 of maximum number of outputs.
uint256 constant LOG2_MAX_OUTPUTS = 63;
InputEncoding
Defines the encoding of inputs added by core trustless and permissionless contracts, such as portals.
Functions
encodeEtherDeposit
Encode an Ether deposit.
function encodeEtherDeposit(address sender, uint256 value, bytes calldata execLayerData)
internal
pure
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
sender | address | The Ether sender |
value | uint256 | The amount of Wei being sent |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The encoded input payload |
encodeERC20Deposit
Encode an ERC-20 token deposit.
function encodeERC20Deposit(IERC20 token, address sender, uint256 value, bytes calldata execLayerData)
internal
pure
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
token | IERC20 | The token contract |
sender | address | The token sender |
value | uint256 | The amount of tokens being sent |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The encoded input payload |
encodeERC721Deposit
Encode an ERC-721 token deposit.
baseLayerData
should be forwarded to token
.
function encodeERC721Deposit(
IERC721 token,
address sender,
uint256 tokenId,
bytes calldata baseLayerData,
bytes calldata execLayerData
) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
token | IERC721 | The token contract |
sender | address | The token sender |
tokenId | uint256 | The token identifier |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The encoded input payload |
encodeSingleERC1155Deposit
Encode an ERC-1155 single token deposit.
baseLayerData
should be forwarded to token
.
function encodeSingleERC1155Deposit(
IERC1155 token,
address sender,
uint256 tokenId,
uint256 value,
bytes calldata baseLayerData,
bytes calldata execLayerData
) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
token | IERC1155 | The ERC-1155 token contract |
sender | address | The token sender |
tokenId | uint256 | The identifier of the token being transferred |
value | uint256 | Transfer amount |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The encoded input payload |
encodeBatchERC1155Deposit
Encode an ERC-1155 batch token deposit.
baseLayerData
should be forwarded to token
.
function encodeBatchERC1155Deposit(
IERC1155 token,
address sender,
uint256[] calldata tokenIds,
uint256[] calldata values,
bytes calldata baseLayerData,
bytes calldata execLayerData
) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
token | IERC1155 | The ERC-1155 token contract |
sender | address | The token sender |
tokenIds | uint256[] | The identifiers of the tokens being transferred |
values | uint256[] | Transfer amounts per token type |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The encoded input payload |
Inputs
Defines the signatures of inputs.
Functions
EvmAdvance
An advance request from an EVM-compatible blockchain to a Cartesi Machine.
See EIP-4399 for safe usage of prevRandao
.
function EvmAdvance(
uint256 chainId,
address appContract,
address msgSender,
uint256 blockNumber,
uint256 blockTimestamp,
uint256 prevRandao,
uint256 index,
bytes calldata payload
) external;
Parameters
Name | Type | Description |
---|---|---|
chainId | uint256 | The chain ID |
appContract | address | The application contract address |
msgSender | address | The address of whoever sent the input |
blockNumber | uint256 | The number of the block in which the input was added |
blockTimestamp | uint256 | The timestamp of the block in which the input was added |
prevRandao | uint256 | The latest RANDAO mix of the post beacon state of the previous block |
index | uint256 | The index of the input in the input box |
payload | bytes | The payload provided by the message sender |
OutputValidityProof
Proof of inclusion of an output in the output Merkle tree.
From the index and siblings, one can calculate the root of the Merkle tree.
The siblings array should have size equal to the log2 of the maximum number of outputs.
See the CanonicalMachine
library for constants.
struct OutputValidityProof {
uint64 outputIndex;
bytes32[] outputHashesSiblings;
}
Properties
Name | Type | Description |
---|---|---|
outputIndex | uint64 | Index of output in the Merkle tree |
outputHashesSiblings | bytes32[] | Siblings of the output in the Merkle tree |
Outputs
Defines the signatures of outputs that can be generated by the off-chain machine and verified by the on-chain contracts.
Functions
Notice
A piece of verifiable information.
function Notice(bytes calldata payload) external;
Parameters
Name | Type | Description |
---|---|---|
payload | bytes | An arbitrary payload. |
Voucher
A single-use permission to execute a specific message call from the context of the application contract.
function Voucher(address destination, uint256 value, bytes calldata payload) external;
Parameters
Name | Type | Description |
---|---|---|
destination | address | The address that will be called |
value | uint256 | The amount of Wei to be transferred through the call |
payload | bytes | The payload, which—in the case of Solidity contracts—encodes a function call |
DelegateCallVoucher
A single-use permission to execute a specific delegate call from the context of the application contract.
function DelegateCallVoucher(address destination, bytes calldata payload) external;
Parameters
Name | Type | Description |
---|---|---|
destination | address | The address that will be called |
payload | bytes | The payload, which—in the case of Solidity libraries—encodes a function call |
Contents
Contents
Authority
Inherits: AbstractConsensus, Ownable
A consensus contract controlled by a single address, the owner.
This contract inherits from OpenZeppelin's Ownable
contract.
For more information on Ownable
, please consult OpenZeppelin's official documentation.
Functions
constructor
constructor(address initialOwner) Ownable(initialOwner);
Parameters
Name | Type | Description |
---|---|---|
initialOwner | address | The initial contract owner |
submitClaim
Submit a claim.
Fires a ClaimSubmission
event and a ClaimAcceptance
event.
Can only be called by the owner.
function submitClaim(address appContract, bytes32 claim) external onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
AuthorityFactory
Inherits: IAuthorityFactory
Allows anyone to reliably deploy a new Authority
contract.
Functions
newAuthority
function newAuthority(address authorityOwner) external override returns (Authority);
newAuthority
function newAuthority(address authorityOwner, bytes32 salt) external override returns (Authority);
calculateAuthorityAddress
function calculateAuthorityAddress(address authorityOwner, bytes32 salt) external view override returns (address);
IAuthorityFactory
Functions
newAuthority
Deploy a new authority.
On success, MUST emit an AuthorityCreated
event.
function newAuthority(address authorityOwner) external returns (Authority);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
Returns
Name | Type | Description |
---|---|---|
<none> | Authority | The authority |
newAuthority
Deploy a new authority deterministically.
On success, MUST emit an AuthorityCreated
event.
function newAuthority(address authorityOwner, bytes32 salt) external returns (Authority);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
salt | bytes32 | The salt used to deterministically generate the authority address |
Returns
Name | Type | Description |
---|---|---|
<none> | Authority | The authority |
calculateAuthorityAddress
Calculate the address of an authority to be deployed deterministically.
Beware that only the newAuthority
function with the salt
parameter
is able to deterministically deploy an authority.
function calculateAuthorityAddress(address authorityOwner, bytes32 salt) external view returns (address);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
salt | bytes32 | The salt used to deterministically generate the authority address |
Returns
Name | Type | Description |
---|---|---|
<none> | address | The deterministic authority address |
Events
AuthorityCreated
A new authority was deployed.
MUST be triggered on a successful call to newAuthority
.
event AuthorityCreated(address authorityOwner, Authority authority);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
authority | Authority | The authority |
Contents
IQuorumFactory
Functions
newQuorum
Deploy a new quorum.
On success, MUST emit a QuorumCreated
event.
function newQuorum(address[] calldata validators) external returns (Quorum);
Parameters
Name | Type | Description |
---|---|---|
validators | address[] | the list of validators |
Returns
Name | Type | Description |
---|---|---|
<none> | Quorum | The quorum |
newQuorum
Deploy a new quorum deterministically.
On success, MUST emit a QuorumCreated
event.
function newQuorum(address[] calldata validators, bytes32 salt) external returns (Quorum);
Parameters
Name | Type | Description |
---|---|---|
validators | address[] | the list of validators |
salt | bytes32 | The salt used to deterministically generate the quorum address |
Returns
Name | Type | Description |
---|---|---|
<none> | Quorum | The quorum |
calculateQuorumAddress
Calculate the address of a quorum to be deployed deterministically.
Beware that only the newQuorum
function with the salt
parameter
is able to deterministically deploy a quorum.
function calculateQuorumAddress(address[] calldata validators, bytes32 salt) external view returns (address);
Parameters
Name | Type | Description |
---|---|---|
validators | address[] | the list of validators |
salt | bytes32 | The salt used to deterministically generate the quorum address |
Returns
Name | Type | Description |
---|---|---|
<none> | address | The deterministic quorum address |
Events
QuorumCreated
A new quorum was deployed.
MUST be triggered on a successful call to newQuorum
.
event QuorumCreated(Quorum quorum);
Parameters
Name | Type | Description |
---|---|---|
quorum | Quorum | The quorum |
Quorum
Inherits: AbstractConsensus
A consensus model controlled by a small, immutable set of n
validators.
You can know the value of n
by calling the numOfValidators
function.
Upon construction, each validator is assigned a unique number between 1 and n
.
These numbers are used internally instead of addresses for gas optimization reasons.
You can list the validators in the quorum by calling the validatorById
function for each ID from 1 to n
.
State Variables
_numOfValidators
The total number of validators.
See the numOfValidators
function.
uint256 private immutable _numOfValidators;
_validatorId
Validator IDs indexed by address.
See the validatorId
function.
Non-validators are assigned to ID zero.
Validators have IDs greater than zero.
mapping(address => uint256) private _validatorId;
_validatorById
Validator addresses indexed by ID.
See the validatorById
function.
Invalid IDs map to address zero.
mapping(uint256 => address) private _validatorById;
_votes
Votes indexed by application contract address and claim.
See the numOfValidatorsInFavorOf
and isValidatorInFavorOf
functions.
mapping(address => mapping(bytes32 => Votes)) private _votes;
Functions
constructor
Duplicates in the validators
array are ignored.
constructor(address[] memory validators);
Parameters
Name | Type | Description |
---|---|---|
validators | address[] | The array of validator addresses |
submitClaim
Submit a claim.
Fires a ClaimSubmission
event if the message sender is a validator.
Fires a ClaimAcceptance
event if the claim reaches a majority.
Can only be called by a validator.
function submitClaim(address appContract, bytes32 claim) external;
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
numOfValidators
Get the number of validators.
function numOfValidators() external view returns (uint256);
validatorId
Get the ID of a validator.
Validators have IDs greater than zero.
Non-validators are assigned to ID zero.
function validatorId(address validator) external view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
validator | address | The validator address |
validatorById
Get the address of a validator by its ID.
Validator IDs range from 1 to N
, the total number of validators.
Invalid IDs map to address zero.
function validatorById(uint256 id) external view returns (address);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | The validator ID |
numOfValidatorsInFavorOf
Get the number of validators in favor of a claim.
function numOfValidatorsInFavorOf(address appContract, bytes32 claim) external view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | Number of validators in favor of claim |
isValidatorInFavorOf
Check whether a validator is in favor of a claim.
Assumes the provided ID is valid.
function isValidatorInFavorOf(address appContract, bytes32 claim, uint256 id) external view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
id | uint256 | The ID of the validator |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | Whether validator is in favor of claim |
_getVotes
Get a Votes
structure from storage from a given claim.
function _getVotes(address appContract, bytes32 claim) internal view returns (Votes storage);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
Returns
Name | Type | Description |
---|---|---|
<none> | Votes | The Votes structure related to a given claim |
Structs
Votes
Votes in favor of a particular claim.
inFavorById
is a bitmap indexed by validator IDs.
struct Votes {
uint256 inFavorCount;
BitMaps.BitMap inFavorById;
}
Properties
Name | Type | Description |
---|---|---|
inFavorCount | uint256 | The number of validators in favor of the claim |
inFavorById | BitMaps.BitMap | The set of validators in favor of the claim |
QuorumFactory
Inherits: IQuorumFactory
Allows anyone to reliably deploy a new Quorum
contract.
Functions
newQuorum
function newQuorum(address[] calldata validators) external override returns (Quorum);
newQuorum
function newQuorum(address[] calldata validators, bytes32 salt) external override returns (Quorum);
calculateQuorumAddress
function calculateQuorumAddress(address[] calldata validators, bytes32 salt) external view override returns (address);
AbstractConsensus
Inherits: IConsensus
Stores accepted claims for several applications.
This contract was designed to be inherited by implementations of the IConsensus
interface
that only need a simple mechanism of storage and retrieval of accepted claims.
State Variables
_acceptedClaims
Indexes accepted claims by application contract address.
mapping(address => mapping(bytes32 => bool)) private _acceptedClaims;
Functions
wasClaimAccepted
Check if an output Merkle root hash was ever accepted by the consensus for a particular application.
function wasClaimAccepted(address appContract, bytes32 claim) public view override returns (bool);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
_acceptClaim
Accept a claim.
Emits a ClaimAcceptance
event.
function _acceptClaim(address appContract, bytes32 claim) internal;
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
IConsensus
Provides consensus over the set of valid output Merkle root hashes for applications.
The latest output Merkle root hash is available after the machine processes every input. This hash can be later used to prove that any given output was ever produced by the machine.
After an epoch is finalized, a validator may submit a claim containing the application contract address, and the output Merkle root hash.
Validators may synchronize epoch finalization, but such mechanism is not specified by this interface.
A validator should be able to save transaction fees by not submitting a claim if it was...
- already submitted by the validator (see the
ClaimSubmission
event) or; - already accepted by the consensus (see the
ClaimAcceptance
event).
The acceptance criteria for claims may depend on the type of consensus, and is not specified by this interface. For example, a claim may be accepted if it was...
- submitted by an authority or;
- submitted by the majority of a quorum or;
- submitted and not proven wrong after some period of time or;
- submitted and proven correct through an on-chain tournament.
Functions
submitClaim
Submit a claim to the consensus.
MUST fire a ClaimSubmission
event.
MAY fire a ClaimAcceptance
event, if the acceptance criteria is met.
function submitClaim(address appContract, bytes32 claim) external;
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
wasClaimAccepted
Check if an output Merkle root hash was ever accepted by the consensus for a particular application.
function wasClaimAccepted(address appContract, bytes32 claim) external view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
Events
ClaimSubmission
MUST trigger when a claim is submitted.
event ClaimSubmission(address indexed submitter, address indexed appContract, bytes32 claim);
Parameters
Name | Type | Description |
---|---|---|
submitter | address | The submitter address |
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
ClaimAcceptance
MUST trigger when a claim is accepted.
MUST be triggered after some ClaimSubmission
event regarding appContract
.
event ClaimAcceptance(address indexed appContract, bytes32 claim);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
claim | bytes32 | The output Merkle root hash |
Contents
- Application
- ApplicationFactory
- IApplication
- IApplicationFactory
- ISelfHostedApplicationFactory
- SelfHostedApplicationFactory
Application
Inherits: IApplication, Ownable, ERC721Holder, ERC1155Holder, ReentrancyGuard
State Variables
_templateHash
The initial machine state hash.
See the getTemplateHash
function.
bytes32 internal immutable _templateHash;
_executed
Keeps track of which outputs have been executed.
See the wasOutputExecuted
function.
BitMaps.BitMap internal _executed;
_consensus
The current consensus contract.
See the getConsensus
and migrateToConsensus
functions.
IConsensus internal _consensus;
Functions
constructor
Creates an Application
contract.
constructor(IConsensus consensus, address initialOwner, bytes32 templateHash) Ownable(initialOwner);
Parameters
Name | Type | Description |
---|---|---|
consensus | IConsensus | The initial consensus contract |
initialOwner | address | The initial application owner |
templateHash | bytes32 | The initial machine state hash |
receive
Accept Ether transfers.
If you wish to transfer Ether to an application while informing the backend of it, then please do so through the Ether portal contract.
receive() external payable;
executeOutput
function executeOutput(bytes calldata output, OutputValidityProof calldata proof) external override nonReentrant;
migrateToConsensus
function migrateToConsensus(IConsensus newConsensus) external override onlyOwner;
wasOutputExecuted
function wasOutputExecuted(uint256 outputIndex) external view override returns (bool);
validateOutput
function validateOutput(bytes calldata output, OutputValidityProof calldata proof) public view override;
validateOutputHash
function validateOutputHash(bytes32 outputHash, OutputValidityProof calldata proof) public view override;
getTemplateHash
function getTemplateHash() external view override returns (bytes32);
getConsensus
function getConsensus() external view override returns (IConsensus);
_wasClaimAccepted
Check if an output Merkle root hash was ever accepted by the current consensus.
function _wasClaimAccepted(bytes32 claim) internal view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
claim | bytes32 | The output Merkle root hash |
_executeVoucher
Executes a voucher
function _executeVoucher(bytes calldata arguments) internal;
Parameters
Name | Type | Description |
---|---|---|
arguments | bytes | ABI-encoded arguments |
_executeDelegateCallVoucher
Executes a delegatecall voucher
function _executeDelegateCallVoucher(bytes calldata arguments) internal;
Parameters
Name | Type | Description |
---|---|---|
arguments | bytes | ABI-encoded arguments |
ApplicationFactory
Inherits: IApplicationFactory
Allows anyone to reliably deploy a new Application
contract.
Functions
newApplication
function newApplication(IConsensus consensus, address appOwner, bytes32 templateHash)
external
override
returns (Application);
newApplication
function newApplication(IConsensus consensus, address appOwner, bytes32 templateHash, bytes32 salt)
external
override
returns (Application);
calculateApplicationAddress
function calculateApplicationAddress(IConsensus consensus, address appOwner, bytes32 templateHash, bytes32 salt)
external
view
override
returns (address);
IApplication
Inherits: IERC721Receiver, IERC1155Receiver
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 IConsensus
contract (see the getConsensus
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 consensus, and may be governed by some owner. The consensus has the power to accept claims, which, in turn, are used to validate outputs. Meanwhile, the owner can replace the consensus at any time. Therefore, the users of an application must trust both the consensus 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)
See IConsensus
for examples of consensus models.
Functions
migrateToConsensus
Migrate the application to a new consensus.
Can only be called by the application owner.
function migrateToConsensus(IConsensus newConsensus) external;
Parameters
Name | Type | Description |
---|---|---|
newConsensus | IConsensus | The new consensus |
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 submitted to the current consensus contract |
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 |
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 submitted to the current consensus contract |
validateOutputHash
Validate an output hash.
May raise InvalidOutputHashesSiblingsArrayLength
or ClaimNotAccepted
.
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 submitted to the current consensus 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 |
getConsensus
Get the current consensus.
function getConsensus() external view returns (IConsensus);
Returns
Name | Type | Description |
---|---|---|
<none> | IConsensus | The current consensus |
Events
NewConsensus
MUST trigger when a new consensus is chosen.
event NewConsensus(IConsensus newConsensus);
Parameters
Name | Type | Description |
---|---|---|
newConsensus | IConsensus | The new consensus |
OutputExecuted
MUST trigger when an output is executed.
event OutputExecuted(uint64 outputIndex, bytes output);
Parameters
Name | Type | Description |
---|---|---|
outputIndex | uint64 | The index of the output |
output | bytes | The 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();
ClaimNotAccepted
Raised when the required claim was not accepted by the current consensus.
error ClaimNotAccepted(bytes32 claim);
IApplicationFactory
Functions
newApplication
Deploy a new application.
On success, MUST emit an ApplicationCreated
event.
function newApplication(IConsensus consensus, address appOwner, bytes32 templateHash) external returns (Application);
Parameters
Name | Type | Description |
---|---|---|
consensus | IConsensus | The initial consensus contract |
appOwner | address | The initial application owner |
templateHash | bytes32 | The initial machine state hash |
Returns
Name | Type | Description |
---|---|---|
<none> | Application | The application |
newApplication
Deploy a new application deterministically.
On success, MUST emit an ApplicationCreated
event.
function newApplication(IConsensus consensus, address appOwner, bytes32 templateHash, bytes32 salt)
external
returns (Application);
Parameters
Name | Type | Description |
---|---|---|
consensus | IConsensus | The initial consensus contract |
appOwner | address | The initial application owner |
templateHash | bytes32 | The initial machine state hash |
salt | bytes32 | The salt used to deterministically generate the application contract address |
Returns
Name | Type | Description |
---|---|---|
<none> | Application | The application |
calculateApplicationAddress
Calculate the address of an application contract to be deployed deterministically.
Beware that only the newApplication
function with the salt
parameter
is able to deterministically deploy an application.
function calculateApplicationAddress(IConsensus consensus, address appOwner, bytes32 templateHash, bytes32 salt)
external
view
returns (address);
Parameters
Name | Type | Description |
---|---|---|
consensus | IConsensus | The initial consensus contract |
appOwner | address | The initial application owner |
templateHash | bytes32 | The initial machine state hash |
salt | bytes32 | The salt used to deterministically generate the application contract address |
Returns
Name | Type | Description |
---|---|---|
<none> | address | The deterministic application contract address |
Events
ApplicationCreated
A new application was deployed.
MUST be triggered on a successful call to newApplication
.
event ApplicationCreated(IConsensus indexed consensus, address appOwner, bytes32 templateHash, Application appContract);
Parameters
Name | Type | Description |
---|---|---|
consensus | IConsensus | The initial consensus contract |
appOwner | address | The initial application owner |
templateHash | bytes32 | The initial machine state hash |
appContract | Application | The application contract |
ISelfHostedApplicationFactory
Functions
getAuthorityFactory
Get the factory used to deploy Authority
contracts
function getAuthorityFactory() external view returns (IAuthorityFactory);
Returns
Name | Type | Description |
---|---|---|
<none> | IAuthorityFactory | The authority factory |
getApplicationFactory
Get the factory used to deploy Application
contracts
function getApplicationFactory() external view returns (IApplicationFactory);
Returns
Name | Type | Description |
---|---|---|
<none> | IApplicationFactory | The application factory |
deployContracts
Deploy new application and authority contracts deterministically.
function deployContracts(address authorityOwner, address appOwner, bytes32 templateHash, bytes32 salt)
external
returns (Application, Authority);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
appOwner | address | The initial Application owner |
templateHash | bytes32 | The initial machine state hash |
salt | bytes32 | The salt used to deterministically generate the addresses |
Returns
Name | Type | Description |
---|---|---|
<none> | Application | The application contract |
<none> | Authority | The authority contract |
calculateAddresses
Calculate the addresses of the application and authority contracts to be deployed deterministically.
function calculateAddresses(address authorityOwner, address appOwner, bytes32 templateHash, bytes32 salt)
external
view
returns (address, address);
Parameters
Name | Type | Description |
---|---|---|
authorityOwner | address | The initial authority owner |
appOwner | address | The initial Application owner |
templateHash | bytes32 | The initial machine state hash |
salt | bytes32 | The salt used to deterministically generate the addresses |
Returns
Name | Type | Description |
---|---|---|
<none> | address | The application address |
<none> | address | The authority address |
SelfHostedApplicationFactory
Inherits: ISelfHostedApplicationFactory
Allows anyone to reliably deploy a new Authority contract, along with an Application contract already linked to it.
State Variables
_authorityFactory
IAuthorityFactory immutable _authorityFactory;
_applicationFactory
IApplicationFactory immutable _applicationFactory;
Functions
constructor
constructor(IAuthorityFactory authorityFactory, IApplicationFactory applicationFactory);
Parameters
Name | Type | Description |
---|---|---|
authorityFactory | IAuthorityFactory | The authority factory |
applicationFactory | IApplicationFactory | The application factory |
getAuthorityFactory
function getAuthorityFactory() external view override returns (IAuthorityFactory);
getApplicationFactory
function getApplicationFactory() external view override returns (IApplicationFactory);
deployContracts
function deployContracts(address authorityOwner, address appOwner, bytes32 templateHash, bytes32 salt)
external
returns (Application application, Authority authority);
calculateAddresses
function calculateAddresses(address authorityOwner, address appOwner, bytes32 templateHash, bytes32 salt)
external
view
returns (address application, address authority);
Contents
SafeERC20Transfer
Functions
safeTransfer
function safeTransfer(IERC20 token, address to, uint256 value) external;
Contents
IInputBox
Provides data availability of inputs for applications.
Each application has its own append-only list of inputs.
Off-chain, inputs can be retrieved via events.
On-chain, only the input hashes are stored.
See LibInput
for more details on how such hashes are computed.
Functions
addInput
Send an input to an application.
MUST fire an InputAdded
event.
function addInput(address appContract, bytes calldata payload) external returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
payload | bytes | The input payload |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The hash of the input blob |
getNumberOfInputs
Get the number of inputs sent to an application.
function getNumberOfInputs(address appContract) external view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
getInputHash
Get the hash of an input in an application's input box.
The provided index must be valid.
function getInputHash(address appContract, uint256 index) external view returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
index | uint256 | The input index |
Events
InputAdded
MUST trigger when an input is added.
event InputAdded(address indexed appContract, uint256 indexed index, bytes input);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
index | uint256 | The input index |
input | bytes | The input blob |
Errors
InputTooLarge
Input is too large.
error InputTooLarge(address appContract, uint256 inputLength, uint256 maxInputLength);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
inputLength | uint256 | The input length |
maxInputLength | uint256 | The maximum input length |
InputBox
Inherits: IInputBox
State Variables
_inputBoxes
Mapping of application contract addresses to arrays of input hashes.
mapping(address => bytes32[]) private _inputBoxes;
Functions
addInput
Send an input to an application.
MUST fire an InputAdded
event.
function addInput(address appContract, bytes calldata payload) external override returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
payload | bytes | The input payload |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The hash of the input blob |
getNumberOfInputs
Get the number of inputs sent to an application.
function getNumberOfInputs(address appContract) external view override returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
getInputHash
Get the hash of an input in an application's input box.
The provided index must be valid.
function getInputHash(address appContract, uint256 index) external view override returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
index | uint256 | The input index |
Contents
LibAddress
Functions
safeCall
Perform a low level call and raise error if failed
function safeCall(address destination, uint256 value, bytes memory payload) internal;
Parameters
Name | Type | Description |
---|---|---|
destination | address | The address that will be called |
value | uint256 | The amount of Wei to be transferred through the call |
payload | bytes | The payload, which—in the case of Solidity contracts—encodes a function call |
safeDelegateCall
Perform a delegate call and raise error if failed
function safeDelegateCall(address destination, bytes memory payload) internal;
Parameters
Name | Type | Description |
---|---|---|
destination | address | The address that will be called |
payload | bytes | The payload, which—in the case of Solidity libraries—encodes a function call |
LibError
Functions
raise
Raise error data
function raise(bytes memory errordata) internal pure;
Parameters
Name | Type | Description |
---|---|---|
errordata | bytes | Data returned by failed low-level call |
LibMerkle32
This library is meant for creating and verifying Merkle proofs.
Each Merkle tree is assumed to have 2^height
leaves.
Nodes are concatenated pairwise and hashed with keccak256
.
Siblings are in bottom-up order, from leaf to root.
Functions
merkleRoot
Compute the root of a Merkle tree from its leaves.
Raises an error if more than 2^height
leaves are provided.
function merkleRoot(bytes32[] memory leaves, uint256 height) internal pure returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
leaves | bytes32[] | The left-most leaves of the Merkle tree |
height | uint256 | The height of the Merkle tree |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The root hash of the Merkle tree |
siblings
Compute the siblings of the ancestors of a leaf in a Merkle tree.
Raises an error if the provided index is out of bounds.
Raises an error if more than 2^height
leaves are provided.
function siblings(bytes32[] memory leaves, uint256 index, uint256 height) internal pure returns (bytes32[] memory);
Parameters
Name | Type | Description |
---|---|---|
leaves | bytes32[] | The left-most leaves of the Merkle tree |
index | uint256 | The index of the leaf |
height | uint256 | The height of the Merkle tree |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32[] | The siblings of the ancestors of the leaf in bottom-up order |
merkleRootAfterReplacement
Compute the root of a Merkle tree after replacing one of its leaves.
Raises an error if the provided index is out of bounds.
function merkleRootAfterReplacement(bytes32[] calldata sibs, uint256 index, bytes32 leaf)
internal
pure
returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
sibs | bytes32[] | The siblings of the ancestors of the leaf in bottom-up order |
index | uint256 | The index of the leaf |
leaf | bytes32 | The new leaf |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The root hash of the new Merkle tree |
parent
Compute the parent of two nodes.
Uses assembly for extra performance
function parent(bytes32 leftNode, bytes32 rightNode) internal pure returns (bytes32 parentNode);
Parameters
Name | Type | Description |
---|---|---|
leftNode | bytes32 | The left node |
rightNode | bytes32 | The right node |
Returns
Name | Type | Description |
---|---|---|
parentNode | bytes32 | The parent node |
parentLevel
Compute the parent level of an array of nodes.
The default node of a parent level is the parent node of two default nodes.
function parentLevel(bytes32[] memory nodes, bytes32 defaultNode) internal pure returns (bytes32[] memory);
Parameters
Name | Type | Description |
---|---|---|
nodes | bytes32[] | The array of left-most nodes |
defaultNode | bytes32 | The default node after the array |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32[] | The left-most nodes of the parent level |
at
Get the node at some index
function at(bytes32[] memory nodes, uint256 index, bytes32 defaultNode) internal pure returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
nodes | bytes32[] | The array of left-most nodes |
index | uint256 | The index of the node |
defaultNode | bytes32 | The default node after the array |
LibOutputValidityProof
Functions
isSiblingsArrayLengthValid
function isSiblingsArrayLengthValid(OutputValidityProof calldata v) internal pure returns (bool);
computeClaim
function computeClaim(OutputValidityProof calldata v, bytes32 outputHash) internal pure returns (bytes32);
Contents
- ERC1155BatchPortal
- ERC1155SinglePortal
- ERC20Portal
- ERC721Portal
- EtherPortal
- IERC1155BatchPortal
- IERC1155SinglePortal
- IERC20Portal
- IERC721Portal
- IEtherPortal
- IPortal
- Portal
ERC1155BatchPortal
Inherits: IERC1155BatchPortal, Portal
This contract allows anyone to perform batch transfers of ERC-1155 tokens to an application contract while informing the off-chain machine.
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox) Portal(inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
depositBatchERC1155Token
function depositBatchERC1155Token(
IERC1155 token,
address appContract,
uint256[] calldata tokenIds,
uint256[] calldata values,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external override;
ERC1155SinglePortal
Inherits: IERC1155SinglePortal, Portal
This contract allows anyone to perform single transfers of ERC-1155 tokens to an application contract while informing the off-chain machine.
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox) Portal(inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
depositSingleERC1155Token
function depositSingleERC1155Token(
IERC1155 token,
address appContract,
uint256 tokenId,
uint256 value,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external override;
ERC20Portal
Inherits: IERC20Portal, Portal
This contract allows anyone to perform transfers of ERC-20 tokens to an application contract while informing the off-chain machine.
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox) Portal(inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
depositERC20Tokens
function depositERC20Tokens(IERC20 token, address appContract, uint256 value, bytes calldata execLayerData)
external
override;
ERC721Portal
Inherits: IERC721Portal, Portal
This contract allows anyone to perform transfers of ERC-721 tokens to an application contract while informing the off-chain machine.
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox) Portal(inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
depositERC721Token
function depositERC721Token(
IERC721 token,
address appContract,
uint256 tokenId,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external override;
EtherPortal
Inherits: IEtherPortal, Portal
This contract allows anyone to perform transfers of Ether to an application contract while informing the off-chain machine.
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox) Portal(inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
depositEther
function depositEther(address appContract, bytes calldata execLayerData) external payable override;
IERC1155BatchPortal
Inherits: IPortal
Functions
depositBatchERC1155Token
Transfer a batch of ERC-1155 tokens of multiple types to an application contract
and add an input to the application's input box to signal such operation.
The caller must enable approval for the portal to manage all of their tokens
beforehand, by calling the setApprovalForAll
function in the token contract.
Please make sure the arrays tokenIds
and values
have the same length.
function depositBatchERC1155Token(
IERC1155 token,
address appContract,
uint256[] calldata tokenIds,
uint256[] calldata values,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external;
Parameters
Name | Type | Description |
---|---|---|
token | IERC1155 | The ERC-1155 token contract |
appContract | address | The application contract address |
tokenIds | uint256[] | The identifiers of the tokens being transferred |
values | uint256[] | Transfer amounts per token type |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
IERC1155SinglePortal
Inherits: IPortal
Functions
depositSingleERC1155Token
Transfer ERC-1155 tokens of a single type to an application contract
and add an input to the application's input box to signal such operation.
The caller must enable approval for the portal to manage all of their tokens
beforehand, by calling the setApprovalForAll
function in the token contract.
function depositSingleERC1155Token(
IERC1155 token,
address appContract,
uint256 tokenId,
uint256 value,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external;
Parameters
Name | Type | Description |
---|---|---|
token | IERC1155 | The ERC-1155 token contract |
appContract | address | The application contract address |
tokenId | uint256 | The identifier of the token being transferred |
value | uint256 | Transfer amount |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
IERC20Portal
Inherits: IPortal
Functions
depositERC20Tokens
Transfer ERC-20 tokens to an application contract
and add an input to the application's input box to signal such operation.
The caller must allow the portal to withdraw at least value
tokens
from their account beforehand, by calling the approve
function in the
token contract.
function depositERC20Tokens(IERC20 token, address appContract, uint256 value, bytes calldata execLayerData) external;
Parameters
Name | Type | Description |
---|---|---|
token | IERC20 | The ERC-20 token contract |
appContract | address | The application contract address |
value | uint256 | The amount of tokens to be transferred |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Errors
ERC20TransferFailed
Failed to transfer ERC-20 tokens to application
error ERC20TransferFailed();
IERC721Portal
Inherits: IPortal
Functions
depositERC721Token
Transfer an ERC-721 token to an application contract
and add an input to the application's input box to signal such operation.
The caller must change the approved address for the ERC-721 token
to the portal address beforehand, by calling the approve
function in the
token contract.
function depositERC721Token(
IERC721 token,
address appContract,
uint256 tokenId,
bytes calldata baseLayerData,
bytes calldata execLayerData
) external;
Parameters
Name | Type | Description |
---|---|---|
token | IERC721 | The ERC-721 token contract |
appContract | address | The application contract address |
tokenId | uint256 | The identifier of the token being transferred |
baseLayerData | bytes | Additional data to be interpreted by the base layer |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
IEtherPortal
Inherits: IPortal
Functions
depositEther
Transfer Ether to an application contract and add an input to the application's input box to signal such operation.
Any Ether sent through this function will be forwarded to the application contract.
If the transfer fails, an EtherTransferFailed
error will be raised.
function depositEther(address appContract, bytes calldata execLayerData) external payable;
Parameters
Name | Type | Description |
---|---|---|
appContract | address | The application contract address |
execLayerData | bytes | Additional data to be interpreted by the execution layer |
Errors
EtherTransferFailed
Failed to transfer Ether to application
error EtherTransferFailed();
IPortal
Functions
getInputBox
Get the input box used by this portal.
function getInputBox() external view returns (IInputBox);
Returns
Name | Type | Description |
---|---|---|
<none> | IInputBox | The input box |
Portal
Inherits: IPortal
This contract serves as a base for all the other portals.
State Variables
_inputBox
The input box used by the portal.
IInputBox internal immutable _inputBox;
Functions
constructor
Constructs the portal.
constructor(IInputBox inputBox);
Parameters
Name | Type | Description |
---|---|---|
inputBox | IInputBox | The input box used by the portal |
getInputBox
function getInputBox() external view override returns (IInputBox);