Skip to content

Commit

Permalink
chore: merge branch 'main' into prerelease/2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
guidanoli committed May 14, 2024
2 parents 4b03ced + d83563a commit a937382
Show file tree
Hide file tree
Showing 55 changed files with 3,777 additions and 2,607 deletions.
5 changes: 5 additions & 0 deletions .changeset/lucky-elephants-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/rollups": minor
---

Add a contract for safe ERC20 transfers. This can be used by delegatecall vouchers.
6 changes: 6 additions & 0 deletions .changeset/olive-crabs-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@cartesi/rollups": major
---

Added contract `AssetTransferToENS` that can be used as a destination for `DELEGATECALL` vouchers to transfer assets to ENS-identified accounts.
Added library `LibAddress` for safe low level call and safe delegate call.
6 changes: 6 additions & 0 deletions .changeset/proud-badgers-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@cartesi/rollups": major
---

Added ENS Portal.
Added a new input encoding for ENS inputs.
5 changes: 5 additions & 0 deletions .changeset/shy-dragons-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/rollups": minor
---

Add self-hosted application factory contract
5 changes: 5 additions & 0 deletions .changeset/thirty-crews-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/rollups": minor
---

Supported the execution of `DELEGATECALL` vouchers
5 changes: 1 addition & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ jobs:

- uses: ./.github/workflows/setup

- name: Generate proofs
run: pnpm proofs:setup

- name: Run tests
run: pnpm test
run: forge test -vvv

- name: Upload signatures
run: forge selectors upload --all
6 changes: 0 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
.DS_Store
.env
.node*
.vscode
/abi
/artifacts
/cache
/contracts.json
/coverage*
/deployments/*/solcInputs/*.json
/deployments/localhost
Expand Down
4 changes: 0 additions & 4 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ cache
deployments
dist
export
generated-src
src/types
abi
out
lib
forge-cache
test/foundry/dapp/helper/input
test/foundry/dapp/helper/output
146 changes: 83 additions & 63 deletions CONTRACTS.md

Large diffs are not rendered by default.

21 changes: 3 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ If you are interested in taking a look at the off-chain part, please, head over

- [pnpm](https://pnpm.io/installation)
- [Forge](https://book.getfoundry.sh/getting-started/installation)
- [Docker](https://docs.docker.com/get-docker/)

## 💡 Basic setup

Expand Down Expand Up @@ -44,24 +43,10 @@ If the node is not listening to `http://localhost:8545/`, please set the `RPC_UR

## 🧪 Tests

If you plan to run the [Forge](https://book.getfoundry.sh/getting-started/installation) tests, there still some setup left to do.
Assuming that [Docker Engine](https://docs.docker.com/get-docker/) is running on the background, you may run the following command.
This command will build the Cartesi Machine image necessary to build the proofs.
If you want to run the tests, please run the following command.

```sh
pnpm proofs:setup
```

Now, you may run the tests!

```sh
pnpm test
```

From this point on, after any change in the source code, you can update the proofs before running the tests again with the following command.

```sh
pnpm proofs:update
forge test -vvv
```

## 📚 Documentation
Expand All @@ -70,7 +55,7 @@ pnpm proofs:update

ℹ️ You may also want to check the [official Cartesi Rollups documentation website](https://docs.cartesi.io/cartesi-rollups/overview/).

🔎 For an in-depth view of the on-chain architecture, we invite you to take a look at the [`CONTRACTS.md`](./CONTRACTS.md) file.
🔎 For an in-depth view of the on-chain architecture, we invite you to take a look at the [`CONTRACTS.md`](https://github.com/cartesi/rollups-contracts/blob/main/CONTRACTS.md) file.

## 🎨 Experimenting

Expand Down
37 changes: 4 additions & 33 deletions contracts/common/CanonicalMachine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,12 @@ pragma solidity ^0.8.8;
/// @notice Defines several constants related to the reference implementation
/// of the RISC-V machine that runs Linux, also known as the "Cartesi Machine".
library CanonicalMachine {
/// @notice Base-2 logarithm of number of bytes.
type Log2Size is uint64;

/// @notice Machine word size (8 bytes).
Log2Size constant WORD_LOG2_SIZE = Log2Size.wrap(3);

/// @notice Machine address space size (2^64 bytes).
Log2Size constant MACHINE_LOG2_SIZE = Log2Size.wrap(64);

/// @notice Keccak-256 output size (32 bytes).
Log2Size constant KECCAK_LOG2_SIZE = Log2Size.wrap(5);

/// @notice Maximum input size (2 megabytes).
uint256 constant INPUT_MAX_SIZE = 1 << 21;

/// @notice Maximum output metadata memory range (2 megabytes).
Log2Size constant OUTPUT_METADATA_LOG2_SIZE = Log2Size.wrap(21);

/// @notice Maximum epoch output memory range (128 megabytes).
Log2Size constant EPOCH_OUTPUT_LOG2_SIZE = Log2Size.wrap(37);

/// @notice Unwrap `s` into its underlying uint64 value.
/// @param s Base-2 logarithm of some number of bytes
function uint64OfSize(Log2Size s) internal pure returns (uint64) {
return Log2Size.unwrap(s);
}
/// @notice Log of maximum number of inputs per epoch.
uint256 constant LOG2_MAX_INPUTS_PER_EPOCH = 32;

/// @notice Return the position of an intra memory range on a memory range
/// with contents with the same size.
/// @param index Index of intra memory range
/// @param log2Size Base-2 logarithm of intra memory range size
function getIntraMemoryRangePosition(
uint64 index,
Log2Size log2Size
) internal pure returns (uint64) {
return index << Log2Size.unwrap(log2Size);
}
/// @notice Log of maximum number of outputs per input.
uint256 constant LOG2_MAX_OUTPUTS_PER_INPUT = 16;
}
26 changes: 22 additions & 4 deletions contracts/common/InputEncoding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
library InputEncoding {
/// @notice Encode an Ether deposit.
/// @param sender The Ether sender
/// @param value The amount of Ether being sent in Wei
/// @param value The amount of Wei being sent
/// @param execLayerData Additional data to be interpreted by the execution layer
/// @return The encoded input payload
function encodeEtherDeposit(
Expand All @@ -33,20 +33,20 @@ library InputEncoding {
/// @notice Encode an ERC-20 token deposit.
/// @param token The token contract
/// @param sender The token sender
/// @param amount The amount of tokens being sent
/// @param value The amount of tokens being sent
/// @param execLayerData Additional data to be interpreted by the execution layer
/// @return The encoded input payload
function encodeERC20Deposit(
IERC20 token,
address sender,
uint256 amount,
uint256 value,
bytes calldata execLayerData
) internal pure returns (bytes memory) {
return
abi.encodePacked(
token, // 20B
sender, // 20B
amount, // 32B
value, // 32B
execLayerData // arbitrary size
);
}
Expand Down Expand Up @@ -134,4 +134,22 @@ library InputEncoding {
data // arbitrary size
);
}

/// @notice Encode an ENS input.
/// @param node The ENS node
/// @param name The ENS name
/// @param execLayerData Additional data to be interpreted by the execution layer
/// @return The encoded input payload
function encodeENSInput(
bytes32 node,
bytes calldata name,
bytes calldata execLayerData
) internal pure returns (bytes memory) {
return
abi.encode(
node, // 32B
name, // arbitrary size
execLayerData // arbitrary size
);
}
}
3 changes: 3 additions & 0 deletions contracts/common/Inputs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ interface Inputs {
/// @param msgSender The address of whoever sent the input
/// @param blockNumber The number of the block in which the input was added
/// @param blockTimestamp The timestamp of the block in which the input was added
/// @param prevRandao The latest RANDAO mix of the post beacon state of the previous block
/// @param index The index of the input in the input box
/// @param payload The payload provided by the message sender
/// @dev 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;
Expand Down
10 changes: 10 additions & 0 deletions contracts/common/Outputs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,14 @@ interface Outputs {
uint256 value,
bytes calldata payload
) external;

/// @notice A single-use permission to execute a specific delegate call
/// from the context of the application contract.
/// @param destination The address that will be called
/// @param payload The payload, which—in the case of Solidity
/// libraries—encodes a function call
function DelegateCallVoucher(
address destination,
bytes calldata payload
) external;
}
37 changes: 24 additions & 13 deletions contracts/dapp/Application.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {LibOutputValidityProof} from "../library/LibOutputValidityProof.sol";
import {OutputValidityProof} from "../common/OutputValidityProof.sol";
import {Outputs} from "../common/Outputs.sol";
import {InputRange} from "../common/InputRange.sol";
import {LibError} from "../library/LibError.sol";
import {LibInputRange} from "../library/LibInputRange.sol";
import {LibAddress} from "../library/LibAddress.sol";

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
Expand All @@ -30,7 +30,7 @@ contract Application is
ReentrancyGuard
{
using BitMaps for BitMaps.BitMap;
using LibError for bytes;
using LibAddress for address;
using LibOutputValidityProof for OutputValidityProof;
using LibInputRange for InputRange;

Expand Down Expand Up @@ -103,6 +103,11 @@ contract Application is
revert OutputNotReexecutable(output);
}
_executeVoucher(arguments);
} else if (selector == Outputs.DelegateCallVoucher.selector) {
if (bitmap.get(inputIndex)) {
revert OutputNotReexecutable(output);
}
_executeDelegateCallVoucher(arguments);
} else {
revert OutputNotExecutable(output);
}
Expand Down Expand Up @@ -135,18 +140,20 @@ contract Application is
revert InputIndexOutOfRange(inputIndex, proof.inputRange);
}

bytes32 epochHash = _getEpochHash(proof.inputRange);
bytes32 outputHash = keccak256(output);

if (!proof.isEpochHashValid(epochHash)) {
revert IncorrectEpochHash();
if (!proof.isOutputHashesRootHashValid(outputHash)) {
revert IncorrectOutputHashesRootHash();
}

if (!proof.isOutputsEpochRootHashValid()) {
revert IncorrectOutputsEpochRootHash();
}

if (!proof.isOutputHashesRootHashValid(output)) {
revert IncorrectOutputHashesRootHash();
bytes32 epochHash = _getEpochHash(proof.inputRange);

if (!proof.isEpochHashValid(epochHash)) {
revert IncorrectEpochHash();
}
}

Expand Down Expand Up @@ -196,13 +203,17 @@ contract Application is
(address, uint256, bytes)
);

bool success;
bytes memory returndata;
destination.safeCall(value, payload);
}

(success, returndata) = destination.call{value: value}(payload);
/// @notice Executes a delegatecall voucher
/// @param arguments ABI-encoded arguments
function _executeDelegateCallVoucher(bytes calldata arguments) internal {
address destination;
bytes memory payload;

if (!success) {
returndata.raise();
}
(destination, payload) = abi.decode(arguments, (address, bytes));

destination.safeDelegateCall(payload);
}
}
62 changes: 62 additions & 0 deletions contracts/dapp/ISelfHostedApplicationFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.8;

import {Authority} from "../consensus/authority/Authority.sol";
import {IAuthorityFactory} from "../consensus/authority/IAuthorityFactory.sol";
import {Application} from "./Application.sol";
import {IApplicationFactory} from "./IApplicationFactory.sol";
import {IInputBox} from "../inputs/IInputBox.sol";
import {IPortal} from "../portals/IPortal.sol";

/// @title Self-hosted Application Factory interface
interface ISelfHostedApplicationFactory {
/// @notice Get the factory used to deploy `Authority` contracts
/// @return The authority factory
function getAuthorityFactory() external view returns (IAuthorityFactory);

/// @notice Get the factory used to deploy `Application` contracts
/// @return The application factory
function getApplicationFactory()
external
view
returns (IApplicationFactory);

/// @notice Deploy new application and authority contracts deterministically.
/// @param authorityOwner The initial authority owner
/// @param inputBox The input box contract
/// @param portals The portals supported by the application
/// @param appOwner The initial Application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the addresses
/// @return The application contract
/// @return The authority contract
function deployContracts(
address authorityOwner,
IInputBox inputBox,
IPortal[] calldata portals,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external returns (Application, Authority);

/// @notice Calculate the addresses of the application and authority contracts
/// to be deployed deterministically.
/// @param authorityOwner The initial authority owner
/// @param inputBox The input box contract
/// @param portals The portals supported by the application
/// @param appOwner The initial Application owner
/// @param templateHash The initial machine state hash
/// @param salt The salt used to deterministically generate the addresses
/// @return The application address
/// @return The authority address
function calculateAddresses(
address authorityOwner,
IInputBox inputBox,
IPortal[] calldata portals,
address appOwner,
bytes32 templateHash,
bytes32 salt
) external view returns (address, address);
}

0 comments on commit a937382

Please sign in to comment.