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

Git Source

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

Git Source

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

NameTypeDescription
senderaddressThe Ether sender
valueuint256The amount of Wei being sent
execLayerDatabytesAdditional data to be interpreted by the execution layer

Returns

NameTypeDescription
<none>bytesThe 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

NameTypeDescription
tokenIERC20The token contract
senderaddressThe token sender
valueuint256The amount of tokens being sent
execLayerDatabytesAdditional data to be interpreted by the execution layer

Returns

NameTypeDescription
<none>bytesThe 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

NameTypeDescription
tokenIERC721The token contract
senderaddressThe token sender
tokenIduint256The token identifier
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

Returns

NameTypeDescription
<none>bytesThe 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

NameTypeDescription
tokenIERC1155The ERC-1155 token contract
senderaddressThe token sender
tokenIduint256The identifier of the token being transferred
valueuint256Transfer amount
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

Returns

NameTypeDescription
<none>bytesThe 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

NameTypeDescription
tokenIERC1155The ERC-1155 token contract
senderaddressThe token sender
tokenIdsuint256[]The identifiers of the tokens being transferred
valuesuint256[]Transfer amounts per token type
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

Returns

NameTypeDescription
<none>bytesThe encoded input payload

Inputs

Git Source

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

NameTypeDescription
chainIduint256The chain ID
appContractaddressThe application contract address
msgSenderaddressThe address of whoever sent the input
blockNumberuint256The number of the block in which the input was added
blockTimestampuint256The timestamp of the block in which the input was added
prevRandaouint256The latest RANDAO mix of the post beacon state of the previous block
indexuint256The index of the input in the input box
payloadbytesThe payload provided by the message sender

OutputValidityProof

Git Source

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

NameTypeDescription
outputIndexuint64Index of output in the Merkle tree
outputHashesSiblingsbytes32[]Siblings of the output in the Merkle tree

Outputs

Git Source

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

NameTypeDescription
payloadbytesAn 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

NameTypeDescription
destinationaddressThe address that will be called
valueuint256The amount of Wei to be transferred through the call
payloadbytesThe 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

NameTypeDescription
destinationaddressThe address that will be called
payloadbytesThe payload, which—in the case of Solidity libraries—encodes a function call

Contents

Contents

Authority

Git Source

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

NameTypeDescription
initialOwneraddressThe 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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

AuthorityFactory

Git Source

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

Git Source

Functions

newAuthority

Deploy a new authority.

On success, MUST emit an AuthorityCreated event.

function newAuthority(address authorityOwner) external returns (Authority);

Parameters

NameTypeDescription
authorityOwneraddressThe initial authority owner

Returns

NameTypeDescription
<none>AuthorityThe authority

newAuthority

Deploy a new authority deterministically.

On success, MUST emit an AuthorityCreated event.

function newAuthority(address authorityOwner, bytes32 salt) external returns (Authority);

Parameters

NameTypeDescription
authorityOwneraddressThe initial authority owner
saltbytes32The salt used to deterministically generate the authority address

Returns

NameTypeDescription
<none>AuthorityThe 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

NameTypeDescription
authorityOwneraddressThe initial authority owner
saltbytes32The salt used to deterministically generate the authority address

Returns

NameTypeDescription
<none>addressThe 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

NameTypeDescription
authorityOwneraddressThe initial authority owner
authorityAuthorityThe authority

Contents

IQuorumFactory

Git Source

Functions

newQuorum

Deploy a new quorum.

On success, MUST emit a QuorumCreated event.

function newQuorum(address[] calldata validators) external returns (Quorum);

Parameters

NameTypeDescription
validatorsaddress[]the list of validators

Returns

NameTypeDescription
<none>QuorumThe 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

NameTypeDescription
validatorsaddress[]the list of validators
saltbytes32The salt used to deterministically generate the quorum address

Returns

NameTypeDescription
<none>QuorumThe 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

NameTypeDescription
validatorsaddress[]the list of validators
saltbytes32The salt used to deterministically generate the quorum address

Returns

NameTypeDescription
<none>addressThe deterministic quorum address

Events

QuorumCreated

A new quorum was deployed.

MUST be triggered on a successful call to newQuorum.

event QuorumCreated(Quorum quorum);

Parameters

NameTypeDescription
quorumQuorumThe quorum

Quorum

Git Source

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

NameTypeDescription
validatorsaddress[]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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The 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

NameTypeDescription
validatoraddressThe 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

NameTypeDescription
iduint256The validator ID

numOfValidatorsInFavorOf

Get the number of validators in favor of a claim.

function numOfValidatorsInFavorOf(address appContract, bytes32 claim) external view returns (uint256);

Parameters

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

Returns

NameTypeDescription
<none>uint256Number 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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash
iduint256The ID of the validator

Returns

NameTypeDescription
<none>boolWhether 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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

Returns

NameTypeDescription
<none>VotesThe 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

NameTypeDescription
inFavorCountuint256The number of validators in favor of the claim
inFavorByIdBitMaps.BitMapThe set of validators in favor of the claim

QuorumFactory

Git Source

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

Git Source

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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

_acceptClaim

Accept a claim.

Emits a ClaimAcceptance event.

function _acceptClaim(address appContract, bytes32 claim) internal;

Parameters

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

IConsensus

Git Source

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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The 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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

Events

ClaimSubmission

MUST trigger when a claim is submitted.

event ClaimSubmission(address indexed submitter, address indexed appContract, bytes32 claim);

Parameters

NameTypeDescription
submitteraddressThe submitter address
appContractaddressThe application contract address
claimbytes32The 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

NameTypeDescription
appContractaddressThe application contract address
claimbytes32The output Merkle root hash

Contents

Application

Git Source

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

NameTypeDescription
consensusIConsensusThe initial consensus contract
initialOwneraddressThe initial application owner
templateHashbytes32The 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

NameTypeDescription
claimbytes32The output Merkle root hash

_executeVoucher

Executes a voucher

function _executeVoucher(bytes calldata arguments) internal;

Parameters

NameTypeDescription
argumentsbytesABI-encoded arguments

_executeDelegateCallVoucher

Executes a delegatecall voucher

function _executeDelegateCallVoucher(bytes calldata arguments) internal;

Parameters

NameTypeDescription
argumentsbytesABI-encoded arguments

ApplicationFactory

Git Source

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

Git Source

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

NameTypeDescription
newConsensusIConsensusThe 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

NameTypeDescription
outputbytesThe output
proofOutputValidityProofThe 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

NameTypeDescription
outputIndexuint256The index of output

Returns

NameTypeDescription
<none>boolWhether 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

NameTypeDescription
outputbytesThe output
proofOutputValidityProofThe 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

NameTypeDescription
outputHashbytes32The output hash
proofOutputValidityProofThe 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

NameTypeDescription
<none>bytes32The application's template hash

getConsensus

Get the current consensus.

function getConsensus() external view returns (IConsensus);

Returns

NameTypeDescription
<none>IConsensusThe current consensus

Events

NewConsensus

MUST trigger when a new consensus is chosen.

event NewConsensus(IConsensus newConsensus);

Parameters

NameTypeDescription
newConsensusIConsensusThe new consensus

OutputExecuted

MUST trigger when an output is executed.

event OutputExecuted(uint64 outputIndex, bytes output);

Parameters

NameTypeDescription
outputIndexuint64The index of the output
outputbytesThe output

Errors

OutputNotExecutable

Could not execute an output, because the application contract doesn't know how to.

error OutputNotExecutable(bytes output);

Parameters

NameTypeDescription
outputbytesThe output

OutputNotReexecutable

Could not execute an output, because it was already executed.

error OutputNotReexecutable(bytes output);

Parameters

NameTypeDescription
outputbytesThe 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

Git Source

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

NameTypeDescription
consensusIConsensusThe initial consensus contract
appOwneraddressThe initial application owner
templateHashbytes32The initial machine state hash

Returns

NameTypeDescription
<none>ApplicationThe 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

NameTypeDescription
consensusIConsensusThe initial consensus contract
appOwneraddressThe initial application owner
templateHashbytes32The initial machine state hash
saltbytes32The salt used to deterministically generate the application contract address

Returns

NameTypeDescription
<none>ApplicationThe 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

NameTypeDescription
consensusIConsensusThe initial consensus contract
appOwneraddressThe initial application owner
templateHashbytes32The initial machine state hash
saltbytes32The salt used to deterministically generate the application contract address

Returns

NameTypeDescription
<none>addressThe 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

NameTypeDescription
consensusIConsensusThe initial consensus contract
appOwneraddressThe initial application owner
templateHashbytes32The initial machine state hash
appContractApplicationThe application contract

ISelfHostedApplicationFactory

Git Source

Functions

getAuthorityFactory

Get the factory used to deploy Authority contracts

function getAuthorityFactory() external view returns (IAuthorityFactory);

Returns

NameTypeDescription
<none>IAuthorityFactoryThe authority factory

getApplicationFactory

Get the factory used to deploy Application contracts

function getApplicationFactory() external view returns (IApplicationFactory);

Returns

NameTypeDescription
<none>IApplicationFactoryThe 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

NameTypeDescription
authorityOwneraddressThe initial authority owner
appOwneraddressThe initial Application owner
templateHashbytes32The initial machine state hash
saltbytes32The salt used to deterministically generate the addresses

Returns

NameTypeDescription
<none>ApplicationThe application contract
<none>AuthorityThe 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

NameTypeDescription
authorityOwneraddressThe initial authority owner
appOwneraddressThe initial Application owner
templateHashbytes32The initial machine state hash
saltbytes32The salt used to deterministically generate the addresses

Returns

NameTypeDescription
<none>addressThe application address
<none>addressThe authority address

SelfHostedApplicationFactory

Git Source

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

NameTypeDescription
authorityFactoryIAuthorityFactoryThe authority factory
applicationFactoryIApplicationFactoryThe 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

Git Source

Functions

safeTransfer

function safeTransfer(IERC20 token, address to, uint256 value) external;

Contents

IInputBox

Git Source

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

NameTypeDescription
appContractaddressThe application contract address
payloadbytesThe input payload

Returns

NameTypeDescription
<none>bytes32The hash of the input blob

getNumberOfInputs

Get the number of inputs sent to an application.

function getNumberOfInputs(address appContract) external view returns (uint256);

Parameters

NameTypeDescription
appContractaddressThe 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

NameTypeDescription
appContractaddressThe application contract address
indexuint256The input index

Events

InputAdded

MUST trigger when an input is added.

event InputAdded(address indexed appContract, uint256 indexed index, bytes input);

Parameters

NameTypeDescription
appContractaddressThe application contract address
indexuint256The input index
inputbytesThe input blob

Errors

InputTooLarge

Input is too large.

error InputTooLarge(address appContract, uint256 inputLength, uint256 maxInputLength);

Parameters

NameTypeDescription
appContractaddressThe application contract address
inputLengthuint256The input length
maxInputLengthuint256The maximum input length

InputBox

Git Source

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

NameTypeDescription
appContractaddressThe application contract address
payloadbytesThe input payload

Returns

NameTypeDescription
<none>bytes32The 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

NameTypeDescription
appContractaddressThe 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

NameTypeDescription
appContractaddressThe application contract address
indexuint256The input index

Contents

LibAddress

Git Source

Functions

safeCall

Perform a low level call and raise error if failed

function safeCall(address destination, uint256 value, bytes memory payload) internal;

Parameters

NameTypeDescription
destinationaddressThe address that will be called
valueuint256The amount of Wei to be transferred through the call
payloadbytesThe 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

NameTypeDescription
destinationaddressThe address that will be called
payloadbytesThe payload, which—in the case of Solidity libraries—encodes a function call

LibError

Git Source

Functions

raise

Raise error data

function raise(bytes memory errordata) internal pure;

Parameters

NameTypeDescription
errordatabytesData returned by failed low-level call

LibMerkle32

Git Source

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

NameTypeDescription
leavesbytes32[]The left-most leaves of the Merkle tree
heightuint256The height of the Merkle tree

Returns

NameTypeDescription
<none>bytes32The 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

NameTypeDescription
leavesbytes32[]The left-most leaves of the Merkle tree
indexuint256The index of the leaf
heightuint256The height of the Merkle tree

Returns

NameTypeDescription
<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

NameTypeDescription
sibsbytes32[]The siblings of the ancestors of the leaf in bottom-up order
indexuint256The index of the leaf
leafbytes32The new leaf

Returns

NameTypeDescription
<none>bytes32The 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

NameTypeDescription
leftNodebytes32The left node
rightNodebytes32The right node

Returns

NameTypeDescription
parentNodebytes32The 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

NameTypeDescription
nodesbytes32[]The array of left-most nodes
defaultNodebytes32The default node after the array

Returns

NameTypeDescription
<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

NameTypeDescription
nodesbytes32[]The array of left-most nodes
indexuint256The index of the node
defaultNodebytes32The default node after the array

LibOutputValidityProof

Git Source

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

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe 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

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe 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

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe input box used by the portal

depositERC20Tokens

function depositERC20Tokens(IERC20 token, address appContract, uint256 value, bytes calldata execLayerData)
    external
    override;

ERC721Portal

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe input box used by the portal

depositERC721Token

function depositERC721Token(
    IERC721 token,
    address appContract,
    uint256 tokenId,
    bytes calldata baseLayerData,
    bytes calldata execLayerData
) external override;

EtherPortal

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe input box used by the portal

depositEther

function depositEther(address appContract, bytes calldata execLayerData) external payable override;

IERC1155BatchPortal

Git Source

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

NameTypeDescription
tokenIERC1155The ERC-1155 token contract
appContractaddressThe application contract address
tokenIdsuint256[]The identifiers of the tokens being transferred
valuesuint256[]Transfer amounts per token type
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

IERC1155SinglePortal

Git Source

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

NameTypeDescription
tokenIERC1155The ERC-1155 token contract
appContractaddressThe application contract address
tokenIduint256The identifier of the token being transferred
valueuint256Transfer amount
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

IERC20Portal

Git Source

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

NameTypeDescription
tokenIERC20The ERC-20 token contract
appContractaddressThe application contract address
valueuint256The amount of tokens to be transferred
execLayerDatabytesAdditional data to be interpreted by the execution layer

Errors

ERC20TransferFailed

Failed to transfer ERC-20 tokens to application

error ERC20TransferFailed();

IERC721Portal

Git Source

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

NameTypeDescription
tokenIERC721The ERC-721 token contract
appContractaddressThe application contract address
tokenIduint256The identifier of the token being transferred
baseLayerDatabytesAdditional data to be interpreted by the base layer
execLayerDatabytesAdditional data to be interpreted by the execution layer

IEtherPortal

Git Source

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

NameTypeDescription
appContractaddressThe application contract address
execLayerDatabytesAdditional data to be interpreted by the execution layer

Errors

EtherTransferFailed

Failed to transfer Ether to application

error EtherTransferFailed();

IPortal

Git Source

Functions

getInputBox

Get the input box used by this portal.

function getInputBox() external view returns (IInputBox);

Returns

NameTypeDescription
<none>IInputBoxThe input box

Portal

Git Source

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

NameTypeDescription
inputBoxIInputBoxThe input box used by the portal

getInputBox

function getInputBox() external view override returns (IInputBox);