Commit 2bc4731d authored by Maurelian's avatar Maurelian Committed by GitHub

ctb: Introduce Process library with run() method (#10677)

* ctb: Introduce Process library with run() method

* ctb: Replace vm.ffi with Process.run
parent be68885e
......@@ -12,6 +12,7 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { LibString } from "@solady/utils/LibString.sol";
import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol";
import { IAddressManager } from "scripts/interfaces/IAddressManager.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @notice Represents a deployment. Is serialized to JSON as a key/value
/// pair. Can be accessed from within scripts.
......@@ -71,7 +72,7 @@ abstract contract Artifacts {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("jq -cr < ", _path);
string memory json = string(vm.ffi(commands));
string memory json = string(Process.run(commands));
string[] memory keys = vm.parseJsonKeys(json, "");
for (uint256 i; i < keys.length; i++) {
string memory key = keys[i];
......@@ -198,7 +199,7 @@ abstract contract Artifacts {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " 'keys' <<< '", json, "'");
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
string[] memory names = stdJson.readStringArray(string(res), "");
Deployment[] memory deployments = new Deployment[](names.length);
......
......@@ -56,6 +56,7 @@ import { Types } from "scripts/Types.sol";
import { LibStateDiff } from "scripts/libraries/LibStateDiff.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @title Deploy
/// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function.
......@@ -1342,11 +1343,11 @@ contract Deploy is Deployer {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\"");
if (vm.ffi(commands).length == 0) {
if (Process.run(commands).length == 0) {
revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root.");
}
commands[2] = string.concat("cat ", filePath, " | jq -r .pre");
mipsAbsolutePrestate_ = Claim.wrap(abi.decode(vm.ffi(commands), (bytes32)));
mipsAbsolutePrestate_ = Claim.wrap(abi.decode(Process.run(commands), (bytes32)));
console.log(
"[Cannon Dispute Game] Using devnet MIPS Absolute prestate: %s",
vm.toString(Claim.unwrap(mipsAbsolutePrestate_))
......
......@@ -5,6 +5,7 @@ import { Script } from "forge-std/Script.sol";
import { console2 as console } from "forge-std/console2.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { Executables } from "scripts/Executables.sol";
import { Process } from "scripts/libraries/Process.sol";
import { Chains } from "scripts/Chains.sol";
/// @title DeployConfig
......@@ -182,7 +183,7 @@ contract DeployConfig is Script {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat("cast block ", vm.toString(tag), " --json | ", Executables.jq, " .timestamp");
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
return stdJson.readUint(string(res), "");
}
return uint256(_l2OutputOracleStartingTimestamp);
......@@ -219,7 +220,7 @@ contract DeployConfig is Script {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat("cast block ", _tag, " --json | ", Executables.jq, " -r .hash");
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
return abi.decode(res, (bytes32));
}
......
......@@ -2,6 +2,7 @@
pragma solidity ^0.8.0;
import { Vm } from "forge-std/Vm.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @notice The executables used in ffi commands. These are set here
/// to have a single source of truth in case absolute paths
......@@ -24,6 +25,6 @@ library Executables {
commands[0] = bash;
commands[1] = "-c";
commands[2] = "cast abi-encode 'f(string)' $(git rev-parse HEAD)";
return abi.decode(vm.ffi(commands), (string));
return abi.decode(Process.run(commands), (string));
}
}
......@@ -8,6 +8,7 @@ import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { Process } from "scripts/libraries/Process.sol";
import "src/dispute/lib/Types.sol";
import "src/dispute/lib/Errors.sol";
......@@ -79,6 +80,6 @@ contract FaultDisputeGameViz is Script, FaultDisputeGame_Init {
commands[0] = "python3";
commands[1] = "scripts/dag-viz.py";
commands[2] = vm.toString(abi.encode(gameData));
vm.ffi(commands);
Process.run(commands);
}
}
......@@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
import { Vm } from "forge-std/Vm.sol";
import { Executables } from "scripts/Executables.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @notice Contains information about a storage slot. Mirrors the layout of the storage
/// slot object in Forge artifacts so that we can deserialize JSON into this struct.
......@@ -41,7 +42,7 @@ library ForgeArtifacts {
cmd[2] = string.concat(
Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'"
);
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
out_ = string(res);
}
......@@ -58,7 +59,7 @@ library ForgeArtifacts {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.storageLayout' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
layout_ = string(res);
}
......@@ -68,7 +69,7 @@ library ForgeArtifacts {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " -r '.abi' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
abi_ = string(res);
}
......@@ -78,7 +79,7 @@ library ForgeArtifacts {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.jq, " '.methodIdentifiers | keys' < ", _getForgeArtifactPath(_name));
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
ids_ = stdJson.readStringArray(string(res), "");
}
......@@ -87,7 +88,7 @@ library ForgeArtifacts {
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.forge, " config --json | ", Executables.jq, " -r .out");
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
string memory contractName = _stripSemver(_name);
dir_ = string.concat(vm.projectRoot(), "/", string(res), "/", contractName, ".sol");
}
......@@ -112,7 +113,7 @@ library ForgeArtifacts {
Executables.jq,
" -R -s -c 'split(\"\n\") | map(select(length > 0))'"
);
bytes memory res = vm.ffi(cmd);
bytes memory res = Process.run(cmd);
string[] memory files = stdJson.readStringArray(string(res), "");
out_ = string.concat(directory, "/", files[0]);
}
......@@ -139,7 +140,7 @@ library ForgeArtifacts {
Executables.jq,
" '.storage[] | select(.label == \"_initialized\" and .type == \"t_uint8\")'"
);
bytes memory rawSlot = vm.parseJson(string(vm.ffi(command)));
bytes memory rawSlot = vm.parseJson(string(Process.run(command)));
slot_ = abi.decode(rawSlot, (StorageSlot));
}
......@@ -184,7 +185,7 @@ library ForgeArtifacts {
Executables.jq,
" -R -s 'split(\"\n\")[:-1]'"
);
string[] memory contractNames = abi.decode(vm.parseJson(string(vm.ffi(command))), (string[]));
string[] memory contractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[]));
abis_ = new Abi[](contractNames.length);
......
......@@ -25,6 +25,7 @@ import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import { Process } from "scripts/libraries/Process.sol";
interface IInitializable {
function initialize(address _addr) external;
......@@ -557,7 +558,7 @@ contract L2Genesis is Deployer {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path);
vm.ffi(commands);
Process.run(commands);
}
/// @notice Funds the default dev accounts with ether
......
......@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
import { Script } from "forge-std/Script.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { console2 as console } from "forge-std/console2.sol";
import { Process } from "scripts/libraries/Process.sol";
contract SemverLock is Script {
function run() public {
......@@ -12,7 +13,7 @@ contract SemverLock is Script {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = "grep -rl '@custom:semver' src | jq -Rs 'split(\"\\n\") | map(select(length > 0))'";
string memory rawFiles = string(vm.ffi(commands));
string memory rawFiles = string(Process.run(commands));
string[] memory files = vm.parseJsonStringArray(rawFiles, "");
writeSemverLock(files);
......@@ -26,17 +27,17 @@ contract SemverLock is Script {
string[] memory commands = new string[](2);
commands[0] = "cat";
commands[1] = _files[i];
string memory fileContents = string(vm.ffi(commands));
string memory fileContents = string(Process.run(commands));
// Grab the contract name
commands = new string[](3);
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("echo \"", _files[i], "\"| sed -E \'s|src/.*/(.+)\\.sol|\\1|\'");
string memory contractName = string(vm.ffi(commands));
string memory contractName = string(Process.run(commands));
commands[2] = "forge config --json | jq -r .out";
string memory artifactsDir = string(vm.ffi(commands));
string memory artifactsDir = string(Process.run(commands));
// Handle the case where there are multiple artifacts for a contract. This happens
// when the same contract is compiled with multiple compiler versions.
......@@ -44,7 +45,7 @@ contract SemverLock is Script {
commands[2] = string.concat(
"ls -1 --color=never ", contractArtifactDir, " | jq -R -s -c 'split(\"\n\") | map(select(length > 0))'"
);
string memory artifactFiles = string(vm.ffi(commands));
string memory artifactFiles = string(Process.run(commands));
string[] memory files = stdJson.readStringArray(artifactFiles, "");
require(files.length > 0, string.concat("No artifacts found for ", contractName));
......
......@@ -15,7 +15,7 @@ To build, run `pnpm build:go-ffi` from this directory or the `contract-bedrock`
### In a Forge Test
To use `go-ffi` in a forge test, simply invoke the binary via the `vm.ffi` cheatcode.
To use `go-ffi` in a forge test, simply invoke the binary using the solidity `Process` library's `run` method.
```solidity
function myFFITest() public {
......@@ -23,7 +23,7 @@ function myFFITest() public {
commands[0] = "./scripts/go-ffi/go-ffi";
commands[1] = "trie";
commands[2] = "valid";
bytes memory result = vm.ffi(commands);
bytes memory result = Process.run(commands);
// Do something with the result of the command
}
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Vm } from "forge-std/Vm.sol";
library Process {
/// @notice Error for when an ffi command fails.
error FfiFailed(string);
/// @notice Foundry cheatcode VM.
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
function run(string[] memory cmd) internal returns (bytes memory stdout_) {
Vm.FfiResult memory result = vm.tryFfi(cmd);
if (result.exitCode != 0) {
string memory command;
for (uint256 i = 0; i < cmd.length; i++) {
command = string.concat(command, cmd[i], " ");
}
revert FfiFailed(string.concat("Command: ", command, "\nError: ", string(result.stderr)));
}
stdout_ = result.stdout;
}
}
......@@ -5,6 +5,7 @@ import { Test } from "forge-std/Test.sol";
import { L2Genesis, OutputMode, L1Dependencies } from "scripts/L2Genesis.s.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @title L2GenesisTest
/// @notice Test suite for L2Genesis script.
......@@ -25,7 +26,7 @@ contract L2GenesisTest is Test {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = "mktemp";
bytes memory result = vm.ffi(commands);
bytes memory result = Process.run(commands);
return string(result);
}
......@@ -36,7 +37,7 @@ contract L2GenesisTest is Test {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("rm ", path);
vm.ffi(commands);
Process.run(commands);
}
/// @notice Returns the number of top level keys in a JSON object at a given
......@@ -46,7 +47,7 @@ contract L2GenesisTest is Test {
commands[0] = "bash";
commands[1] = "-c";
commands[2] = string.concat("jq 'keys | length' < ", path, " | xargs cast abi-encode 'f(uint256)'");
return abi.decode(vm.ffi(commands), (uint256));
return abi.decode(Process.run(commands), (uint256));
}
/// @notice Helper function to run a function with a temporary dump file.
......@@ -63,7 +64,7 @@ contract L2GenesisTest is Test {
commands[1] = "-c";
commands[2] =
string.concat("jq -r '.[\"", vm.toLowercase(vm.toString(_addr)), "\"].storage | length' < ", _path);
return vm.parseUint(string(vm.ffi(commands)));
return vm.parseUint(string(Process.run(commands)));
}
/// @notice Returns the number of accounts that contain particular code at a given path to a genesis file.
......@@ -79,7 +80,7 @@ contract L2GenesisTest is Test {
path,
" | xargs cast abi-encode 'f(uint256)'"
);
return abi.decode(vm.ffi(commands), (uint256));
return abi.decode(Process.run(commands), (uint256));
}
/// @notice Returns the number of accounts that have a particular slot set.
......@@ -94,7 +95,7 @@ contract L2GenesisTest is Test {
path,
" | xargs cast abi-encode 'f(uint256)'"
);
return abi.decode(vm.ffi(commands), (uint256));
return abi.decode(Process.run(commands), (uint256));
}
/// @notice Returns the number of accounts that have a particular slot set to a particular value.
......@@ -118,7 +119,7 @@ contract L2GenesisTest is Test {
path,
" | xargs cast abi-encode 'f(uint256)'"
);
return abi.decode(vm.ffi(commands), (uint256));
return abi.decode(Process.run(commands), (uint256));
}
/// @notice Tests the genesis predeploys setup using a temp file for the case where useInterop is false.
......
......@@ -7,6 +7,7 @@ import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
import { PreimageKeyLib } from "src/cannon/PreimageKeyLib.sol";
import { LibKeccak } from "@lib-keccak/LibKeccak.sol";
import { Bytes } from "src/libraries/Bytes.sol";
import { Process } from "scripts/libraries/Process.sol";
import "src/cannon/libraries/CannonErrors.sol";
import "src/cannon/libraries/CannonTypes.sol";
......@@ -1346,7 +1347,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test {
commands[2] = "gen_proof";
commands[3] = vm.toString(abi.encodePacked(leaves));
commands[4] = vm.toString(_leafIdx);
(root_, proof_) = abi.decode(vm.ffi(commands), (bytes32, bytes32[]));
(root_, proof_) = abi.decode(Process.run(commands), (bytes32, bytes32[]));
}
fallback() external payable { }
......
......@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
import { Types } from "src/libraries/Types.sol";
import { Vm } from "forge-std/Vm.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @title FFIInterface
/// @notice This contract is set into state using `etch` and therefore must not have constructor logic.
......@@ -27,7 +28,7 @@ contract FFIInterface {
cmds[7] = vm.toString(_tx.gasLimit);
cmds[8] = vm.toString(_tx.data);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
(
bytes32 stateRoot,
bytes32 storageRoot,
......@@ -61,7 +62,7 @@ contract FFIInterface {
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes32));
}
......@@ -87,7 +88,7 @@ contract FFIInterface {
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes32));
}
......@@ -109,7 +110,7 @@ contract FFIInterface {
cmds[5] = Strings.toHexString(uint256(_messagePasserStorageRoot));
cmds[6] = Strings.toHexString(uint256(_latestBlockhash));
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes32));
}
......@@ -138,7 +139,7 @@ contract FFIInterface {
cmds[9] = vm.toString(_gas);
cmds[10] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes32));
}
......@@ -157,7 +158,7 @@ contract FFIInterface {
cmds[10] = vm.toString(txn.l1BlockHash);
cmds[11] = vm.toString(txn.logIndex);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes));
}
......@@ -183,7 +184,7 @@ contract FFIInterface {
cmds[7] = vm.toString(_gasLimit);
cmds[8] = vm.toString(_data);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes));
}
......@@ -194,7 +195,7 @@ contract FFIInterface {
cmds[2] = "decodeVersionedNonce";
cmds[3] = vm.toString(nonce);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (uint256, uint256));
}
......@@ -207,7 +208,7 @@ contract FFIInterface {
cmds[1] = "trie";
cmds[2] = variant;
return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));
return abi.decode(Process.run(cmds), (bytes32, bytes, bytes, bytes[]));
}
function getCannonMemoryProof(uint32 pc, uint32 insn) external returns (bytes32, bytes memory) {
......@@ -217,7 +218,7 @@ contract FFIInterface {
cmds[2] = "cannonMemoryProof";
cmds[3] = vm.toString(pc);
cmds[4] = vm.toString(insn);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
(bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes));
return (memRoot, proof);
}
......@@ -239,7 +240,7 @@ contract FFIInterface {
cmds[4] = vm.toString(insn);
cmds[5] = vm.toString(memAddr);
cmds[6] = vm.toString(memVal);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
(bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes));
return (memRoot, proof);
}
......@@ -251,7 +252,7 @@ contract FFIInterface {
cmds[2] = "encodeScalarEcotone";
cmds[3] = vm.toString(_basefeeScalar);
cmds[4] = vm.toString(_blobbasefeeScalar);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes32));
}
......@@ -261,7 +262,7 @@ contract FFIInterface {
cmds[1] = "diff";
cmds[2] = "decodeScalarEcotone";
cmds[3] = vm.toString(_scalar);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (uint32, uint32));
}
......@@ -283,7 +284,7 @@ contract FFIInterface {
cmds[5] = vm.toString(_name);
cmds[6] = vm.toString(_symbol);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes));
}
......@@ -294,7 +295,7 @@ contract FFIInterface {
cmds[2] = "encodeDependency";
cmds[3] = vm.toString(_chainId);
bytes memory result = vm.ffi(cmds);
bytes memory result = Process.run(cmds);
return abi.decode(result, (bytes));
}
}
......@@ -46,8 +46,6 @@ import { WETH } from "src/L2/WETH.sol";
/// up behind proxies. In the future we will migrate to importing the genesis JSON
/// file that is created to set up the L2 contracts instead of setting them up manually.
contract Setup {
error FfiFailed(string);
/// @notice The address of the foundry Vm contract.
Vm private constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
......
......@@ -10,6 +10,7 @@ import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { ResourceMetering } from "src/L1/ResourceMetering.sol";
import { OptimismPortal } from "src/L1/OptimismPortal.sol";
import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol";
import { Process } from "scripts/libraries/Process.sol";
import "src/L1/ProtocolVersions.sol";
import "src/dispute/lib/Types.sol";
import "scripts/Deployer.sol";
......@@ -388,7 +389,7 @@ contract Initializer_Test is Bridge_Initializer {
Executables.jq,
" -R -s 'split(\"\n\")[:-1]'"
);
string[] memory l1ContractNames = abi.decode(vm.parseJson(string(vm.ffi(command))), (string[]));
string[] memory l1ContractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[]));
for (uint256 i; i < l1ContractNames.length; i++) {
string memory contractName = l1ContractNames[i];
......@@ -404,7 +405,7 @@ contract Initializer_Test is Bridge_Initializer {
Executables.jq,
" '.[] | select(.name == \"initialize\" and .type == \"function\")'"
);
bytes memory res = vm.ffi(command);
bytes memory res = Process.run(command);
// If the contract has an `initialize()` function, the resulting query will be non-empty.
// In this case, increment the number of `Initializable` contracts.
......@@ -425,7 +426,7 @@ contract Initializer_Test is Bridge_Initializer {
Executables.jq,
" -R -s 'split(\"\n\")[:-1]'"
);
string[] memory l2ContractNames = abi.decode(vm.parseJson(string(vm.ffi(command))), (string[]));
string[] memory l2ContractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[]));
for (uint256 i; i < l2ContractNames.length; i++) {
string memory contractName = l2ContractNames[i];
......@@ -441,7 +442,7 @@ contract Initializer_Test is Bridge_Initializer {
Executables.jq,
" '.[] | select(.name == \"initialize\" and .type == \"function\")'"
);
bytes memory res = vm.ffi(command);
bytes memory res = Process.run(command);
// If the contract has an `initialize()` function, the resulting query will be non-empty.
// In this case, increment the number of `Initializable` contracts.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment