Skip to content

Commit

Permalink
feat(cheatcodes): restrict cheatcode usage on precompiles (#4905)
Browse files Browse the repository at this point in the history
* feat(cheatcodes): restrict cheatcodes on precompiles

* chore: exclude address(0) from precompiles check

* chore: fix test

* chore: add revert tests
  • Loading branch information
Evalir authored May 10, 2023
1 parent 7bba788 commit db96393
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 2 deletions.
8 changes: 7 additions & 1 deletion evm/src/executor/inspector/cheatcodes/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
abi::HEVMCalls,
executor::{
backend::DatabaseExt,
inspector::cheatcodes::{util::with_journaled_account, DealRecord},
inspector::cheatcodes::{
util::{is_potential_precompile, with_journaled_account},
DealRecord,
},
},
utils::{b160_to_h160, h160_to_b160, ru256_to_u256, u256_to_ru256},
};
Expand Down Expand Up @@ -232,6 +235,7 @@ pub fn apply<DB: DatabaseExt>(
Bytes::new()
}
HEVMCalls::Store(inner) => {
ensure!(!is_potential_precompile(inner.0), "Store cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead");
data.journaled_state.load_account(h160_to_b160(inner.0), data.db)?;
// ensure the account is touched
data.journaled_state.touch(&h160_to_b160(inner.0));
Expand All @@ -245,6 +249,7 @@ pub fn apply<DB: DatabaseExt>(
Bytes::new()
}
HEVMCalls::Load(inner) => {
ensure!(!is_potential_precompile(inner.0), "Load cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead");
// TODO: Does this increase gas usage?
data.journaled_state.load_account(h160_to_b160(inner.0), data.db)?;
let (val, _) = data.journaled_state.sload(
Expand All @@ -257,6 +262,7 @@ pub fn apply<DB: DatabaseExt>(
HEVMCalls::Breakpoint0(inner) => add_breakpoint(state, caller, &inner.0, true)?,
HEVMCalls::Breakpoint1(inner) => add_breakpoint(state, caller, &inner.0, inner.1)?,
HEVMCalls::Etch(inner) => {
ensure!(!is_potential_precompile(inner.0), "Etch cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead");
let code = inner.1.clone();
trace!(address=?inner.0, code=?hex::encode(&code), "etch cheatcode");
// TODO: Does this increase gas usage?
Expand Down
5 changes: 5 additions & 0 deletions evm/src/executor/inspector/cheatcodes/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ pub fn check_if_fixed_gas_limit<DB: DatabaseExt>(
&& call_gas_limit > 2300
}

/// Small utility function that checks if an address is a potential precompile.
pub fn is_potential_precompile(address: H160) -> bool {
address < H160::from_low_u64_be(10) && address != H160::zero()
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion testdata/cheats/Deal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract DealTest is DSTest {
Cheats constant cheats = Cheats(HEVM_ADDRESS);

function testDeal(uint256 amount) public {
address target = address(1);
address target = address(10);
assertEq(target.balance, 0, "initial balance incorrect");

// Give half the amount
Expand Down
9 changes: 9 additions & 0 deletions testdata/cheats/Etch.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ contract EtchTest is DSTest {
cheats.etch(target, code);
assertEq(string(code), string(target.code));
}

function testEtchNotAvailableOnPrecompiles() public {
address target = address(1);
bytes memory code = hex"1010";
cheats.expectRevert(
bytes("Etch cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead")
);
cheats.etch(target, code);
}
}
7 changes: 7 additions & 0 deletions testdata/cheats/Load.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ contract LoadTest is DSTest {
assertEq(val, 20, "load failed");
}

function testLoadNotAvailableOnPrecompiles() public {
cheats.expectRevert(
bytes("Load cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead")
);
uint256 val = uint256(cheats.load(address(1), bytes32(0)));
}

function testLoadOtherStorage() public {
uint256 val = uint256(cheats.load(address(store), bytes32(0)));
assertEq(val, 10, "load failed");
Expand Down
10 changes: 10 additions & 0 deletions testdata/cheats/Store.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ contract StoreTest is DSTest {
assertEq(store.slot1(), 20, "store failed");
}

function testStoreNotAvailableOnPrecompiles() public {
assertEq(store.slot0(), 10, "initial value for slot 0 is incorrect");
assertEq(store.slot1(), 20, "initial value for slot 1 is incorrect");

cheats.expectRevert(
bytes("Store cannot be used on precompile addresses (N < 10). Please use an address bigger than 10 instead")
);
cheats.store(address(1), bytes32(0), bytes32(uint256(1)));
}

function testStoreFuzzed(uint256 slot0, uint256 slot1) public {
assertEq(store.slot0(), 10, "initial value for slot 0 is incorrect");
assertEq(store.slot1(), 20, "initial value for slot 1 is incorrect");
Expand Down

0 comments on commit db96393

Please sign in to comment.