non-fungible-apps/lib/forge-std/test/StdCheats.t.sol

292 lines
11 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import "../src/StdCheats.sol";
import "../src/Test.sol";
import "../src/StdJson.sol";
contract StdCheatsTest is Test {
Bar test;
using stdJson for string;
function setUp() public {
test = new Bar();
}
function testSkip() public {
vm.warp(100);
skip(25);
assertEq(block.timestamp, 125);
}
function testRewind() public {
vm.warp(100);
rewind(25);
assertEq(block.timestamp, 75);
}
function testHoax() public {
hoax(address(1337));
test.bar{value: 100}(address(1337));
}
function testHoaxOrigin() public {
hoax(address(1337), address(1337));
test.origin{value: 100}(address(1337));
}
function testHoaxDifferentAddresses() public {
hoax(address(1337), address(7331));
test.origin{value: 100}(address(1337), address(7331));
}
function testStartHoax() public {
startHoax(address(1337));
test.bar{value: 100}(address(1337));
test.bar{value: 100}(address(1337));
vm.stopPrank();
test.bar(address(this));
}
function testStartHoaxOrigin() public {
startHoax(address(1337), address(1337));
test.origin{value: 100}(address(1337));
test.origin{value: 100}(address(1337));
vm.stopPrank();
test.bar(address(this));
}
function testChangePrank() public {
vm.startPrank(address(1337));
test.bar(address(1337));
changePrank(address(0xdead));
test.bar(address(0xdead));
changePrank(address(1337));
test.bar(address(1337));
vm.stopPrank();
}
function testMakeAddrEquivalence() public {
(address addr,) = makeAddrAndKey("1337");
assertEq(makeAddr("1337"), addr);
}
function testMakeAddrSigning() public {
(address addr, uint256 key) = makeAddrAndKey("1337");
bytes32 hash = keccak256("some_message");
(uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash);
assertEq(ecrecover(hash, v, r, s), addr);
}
function testDeal() public {
deal(address(this), 1 ether);
assertEq(address(this).balance, 1 ether);
}
function testDealToken() public {
Bar barToken = new Bar();
address bar = address(barToken);
deal(bar, address(this), 10000e18);
assertEq(barToken.balanceOf(address(this)), 10000e18);
}
function testDealTokenAdjustTS() public {
Bar barToken = new Bar();
address bar = address(barToken);
deal(bar, address(this), 10000e18, true);
assertEq(barToken.balanceOf(address(this)), 10000e18);
assertEq(barToken.totalSupply(), 20000e18);
deal(bar, address(this), 0, true);
assertEq(barToken.balanceOf(address(this)), 0);
assertEq(barToken.totalSupply(), 10000e18);
}
function testDeployCode() public {
address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""));
assertEq(string(getCode(deployed)), string(getCode(address(test))));
}
function testDeployCodeNoArgs() public {
address deployed = deployCode("StdCheats.t.sol:Bar");
assertEq(string(getCode(deployed)), string(getCode(address(test))));
}
function testDeployCodeVal() public {
address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""), 1 ether);
assertEq(string(getCode(deployed)), string(getCode(address(test))));
assertEq(deployed.balance, 1 ether);
}
function testDeployCodeValNoArgs() public {
address deployed = deployCode("StdCheats.t.sol:Bar", 1 ether);
assertEq(string(getCode(deployed)), string(getCode(address(test))));
assertEq(deployed.balance, 1 ether);
}
// We need this so we can call "this.deployCode" rather than "deployCode" directly
function deployCodeHelper(string memory what) external {
deployCode(what);
}
function testDeployCodeFail() public {
vm.expectRevert(bytes("StdCheats deployCode(string): Deployment failed."));
this.deployCodeHelper("StdCheats.t.sol:RevertingContract");
}
function getCode(address who) internal view returns (bytes memory o_code) {
/// @solidity memory-safe-assembly
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(who)
// allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size)
o_code := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(o_code, size)
// actually retrieve the code, this needs assembly
extcodecopy(who, add(o_code, 0x20), 0, size)
}
}
function testDeriveRememberKey() public {
string memory mnemonic = "test test test test test test test test test test test junk";
(address deployer, uint256 privateKey) = deriveRememberKey(mnemonic, 0);
assertEq(deployer, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
assertEq(privateKey, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80);
}
function testBytesToUint() public {
assertEq(3, bytesToUint_test(hex"03"));
assertEq(2, bytesToUint_test(hex"02"));
assertEq(255, bytesToUint_test(hex"ff"));
assertEq(29625, bytesToUint_test(hex"73b9"));
}
function testParseJsonTxDetail() public {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
string memory json = vm.readFile(path);
bytes memory transactionDetails = json.parseRaw(".transactions[0].tx");
RawTx1559Detail memory rawTxDetail = abi.decode(transactionDetails, (RawTx1559Detail));
Tx1559Detail memory txDetail = rawToConvertedEIP1559Detail(rawTxDetail);
assertEq(txDetail.from, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
assertEq(txDetail.to, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);
assertEq(
txDetail.data,
hex"23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"
);
assertEq(txDetail.nonce, 3);
assertEq(txDetail.txType, 2);
assertEq(txDetail.gas, 29625);
assertEq(txDetail.value, 0);
}
function testReadEIP1559Transaction() public view {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
uint256 index = 0;
Tx1559 memory transaction = readTx1559(path, index);
transaction;
}
function testReadEIP1559Transactions() public view {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
Tx1559[] memory transactions = readTx1559s(path);
transactions;
}
function testReadReceipt() public {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
uint256 index = 5;
Receipt memory receipt = readReceipt(path, index);
assertEq(
receipt.logsBloom,
hex"00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100"
);
}
function testReadReceipts() public view {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
Receipt[] memory receipts = readReceipts(path);
receipts;
}
function bytesToUint_test(bytes memory b) private pure returns (uint256) {
uint256 number;
for (uint256 i = 0; i < b.length; i++) {
number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
}
return number;
}
function testChainRpcInitialization() public {
// RPCs specified in `foundry.toml` should be updated.
assertEq(stdChains["mainnet"].rpcUrl, "https://mainnet.infura.io/v3/7a8769b798b642f6933f2ed52042bd70");
assertEq(stdChains["optimism_goerli"].rpcUrl, "https://goerli.optimism.io/");
assertEq(stdChains["arbitrum_one_goerli"].rpcUrl, "https://goerli-rollup.arbitrum.io/rpc/");
// Other RPCs should remain unchanged.
assertEq(stdChains["anvil"].rpcUrl, "http://127.0.0.1:8545");
assertEq(stdChains["hardhat"].rpcUrl, "http://127.0.0.1:8545");
assertEq(stdChains["sepolia"].rpcUrl, "https://rpc.sepolia.dev");
}
// Ensure we can connect to the default RPC URL for each chain.
function testRpcs() public {
(string[2][] memory rpcs) = vm.rpcUrls();
for (uint256 i = 0; i < rpcs.length; i++) {
( /* string memory name */ , string memory rpcUrl) = (rpcs[i][0], rpcs[i][1]);
vm.createSelectFork(rpcUrl);
}
}
function testAssumeNoPrecompiles(address addr) external {
assumeNoPrecompiles(addr, stdChains["optimism_goerli"].chainId);
assertTrue(
addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
|| addr > address(0x4200000000000000000000000000000000000800)
);
}
}
contract Bar {
constructor() payable {
/// `DEAL` STDCHEAT
totalSupply = 10000e18;
balanceOf[address(this)] = totalSupply;
}
/// `HOAX` STDCHEATS
function bar(address expectedSender) public payable {
require(msg.sender == expectedSender, "!prank");
}
function origin(address expectedSender) public payable {
require(msg.sender == expectedSender, "!prank");
require(tx.origin == expectedSender, "!prank");
}
function origin(address expectedSender, address expectedOrigin) public payable {
require(msg.sender == expectedSender, "!prank");
require(tx.origin == expectedOrigin, "!prank");
}
/// `DEAL` STDCHEAT
mapping(address => uint256) public balanceOf;
uint256 public totalSupply;
}
contract RevertingContract {
constructor() {
revert();
}
}