Skip to content
68 changes: 68 additions & 0 deletions crates/forge/tests/cli/revive_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,71 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests)

"#]]);
});

forgetest!(vm_load, |prj, cmd| {
prj.insert_ds_test();
prj.insert_vm();
prj.insert_console();
prj.add_source(
"Counter.sol",
r#"
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {
uint256 public number;

constructor (uint256 number_) {
number = number_;
}
}
"#,
)
.unwrap();
prj.add_source(
"Load.t.sol",
r#"
import "./test.sol";
import "./Vm.sol";
import {console} from "./console.sol";
import {Counter} from "./Counter.sol";

contract Load is DSTest {
Vm constant vm = Vm(HEVM_ADDRESS);

function testFuzz_Load(uint256 x) public {
vm.pvm(true);
Counter counter = new Counter(x);
bytes32 res = vm.load(address(counter), bytes32(uint256(0)));
assertEq(uint256(res), x);
}
}
"#,
)
.unwrap();

let res = cmd.args(["test", "--resolc", "-vvv"]).assert_success();
res.stderr_eq(str![""]).stdout_eq(str![[r#"
[COMPILING_FILES] with [SOLC_VERSION]
[SOLC_VERSION] [ELAPSED]
Compiler run successful!
[COMPILING_FILES] with [RESOLC_VERSION]
[RESOLC_VERSION] [ELAPSED]
Compiler run successful with warnings:
Warning: Warning: Your code or one of its dependencies uses the 'extcodesize' instruction, which is
usually needed in the following cases:
1. To detect whether an address belongs to a smart contract.
2. To detect whether the deploy code execution has finished.
Polkadot comes with native account abstraction support (so smart contracts are just accounts
coverned by code), and you should avoid differentiating between contracts and non-contract
addresses.
[FILE]

Ran 1 test for src/Load.t.sol:Load
[PASS] testFuzz_Load(uint256) (runs: 256, [AVG_GAS])
Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED]

Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests)

"#]]);
});
20 changes: 19 additions & 1 deletion crates/revive-strategy/src/cheatcodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use foundry_cheatcodes::{
Broadcast, BroadcastableTransactions, CheatcodeInspectorStrategy,
CheatcodeInspectorStrategyContext, CheatcodeInspectorStrategyRunner, CheatsConfig, CheatsCtxt,
CommonCreateInput, DealRecord, Ecx, EvmCheatcodeInspectorStrategyRunner, Result,
Vm::{dealCall, getNonce_0Call, pvmCall, rollCall, setNonceCall, setNonceUnsafeCall, warpCall},
Vm::{
dealCall, getNonce_0Call, loadCall, pvmCall, rollCall, setNonceCall, setNonceUnsafeCall,
warpCall,
},
};
use foundry_common::sh_err;
use foundry_compilers::resolc::dual_compiled_contracts::DualCompiledContracts;
Expand Down Expand Up @@ -246,6 +249,21 @@ impl CheatcodeInspectorStrategyRunner for PvmCheatcodeInspectorStrategyRunner {

Ok(Default::default())
}
t if using_pvm && is::<loadCall>(t) => {
let &loadCall { target, slot } = cheatcode.as_any().downcast_ref().unwrap();
let target_address_h160 = H160::from_slice(target.as_slice());
let storage_value = execute_with_externalities(|externalities| {
externalities.execute_with(|| {
Pallet::<Runtime>::get_storage(target_address_h160, slot.into())
})
});
let result = storage_value
.ok()
.flatten()
.map(|b| B256::from_slice(&b))
.unwrap_or(B256::ZERO);
Ok(result.abi_encode())
}
// Not custom, just invoke the default behavior
_ => cheatcode.dyn_apply(ccx, executor),
}
Expand Down
Loading