Skip to content

Commit 90d4dce

Browse files
authored
fix: trace decoding off-by-one (#6277)
1 parent 4c11a23 commit 90d4dce

File tree

8 files changed

+76
-43
lines changed

8 files changed

+76
-43
lines changed

.github/workflows/test.yml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,28 @@ jobs:
4949
with:
5050
target: ${{ matrix.target }}
5151
- uses: taiki-e/install-action@nextest
52-
# - uses: taiki-e/setup-cross-toolchain-action@v1
53-
# with:
54-
# target: ${{ matrix.target }}
52+
53+
# External tests dependencies
54+
- name: Setup Python
55+
if: contains(matrix.name, 'external')
56+
uses: actions/setup-python@v4
57+
with:
58+
python-version: 3.11
59+
- name: Setup Node.js
60+
if: contains(matrix.name, 'external')
61+
uses: actions/setup-node@v4
62+
with:
63+
node-version: 20
64+
- name: Install pnpm
65+
if: contains(matrix.name, 'external')
66+
uses: pnpm/action-setup@v2
67+
with:
68+
version: latest
69+
run_install: false
70+
- name: Install Vyper
71+
if: contains(matrix.name, 'external')
72+
run: pip install vyper
73+
5574
- name: Forge RPC cache
5675
uses: actions/cache@v3
5776
with:
@@ -61,7 +80,6 @@ jobs:
6180
key: rpc-cache-${{ hashFiles('crates/forge/tests/rpc-cache-keyfile') }}
6281
- uses: Swatinem/rust-cache@v2
6382
with:
64-
# key: ${{ matrix.target }}
6583
cache-on-failure: true
6684
- name: Setup Git config
6785
run: |

crates/anvil/tests/it/otterscan.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,12 @@ async fn can_call_ots_has_code() {
232232
.await
233233
.unwrap());
234234

235-
client.send_transaction(deploy_tx, None).await.unwrap();
235+
let pending = client.send_transaction(deploy_tx, None).await.unwrap();
236+
let receipt = pending.await.unwrap().unwrap();
236237

237238
let num = client.get_block_number().await.unwrap();
239+
assert_eq!(num, receipt.block_number.unwrap());
240+
238241
// code is detected after deploying
239242
assert!(api.ots_has_code(pending_contract_address, BlockNumber::Number(num)).await.unwrap());
240243

crates/evm/traces/src/decoder/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ impl CallTraceDecoder {
431431
let &[t0, ..] = raw_log.topics() else { return };
432432

433433
let mut events = Vec::new();
434-
let events = match self.events.get(&(t0, raw_log.topics().len())) {
434+
let events = match self.events.get(&(t0, raw_log.topics().len() - 1)) {
435435
Some(es) => es,
436436
None => {
437437
if let Some(identifier) = &self.signature_identifier {

crates/evm/traces/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,7 @@ impl fmt::Display for CallTraceArena {
207207
let node = &arena.arena[idx];
208208

209209
// Display trace header
210-
f.write_str(left)?;
211-
node.trace.fmt(f)?;
210+
writeln!(f, "{left}{}", node.trace)?;
212211

213212
// Display logs and subcalls
214213
let left_prefix = format!("{child}{BRANCH}");

crates/forge/tests/cli/ext_integration.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ forgetest_external!(
1111
forgetest_external!(stringutils, "Arachnid/solidity-stringutils");
1212
forgetest_external!(lootloose, "gakonst/lootloose");
1313
forgetest_external!(lil_web3, "m1guelpf/lil-web3");
14+
forgetest_external!(snekmate, "pcaversaccio/snekmate");
1415

1516
// Forking tests
1617

crates/test-utils/src/macros.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -147,31 +147,18 @@ macro_rules! forgetest_external {
147147
prj.wipe();
148148

149149
// Clone the external repository
150-
let git_clone =
151-
$crate::util::clone_remote(&format!("https://github.com/{}", $repo), prj.root())
152-
.expect("Could not clone repository. Is git installed?");
153-
assert!(
154-
git_clone.status.success(),
155-
"could not clone repository:\nstdout:\n{}\nstderr:\n{}",
156-
String::from_utf8_lossy(&git_clone.stdout),
157-
String::from_utf8_lossy(&git_clone.stderr)
158-
);
150+
$crate::util::clone_remote(concat!("https://github.com/", $repo), prj.root().to_str().unwrap());
159151

160-
// We just run make install, but we do not care if it worked or not,
161-
// since some repositories do not have that target
162-
let make_install = Command::new("make")
163-
.arg("install")
164-
.current_dir(prj.root())
165-
.stdout(Stdio::null())
166-
.stderr(Stdio::null())
167-
.status();
152+
// Run common installation commands
153+
$crate::util::run_install_commands(prj.root());
168154

169155
// Run the tests
170156
cmd.arg("test").args($forge_opts).args([
171157
"--optimize",
172-
"--optimizer-runs",
173-
"20000",
158+
"--optimizer-runs=20000",
159+
"--fuzz-runs=256",
174160
"--ffi",
161+
"-vvvvv",
175162
]);
176163
cmd.set_env("FOUNDRY_FUZZ_RUNS", "1");
177164

crates/test-utils/src/util.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,44 @@ pub fn initialize(target: impl AsRef<Path>) {
7676
}
7777
}
7878

79-
/// Clones a remote repository into the specified directory.
80-
pub fn clone_remote(
81-
repo_url: &str,
82-
target_dir: impl AsRef<Path>,
83-
) -> std::io::Result<process::Output> {
84-
Command::new("git")
85-
.args([
86-
"clone",
87-
"--depth",
88-
"1",
89-
"--recursive",
90-
repo_url,
91-
target_dir.as_ref().to_str().expect("Target path for git clone does not exist"),
92-
])
93-
.output()
79+
/// Clones a remote repository into the specified directory. Panics if the command fails.
80+
pub fn clone_remote(repo_url: &str, target_dir: &str) {
81+
let mut cmd = Command::new("git");
82+
let status = cmd
83+
.args(["clone", "--depth=1", "--recursive", "--shallow-submodules", repo_url, target_dir])
84+
.status()
85+
.unwrap();
86+
if !status.success() {
87+
panic!("{cmd:?}");
88+
}
89+
eprintln!();
90+
}
91+
92+
/// Runs common installation commands, such as `make` and `npm`. Continues if any command fails.
93+
pub fn run_install_commands(root: &Path) {
94+
let root_files =
95+
std::fs::read_dir(root).unwrap().flatten().map(|x| x.path()).collect::<Vec<_>>();
96+
let contains = |path: &str| root_files.iter().any(|p| p.to_str().unwrap().contains(path));
97+
let run = |args: &[&str]| {
98+
let mut cmd = Command::new(args[0]);
99+
cmd.args(&args[1..]).current_dir(root).stdout(Stdio::null()).stderr(Stdio::null());
100+
let st = cmd.status();
101+
eprintln!("\n\n{cmd:?} -> {st:?}");
102+
};
103+
let maybe_run = |path: &str, args: &[&str]| {
104+
let c = contains(path);
105+
if c {
106+
run(args);
107+
}
108+
c
109+
};
110+
111+
maybe_run("Makefile", &["make", "install"]);
112+
let pnpm = maybe_run("pnpm-lock.yaml", &["pnpm", "install", "--prefer-offline"]);
113+
let yarn = maybe_run("yarn.lock", &["yarn", "install", "--prefer-offline"]);
114+
if !pnpm && !yarn && contains("package.json") {
115+
run(&["npm", "install"]);
116+
}
94117
}
95118

96119
/// Setup an empty test project and return a command pointing to the forge

testdata/cheats/UnixTime.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import "./Vm.sol";
66

77
contract UnixTimeTest is DSTest {
88
Vm constant vm = Vm(HEVM_ADDRESS);
9-
uint256 errMargin = 100; // allow errors of up to errMargin milliseconds
9+
10+
// This is really wide because CI sucks.
11+
uint256 constant errMargin = 300;
1012

1113
function testUnixTimeAgainstDate() public {
1214
string[] memory inputs = new string[](2);

0 commit comments

Comments
 (0)