Skip to content
Draft
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
20 changes: 20 additions & 0 deletions cannonfile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ create2 = true
salt = "<%= zeroHash %>"
ifExists = "continue"

[deploy.DirectInputApplicationFactory]
artifact = "DirectInputApplicationFactory"
args = [
"<%= contracts.ApplicationFactory.address %>",
"<%= contracts.InputBox.address %>",
]
create2 = true
salt = "<%= zeroHash %>"
ifExists = "continue"

[deploy.EspressoApplicationFactory]
artifact = "EspressoApplicationFactory"
args = [
"<%= contracts.ApplicationFactory.address %>",
"<%= contracts.InputBox.address %>",
]
create2 = true
salt = "<%= zeroHash %>"
ifExists = "continue"

[deploy.SelfHostedApplicationFactory]
artifact = "SelfHostedApplicationFactory"
args = [
Expand Down
63 changes: 63 additions & 0 deletions src/dapp/DirectInputApplicationFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.8;

import {Create2} from "@openzeppelin-contracts-5.2.0/utils/Create2.sol";

import {IApplicationFactory} from "./IApplicationFactory.sol";
import {IDirectInputApplicationFactory} from "./IDirectInputApplicationFactory.sol";
import {IOutputsMerkleRootValidator} from "../consensus/IOutputsMerkleRootValidator.sol";
import {Application} from "./Application.sol";
import {DataAvailability} from "../common/DataAvailability.sol";
import {IApplication} from "./IApplication.sol";
import {IInputBox} from "../inputs/IInputBox.sol";

/// @title Application Factory
/// @notice Allows anyone to reliably deploy a new `IApplication` contract.
contract DirectInputApplicationFactory is IDirectInputApplicationFactory {
IApplicationFactory private immutable _applicationFactory;
IInputBox private immutable _inputBox;

constructor(IApplicationFactory applicationFactory, IInputBox inputBox) {
_applicationFactory = applicationFactory;
_inputBox = inputBox;
}

function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external override returns (IApplication) {
bytes memory dataAvailability =
abi.encodeCall(DataAvailability.InputBox, (_inputBox));
return _applicationFactory.newApplication(
outputsMerkleRootValidator, appOwner, templateHash, dataAvailability, salt
);
}

function calculateApplicationAddress(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external view override returns (address) {
bytes memory dataAvailability =
abi.encodeCall(DataAvailability.InputBox, (_inputBox));
return Create2.computeAddress(
salt,
keccak256(
abi.encodePacked(
type(Application).creationCode,
abi.encode(
outputsMerkleRootValidator,
appOwner,
templateHash,
dataAvailability
)
)
)
);
}
}
69 changes: 69 additions & 0 deletions src/dapp/EspressoApplicationFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.8;

import {Create2} from "@openzeppelin-contracts-5.2.0/utils/Create2.sol";

import {IApplicationFactory} from "./IApplicationFactory.sol";
import {IEspressoApplicationFactory} from "./IEspressoApplicationFactory.sol";
import {IOutputsMerkleRootValidator} from "../consensus/IOutputsMerkleRootValidator.sol";
import {Application} from "./Application.sol";
import {DataAvailability} from "../common/DataAvailability.sol";
import {IApplication} from "./IApplication.sol";
import {IInputBox} from "../inputs/IInputBox.sol";

/// @title Application Factory
/// @notice Allows anyone to reliably deploy a new `IApplication` contract.
contract EspressoApplicationFactory is IEspressoApplicationFactory {
IApplicationFactory private immutable _applicationFactory;
IInputBox private immutable _inputBox;

constructor(IApplicationFactory applicationFactory, IInputBox inputBox) {
_applicationFactory = applicationFactory;
_inputBox = inputBox;
}

function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
uint256 fromBlock,
uint32 namespaceId,
bytes32 salt
) external override returns (IApplication) {
bytes memory dataAvailability = abi.encodeCall(
DataAvailability.InputBoxAndEspresso, (_inputBox, fromBlock, namespaceId)
);
return _applicationFactory.newApplication(
outputsMerkleRootValidator, appOwner, templateHash, dataAvailability, salt
);
}

function calculateApplicationAddress(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
uint256 fromBlock,
uint32 namespaceId,
bytes32 salt
) external view override returns (address) {
bytes memory dataAvailability = abi.encodeCall(
DataAvailability.InputBoxAndEspresso, (_inputBox, fromBlock, namespaceId)
);
return Create2.computeAddress(
salt,
keccak256(
abi.encodePacked(
type(Application).creationCode,
abi.encode(
outputsMerkleRootValidator,
appOwner,
templateHash,
dataAvailability
)
)
)
);
}
}
40 changes: 40 additions & 0 deletions src/dapp/IDirectInputApplicationFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.8;

import {IApplication} from "./IApplication.sol";
import {IOutputsMerkleRootValidator} from "../consensus/IOutputsMerkleRootValidator.sol";

/// @title Application Factory interface
interface IDirectInputApplicationFactory {
/// @notice Deploy a new application deterministically.
/// @param outputsMerkleRootValidator The initial outputs Merkle root validator contract
/// @param appOwner The initial application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the application contract address
/// @return The application
/// @dev On success, MUST emit an `ApplicationCreated` event.
/// @dev Reverts if the application owner address is zero.
function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external returns (IApplication);

/// @notice Calculate the address of an application contract to be deployed deterministically.
/// @param outputsMerkleRootValidator The initial outputs Merkle root validator contract
/// @param appOwner The initial application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the application contract address
/// @return The deterministic application contract address
/// @dev Beware that only the `newApplication` function with the `salt` parameter
/// is able to deterministically deploy an application.
function calculateApplicationAddress(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external view returns (address);
}
48 changes: 48 additions & 0 deletions src/dapp/IEspressoApplicationFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

pragma solidity ^0.8.8;

import {IApplication} from "./IApplication.sol";
import {IOutputsMerkleRootValidator} from "../consensus/IOutputsMerkleRootValidator.sol";

/// @title Application Factory interface
interface IEspressoApplicationFactory {
/// @notice Deploy a new application deterministically.
/// @param outputsMerkleRootValidator The initial outputs Merkle root validator contract
/// @param appOwner The initial application owner
/// @param templateHash The initial machine state hash
/// @param fromBlock Height of first Espresso block to consider
/// @param namespaceId The Espresso namespace ID
/// @param salt The salt used to deterministically generate the application contract address
/// @return The application
/// @dev On success, MUST emit an `ApplicationCreated` event.
/// @dev Reverts if the application owner address is zero.
function newApplication(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
uint256 fromBlock,
uint32 namespaceId,
bytes32 salt
) external returns (IApplication);

/// @notice Calculate the address of an application contract to be deployed deterministically.
/// @param outputsMerkleRootValidator The initial outputs Merkle root validator contract
/// @param appOwner The initial application owner
/// @param templateHash The initial machine state hash
/// @param fromBlock Height of first Espresso block to consider
/// @param namespaceId The Espresso namespace ID
/// @param salt The salt used to deterministically generate the application contract address
/// @return The deterministic application contract address
/// @dev Beware that only the `newApplication` function with the `salt` parameter
/// is able to deterministically deploy an application.
function calculateApplicationAddress(
IOutputsMerkleRootValidator outputsMerkleRootValidator,
address appOwner,
bytes32 templateHash,
uint256 fromBlock,
uint32 namespaceId,
bytes32 salt
) external view returns (address);
}
Loading