Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forge): readCallers cheatcode #4884

Merged
merged 22 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8a730c1
feat(forge): started working on the readPrank cheat code
xeno097 May 5, 2023
dc3c231
test(forge): started implementing tests for readPrank cheat code
xeno097 May 5, 2023
47b38d7
refactor(forge): refactored read_prank func
xeno097 May 5, 2023
907ee5c
test(forge): improved tests for readPrank cheat code
xeno097 May 5, 2023
d88b688
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 5, 2023
d90c98e
fix(forge): fixed readPrank solidity test formatting
xeno097 May 5, 2023
7e5ae8c
chore(forge): forge fmt
xeno097 May 5, 2023
b685ce5
feat(forge): replaced 0 address with default msg.sender when no prank…
xeno097 May 7, 2023
2a11ead
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 7, 2023
2a58047
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 8, 2023
5a6d6f2
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 13, 2023
db2455a
feat(forge): renamed readPrank to readCallers and started working on …
xeno097 May 18, 2023
49592fa
refactor(forge): renamed ReadPrank.t.sol -> ReadCallers.t.sol
xeno097 May 18, 2023
bf8170d
refactor(forge): updated the read_callers cheat code returndata
xeno097 May 18, 2023
b8a8e24
test(forge): added tests for broadcasting case for readCallers cheat …
xeno097 May 18, 2023
4834ead
refactor(forge): added the CallerMode enum to remove hardcoded number…
xeno097 May 18, 2023
9bc8bd3
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 18, 2023
5916fa9
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 28, 2023
375b19e
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 May 28, 2023
6b191a8
chore(forge): hevm.rs
xeno097 May 28, 2023
cb05f40
Merge branch 'master' of github.com:foundry-rs/foundry into read-pran…
xeno097 Jun 3, 2023
b1dc89a
docs(forge): added doc comments to read_callers func and CallerMode enum
xeno097 Jun 3, 2023
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
1 change: 1 addition & 0 deletions evm/src/executor/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ abigen!(

prank(address)
prank(address,address)
readPrank()(bool,address,address)
startPrank(address)
startPrank(address,address)
stopPrank()
Expand Down
21 changes: 20 additions & 1 deletion evm/src/executor/inspector/cheatcodes/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
use ethers::{
abi::{self, AbiEncode, RawLog, Token, Tokenizable, Tokenize},
signers::{LocalWallet, Signer},
types::{Address, Bytes, U256},
types::{Address, Bytes, H160, U256},
};
use foundry_config::Config;
use revm::{primitives::Bytecode, Database, EVMData};
Expand Down Expand Up @@ -108,6 +108,24 @@ fn prank(
Ok(Bytes::new())
}

fn read_prank(prank: &Option<Prank>) -> Bytes {
let is_prank_active = prank.is_some();

let data = if let Some(prank) = prank {
[
Token::Bool(is_prank_active),
Token::Address(prank.new_caller),
Token::Address(prank.new_origin.unwrap_or_default()),
]
} else {
let zero_address = H160::default();

[Token::Bool(is_prank_active), Token::Address(zero_address), Token::Address(zero_address)]
};

abi::encode(&data).into()
}

#[derive(Clone, Debug, Default)]
pub struct RecordAccess {
pub reads: BTreeMap<Address, Vec<U256>>,
Expand Down Expand Up @@ -308,6 +326,7 @@ pub fn apply<DB: DatabaseExt>(
state.prank = None;
Bytes::new()
}
HEVMCalls::ReadPrank(_) => read_prank(&state.prank),
HEVMCalls::Record(_) => {
start_record(state);
Bytes::new()
Expand Down
3 changes: 3 additions & 0 deletions testdata/cheats/Cheats.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ interface Cheats {
// Resets subsequent calls' msg.sender to be `address(this)`
function stopPrank() external;

// Reads the current prank from state
function readPrank() external returns (bool, address, address);

// Sets an address' balance, (who, newBalance)
function deal(address, uint256) external;

Expand Down
169 changes: 169 additions & 0 deletions testdata/cheats/ReadPrank.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.0;

import "ds-test/test.sol";
import "./Cheats.sol";
import "../logs/console.sol";

contract Target {
function consumePrank() external {}
}

contract ReadPrankTest is DSTest {
Cheats constant cheats = Cheats(HEVM_ADDRESS);

function testReadPrankWithNoActivePrank() public {
// Act
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertEq(isActive, false);
assertEq(newSender, address(0));
assertEq(newOrigin, address(0));
}

function testReadPrankWithActivePrankForMsgSender(address sender) public {
// Arrange
cheats.prank(sender);

// Act
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertTrue(isActive);
assertEq(newSender, sender);
assertEq(newOrigin, address(0));
}

function testReadPrankWithActivePrankForMsgSenderAndTxOrigin(
address sender,
address origin
) public {
// Arrange
cheats.prank(sender, origin);

// Act
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertTrue(isActive);
assertEq(newSender, sender);
assertEq(newOrigin, origin);
}

function testReadPrankAfterConsumingMsgSenderPrank(address sender) public {
// Arrange
Target target = new Target();
cheats.prank(sender);

// Act
target.consumePrank();
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertEq(isActive, false);
assertEq(newSender, address(0));
assertEq(newOrigin, address(0));
}

function testReadPrankAfterConsumingMsgSenderAndTxOriginPrank(
address sender,
address origin
) public {
// Arrange
Target target = new Target();
cheats.prank(sender, origin);

// Act
target.consumePrank();
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertEq(isActive, false);
assertEq(newSender, address(0));
assertEq(newOrigin, address(0));
}

function testReadPrankWithActiveRecurrentMsgSenderPrank(address sender)
public
{
// Arrange
Target target = new Target();
cheats.startPrank(sender);

for (uint i = 0; i < 5; i++) {
// Act
target.consumePrank();
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertTrue(isActive);
assertEq(newSender, sender);
assertEq(newOrigin, address(0));
}
}

function testReadPrankWithActiveRecurrentMsgSenderAndTxOriginPrank(
address sender,
address origin
) public {
// Arrange
Target target = new Target();
cheats.startPrank(sender, origin);

for (uint i = 0; i < 5; i++) {
// Act
target.consumePrank();
(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertTrue(isActive);
assertEq(newSender, sender);
assertEq(newOrigin, origin);
}
}

function testReadPrankAfterStoppingRecurrentMsgSenderPrank(address sender)
public
{
// Arrange
cheats.startPrank(sender);

// Act
cheats.stopPrank();

(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertEq(isActive, false);
assertEq(newSender, address(0));
assertEq(newOrigin, address(0));
}

function testReadPrankAfterStoppingRecurrentMsgSenderAndTxOriginPrank(
address sender,
address origin
) public {
// Arrange
cheats.startPrank(sender, origin);

// Act
cheats.stopPrank();

(bool isActive, address newSender, address newOrigin) = cheats
.readPrank();

// Assert
assertEq(isActive, false);
assertEq(newSender, address(0));
assertEq(newOrigin, address(0));
}
}