Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ The application keeps a dedicated region of machine memory called the **accounts

An application supports emergency withdrawal only if:

1. It maintains an accounts drive, and
2. The drive's layout matches the [`WithdrawalConfig`](../contracts/withdrawal/withdrawal-config.md) the application was deployed with.
3. The WithdrawalOutputBuilder contract configured in the application can decode the account and build a valid output to withdraw the assets
1. It maintains an accounts drive.
2. The drive's layout matches the [`WithdrawalConfig`](../contracts/withdrawal/withdrawal-config.md) used when the application was deployed.
3. Every account record stores its owner address in the final 20 bytes.
4. The configured withdrawal output builder can decode each account and produce a valid withdrawal output.

If the layout the guest writes and the config the contract was given disagree, proofs will not validate and funds cannot be withdrawn.

Expand All @@ -25,19 +26,15 @@ The [`WithdrawalConfig`](../contracts/withdrawal/withdrawal-config.md) describes
- `log2MaxNumOfAccounts` sets how many accounts fit (the tree depth);
- `log2LeavesPerAccount` sets each record's size, which is `2^(5 + log2LeavesPerAccount)` bytes.

For the single-token case (see [`UsdWithdrawalOutputBuilder`](../contracts/withdrawal/usd-withdrawal-output-builder.md)), each record is 32 bytes: an 8-byte little-endian balance, followed by the 20-byte owner address, followed by padding.
For the single-token case, each record is exactly 32 bytes. The [`UsdWithdrawalOutputBuilder`](../contracts/withdrawal/usd-withdrawal-output-builder.md) reads the first 12 bytes as a little-endian `uint96` balance and the final 20 bytes as the owner's address. There is no padding between these fields.

## Creating the accounts drive

The accounts drive is a standard Cartesi Machine drive, declared in your project's `cartesi.toml` alongside every other drive. The [Advanced configuration](../../development/advanced-configuration.md#drives) guide covers how drives are defined and built in general; the accounts drive is distinctive only in that it is left raw, so the guest can write balance records into it directly.

Declare it next to the root drive as an empty, raw, unmounted flash drive, and set `final_hash = true` so the build produces the machine hash that on-chain deployment requires:
Declare it next to the root drive as an empty, raw, unmounted flash drive. `cartesi build` computes and stores the final machine hash automatically:

```toml
[machine]
# ...your existing machine settings...
final_hash = true

# The application and OS, built from your Dockerfile.
[drives.root]
builder = "docker"
Expand All @@ -53,7 +50,7 @@ mount = false
user = "dapp"
```

Leaving the drive raw and unmounted is deliberate. Rather than layering a filesystem on top, the guest opens the block device directly (for example `/dev/pmem1`) and writes fixed-size records at deterministic offsets. That predictable layout is precisely what allows the drive to be Merkle-proven against the machine state after foreclosure. The [Common drive options](../../development/advanced-configuration.md#common-drive-options) reference explains each field used above.
Leaving the drive raw and unmounted allows the guest to open the block device directly, for example `/dev/pmem1`, and write fixed-size records at deterministic offsets. This predictable layout allows the drive to be proven against the machine state after foreclosure. The [Common drive options](../../development/advanced-configuration.md#common-drive-options) reference explains each field used above.

Two properties of the drive must agree with the [`WithdrawalConfig`](../contracts/withdrawal/withdrawal-config.md):

Expand All @@ -68,7 +65,7 @@ You rarely need to write the drive by hand. A ledger library maintains the accou

## The account encoding must round-trip

The bytes the guest writes for an account must be the same bytes the on-chain [withdrawal output builder](../contracts/withdrawal/iwithdrawal-output-builder.md) decodes at withdrawal time. For the USD builder, that means the `(owner, balance)` encoding the guest produces must match what the builder reads back to build the transfer.
The bytes written by the guest must match the account format decoded by the on-chain [withdrawal output builder](../contracts/withdrawal/iwithdrawal-output-builder.md). For the USD builder, write the balance into bytes 0 through 11 in little-endian order and the owner address into bytes 12 through 31. The builder reads those same bytes when it creates the token-transfer output.

:::note
Emergency withdrawal relies on four descriptions of the accounts drive agreeing: the layout the **guest** writes, the **`WithdrawalConfig`** on-chain, the parameters used to **generate proofs** off-chain, and the account encoding the **output builder** decodes. Choose these together at deploy time. See [Withdrawal Contracts Overview](../contracts/withdrawal/overview.md#the-four-way-agreement).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,152 +2,146 @@
id: application-factory
title: ApplicationFactory
resources:
- url: https://github.com/cartesi/rollups-contracts/tree/v3.0.0-alpha.6/src/dapp/ApplicationFactory.sol
title: Application Factory contract
- url: https://github.com/cartesi/rollups-contracts/blob/v3.0.0-alpha.9/src/dapp/ApplicationFactory.sol
title: ApplicationFactory contract
- url: https://github.com/cartesi/rollups-contracts/blob/v3.0.0-alpha.9/src/dapp/IApplicationFactory.sol
title: IApplicationFactory interface
---

The **ApplicationFactory** contract is a tool for reliably deploying new instances of the [`Application`](../contracts/application.md) contract with or without a specified salt value for address derivation.
The **ApplicationFactory** deploys [`Application`](./application.md) contracts directly or at deterministic `CREATE2` addresses.

Additionally, it provides a function to calculate the address of a potential new `CartesiDApp` contract based on input parameters.
Every Application created by one factory uses the same immutable [refund output builder](./refund/overview.md). The caller still chooses the validator, owner, template hash, input box, and withdrawal configuration for each deployment.

This contract ensures efficient and secure deployment of `Application` contracts within the Cartesi Rollups framework.
## `constructor()`

## Functions
```solidity
constructor(IRefundOutputBuilder refundOutputBuilder)
```

| Parameter | Type | Description |
| --- | --- | --- |
| `refundOutputBuilder` | `IRefundOutputBuilder` | Builder assigned to every Application deployed by this factory |

### `newApplication()`
## `newApplication()`

```solidity
function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes calldata dataAvailability,
IInputBox inputBox,
WithdrawalConfig calldata withdrawalConfig
) external override returns (IApplication)
) external returns (IApplication appContract)
```

Deploys a new Application contract without a salt value for address derivation.
Deploys an Application with the standard `CREATE` opcode.

**Parameters**
| Parameter | Type | Description |
| --- | --- | --- |
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | Initial output validator |
| `appOwner` | `address` | Nonzero initial Application owner |
| `templateHash` | `bytes32` | Initial machine state hash |
| `inputBox` | `IInputBox` | Input box used by the Application and its portals |
| `withdrawalConfig` | `WithdrawalConfig` | Guardian, accounts-drive geometry, and withdrawal builder; use a zero-valued config to disable recovery |

| Name | Type | Description |
|------|------|-------------|
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | The initial outputs Merkle root validator contract |
| `appOwner` | `address` | Address of the owner of the application |
| `templateHash` | `bytes32` | Hash of the template for the application |
| `dataAvailability` | `bytes` | The data availability solution |
| `withdrawalConfig` | `WithdrawalConfig` | The withdrawal configuration (see [WithdrawalConfig](./withdrawal/withdrawal-config.md)). Pass a zero-valued config to deploy without emergency withdrawal |
Returns the deployed Application and emits `ApplicationCreated`.

**Return Values**
| Return value | Type | Description |
| --- | --- | --- |
| `appContract` | `IApplication` | Deployed Application contract |

| Name | Type | Description |
|------|------|-------------|
| `[0]` | `IApplication` | The deployed Application contract |

### `newApplication()` (with salt)
## `newApplication()` with salt

```solidity
function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes calldata dataAvailability,
IInputBox inputBox,
WithdrawalConfig calldata withdrawalConfig,
bytes32 salt
) external override returns (IApplication)
) external returns (IApplication appContract)
```

Deploys a new `Application` contract with a specified salt value for address derivation.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | The initial outputs Merkle root validator contract |
| `appOwner` | `address` | Address of the owner of the application |
| `templateHash` | `bytes32` | Hash of the template for the application |
| `dataAvailability` | `bytes` | The data availability solution |
| `withdrawalConfig` | `WithdrawalConfig` | The withdrawal configuration (see [WithdrawalConfig](./withdrawal/withdrawal-config.md)). Pass a zero-valued config to deploy without emergency withdrawal |
| `salt` | `bytes32` | Salt value for address derivation |
Deploys the same configuration with `CREATE2`. The address depends on every constructor value, the factory's immutable refund builder, and `salt`.

**Return Values**
| Parameter | Type | Description |
| --- | --- | --- |
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | Initial output validator |
| `appOwner` | `address` | Nonzero initial Application owner |
| `templateHash` | `bytes32` | Initial machine state hash |
| `inputBox` | `IInputBox` | Input box used by the Application and its portals |
| `withdrawalConfig` | `WithdrawalConfig` | Guardian, accounts-drive geometry, and withdrawal builder; use a zero-valued config to disable recovery |
| `salt` | `bytes32` | Value used to derive the deterministic deployment address |

| Name | Type | Description |
|------|------|-------------|
| `[0]` | `IApplication` | The deployed Application contract |
| Return value | Type | Description |
| --- | --- | --- |
| `appContract` | `IApplication` | Deployed Application contract |

### `calculateApplicationAddress()`
## `calculateApplicationAddress()`

```solidity
function calculateApplicationAddress(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes calldata dataAvailability,
IInputBox inputBox,
WithdrawalConfig calldata withdrawalConfig,
bytes32 salt
) external view override returns (address)
) external view returns (address appContract)
```

Calculates the address of a potential new Application contract based on input parameters.
Returns the address at which the salted `newApplication` overload would deploy the Application. It does not deploy a contract.

**Parameters**
| Parameter | Type | Description |
| --- | --- | --- |
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | Initial output validator |
| `appOwner` | `address` | Nonzero initial Application owner |
| `templateHash` | `bytes32` | Initial machine state hash |
| `inputBox` | `IInputBox` | Input box used by the Application and its portals |
| `withdrawalConfig` | `WithdrawalConfig` | Guardian, accounts-drive geometry, and withdrawal builder; use a zero-valued config to disable recovery |
| `salt` | `bytes32` | Value used to derive the deterministic deployment address |

| Name | Type | Description |
|------|------|-------------|
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | The initial outputs Merkle root validator contract |
| `appOwner` | `address` | Address of the owner of the application |
| `templateHash` | `bytes32` | Hash of the template for the application |
| `dataAvailability` | `bytes` | The data availability solution |
| `withdrawalConfig` | `WithdrawalConfig` | The withdrawal configuration (see [WithdrawalConfig](./withdrawal/withdrawal-config.md)). Pass a zero-valued config to deploy without emergency withdrawal |
| `salt` | `bytes32` | Salt value for address derivation |
| Return value | Type | Description |
| --- | --- | --- |
| `appContract` | `address` | Address calculated for the Application |

**Return Values**
Use exactly the same factory and arguments for calculation and deployment. Changing the input box, validator, withdrawal configuration, or any other constructor value changes the resulting address.

| Name | Type | Description |
|------|------|-------------|
| `[0]` | `address` | Address of the potential new Application contract |

## Events

### `ApplicationCreated()`
## `ApplicationCreated`

```solidity
event ApplicationCreated(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
IOutputsMerkleRootValidator indexed outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes dataAvailability,
IInputBox inputBox,
WithdrawalConfig withdrawalConfig,
IApplication appContract
)
```

A new Application contract was deployed.
Emitted after either deployment method succeeds.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | The outputs Merkle root validator contract |
| `appOwner` | `address` | The owner of the application |
| `templateHash` | `bytes32` | The template hash |
| `dataAvailability` | `bytes` | The data availability solution |
| `withdrawalConfig` | `WithdrawalConfig` | The withdrawal configuration (see [WithdrawalConfig](./withdrawal/withdrawal-config.md)). Pass a zero-valued config to deploy without emergency withdrawal |
| `appContract` | `IApplication` | The deployed Application contract |
| Parameter | Type | Description |
| --- | --- | --- |
| `outputsMerkleRootValidator` | `IOutputsMerkleRootValidator` | Initial output validator assigned to the Application |
| `appOwner` | `address` | Initial Application owner |
| `templateHash` | `bytes32` | Initial machine state hash |
| `inputBox` | `IInputBox` | Input box assigned to the Application |
| `withdrawalConfig` | `WithdrawalConfig` | Withdrawal configuration assigned to the Application |
| `appContract` | `IApplication` | Deployed Application contract |

## Errors

### `InvalidWithdrawalConfig()`
### `InvalidWithdrawalConfig`

```solidity
error InvalidWithdrawalConfig(WithdrawalConfig withdrawalConfig)
```

Raised at deployment when the provided [`WithdrawalConfig`](./withdrawal/withdrawal-config.md) is invalid, meaning its accounts-drive layout does not fit inside the machine memory (see [`LibWithdrawalConfig.isValid`](./withdrawal/withdrawal-config.md#validation)). Checking the config in the factory means users and the node do not have to check it themselves.

**Parameters**
Raised when the accounts-drive layout in `withdrawalConfig` does not fit within the Cartesi Machine memory. See [`WithdrawalConfig` validation](./withdrawal/withdrawal-config.md#validation).

| Name | Type | Description |
|------|------|-------------|
| `withdrawalConfig` | `WithdrawalConfig` | The invalid withdrawal configuration |
| Parameter | Type | Description |
| --- | --- | --- |
| `withdrawalConfig` | `WithdrawalConfig` | Invalid withdrawal configuration supplied for deployment |
Loading
Loading