Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/deep-sites-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cartesi/devnet": patch
---

Add a deployment script for UsdWithdrawalOutputBuilder to support emergency withdrawal tests. Remove solidity code and deployment script for test-tokens, instead it will package only the ones provided by rollups-contracts artifacts (devnet only).
65 changes: 60 additions & 5 deletions packages/devnet/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { semver } from "bun";
import { existsSync, readdirSync } from "fs-extra";
import { cpSync, existsSync, readdirSync } from "fs-extra";
import { Listr, type ListrTask } from "listr2";
import * as path from "node:path";
import {
Expand Down Expand Up @@ -135,15 +135,18 @@ const perChainDeploymentTasks: ListrTask[] = Object.entries(
* @param options - The options for deploying contracts
* @param options.privateKey - The private key to use for the deployment
* @param options.rpcUrl - The RPC URL to use for the deployment
* @returns
* @returns <number> - the exit code of the deployment script, 0 if successful
* @throws {Error} - if the deployment script exits with a non-zero code, the error message will contain the stderr output of the script
*/
const deploy = async (options: { privateKey: string; rpcUrl: string }) => {
// execute forge script
const runDeploymentScript = async (
scriptName: string,
options: { privateKey: string; rpcUrl: string },
) => {
const proc = Bun.spawn(
[
"forge",
"script",
"Deploy",
scriptName,
"--broadcast",
"--non-interactive",
"--private-key",
Expand All @@ -155,14 +158,66 @@ const deploy = async (options: { privateKey: string; rpcUrl: string }) => {
{ stdio: ["ignore", "pipe", "pipe"] },
);
const exitCode = await proc.exited;

if (exitCode !== 0) {
throw new Error(`Forge script exited with code ${exitCode}`, {
cause: await new Response(proc.stderr).text(),
});
}

return exitCode;
};

const deploy = async (options: { privateKey: string; rpcUrl: string }) => {
const contractName = "UsdWithdrawalOutputBuilder";

// Deploys an UsdWithdrawalOutputBuilder but saves the deployment information as TestUsdWithdrawalOutputBuilder.
const exitCode = await runDeploymentScript(
`DeployTest${contractName}`,
options,
);

if (exitCode === 0) {
// To continue the build process, we make sure there is a copy of the expected <contract-name>.sol folder + JSON content with added prefix
// in the name (i.e. Test<contract-name>[.sol, .json]) in the out folder. Therefore, the rest of the process can find the expected information
// and copy it to the right place.
const targetPath = path.join(
"out",
`${contractName}.sol`,
`${contractName}.json`,
);
const destinationPath = path.join(
"out",
`Test${contractName}.sol`,
`Test${contractName}.json`,
);
createCopy(targetPath, destinationPath);
}

return exitCode;
};

/**
* Copy file or directory from source to destination, if source is a directory it will be copied recursively,
* if destination already exist it will be overwritten.
* @param source - path to file or directory to be copied
* @param destination - path to destination where file or directory should be copied
* @returns true if copy was successful, otherwise throws an error
* @throws {Error} if copy operation fails, the error message will contain the original error message
*/
const createCopy = (source: string, destination: string) => {
try {
cpSync(source, destination, { recursive: true, force: true });
console.info(`Source copied from ${source} to ${destination}`);
} catch (error) {
throw new Error(`Failed to copy from ${source} to ${destination}`, {
cause: (error as Error).message,
});
}

return true;
};

const build = async () => {
type Ctx = {
anvilProc?: Bun.Subprocess;
Expand Down
3 changes: 2 additions & 1 deletion packages/devnet/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ optimizer = true
fs_permissions = [{ access = "read-write", path = "build" }]

[dependencies]
"@openzeppelin-contracts" = "5.5.0"
"@openzeppelin-contracts" = "5.2.0"
forge-std = "1.9.6"
cartesi-rollups-contracts = "3.0.0-alpha.6"
2 changes: 1 addition & 1 deletion packages/devnet/script/BaseDeploymentScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pragma solidity ^0.8.8;

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

import {Script} from "forge-std-1.9.6/src/Script.sol";

Expand Down
35 changes: 0 additions & 35 deletions packages/devnet/script/Deploy.s.sol

This file was deleted.

40 changes: 40 additions & 0 deletions packages/devnet/script/DeployTestUsdWithdrawalOutputBuilder.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8;

import {BaseDeploymentScript} from "./BaseDeploymentScript.sol";
import {IERC20} from "@openzeppelin-contracts-5.2.0/token/ERC20/IERC20.sol";
import {IUsdWithdrawalOutputBuilderFactory} from "cartesi-rollups-contracts-3.0.0-alpha.6/src/withdrawal/IUsdWithdrawalOutputBuilderFactory.sol";

contract DeployTestUsdWithdrawalOutputBuilder is BaseDeploymentScript {
bytes32 private constant SALT = bytes32(uint256(0));

function run() public {
address factoryAddress = _loadDeployment(
".",
"UsdWithdrawalOutputBuilderFactory"
);
IERC20 token = IERC20(_loadDeployment(".", "TestFungibleToken"));

IUsdWithdrawalOutputBuilderFactory factory =
IUsdWithdrawalOutputBuilderFactory(factoryAddress);

vm.startBroadcast();

address builder = factory.calculateUsdWithdrawalOutputBuilderAddress(
token,
SALT
);

// Keep this script idempotent when running against a state dump that
// may already contain this token+salt deployment.
if (builder.code.length == 0) {
address deployed = address(factory.newUsdWithdrawalOutputBuilder(token, SALT));
vm.assertEq(deployed, builder);
builder = deployed;
}

_storeDeployment("TestUsdWithdrawalOutputBuilder", builder);

vm.stopBroadcast();
}
}
15 changes: 11 additions & 4 deletions packages/devnet/soldeer.lock
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
[[dependencies]]
name = "@openzeppelin-contracts"
version = "5.5.0"
url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_5_0_01-11-2025_09:56:40_contracts.zip"
checksum = "2ee78837130cf06b456d9ef7ab70753685d9c1c9c2c5b70f24bd4c16695d0337"
integrity = "da8336cf949f0e0667ae8360af849681e3a3e76d7e61e7a86b1a3414a158aeea"
version = "5.2.0"
url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_2_0_11-01-2025_09:30:20_contracts.zip"
checksum = "6dbd0440446b2ed16ca25e9f1af08fc0c5c1e73e71fee86ae8a00daa774e3817"
integrity = "4cb7f3777f67fdf4b7d0e2f94d2f93f198b2e5dce718b7062ac7c2c83e1183bd"

[[dependencies]]
name = "cartesi-rollups-contracts"
version = "3.0.0-alpha.6"
url = "https://soldeer-revisions.s3.amazonaws.com/cartesi-rollups-contracts/3_0_0-alpha_6_21-05-2026_12:17:44_rollups-contracts.zip"
checksum = "cdfd86f90895ba37e188103e8fb62d6ca8e45a53846ebc63cb7b7af66f18d034"
integrity = "664e731ff29c1f9c27d32391cbe45529ab812a71eed188cb235a1f37f84ee012"

[[dependencies]]
name = "forge-std"
Expand Down
32 changes: 0 additions & 32 deletions packages/devnet/src/TestMultiToken.sol

This file was deleted.

38 changes: 0 additions & 38 deletions packages/devnet/src/TestNFT.sol

This file was deleted.

53 changes: 0 additions & 53 deletions packages/devnet/src/TestToken.sol

This file was deleted.

Loading