Skip to content

Commit

Permalink
docs: (Cartesi)?DApp -> Application
Browse files Browse the repository at this point in the history
  • Loading branch information
guidanoli committed Jan 23, 2024
1 parent 697782f commit 7867b74
Showing 1 changed file with 20 additions and 20 deletions.
40 changes: 20 additions & 20 deletions CONTRACTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,25 @@ graph TD

### Input Box

This module is the one responsible for receiving inputs from users that want to interact with DApps. For each DApp, the module keeps an append-only list of hashes. Each hash is derived from the input and some metadata, such as the input sender, and the block timestamp. All the data needed to reconstruct a hash is available forever on-chain. As a result, one does not need to trust data providers in order to sync the off-chain machine with the latest input. Note that this module is completely permissionless, and we leave the off-chain machine to judge whether an input is valid or not.
This module is the one responsible for receiving inputs from users that want to interact with applications. For each application, the module keeps an append-only list of hashes. Each hash is derived from the input and some metadata, such as the input sender, and the block timestamp. All the data needed to reconstruct a hash is available forever on-chain. As a result, one does not need to trust data providers in order to sync the off-chain machine with the latest input. Note that this module is completely permissionless, and we leave the off-chain machine to judge whether an input is valid or not.

### Cartesi DApp
### Application

A Cartesi DApp contract, just like any other contract on Ethereum, has a unique address. With this address, a DApp can hold ownership over digital assets on the base layer like Ether, ERC-20 tokens, and NFTs. In the next sections, we'll explain how DApps are able to receive assets through portals, and perform arbitrary message calls, such as asset transfers, through vouchers.
An `Application` contract, just like any other contract on Ethereum, has a unique address. With this address, an application can hold ownership over digital assets on the base layer like Ether, ERC-20 tokens, and NFTs. In the next sections, we'll explain how applications are able to receive assets through portals, and perform arbitrary message calls, such as asset transfers, through vouchers.

Since there is no access control to execute a voucher, the caller must also provide a proof that such voucher was generated by the off-chain machine. This proof is checked on-chain against a claim, that is provided by the DApp's consensus. Therefore, a DApp must trust its consensus to only provide valid claims. However, if the consensus goes inactive or rogue, the DApp owner can migrate to a new consensus. In summary, DApp users must trust the DApp owner to choose a trustworthy consensus.
Since there is no access control to execute a voucher, the caller must also provide a proof that such voucher was generated by the off-chain machine. This proof is checked on-chain against a claim, that is provided by the application's consensus. Therefore, an application must trust its consensus to only provide valid claims. However, if the consensus goes inactive or rogue, the application owner can migrate to a new consensus. In summary, application users must trust the application owner to choose a trustworthy consensus.

### Cartesi DApp Factory
### Application Factory

The Cartesi DApp Factory allows anyone to deploy Cartesi DApp contracts with a simple function call, costing only 3.5% more gas than deploying the DApp contract directly. It also provides greater convenience to the deployer, and security to users and validators, as they know the bytecode could not have been altered maliciously.
The Application Factory allows anyone to deploy `Application` contracts with a simple function call. It provides greater convenience to the deployer, and security to users and validators, as they know the bytecode could not have been altered maliciously.

### Portals

Portals, as the name suggests, are used to safely teleport assets from the base layer to the execution layer. It works in the following way. First, for some types of assets, the user has to allow the portal to deduct the asset(s) from their account. Second, the user tells the portal to transfer the asset(s) from their account to some DApp's account. The portal then adds an input to the DApp's input box to inform the machine of the transfer that just took place in the base layer. Finally, the off-chain machine is made aware of the transfer through the input sent by the portal. Note that the machine must know the address of the portal beforehand in order to validate such input.
Portals, as the name suggests, are used to safely teleport assets from the base layer to the execution layer. It works in the following way. First, for some types of assets, the user has to allow the portal to deduct the asset(s) from their account. Second, the user tells the portal to transfer the asset(s) from their account to some application's account. The portal then adds an input to the application's input box to inform the machine of the transfer that just took place in the base layer. Finally, the off-chain machine is made aware of the transfer through the input sent by the portal. Note that the machine must know the address of the portal beforehand in order to validate such input.

The DApp developer can choose to do whatever they want with this information. For example, they might choose to create a wallet for each user in the execution layer, where assets can be managed at a much lower cost through inputs that are understood by the Linux logic. In this sense, one could think of the DApp contract as a wallet, owned by the off-chain machine. Anyone can deposit assets there but only the DApp—through vouchers—can decide on withdrawals.
The application developer can choose to do whatever they want with this information. For example, they might choose to create a wallet for each user in the execution layer, where assets can be managed at a much lower cost through inputs that are understood by the Linux logic. In this sense, one could think of the application contract as a wallet, owned by the off-chain machine. Anyone can deposit assets there but only the application—through vouchers—can decide on withdrawals.

The withdrawal process is quite simple from the user's perspective. Typically, the user would first send an input to the DApp requesting the withdrawal, which would then get processed and interpreted off-chain. If all goes well, the machine should generate a voucher that, once executed, transfers the asset(s) to the rightful recipient.
The withdrawal process is quite simple from the user's perspective. Typically, the user would first send an input to the application requesting the withdrawal, which would then get processed and interpreted off-chain. If all goes well, the machine should generate a voucher that, once executed, transfers the asset(s) to the rightful recipient.

Currently, we support the following types of assets:

Expand All @@ -96,7 +96,7 @@ Currently, we support the following types of assets:

#### Input encodings for deposits

As explained above, in order to teleport an asset from the base layer to the execution layer, you need the corresponding portal to add an input to the DApp's input box, which will then be interpreted and validated by the off-chain machine. To do that, the machine will need to decode the input payload.
As explained above, in order to teleport an asset from the base layer to the execution layer, you need the corresponding portal to add an input to the application's input box, which will then be interpreted and validated by the off-chain machine. To do that, the machine will need to decode the input payload.

The input payloads for deposits are always specified as packed ABI-encoded parameters, as detailed below. In Solidity, packed ABI-encoding is denoted by `abi.encodePacked(...)` and standard ABI-encoded is denoted by `abi.encode(...)`.

Expand All @@ -116,15 +116,15 @@ As an example, the deposit of 100 Wei (of Ether) sent by address `0xf39fd6e51aad

### Vouchers

Vouchers allow DApps in the execution layer to interact with contracts in the base layer through message calls. They are emitted by the off-chain machine, and executed by anyone in the base layer. Each voucher is composed of a destination address and a payload. In the case of vouchers destined to Solidity contracts, the payload generally encodes a function call.
Vouchers allow applications in the execution layer to interact with contracts in the base layer through message calls. They are emitted by the off-chain machine, and executed by anyone in the base layer. Each voucher is composed of a destination address and a payload. In the case of vouchers destined to Solidity contracts, the payload generally encodes a function call.

A voucher can only be executed once the DApp's consensus submits a claim containing it. They can be executed in any order. Although the DApp contract is indifferent to the content of the voucher being executed, it enforces some sanity checks before allowing its execution. First, it checks whether the voucher has been successfully executed already. Second, it ensures that the voucher has been emitted by the off-chain machine, by requiring a validity proof.
A voucher can only be executed once the application's consensus accepts a claim containing it. They can be executed in any order. Although the application contract is indifferent to the content of the voucher being executed, it enforces some sanity checks before allowing its execution. First, it checks whether the voucher has been successfully executed already. Second, it ensures that the voucher has been emitted by the off-chain machine, by requiring a validity proof.

Because of their generality, vouchers can be used in a wide range of applications: from withdrawing funds to providing liquidity in a DeFi protocol. Typically, DApps use vouchers to withdraw assets. Below, we show how vouchers can be used to withdraw several types of assets. You can find more information about a particular function by clicking on the :page_facing_up: emoji near it.
Because of their generality, vouchers can be used in a wide range of applications: from withdrawing funds to providing liquidity in a DeFi protocol. Typically, applications use vouchers to withdraw assets. Below, we show how vouchers can be used to withdraw several types of assets. You can find more information about a particular function by clicking on the :page_facing_up: emoji near it.

| Asset | Destination | Function signature |
| :- | :- | :- |
| Ether | DApp contract | `withdrawEther(address,uint256)` [:page_facing_up:](./onchain/rollups/contracts/dapp/Application.sol) |
| Ether | Application contract | `withdrawEther(address,uint256)` [:page_facing_up:](./onchain/rollups/contracts/dapp/Application.sol) |
| ERC-20 | Token contract | `transfer(address,uint256)` [:page_facing_up:](https://eips.ethereum.org/EIPS/eip-20#methods) |
| ERC-20 | Token contract | `transferFrom(address,address,uint256)` [:page_facing_up:](https://eips.ethereum.org/EIPS/eip-20#methods) [^1] |
| ERC-721 | Token contract | `safeTransferFrom(address,address,uint256)` [:page_facing_up:](https://eips.ethereum.org/EIPS/eip-721#specification) |
Expand All @@ -140,23 +140,23 @@ As an example, the voucher for a simple ERC-20 transfer (2nd line in the table a
0xa9059cbb000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000064
```

[^1]: If the DApp owns the tokens, prefer to use `transfer(address,uint256)`
[^1]: If the application owns the tokens, prefer to use `transfer(address,uint256)`
[^2]: If no data is being passed as an argument, prefer to use `safeTransferFrom(address,address,uint256)`
[^3]: If only one token is being transferred, prefer to use `safeTransferFrom(address,address,uint256,uint256,data)`

### DApp Address Relay
### Application Address Relay

In the previous section, we showed how vouchers can be used to withdraw different types of assets. Most of those vouchers contain the address of the DApp contract, either as the destination address or as a function argument. So, the off-chain machine needs to "know" the DApp contract address at some point. If the off-chain machine knew the DApp contract address from the beginning, it would create a cyclical dependency between the initial machine state hash (also called "template hash") and the DApp contract address. This is due to the fact that the address of a DApp contract depends on its construction arguments, which include the template hash; and that the template hash is the Merkle root of the machine address space, which includes the DApp contract address.
In the previous section, we showed how vouchers can be used to withdraw different types of assets. Most of those vouchers contain the address of the application contract, either as the destination address or as a function argument. So, the off-chain machine needs to "know" the application contract address at some point. If the off-chain machine knew the application contract address from the beginning, it would create a cyclical dependency between the initial machine state hash (also called "template hash") and the application contract address. This is due to the fact that the address of an application contract depends on its construction arguments, which include the template hash; and that the template hash is the Merkle root of the machine address space, which includes the application contract address.

This "chicken-and-egg" problem is circumvented by a very small permissionless contract in the base layer, the DApp Address Relay ([source](./onchain/rollups/contracts/relays/ApplicationAddressRelay.sol)). Its only job is to add an input to a DApp's input box with the DApp contract address. The off-chain machine then decodes this input and stores the address somewhere for future use. Just like in the case of portals, the machine must also know the address of the relay in order to validate the origin of the input.
This "chicken-and-egg" problem is circumvented by a very small permissionless contract in the base layer, the Application Address Relay ([source](./onchain/rollups/contracts/relays/ApplicationAddressRelay.sol)). Its only job is to add an input to an application's input box with the application contract address. The off-chain machine then decodes this input and stores the address somewhere for future use. Just like in the case of portals, the machine must also know the address of the relay in order to validate the origin of the input.

### Notices

Notices are informational statements that can be proved by contracts in the base layer. They're emitted by the off-chain machine and contain a payload, in bytes. DApp developers are free to explore different use cases for notices, their generality and negligible cost of emission makes them a powerful tool to assist integration between DApps and contracts or even other DApps. Similar to vouchers, notices can only be proved once they've been finalized on-chain and if they're accompanied by a validity proof. A chess DApp could, for example, emit a notice informing the underlying blockchain of the winner of a tournament. While that information is not necessarily "actionable", it could be used by other applications for different purposes.
Notices are informational statements that can be proved by contracts in the base layer. They're emitted by the off-chain machine and contain a payload, in bytes. Application developers are free to explore different use cases for notices, their generality and negligible cost of emission makes them a powerful tool to assist integration between applications and contracts, or even other applications. Similar to vouchers, notices can only be proved once they've been finalized on-chain and if they're accompanied by a validity proof. A chess application could, for example, emit a notice informing the underlying blockchain of the winner of a tournament. While that information is not necessarily "actionable", it could be used by other applications for different purposes.

### Consensus

This module is responsible for providing valid claims to DApps after reaching some form of consensus. Each DApp has its own mapping of claims, each of which is mapped by the range of input indices of an epoch.
This module is responsible for providing valid claims to applications after reaching some form of consensus. Each application has its own mapping of claims, each of which is mapped by the range of input indices of an epoch.

The module's interface aims to be as generic as possible to accommodate any consensus model, since there are plenty to choose from. The types of consensus currently implemented include:
- Authority: managed by a single address, who has complete power over the consensus. It is trivial to implement, yet quite vulnerable.
Expand Down

0 comments on commit 7867b74

Please sign in to comment.