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
4 changes: 4 additions & 0 deletions .github/scripts/matrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __init__(
self.partition = partition


profile = os.environ.get("PROFILE")
is_pr = os.environ.get("EVENT_NAME") == "pull_request"
t_linux_x86 = Target("ubuntu-latest", "x86_64-unknown-linux-gnu", "linux-amd64")
# TODO: Figure out how to make this work
Expand Down Expand Up @@ -119,6 +120,9 @@ def main():
s = f"{partition}/{case.n_partitions}"
name += f" ({s})"
flags += f" --partition count:{s}"

if profile == "isolate":
flags += " --features=isolate-by-default"
name += os_str

obj = Expanded(
Expand Down
96 changes: 96 additions & 0 deletions .github/workflows/nextest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Reusable workflow for running tests via `cargo nextest`

name: nextest

on:
workflow_call:
inputs:
profile:
required: true
type: string

concurrency:
group: tests-${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always

jobs:
matrices:
name: build matrices
runs-on: ubuntu-latest
outputs:
test-matrix: ${{ steps.gen.outputs.test-matrix }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Generate matrices
id: gen
env:
EVENT_NAME: ${{ github.event_name }}
PROFILE: ${{ inputs.profile }}
run: |
output=$(python3 .github/scripts/matrices.py)
echo "::debug::test-matrix=$output"
echo "test-matrix=$output" >> $GITHUB_OUTPUT

test:
name: test ${{ matrix.name }}
runs-on: ${{ matrix.runner_label }}
timeout-minutes: 60
needs: matrices
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrices.outputs.test-matrix) }}
env:
ETH_RPC_URL: https://eth-mainnet.alchemyapi.io/v2/C3JEvfW6VgtqZQa-Qp1E-2srEiIc02sD
CARGO_PROFILE_DEV_DEBUG: 0
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
target: ${{ matrix.target }}
- uses: taiki-e/install-action@nextest

# External tests dependencies
- name: Setup Node.js
if: contains(matrix.name, 'external')
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Bun
if: contains(matrix.name, 'external') && !contains(matrix.runner_label, 'windows')
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Setup Python
if: contains(matrix.name, 'external')
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install Vyper
if: contains(matrix.name, 'external')
run: pip install vyper

- name: Forge RPC cache
uses: actions/cache@v3
with:
path: |
~/.foundry/cache
~/.config/.foundry/cache
key: rpc-cache-${{ hashFiles('crates/forge/tests/rpc-cache-keyfile') }}
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: Setup Git config
run: |
git config --global user.name "GitHub Actions Bot"
git config --global user.email "<>"
git config --global url."https://github.com/".insteadOf "git@github.com:"
- name: Test
env:
SVM_TARGET_PLATFORM: ${{ matrix.svm_target_platform }}
run: cargo nextest run ${{ matrix.flags }}
14 changes: 14 additions & 0 deletions .github/workflows/test-isolate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Daily CI job to run tests with isolation mode enabled by default

name: test-isolate

on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:

jobs:
nextest:
uses: ./.github/workflows/nextest.yml
with:
profile: isolate
80 changes: 4 additions & 76 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,82 +14,10 @@ env:
CARGO_TERM_COLOR: always

jobs:
matrices:
name: build matrices
runs-on: ubuntu-latest
outputs:
test-matrix: ${{ steps.gen.outputs.test-matrix }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Generate matrices
id: gen
env:
EVENT_NAME: ${{ github.event_name }}
run: |
output=$(python3 .github/scripts/matrices.py)
echo "::debug::test-matrix=$output"
echo "test-matrix=$output" >> $GITHUB_OUTPUT

test:
name: test ${{ matrix.name }}
runs-on: ${{ matrix.runner_label }}
timeout-minutes: 60
needs: matrices
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrices.outputs.test-matrix) }}
env:
ETH_RPC_URL: https://eth-mainnet.alchemyapi.io/v2/C3JEvfW6VgtqZQa-Qp1E-2srEiIc02sD
CARGO_PROFILE_DEV_DEBUG: 0
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
target: ${{ matrix.target }}
- uses: taiki-e/install-action@nextest

# External tests dependencies
- name: Setup Node.js
if: contains(matrix.name, 'external')
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Bun
if: contains(matrix.name, 'external') && !contains(matrix.runner_label, 'windows')
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Setup Python
if: contains(matrix.name, 'external')
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install Vyper
if: contains(matrix.name, 'external')
run: pip install vyper

- name: Forge RPC cache
uses: actions/cache@v3
with:
path: |
~/.foundry/cache
~/.config/.foundry/cache
key: rpc-cache-${{ hashFiles('crates/forge/tests/rpc-cache-keyfile') }}
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: Setup Git config
run: |
git config --global user.name "GitHub Actions Bot"
git config --global user.email "<>"
git config --global url."https://github.com/".insteadOf "git@github.com:"
- name: Test
env:
SVM_TARGET_PLATFORM: ${{ matrix.svm_target_platform }}
run: cargo nextest run ${{ matrix.flags }}
nextest:
uses: ./.github/workflows/nextest.yml
with:
profile: default

docs:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions crates/cast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ openssl = ["foundry-cli/openssl"]
asm-keccak = ["alloy-primitives/asm-keccak"]
jemalloc = ["dep:tikv-jemallocator"]
aws-kms = ["foundry-wallets/aws-kms", "dep:aws-sdk-kms"]
isolate-by-default = ["foundry-config/isolate-by-default"]

[[bench]]
name = "vanity"
Expand Down
1 change: 1 addition & 0 deletions crates/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ tempfile.workspace = true
[features]
default = ["rustls"]
rustls = ["reqwest/rustls-tls-native-roots"]
isolate-by-default = []
3 changes: 3 additions & 0 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,10 @@ impl Default for Config {
profile: Self::DEFAULT_PROFILE,
fs_permissions: FsPermissions::new([PathPermission::read("out")]),
prague: false,
#[cfg(not(feature = "isolate-by-default"))]
isolate: false,
#[cfg(feature = "isolate-by-default")]
isolate: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be cfg!() macro

root: Default::default(),
src: "src".into(),
test: "test".into(),
Expand Down
10 changes: 5 additions & 5 deletions crates/evm/core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,6 @@ pub fn create2_handler_register<DB: revm::Database, I: InspectorExt<DB>>(
.borrow_mut()
.push((ctx.evm.journaled_state.depth(), call_inputs.clone()));

// Handle potential inspector override.
if let Some(outcome) = outcome {
return Ok(FrameOrResult::Result(FrameResult::Call(outcome)));
}

// Sanity check that CREATE2 deployer exists.
let code_hash = ctx.evm.load_account(DEFAULT_CREATE2_DEPLOYER)?.0.info.code_hash;
if code_hash == KECCAK_EMPTY {
Expand All @@ -174,6 +169,11 @@ pub fn create2_handler_register<DB: revm::Database, I: InspectorExt<DB>>(
})))
}

// Handle potential inspector override.
if let Some(outcome) = outcome {
return Ok(FrameOrResult::Result(FrameResult::Call(outcome)));
}

// Create CALL frame for CREATE2 factory invocation.
let mut frame_or_result = ctx.evm.make_call_frame(&call_inputs);

Expand Down
10 changes: 8 additions & 2 deletions crates/evm/evm/src/inspectors/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use revm::{
CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, Gas, InstructionResult,
Interpreter, InterpreterResult,
},
primitives::{BlockEnv, Env, EnvWithHandlerCfg, ExecutionResult, Output, TransactTo},
primitives::{
BlockEnv, CreateScheme, Env, EnvWithHandlerCfg, ExecutionResult, Output, TransactTo,
},
DatabaseCommit, EvmContext, Inspector,
};
use std::{collections::HashMap, sync::Arc};
Expand Down Expand Up @@ -749,7 +751,11 @@ impl<DB: DatabaseExt + DatabaseCommit> Inspector<&mut DB> for InspectorStack {
ecx
);

if self.enable_isolation && !self.in_inner_context && ecx.journaled_state.depth == 1 {
if !matches!(create.scheme, CreateScheme::Create2 { .. }) &&
self.enable_isolation &&
!self.in_inner_context &&
ecx.journaled_state.depth == 1
{
let (result, address) = self.transact_inner(
ecx,
TransactTo::Create,
Expand Down
1 change: 1 addition & 0 deletions crates/forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ openssl = ["foundry-cli/openssl", "reqwest/default-tls"]
asm-keccak = ["alloy-primitives/asm-keccak"]
jemalloc = ["dep:tikv-jemallocator"]
aws-kms = ["foundry-wallets/aws-kms"]
isolate-by-default = ["foundry-config/isolate-by-default"]

[[bench]]
name = "test"
Expand Down
33 changes: 23 additions & 10 deletions crates/forge/tests/cli/ext_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ fn forge_std() {

#[test]
fn solmate() {
ExtTester::new("transmissions11", "solmate", "c892309933b25c03d32b1b0d674df7ae292ba925").run();
let tester =
ExtTester::new("transmissions11", "solmate", "c892309933b25c03d32b1b0d674df7ae292ba925");

#[cfg(feature = "isolate-by-default")]
let tester = tester.args(["--nmc", "ReentrancyGuardTest"]);

tester.run();
}

#[test]
Expand All @@ -36,15 +42,22 @@ fn prb_proxy() {
#[test]
#[cfg_attr(windows, ignore = "Windows cannot find installed programs")]
fn sablier_v2() {
ExtTester::new("sablier-labs", "v2-core", "84758a40077bf3ccb1c8f7bb8d00278e672fbfef")
// Skip fork tests.
.args(["--nmc", "Fork"])
// Run tests without optimizations.
.env("FOUNDRY_PROFILE", "lite")
.install_command(&["bun", "install", "--prefer-offline"])
// Try npm if bun fails / is not installed.
.install_command(&["npm", "install", "--prefer-offline"])
.run();
let tester =
ExtTester::new("sablier-labs", "v2-core", "84758a40077bf3ccb1c8f7bb8d00278e672fbfef")
// Skip fork tests.
.args(["--nmc", "Fork"])
// Run tests without optimizations.
.env("FOUNDRY_PROFILE", "lite")
.install_command(&["bun", "install", "--prefer-offline"])
// Try npm if bun fails / is not installed.
.install_command(&["npm", "install", "--prefer-offline"]);

// This test reverts due to memory limit without isolation. This revert is not reached with
// isolation because memory is divided between separate EVMs created by inner calls.
#[cfg(feature = "isolate-by-default")]
let tester = tester.args(["--nmt", "test_RevertWhen_LoopCalculationOverflowsBlockGasLimit"]);

tester.run();
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions crates/forge/tests/cli/test_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ contract MyTest is DSTest {
});

// checks that forge test repeatedly produces the same output
#[cfg(not(feature = "isolate-by-default"))]
forgetest_init!(can_test_repeatedly, |_prj, cmd| {
cmd.arg("test");
cmd.assert_non_empty_stdout();
Expand Down Expand Up @@ -264,6 +265,7 @@ contract ContractTest is DSTest {
});

// tests that libraries are handled correctly in multiforking mode
#[cfg(not(feature = "isolate-by-default"))]
forgetest_init!(can_use_libs_in_multi_fork, |prj, cmd| {
prj.wipe_contracts();

Expand Down
4 changes: 4 additions & 0 deletions crates/forge/tests/it/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ async fn test_cheats_local(test_data: &ForgeTestData) {
filter = filter.exclude_tests("(Ffi|File|Line|Root)");
}

if cfg!(feature = "isolate-by-default") {
filter = filter.exclude_contracts("LastCallGasDefaultTest");
}

let mut config = test_data.config.clone();
config.fs_permissions = FsPermissions::new(vec![PathPermission::read_write("./")]);
let runner = test_data.runner_with_config(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ contract Malicious {
function world() public {
// add code so contract is accounted as valid sender
// see https://github.com/foundry-rs/foundry/issues/4245
payable(msg.sender).transfer(1);
payable(msg.sender).call("");
}
}

Expand Down