mirror of
https://github.com/autistic-symposium/blockchains-security-toolkit.git
synced 2025-05-13 12:12:19 -04:00
💾
This commit is contained in:
parent
7c4b4cc16f
commit
fd8a437ebf
70 changed files with 10585 additions and 1 deletions
|
@ -0,0 +1,823 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdAssertionsTest is Test {
|
||||
string constant CUSTOM_ERROR = "guh!";
|
||||
|
||||
bool constant EXPECT_PASS = false;
|
||||
bool constant EXPECT_FAIL = true;
|
||||
|
||||
TestTest t = new TestTest();
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
FAIL(STRING)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testShouldFail() external {
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._fail(CUSTOM_ERROR);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
ASSERT_FALSE
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertFalse_Pass() external {
|
||||
t._assertFalse(false, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertFalse_Fail() external {
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: Assertion Failed");
|
||||
t._assertFalse(true, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertFalse_Err_Pass() external {
|
||||
t._assertFalse(false, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertFalse_Err_Fail() external {
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertFalse(true, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
ASSERT_EQ(BOOL)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertEq_Bool_Pass(bool a) external {
|
||||
t._assertEq(a, a, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_Bool_Fail(bool a, bool b) external {
|
||||
vm.assume(a != b);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [bool]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_BoolErr_Pass(bool a) external {
|
||||
t._assertEq(a, a, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_BoolErr_Fail(bool a, bool b) external {
|
||||
vm.assume(a != b);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
ASSERT_EQ(BYTES)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertEq_Bytes_Pass(bytes calldata a) external {
|
||||
t._assertEq(a, a, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_Bytes_Fail(bytes calldata a, bytes calldata b) external {
|
||||
vm.assume(keccak256(a) != keccak256(b));
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [bytes]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_BytesErr_Pass(bytes calldata a) external {
|
||||
t._assertEq(a, a, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_BytesErr_Fail(bytes calldata a, bytes calldata b) external {
|
||||
vm.assume(keccak256(a) != keccak256(b));
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
ASSERT_EQ(ARRAY)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertEq_UintArr_Pass(uint256 e0, uint256 e1, uint256 e2) public {
|
||||
uint256[] memory a = new uint256[](3);
|
||||
a[0] = e0;
|
||||
a[1] = e1;
|
||||
a[2] = e2;
|
||||
uint256[] memory b = new uint256[](3);
|
||||
b[0] = e0;
|
||||
b[1] = e1;
|
||||
b[2] = e2;
|
||||
|
||||
t._assertEq(a, b, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_IntArr_Pass(int256 e0, int256 e1, int256 e2) public {
|
||||
int256[] memory a = new int256[](3);
|
||||
a[0] = e0;
|
||||
a[1] = e1;
|
||||
a[2] = e2;
|
||||
int256[] memory b = new int256[](3);
|
||||
b[0] = e0;
|
||||
b[1] = e1;
|
||||
b[2] = e2;
|
||||
|
||||
t._assertEq(a, b, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_AddressArr_Pass(address e0, address e1, address e2) public {
|
||||
address[] memory a = new address[](3);
|
||||
a[0] = e0;
|
||||
a[1] = e1;
|
||||
a[2] = e2;
|
||||
address[] memory b = new address[](3);
|
||||
b[0] = e0;
|
||||
b[1] = e1;
|
||||
b[2] = e2;
|
||||
|
||||
t._assertEq(a, b, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertEq_UintArr_FailEl(uint256 e1) public {
|
||||
vm.assume(e1 != 0);
|
||||
uint256[] memory a = new uint256[](3);
|
||||
uint256[] memory b = new uint256[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [uint[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_IntArr_FailEl(int256 e1) public {
|
||||
vm.assume(e1 != 0);
|
||||
int256[] memory a = new int256[](3);
|
||||
int256[] memory b = new int256[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [int[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_AddressArr_FailEl(address e1) public {
|
||||
vm.assume(e1 != address(0));
|
||||
address[] memory a = new address[](3);
|
||||
address[] memory b = new address[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [address[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_UintArrErr_FailEl(uint256 e1) public {
|
||||
vm.assume(e1 != 0);
|
||||
uint256[] memory a = new uint256[](3);
|
||||
uint256[] memory b = new uint256[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [uint[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_IntArrErr_FailEl(int256 e1) public {
|
||||
vm.assume(e1 != 0);
|
||||
int256[] memory a = new int256[](3);
|
||||
int256[] memory b = new int256[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [int[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_AddressArrErr_FailEl(address e1) public {
|
||||
vm.assume(e1 != address(0));
|
||||
address[] memory a = new address[](3);
|
||||
address[] memory b = new address[](3);
|
||||
b[1] = e1;
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [address[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_UintArr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
uint256[] memory a = new uint256[](lenA);
|
||||
uint256[] memory b = new uint256[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [uint[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_IntArr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
int256[] memory a = new int256[](lenA);
|
||||
int256[] memory b = new int256[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [int[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_AddressArr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
address[] memory a = new address[](lenA);
|
||||
address[] memory b = new address[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [address[]]");
|
||||
t._assertEq(a, b, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_UintArrErr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
uint256[] memory a = new uint256[](lenA);
|
||||
uint256[] memory b = new uint256[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [uint[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_IntArrErr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
int256[] memory a = new int256[](lenA);
|
||||
int256[] memory b = new int256[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [int[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertEq_AddressArrErr_FailLen(uint256 lenA, uint256 lenB) public {
|
||||
vm.assume(lenA != lenB);
|
||||
vm.assume(lenA <= 10000);
|
||||
vm.assume(lenB <= 10000);
|
||||
address[] memory a = new address[](lenA);
|
||||
address[] memory b = new address[](lenB);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a == b not satisfied [address[]]");
|
||||
t._assertEq(a, b, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
ASSERT_EQ(UINT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertEqUint() public {
|
||||
assertEqUint(uint8(1), uint128(1));
|
||||
assertEqUint(uint64(2), uint64(2));
|
||||
}
|
||||
|
||||
function testFailAssertEqUint() public {
|
||||
assertEqUint(uint64(1), uint96(2));
|
||||
assertEqUint(uint160(3), uint160(4));
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_ABS(UINT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqAbs_Uint_Pass(uint256 a, uint256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbs(a, b, maxDelta, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_Uint_Fail(uint256 a, uint256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [uint]");
|
||||
t._assertApproxEqAbs(a, b, maxDelta, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_UintErr_Pass(uint256 a, uint256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbs(a, b, maxDelta, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_UintErr_Fail(uint256 a, uint256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqAbs(a, b, maxDelta, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_ABS_DECIMAL(UINT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqAbsDecimal_Uint_Pass(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_Uint_Fail(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [uint]");
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_UintErr_Pass(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_UintErr_Fail(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_ABS(INT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqAbs_Int_Pass(int256 a, int256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbs(a, b, maxDelta, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_Int_Fail(int256 a, int256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [int]");
|
||||
t._assertApproxEqAbs(a, b, maxDelta, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_IntErr_Pass(int256 a, int256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbs(a, b, maxDelta, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbs_IntErr_Fail(int256 a, int256 b, uint256 maxDelta) external {
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqAbs(a, b, maxDelta, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_ABS_DECIMAL(INT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqAbsDecimal_Int_Pass(int256 a, int256 b, uint256 maxDelta, uint256 decimals) external {
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_Int_Fail(int256 a, int256 b, uint256 maxDelta, uint256 decimals) external {
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [int]");
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_IntErr_Pass(int256 a, int256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) <= maxDelta);
|
||||
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqAbsDecimal_IntErr_Fail(int256 a, int256 b, uint256 maxDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(stdMath.delta(a, b) > maxDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqAbsDecimal(a, b, maxDelta, decimals, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_REL(UINT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqRel_Uint_Pass(uint256 a, uint256 b, uint256 maxPercentDelta) external {
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_Uint_Fail(uint256 a, uint256 b, uint256 maxPercentDelta) external {
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [uint]");
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_UintErr_Pass(uint256 a, uint256 b, uint256 maxPercentDelta) external {
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_UintErr_Fail(uint256 a, uint256 b, uint256 maxPercentDelta) external {
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_REL_DECIMAL(UINT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqRelDecimal_Uint_Pass(uint256 a, uint256 b, uint256 maxPercentDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_Uint_Fail(uint256 a, uint256 b, uint256 maxPercentDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [uint]");
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_UintErr_Pass(uint256 a, uint256 b, uint256 maxPercentDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_UintErr_Fail(uint256 a, uint256 b, uint256 maxPercentDelta, uint256 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(a < type(uint128).max && b < type(uint128).max && b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_REL(INT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqRel_Int_Pass(int128 a, int128 b, uint128 maxPercentDelta) external {
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_Int_Fail(int128 a, int128 b, uint128 maxPercentDelta) external {
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [int]");
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_IntErr_Pass(int128 a, int128 b, uint128 maxPercentDelta) external {
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRel_IntErr_Fail(int128 a, int128 b, uint128 maxPercentDelta) external {
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqRel(a, b, maxPercentDelta, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
APPROX_EQ_REL_DECIMAL(INT)
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testAssertApproxEqRelDecimal_Int_Pass(int128 a, int128 b, uint128 maxPercentDelta, uint128 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_Int_Fail(int128 a, int128 b, uint128 maxPercentDelta, uint128 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log("Error: a ~= b not satisfied [int]");
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, EXPECT_FAIL);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_IntErr_Pass(int128 a, int128 b, uint128 maxPercentDelta, uint128 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) <= maxPercentDelta);
|
||||
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, CUSTOM_ERROR, EXPECT_PASS);
|
||||
}
|
||||
|
||||
function testAssertApproxEqRelDecimal_IntErr_Fail(int128 a, int128 b, uint128 maxPercentDelta, uint128 decimals)
|
||||
external
|
||||
{
|
||||
vm.assume(b != 0);
|
||||
vm.assume(stdMath.percentDelta(a, b) > maxPercentDelta);
|
||||
|
||||
vm.expectEmit(false, false, false, true);
|
||||
emit log_named_string("Error", CUSTOM_ERROR);
|
||||
t._assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, CUSTOM_ERROR, EXPECT_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
contract TestTest is Test {
|
||||
modifier expectFailure(bool expectFail) {
|
||||
bool preState = vm.load(HEVM_ADDRESS, bytes32("failed")) != bytes32(0x00);
|
||||
_;
|
||||
bool postState = vm.load(HEVM_ADDRESS, bytes32("failed")) != bytes32(0x00);
|
||||
|
||||
if (preState == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectFail) {
|
||||
require(postState == true, "expected failure not triggered");
|
||||
|
||||
// unwind the expected failure
|
||||
vm.store(HEVM_ADDRESS, bytes32("failed"), bytes32(uint256(0x00)));
|
||||
} else {
|
||||
require(postState == false, "unexpected failure was triggered");
|
||||
}
|
||||
}
|
||||
|
||||
function _fail(string memory err) external expectFailure(true) {
|
||||
fail(err);
|
||||
}
|
||||
|
||||
function _assertFalse(bool data, bool expectFail) external expectFailure(expectFail) {
|
||||
assertFalse(data);
|
||||
}
|
||||
|
||||
function _assertFalse(bool data, string memory err, bool expectFail) external expectFailure(expectFail) {
|
||||
assertFalse(data, err);
|
||||
}
|
||||
|
||||
function _assertEq(bool a, bool b, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b);
|
||||
}
|
||||
|
||||
function _assertEq(bool a, bool b, string memory err, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b, err);
|
||||
}
|
||||
|
||||
function _assertEq(bytes memory a, bytes memory b, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b);
|
||||
}
|
||||
|
||||
function _assertEq(bytes memory a, bytes memory b, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertEq(a, b, err);
|
||||
}
|
||||
|
||||
function _assertEq(uint256[] memory a, uint256[] memory b, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b);
|
||||
}
|
||||
|
||||
function _assertEq(int256[] memory a, int256[] memory b, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b);
|
||||
}
|
||||
|
||||
function _assertEq(address[] memory a, address[] memory b, bool expectFail) external expectFailure(expectFail) {
|
||||
assertEq(a, b);
|
||||
}
|
||||
|
||||
function _assertEq(uint256[] memory a, uint256[] memory b, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertEq(a, b, err);
|
||||
}
|
||||
|
||||
function _assertEq(int256[] memory a, int256[] memory b, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertEq(a, b, err);
|
||||
}
|
||||
|
||||
function _assertEq(address[] memory a, address[] memory b, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertEq(a, b, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbs(a, b, maxDelta);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbs(a, b, maxDelta, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbsDecimal(a, b, maxDelta, decimals);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbsDecimal(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
uint256 maxDelta,
|
||||
uint256 decimals,
|
||||
string memory err,
|
||||
bool expectFail
|
||||
) external expectFailure(expectFail) {
|
||||
assertApproxEqAbsDecimal(a, b, maxDelta, decimals, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbs(a, b, maxDelta);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbs(a, b, maxDelta, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqAbsDecimal(a, b, maxDelta, decimals);
|
||||
}
|
||||
|
||||
function _assertApproxEqAbsDecimal(
|
||||
int256 a,
|
||||
int256 b,
|
||||
uint256 maxDelta,
|
||||
uint256 decimals,
|
||||
string memory err,
|
||||
bool expectFail
|
||||
) external expectFailure(expectFail) {
|
||||
assertApproxEqAbsDecimal(a, b, maxDelta, decimals, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqRel(uint256 a, uint256 b, uint256 maxPercentDelta, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRel(a, b, maxPercentDelta);
|
||||
}
|
||||
|
||||
function _assertApproxEqRel(uint256 a, uint256 b, uint256 maxPercentDelta, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRel(a, b, maxPercentDelta, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqRelDecimal(uint256 a, uint256 b, uint256 maxPercentDelta, uint256 decimals, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);
|
||||
}
|
||||
|
||||
function _assertApproxEqRelDecimal(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
uint256 maxPercentDelta,
|
||||
uint256 decimals,
|
||||
string memory err,
|
||||
bool expectFail
|
||||
) external expectFailure(expectFail) {
|
||||
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRel(a, b, maxPercentDelta);
|
||||
}
|
||||
|
||||
function _assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRel(a, b, maxPercentDelta, err);
|
||||
}
|
||||
|
||||
function _assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, bool expectFail)
|
||||
external
|
||||
expectFailure(expectFail)
|
||||
{
|
||||
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);
|
||||
}
|
||||
|
||||
function _assertApproxEqRelDecimal(
|
||||
int256 a,
|
||||
int256 b,
|
||||
uint256 maxPercentDelta,
|
||||
uint256 decimals,
|
||||
string memory err,
|
||||
bool expectFail
|
||||
) external expectFailure(expectFail) {
|
||||
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals, err);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdChainsTest is Test {
|
||||
function testChainRpcInitialization() public {
|
||||
// RPCs specified in `foundry.toml` should be updated.
|
||||
assertEq(getChain(1).rpcUrl, "https://mainnet.infura.io/v3/16a8be88795540b9b3903d8de0f7baa5");
|
||||
assertEq(getChain("optimism_goerli").rpcUrl, "https://goerli.optimism.io/");
|
||||
assertEq(getChain("arbitrum_one_goerli").rpcUrl, "https://goerli-rollup.arbitrum.io/rpc/");
|
||||
|
||||
// Environment variables should be the next fallback
|
||||
assertEq(getChain("arbitrum_nova").rpcUrl, "https://nova.arbitrum.io/rpc");
|
||||
vm.setEnv("ARBITRUM_NOVA_RPC_URL", "myoverride");
|
||||
assertEq(getChain("arbitrum_nova").rpcUrl, "myoverride");
|
||||
vm.setEnv("ARBITRUM_NOVA_RPC_URL", "https://nova.arbitrum.io/rpc");
|
||||
|
||||
// Cannot override RPCs defined in `foundry.toml`
|
||||
vm.setEnv("MAINNET_RPC_URL", "myoverride2");
|
||||
assertEq(getChain("mainnet").rpcUrl, "https://mainnet.infura.io/v3/16a8be88795540b9b3903d8de0f7baa5");
|
||||
|
||||
// Other RPCs should remain unchanged.
|
||||
assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545");
|
||||
assertEq(getChain("sepolia").rpcUrl, "https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b");
|
||||
}
|
||||
|
||||
function testRpc(string memory rpcAlias) internal {
|
||||
string memory rpcUrl = getChain(rpcAlias).rpcUrl;
|
||||
vm.createSelectFork(rpcUrl);
|
||||
}
|
||||
|
||||
// Ensure we can connect to the default RPC URL for each chain.
|
||||
function testRpcs() public {
|
||||
testRpc("mainnet");
|
||||
testRpc("goerli");
|
||||
testRpc("sepolia");
|
||||
testRpc("optimism");
|
||||
testRpc("optimism_goerli");
|
||||
testRpc("arbitrum_one");
|
||||
testRpc("arbitrum_one_goerli");
|
||||
testRpc("arbitrum_nova");
|
||||
testRpc("polygon");
|
||||
testRpc("polygon_mumbai");
|
||||
testRpc("avalanche");
|
||||
testRpc("avalanche_fuji");
|
||||
testRpc("bnb_smart_chain");
|
||||
testRpc("bnb_smart_chain_testnet");
|
||||
testRpc("gnosis_chain");
|
||||
}
|
||||
|
||||
function testChainNoDefault() public {
|
||||
vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found.");
|
||||
getChain("does_not_exist");
|
||||
}
|
||||
|
||||
function testSetChainFirstFails() public {
|
||||
vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\".");
|
||||
setChain("anvil2", ChainData("Anvil", 31337, "URL"));
|
||||
}
|
||||
|
||||
function testChainBubbleUp() public {
|
||||
setChain("needs_undefined_env_var", ChainData("", 123456789, ""));
|
||||
vm.expectRevert(
|
||||
"Failed to resolve env var `UNDEFINED_RPC_URL_PLACEHOLDER` in `${UNDEFINED_RPC_URL_PLACEHOLDER}`: environment variable not found"
|
||||
);
|
||||
getChain("needs_undefined_env_var");
|
||||
}
|
||||
|
||||
function testCannotSetChain_ChainIdExists() public {
|
||||
setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
|
||||
|
||||
vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".');
|
||||
|
||||
setChain("another_custom_chain", ChainData("", 123456789, ""));
|
||||
}
|
||||
|
||||
function testSetChain() public {
|
||||
setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
|
||||
Chain memory customChain = getChain("custom_chain");
|
||||
assertEq(customChain.name, "Custom Chain");
|
||||
assertEq(customChain.chainId, 123456789);
|
||||
assertEq(customChain.chainAlias, "custom_chain");
|
||||
assertEq(customChain.rpcUrl, "https://custom.chain/");
|
||||
Chain memory chainById = getChain(123456789);
|
||||
assertEq(chainById.name, customChain.name);
|
||||
assertEq(chainById.chainId, customChain.chainId);
|
||||
assertEq(chainById.chainAlias, customChain.chainAlias);
|
||||
assertEq(chainById.rpcUrl, customChain.rpcUrl);
|
||||
customChain.name = "Another Custom Chain";
|
||||
customChain.chainId = 987654321;
|
||||
setChain("another_custom_chain", customChain);
|
||||
Chain memory anotherCustomChain = getChain("another_custom_chain");
|
||||
assertEq(anotherCustomChain.name, "Another Custom Chain");
|
||||
assertEq(anotherCustomChain.chainId, 987654321);
|
||||
assertEq(anotherCustomChain.chainAlias, "another_custom_chain");
|
||||
assertEq(anotherCustomChain.rpcUrl, "https://custom.chain/");
|
||||
// Verify the first chain data was not overwritten
|
||||
chainById = getChain(123456789);
|
||||
assertEq(chainById.name, "Custom Chain");
|
||||
assertEq(chainById.chainId, 123456789);
|
||||
}
|
||||
|
||||
function testSetNoEmptyAlias() public {
|
||||
vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string.");
|
||||
setChain("", ChainData("", 123456789, ""));
|
||||
}
|
||||
|
||||
function testSetNoChainId0() public {
|
||||
vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0.");
|
||||
setChain("alias", ChainData("", 0, ""));
|
||||
}
|
||||
|
||||
function testGetNoChainId0() public {
|
||||
vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0.");
|
||||
getChain(0);
|
||||
}
|
||||
|
||||
function testGetNoEmptyAlias() public {
|
||||
vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string.");
|
||||
getChain("");
|
||||
}
|
||||
|
||||
function testChainIdNotFound() public {
|
||||
vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found.");
|
||||
getChain("no_such_alias");
|
||||
}
|
||||
|
||||
function testChainAliasNotFound() public {
|
||||
vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found.");
|
||||
getChain(321);
|
||||
}
|
||||
|
||||
function testSetChain_ExistingOne() public {
|
||||
setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
|
||||
assertEq(getChain(123456789).chainId, 123456789);
|
||||
|
||||
setChain("custom_chain", ChainData("Modified Chain", 999999999, "https://modified.chain/"));
|
||||
vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found.");
|
||||
getChain(123456789);
|
||||
|
||||
Chain memory modifiedChain = getChain(999999999);
|
||||
assertEq(modifiedChain.name, "Modified Chain");
|
||||
assertEq(modifiedChain.chainId, 999999999);
|
||||
assertEq(modifiedChain.rpcUrl, "https://modified.chain/");
|
||||
}
|
||||
|
||||
function testDontUseDefaultRpcUrl() public {
|
||||
// Should error if default RPCs flag is set to false.
|
||||
setFallbackToDefaultRpcUrls(false);
|
||||
vm.expectRevert(
|
||||
"Failed to get environment variable `ANVIL_RPC_URL` as type `string`: environment variable not found"
|
||||
);
|
||||
getChain(31337);
|
||||
vm.expectRevert(
|
||||
"Failed to get environment variable `SEPOLIA_RPC_URL` as type `string`: environment variable not found"
|
||||
);
|
||||
getChain("sepolia");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,329 @@
|
|||
// 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 testGasMeteringModifier() public {
|
||||
uint256 gas_start_normal = gasleft();
|
||||
addInLoop();
|
||||
uint256 gas_used_normal = gas_start_normal - gasleft();
|
||||
|
||||
uint256 gas_start_single = gasleft();
|
||||
addInLoopNoGas();
|
||||
uint256 gas_used_single = gas_start_single - gasleft();
|
||||
|
||||
uint256 gas_start_double = gasleft();
|
||||
addInLoopNoGasNoGas();
|
||||
uint256 gas_used_double = gas_start_double - gasleft();
|
||||
|
||||
emit log_named_uint("Normal gas", gas_used_normal);
|
||||
emit log_named_uint("Single modifier gas", gas_used_single);
|
||||
emit log_named_uint("Double modifier gas", gas_used_double);
|
||||
assertTrue(gas_used_double + gas_used_single < gas_used_normal);
|
||||
}
|
||||
|
||||
function addInLoop() internal pure returns (uint256) {
|
||||
uint256 b;
|
||||
for (uint256 i; i < 10000; i++) {
|
||||
b += i;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
function addInLoopNoGas() internal noGasMetering returns (uint256) {
|
||||
return addInLoop();
|
||||
}
|
||||
|
||||
function addInLoopNoGasNoGas() internal noGasMetering returns (uint256) {
|
||||
return addInLoopNoGas();
|
||||
}
|
||||
|
||||
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 testAssumeNoPrecompiles(address addr) external {
|
||||
assumeNoPrecompiles(addr, getChain("optimism_goerli").chainId);
|
||||
assertTrue(
|
||||
addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
|
||||
|| addr > address(0x4200000000000000000000000000000000000800)
|
||||
);
|
||||
}
|
||||
|
||||
function testAssumePayable() external {
|
||||
// all should revert since these addresses are not payable
|
||||
|
||||
// VM address
|
||||
vm.expectRevert();
|
||||
assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
|
||||
|
||||
// Console address
|
||||
vm.expectRevert();
|
||||
assumePayable(0x000000000000000000636F6e736F6c652e6c6f67);
|
||||
|
||||
// Create2Deployer
|
||||
vm.expectRevert();
|
||||
assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
|
||||
}
|
||||
|
||||
function testAssumePayable(address addr) external {
|
||||
assumePayable(addr);
|
||||
assertTrue(
|
||||
addr != 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D && addr != 0x000000000000000000636F6e736F6c652e6c6f67
|
||||
&& addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.0 <0.9.0;
|
||||
|
||||
import "../src/StdError.sol";
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdErrorsTest is Test {
|
||||
ErrorsTest test;
|
||||
|
||||
function setUp() public {
|
||||
test = new ErrorsTest();
|
||||
}
|
||||
|
||||
function testExpectAssertion() public {
|
||||
vm.expectRevert(stdError.assertionError);
|
||||
test.assertionError();
|
||||
}
|
||||
|
||||
function testExpectArithmetic() public {
|
||||
vm.expectRevert(stdError.arithmeticError);
|
||||
test.arithmeticError(10);
|
||||
}
|
||||
|
||||
function testExpectDiv() public {
|
||||
vm.expectRevert(stdError.divisionError);
|
||||
test.divError(0);
|
||||
}
|
||||
|
||||
function testExpectMod() public {
|
||||
vm.expectRevert(stdError.divisionError);
|
||||
test.modError(0);
|
||||
}
|
||||
|
||||
function testExpectEnum() public {
|
||||
vm.expectRevert(stdError.enumConversionError);
|
||||
test.enumConversion(1);
|
||||
}
|
||||
|
||||
function testExpectEncodeStg() public {
|
||||
vm.expectRevert(stdError.encodeStorageError);
|
||||
test.encodeStgError();
|
||||
}
|
||||
|
||||
function testExpectPop() public {
|
||||
vm.expectRevert(stdError.popError);
|
||||
test.pop();
|
||||
}
|
||||
|
||||
function testExpectOOB() public {
|
||||
vm.expectRevert(stdError.indexOOBError);
|
||||
test.indexOOBError(1);
|
||||
}
|
||||
|
||||
function testExpectMem() public {
|
||||
vm.expectRevert(stdError.memOverflowError);
|
||||
test.mem();
|
||||
}
|
||||
|
||||
function testExpectIntern() public {
|
||||
vm.expectRevert(stdError.zeroVarError);
|
||||
test.intern();
|
||||
}
|
||||
}
|
||||
|
||||
contract ErrorsTest {
|
||||
enum T {T1}
|
||||
|
||||
uint256[] public someArr;
|
||||
bytes someBytes;
|
||||
|
||||
function assertionError() public pure {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
function arithmeticError(uint256 a) public pure {
|
||||
a -= 100;
|
||||
}
|
||||
|
||||
function divError(uint256 a) public pure {
|
||||
100 / a;
|
||||
}
|
||||
|
||||
function modError(uint256 a) public pure {
|
||||
100 % a;
|
||||
}
|
||||
|
||||
function enumConversion(uint256 a) public pure {
|
||||
T(a);
|
||||
}
|
||||
|
||||
function encodeStgError() public {
|
||||
/// @solidity memory-safe-assembly
|
||||
assembly {
|
||||
sstore(someBytes.slot, 1)
|
||||
}
|
||||
keccak256(someBytes);
|
||||
}
|
||||
|
||||
function pop() public {
|
||||
someArr.pop();
|
||||
}
|
||||
|
||||
function indexOOBError(uint256 a) public pure {
|
||||
uint256[] memory t = new uint256[](0);
|
||||
t[a];
|
||||
}
|
||||
|
||||
function mem() public pure {
|
||||
uint256 l = 2 ** 256 / 32;
|
||||
new uint256[](l);
|
||||
}
|
||||
|
||||
function intern() public returns (uint256) {
|
||||
function(uint256) internal returns (uint256) x;
|
||||
x(2);
|
||||
return 7;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.0 <0.9.0;
|
||||
|
||||
import "../src/StdMath.sol";
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdMathTest is Test {
|
||||
function testGetAbs() external {
|
||||
assertEq(stdMath.abs(-50), 50);
|
||||
assertEq(stdMath.abs(50), 50);
|
||||
assertEq(stdMath.abs(-1337), 1337);
|
||||
assertEq(stdMath.abs(0), 0);
|
||||
|
||||
assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1);
|
||||
assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1));
|
||||
}
|
||||
|
||||
function testGetAbs_Fuzz(int256 a) external {
|
||||
uint256 manualAbs = getAbs(a);
|
||||
|
||||
uint256 abs = stdMath.abs(a);
|
||||
|
||||
assertEq(abs, manualAbs);
|
||||
}
|
||||
|
||||
function testGetDelta_Uint() external {
|
||||
assertEq(stdMath.delta(uint256(0), uint256(0)), 0);
|
||||
assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337);
|
||||
assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max);
|
||||
assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max);
|
||||
assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max);
|
||||
|
||||
assertEq(stdMath.delta(0, uint256(0)), 0);
|
||||
assertEq(stdMath.delta(1337, uint256(0)), 1337);
|
||||
assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max);
|
||||
assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max);
|
||||
assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max);
|
||||
|
||||
assertEq(stdMath.delta(1337, uint256(1337)), 0);
|
||||
assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0);
|
||||
assertEq(stdMath.delta(5000, uint256(1250)), 3750);
|
||||
}
|
||||
|
||||
function testGetDelta_Uint_Fuzz(uint256 a, uint256 b) external {
|
||||
uint256 manualDelta;
|
||||
if (a > b) {
|
||||
manualDelta = a - b;
|
||||
} else {
|
||||
manualDelta = b - a;
|
||||
}
|
||||
|
||||
uint256 delta = stdMath.delta(a, b);
|
||||
|
||||
assertEq(delta, manualDelta);
|
||||
}
|
||||
|
||||
function testGetDelta_Int() external {
|
||||
assertEq(stdMath.delta(int256(0), int256(0)), 0);
|
||||
assertEq(stdMath.delta(int256(0), int256(1337)), 1337);
|
||||
assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1);
|
||||
assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1);
|
||||
assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1);
|
||||
|
||||
assertEq(stdMath.delta(0, int256(0)), 0);
|
||||
assertEq(stdMath.delta(1337, int256(0)), 1337);
|
||||
assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1);
|
||||
assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1);
|
||||
assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1);
|
||||
|
||||
assertEq(stdMath.delta(-0, int256(0)), 0);
|
||||
assertEq(stdMath.delta(-1337, int256(0)), 1337);
|
||||
assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1);
|
||||
assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1);
|
||||
assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1);
|
||||
|
||||
assertEq(stdMath.delta(int256(0), -0), 0);
|
||||
assertEq(stdMath.delta(int256(0), -1337), 1337);
|
||||
assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1);
|
||||
assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1);
|
||||
assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1);
|
||||
|
||||
assertEq(stdMath.delta(1337, int256(1337)), 0);
|
||||
assertEq(stdMath.delta(type(int256).max, type(int256).max), 0);
|
||||
assertEq(stdMath.delta(type(int256).min, type(int256).min), 0);
|
||||
assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max);
|
||||
assertEq(stdMath.delta(5000, int256(1250)), 3750);
|
||||
}
|
||||
|
||||
function testGetDelta_Int_Fuzz(int256 a, int256 b) external {
|
||||
uint256 absA = getAbs(a);
|
||||
uint256 absB = getAbs(b);
|
||||
uint256 absDelta = absA > absB ? absA - absB : absB - absA;
|
||||
|
||||
uint256 manualDelta;
|
||||
if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
|
||||
manualDelta = absDelta;
|
||||
}
|
||||
// (a < 0 && b >= 0) || (a >= 0 && b < 0)
|
||||
else {
|
||||
manualDelta = absA + absB;
|
||||
}
|
||||
|
||||
uint256 delta = stdMath.delta(a, b);
|
||||
|
||||
assertEq(delta, manualDelta);
|
||||
}
|
||||
|
||||
function testGetPercentDelta_Uint() external {
|
||||
assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18);
|
||||
assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18);
|
||||
assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18);
|
||||
assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18);
|
||||
|
||||
assertEq(stdMath.percentDelta(1337, uint256(1337)), 0);
|
||||
assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0);
|
||||
assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18);
|
||||
assertEq(stdMath.percentDelta(2500, uint256(2500)), 0);
|
||||
assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18);
|
||||
assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18);
|
||||
|
||||
vm.expectRevert(stdError.divisionError);
|
||||
stdMath.percentDelta(uint256(1), 0);
|
||||
}
|
||||
|
||||
function testGetPercentDelta_Uint_Fuzz(uint192 a, uint192 b) external {
|
||||
vm.assume(b != 0);
|
||||
uint256 manualDelta;
|
||||
if (a > b) {
|
||||
manualDelta = a - b;
|
||||
} else {
|
||||
manualDelta = b - a;
|
||||
}
|
||||
|
||||
uint256 manualPercentDelta = manualDelta * 1e18 / b;
|
||||
uint256 percentDelta = stdMath.percentDelta(a, b);
|
||||
|
||||
assertEq(percentDelta, manualPercentDelta);
|
||||
}
|
||||
|
||||
function testGetPercentDelta_Int() external {
|
||||
assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), -1337), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18);
|
||||
assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18);
|
||||
|
||||
assertEq(stdMath.percentDelta(1337, int256(1337)), 0);
|
||||
assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0);
|
||||
assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0);
|
||||
|
||||
assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down
|
||||
assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down
|
||||
assertEq(stdMath.percentDelta(0, int256(2500)), 1e18);
|
||||
assertEq(stdMath.percentDelta(2500, int256(2500)), 0);
|
||||
assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18);
|
||||
assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18);
|
||||
|
||||
vm.expectRevert(stdError.divisionError);
|
||||
stdMath.percentDelta(int256(1), 0);
|
||||
}
|
||||
|
||||
function testGetPercentDelta_Int_Fuzz(int192 a, int192 b) external {
|
||||
vm.assume(b != 0);
|
||||
uint256 absA = getAbs(a);
|
||||
uint256 absB = getAbs(b);
|
||||
uint256 absDelta = absA > absB ? absA - absB : absB - absA;
|
||||
|
||||
uint256 manualDelta;
|
||||
if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
|
||||
manualDelta = absDelta;
|
||||
}
|
||||
// (a < 0 && b >= 0) || (a >= 0 && b < 0)
|
||||
else {
|
||||
manualDelta = absA + absB;
|
||||
}
|
||||
|
||||
uint256 manualPercentDelta = manualDelta * 1e18 / absB;
|
||||
uint256 percentDelta = stdMath.percentDelta(a, b);
|
||||
|
||||
assertEq(percentDelta, manualPercentDelta);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
HELPERS
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function getAbs(int256 a) private pure returns (uint256) {
|
||||
if (a < 0) {
|
||||
return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a);
|
||||
}
|
||||
|
||||
return uint256(a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
import "../src/StdStorage.sol";
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdStorageTest is Test {
|
||||
using stdStorage for StdStorage;
|
||||
|
||||
StorageTest internal test;
|
||||
|
||||
function setUp() public {
|
||||
test = new StorageTest();
|
||||
}
|
||||
|
||||
function testStorageHidden() public {
|
||||
assertEq(uint256(keccak256("my.random.var")), stdstore.target(address(test)).sig("hidden()").find());
|
||||
}
|
||||
|
||||
function testStorageObvious() public {
|
||||
assertEq(uint256(0), stdstore.target(address(test)).sig("exists()").find());
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteHidden() public {
|
||||
stdstore.target(address(test)).sig(test.hidden.selector).checked_write(100);
|
||||
assertEq(uint256(test.hidden()), 100);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteObvious() public {
|
||||
stdstore.target(address(test)).sig(test.exists.selector).checked_write(100);
|
||||
assertEq(test.exists(), 100);
|
||||
}
|
||||
|
||||
function testStorageMapStructA() public {
|
||||
uint256 slot =
|
||||
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).find();
|
||||
assertEq(uint256(keccak256(abi.encode(address(this), 4))), slot);
|
||||
}
|
||||
|
||||
function testStorageMapStructB() public {
|
||||
uint256 slot =
|
||||
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).find();
|
||||
assertEq(uint256(keccak256(abi.encode(address(this), 4))) + 1, slot);
|
||||
}
|
||||
|
||||
function testStorageDeepMap() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(
|
||||
address(this)
|
||||
).find();
|
||||
assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteDeepMap() public {
|
||||
stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(address(this))
|
||||
.checked_write(100);
|
||||
assertEq(100, test.deep_map(address(this), address(this)));
|
||||
}
|
||||
|
||||
function testStorageDeepMapStructA() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
||||
.with_key(address(this)).depth(0).find();
|
||||
assertEq(
|
||||
bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0),
|
||||
bytes32(slot)
|
||||
);
|
||||
}
|
||||
|
||||
function testStorageDeepMapStructB() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
|
||||
.with_key(address(this)).depth(1).find();
|
||||
assertEq(
|
||||
bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1),
|
||||
bytes32(slot)
|
||||
);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteDeepMapStructA() public {
|
||||
stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
|
||||
address(this)
|
||||
).depth(0).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
|
||||
assertEq(100, a);
|
||||
assertEq(0, b);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteDeepMapStructB() public {
|
||||
stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
|
||||
address(this)
|
||||
).depth(1).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
|
||||
assertEq(0, a);
|
||||
assertEq(100, b);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapStructA() public {
|
||||
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.map_struct(address(this));
|
||||
assertEq(a, 100);
|
||||
assertEq(b, 0);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapStructB() public {
|
||||
stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.map_struct(address(this));
|
||||
assertEq(a, 0);
|
||||
assertEq(b, 100);
|
||||
}
|
||||
|
||||
function testStorageStructA() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(0).find();
|
||||
assertEq(uint256(7), slot);
|
||||
}
|
||||
|
||||
function testStorageStructB() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(1).find();
|
||||
assertEq(uint256(7) + 1, slot);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteStructA() public {
|
||||
stdstore.target(address(test)).sig(test.basic.selector).depth(0).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.basic();
|
||||
assertEq(a, 100);
|
||||
assertEq(b, 1337);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteStructB() public {
|
||||
stdstore.target(address(test)).sig(test.basic.selector).depth(1).checked_write(100);
|
||||
(uint256 a, uint256 b) = test.basic();
|
||||
assertEq(a, 1337);
|
||||
assertEq(b, 100);
|
||||
}
|
||||
|
||||
function testStorageMapAddrFound() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find();
|
||||
assertEq(uint256(keccak256(abi.encode(address(this), uint256(1)))), slot);
|
||||
}
|
||||
|
||||
function testStorageMapUintFound() public {
|
||||
uint256 slot = stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).find();
|
||||
assertEq(uint256(keccak256(abi.encode(100, uint256(2)))), slot);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapUint() public {
|
||||
stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).checked_write(100);
|
||||
assertEq(100, test.map_uint(100));
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapAddr() public {
|
||||
stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).checked_write(100);
|
||||
assertEq(100, test.map_addr(address(this)));
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapBool() public {
|
||||
stdstore.target(address(test)).sig(test.map_bool.selector).with_key(address(this)).checked_write(true);
|
||||
assertTrue(test.map_bool(address(this)));
|
||||
}
|
||||
|
||||
function testFailStorageCheckedWriteMapPacked() public {
|
||||
// expect PackedSlot error but not external call so cant expectRevert
|
||||
stdstore.target(address(test)).sig(test.read_struct_lower.selector).with_key(address(uint160(1337)))
|
||||
.checked_write(100);
|
||||
}
|
||||
|
||||
function testStorageCheckedWriteMapPackedSuccess() public {
|
||||
uint256 full = test.map_packed(address(1337));
|
||||
// keep upper 128, set lower 128 to 1337
|
||||
full = (full & (uint256((1 << 128) - 1) << 128)) | 1337;
|
||||
stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))).checked_write(
|
||||
full
|
||||
);
|
||||
assertEq(1337, test.read_struct_lower(address(1337)));
|
||||
}
|
||||
|
||||
function testFailStorageConst() public {
|
||||
// vm.expectRevert(abi.encodeWithSignature("NotStorage(bytes4)", bytes4(keccak256("const()"))));
|
||||
stdstore.target(address(test)).sig("const()").find();
|
||||
}
|
||||
|
||||
function testFailStorageNativePack() public {
|
||||
stdstore.target(address(test)).sig(test.tA.selector).find();
|
||||
stdstore.target(address(test)).sig(test.tB.selector).find();
|
||||
|
||||
// these both would fail
|
||||
stdstore.target(address(test)).sig(test.tC.selector).find();
|
||||
stdstore.target(address(test)).sig(test.tD.selector).find();
|
||||
}
|
||||
|
||||
function testStorageReadBytes32() public {
|
||||
bytes32 val = stdstore.target(address(test)).sig(test.tE.selector).read_bytes32();
|
||||
assertEq(val, hex"1337");
|
||||
}
|
||||
|
||||
function testStorageReadBool_False() public {
|
||||
bool val = stdstore.target(address(test)).sig(test.tB.selector).read_bool();
|
||||
assertEq(val, false);
|
||||
}
|
||||
|
||||
function testStorageReadBool_True() public {
|
||||
bool val = stdstore.target(address(test)).sig(test.tH.selector).read_bool();
|
||||
assertEq(val, true);
|
||||
}
|
||||
|
||||
function testStorageReadBool_Revert() public {
|
||||
vm.expectRevert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
|
||||
this.readNonBoolValue();
|
||||
}
|
||||
|
||||
function readNonBoolValue() public {
|
||||
stdstore.target(address(test)).sig(test.tE.selector).read_bool();
|
||||
}
|
||||
|
||||
function testStorageReadAddress() public {
|
||||
address val = stdstore.target(address(test)).sig(test.tF.selector).read_address();
|
||||
assertEq(val, address(1337));
|
||||
}
|
||||
|
||||
function testStorageReadUint() public {
|
||||
uint256 val = stdstore.target(address(test)).sig(test.exists.selector).read_uint();
|
||||
assertEq(val, 1);
|
||||
}
|
||||
|
||||
function testStorageReadInt() public {
|
||||
int256 val = stdstore.target(address(test)).sig(test.tG.selector).read_int();
|
||||
assertEq(val, type(int256).min);
|
||||
}
|
||||
}
|
||||
|
||||
contract StorageTest {
|
||||
uint256 public exists = 1;
|
||||
mapping(address => uint256) public map_addr;
|
||||
mapping(uint256 => uint256) public map_uint;
|
||||
mapping(address => uint256) public map_packed;
|
||||
mapping(address => UnpackedStruct) public map_struct;
|
||||
mapping(address => mapping(address => uint256)) public deep_map;
|
||||
mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
|
||||
UnpackedStruct public basic;
|
||||
|
||||
uint248 public tA;
|
||||
bool public tB;
|
||||
|
||||
bool public tC = false;
|
||||
uint248 public tD = 1;
|
||||
|
||||
struct UnpackedStruct {
|
||||
uint256 a;
|
||||
uint256 b;
|
||||
}
|
||||
|
||||
mapping(address => bool) public map_bool;
|
||||
|
||||
bytes32 public tE = hex"1337";
|
||||
address public tF = address(1337);
|
||||
int256 public tG = type(int256).min;
|
||||
bool public tH = true;
|
||||
|
||||
constructor() {
|
||||
basic = UnpackedStruct({a: 1337, b: 1337});
|
||||
|
||||
uint256 two = (1 << 128) | 1;
|
||||
map_packed[msg.sender] = two;
|
||||
map_packed[address(uint160(1337))] = 1 << 128;
|
||||
}
|
||||
|
||||
function read_struct_upper(address who) public view returns (uint256) {
|
||||
return map_packed[who] >> 128;
|
||||
}
|
||||
|
||||
function read_struct_lower(address who) public view returns (uint256) {
|
||||
return map_packed[who] & ((1 << 128) - 1);
|
||||
}
|
||||
|
||||
function hidden() public view returns (bytes32 t) {
|
||||
bytes32 slot = keccak256("my.random.var");
|
||||
/// @solidity memory-safe-assembly
|
||||
assembly {
|
||||
t := sload(slot)
|
||||
}
|
||||
}
|
||||
|
||||
function const() public pure returns (bytes32 t) {
|
||||
t = bytes32(hex"1337");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
import "../src/Test.sol";
|
||||
|
||||
contract StdUtilsMock is StdUtils {
|
||||
// We deploy a mock version so we can properly test expected reverts.
|
||||
function getTokenBalances_(address token, address[] memory addresses)
|
||||
external
|
||||
returns (uint256[] memory balances)
|
||||
{
|
||||
return getTokenBalances(token, addresses);
|
||||
}
|
||||
}
|
||||
|
||||
contract StdUtilsTest is Test {
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
BOUND UINT
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testBound() public {
|
||||
assertEq(bound(uint256(5), 0, 4), 0);
|
||||
assertEq(bound(uint256(0), 69, 69), 69);
|
||||
assertEq(bound(uint256(0), 68, 69), 68);
|
||||
assertEq(bound(uint256(10), 150, 190), 174);
|
||||
assertEq(bound(uint256(300), 2800, 3200), 3107);
|
||||
assertEq(bound(uint256(9999), 1337, 6666), 4669);
|
||||
}
|
||||
|
||||
function testBound_WithinRange() public {
|
||||
assertEq(bound(uint256(51), 50, 150), 51);
|
||||
assertEq(bound(uint256(51), 50, 150), bound(bound(uint256(51), 50, 150), 50, 150));
|
||||
assertEq(bound(uint256(149), 50, 150), 149);
|
||||
assertEq(bound(uint256(149), 50, 150), bound(bound(uint256(149), 50, 150), 50, 150));
|
||||
}
|
||||
|
||||
function testBound_EdgeCoverage() public {
|
||||
assertEq(bound(uint256(0), 50, 150), 50);
|
||||
assertEq(bound(uint256(1), 50, 150), 51);
|
||||
assertEq(bound(uint256(2), 50, 150), 52);
|
||||
assertEq(bound(uint256(3), 50, 150), 53);
|
||||
assertEq(bound(type(uint256).max, 50, 150), 150);
|
||||
assertEq(bound(type(uint256).max - 1, 50, 150), 149);
|
||||
assertEq(bound(type(uint256).max - 2, 50, 150), 148);
|
||||
assertEq(bound(type(uint256).max - 3, 50, 150), 147);
|
||||
}
|
||||
|
||||
function testBound_DistributionIsEven(uint256 min, uint256 size) public {
|
||||
size = size % 100 + 1;
|
||||
min = bound(min, UINT256_MAX / 2, UINT256_MAX / 2 + size);
|
||||
uint256 max = min + size - 1;
|
||||
uint256 result;
|
||||
|
||||
for (uint256 i = 1; i <= size * 4; ++i) {
|
||||
// x > max
|
||||
result = bound(max + i, min, max);
|
||||
assertEq(result, min + (i - 1) % size);
|
||||
// x < min
|
||||
result = bound(min - i, min, max);
|
||||
assertEq(result, max - (i - 1) % size);
|
||||
}
|
||||
}
|
||||
|
||||
function testBound(uint256 num, uint256 min, uint256 max) public {
|
||||
if (min > max) (min, max) = (max, min);
|
||||
|
||||
uint256 result = bound(num, min, max);
|
||||
|
||||
assertGe(result, min);
|
||||
assertLe(result, max);
|
||||
assertEq(result, bound(result, min, max));
|
||||
if (num >= min && num <= max) assertEq(result, num);
|
||||
}
|
||||
|
||||
function testBoundUint256Max() public {
|
||||
assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1);
|
||||
assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max);
|
||||
}
|
||||
|
||||
function testCannotBoundMaxLessThanMin() public {
|
||||
vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
|
||||
bound(uint256(5), 100, 10);
|
||||
}
|
||||
|
||||
function testCannotBoundMaxLessThanMin(uint256 num, uint256 min, uint256 max) public {
|
||||
vm.assume(min > max);
|
||||
vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
|
||||
bound(num, min, max);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
BOUND INT
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testBoundInt() public {
|
||||
assertEq(bound(-3, 0, 4), 2);
|
||||
assertEq(bound(0, -69, -69), -69);
|
||||
assertEq(bound(0, -69, -68), -68);
|
||||
assertEq(bound(-10, 150, 190), 154);
|
||||
assertEq(bound(-300, 2800, 3200), 2908);
|
||||
assertEq(bound(9999, -1337, 6666), 1995);
|
||||
}
|
||||
|
||||
function testBoundInt_WithinRange() public {
|
||||
assertEq(bound(51, -50, 150), 51);
|
||||
assertEq(bound(51, -50, 150), bound(bound(51, -50, 150), -50, 150));
|
||||
assertEq(bound(149, -50, 150), 149);
|
||||
assertEq(bound(149, -50, 150), bound(bound(149, -50, 150), -50, 150));
|
||||
}
|
||||
|
||||
function testBoundInt_EdgeCoverage() public {
|
||||
assertEq(bound(type(int256).min, -50, 150), -50);
|
||||
assertEq(bound(type(int256).min + 1, -50, 150), -49);
|
||||
assertEq(bound(type(int256).min + 2, -50, 150), -48);
|
||||
assertEq(bound(type(int256).min + 3, -50, 150), -47);
|
||||
assertEq(bound(type(int256).min, 10, 150), 10);
|
||||
assertEq(bound(type(int256).min + 1, 10, 150), 11);
|
||||
assertEq(bound(type(int256).min + 2, 10, 150), 12);
|
||||
assertEq(bound(type(int256).min + 3, 10, 150), 13);
|
||||
|
||||
assertEq(bound(type(int256).max, -50, 150), 150);
|
||||
assertEq(bound(type(int256).max - 1, -50, 150), 149);
|
||||
assertEq(bound(type(int256).max - 2, -50, 150), 148);
|
||||
assertEq(bound(type(int256).max - 3, -50, 150), 147);
|
||||
assertEq(bound(type(int256).max, -50, -10), -10);
|
||||
assertEq(bound(type(int256).max - 1, -50, -10), -11);
|
||||
assertEq(bound(type(int256).max - 2, -50, -10), -12);
|
||||
assertEq(bound(type(int256).max - 3, -50, -10), -13);
|
||||
}
|
||||
|
||||
function testBoundInt_DistributionIsEven(int256 min, uint256 size) public {
|
||||
size = size % 100 + 1;
|
||||
min = bound(min, -int256(size / 2), int256(size - size / 2));
|
||||
int256 max = min + int256(size) - 1;
|
||||
int256 result;
|
||||
|
||||
for (uint256 i = 1; i <= size * 4; ++i) {
|
||||
// x > max
|
||||
result = bound(max + int256(i), min, max);
|
||||
assertEq(result, min + int256((i - 1) % size));
|
||||
// x < min
|
||||
result = bound(min - int256(i), min, max);
|
||||
assertEq(result, max - int256((i - 1) % size));
|
||||
}
|
||||
}
|
||||
|
||||
function testBoundInt(int256 num, int256 min, int256 max) public {
|
||||
if (min > max) (min, max) = (max, min);
|
||||
|
||||
int256 result = bound(num, min, max);
|
||||
|
||||
assertGe(result, min);
|
||||
assertLe(result, max);
|
||||
assertEq(result, bound(result, min, max));
|
||||
if (num >= min && num <= max) assertEq(result, num);
|
||||
}
|
||||
|
||||
function testBoundIntInt256Max() public {
|
||||
assertEq(bound(0, type(int256).max - 1, type(int256).max), type(int256).max - 1);
|
||||
assertEq(bound(1, type(int256).max - 1, type(int256).max), type(int256).max);
|
||||
}
|
||||
|
||||
function testBoundIntInt256Min() public {
|
||||
assertEq(bound(0, type(int256).min, type(int256).min + 1), type(int256).min);
|
||||
assertEq(bound(1, type(int256).min, type(int256).min + 1), type(int256).min + 1);
|
||||
}
|
||||
|
||||
function testCannotBoundIntMaxLessThanMin() public {
|
||||
vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
|
||||
bound(-5, 100, 10);
|
||||
}
|
||||
|
||||
function testCannotBoundIntMaxLessThanMin(int256 num, int256 min, int256 max) public {
|
||||
vm.assume(min > max);
|
||||
vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
|
||||
bound(num, min, max);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
BYTES TO UINT
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testBytesToUint() external {
|
||||
bytes memory maxUint = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
||||
bytes memory two = hex"02";
|
||||
bytes memory millionEther = hex"d3c21bcecceda1000000";
|
||||
|
||||
assertEq(bytesToUint(maxUint), type(uint256).max);
|
||||
assertEq(bytesToUint(two), 2);
|
||||
assertEq(bytesToUint(millionEther), 1_000_000 ether);
|
||||
}
|
||||
|
||||
function testCannotConvertGT32Bytes() external {
|
||||
bytes memory thirty3Bytes = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
||||
vm.expectRevert("StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
|
||||
bytesToUint(thirty3Bytes);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
COMPUTE CREATE ADDRESS
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testComputeCreateAddress() external {
|
||||
address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
|
||||
uint256 nonce = 14;
|
||||
address createAddress = computeCreateAddress(deployer, nonce);
|
||||
assertEq(createAddress, 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
COMPUTE CREATE2 ADDRESS
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
function testComputeCreate2Address() external {
|
||||
bytes32 salt = bytes32(uint256(31415));
|
||||
bytes32 initcodeHash = keccak256(abi.encode(0x6080));
|
||||
address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
|
||||
address create2Address = computeCreate2Address(salt, initcodeHash, deployer);
|
||||
assertEq(create2Address, 0xB147a5d25748fda14b463EB04B111027C290f4d3);
|
||||
}
|
||||
|
||||
function testComputeCreate2AddressWithDefaultDeployer() external {
|
||||
bytes32 salt = 0xc290c670fde54e5ef686f9132cbc8711e76a98f0333a438a92daa442c71403c0;
|
||||
bytes32 initcodeHash = hashInitCode(hex"6080", "");
|
||||
assertEq(initcodeHash, 0x1a578b7a4b0b5755db6d121b4118d4bc68fe170dca840c59bc922f14175a76b0);
|
||||
address create2Address = computeCreate2Address(salt, initcodeHash);
|
||||
assertEq(create2Address, 0xc0ffEe2198a06235aAbFffe5Db0CacF1717f5Ac6);
|
||||
}
|
||||
}
|
||||
|
||||
contract StdUtilsForkTest is Test {
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
GET TOKEN BALANCES
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
address internal SHIB = 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE;
|
||||
address internal SHIB_HOLDER_0 = 0x855F5981e831D83e6A4b4EBFCAdAa68D92333170;
|
||||
address internal SHIB_HOLDER_1 = 0x8F509A90c2e47779cA408Fe00d7A72e359229AdA;
|
||||
address internal SHIB_HOLDER_2 = 0x0e3bbc0D04fF62211F71f3e4C45d82ad76224385;
|
||||
|
||||
address internal USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
|
||||
address internal USDC_HOLDER_0 = 0xDa9CE944a37d218c3302F6B82a094844C6ECEb17;
|
||||
address internal USDC_HOLDER_1 = 0x3e67F4721E6d1c41a015f645eFa37BEd854fcf52;
|
||||
|
||||
function setUp() public {
|
||||
// All tests of the `getTokenBalances` method are fork tests using live contracts.
|
||||
vm.createSelectFork({urlOrAlias: "mainnet", blockNumber: 16_428_900});
|
||||
}
|
||||
|
||||
function testCannotGetTokenBalances_NonTokenContract() external {
|
||||
// We deploy a mock version so we can properly test the revert.
|
||||
StdUtilsMock stdUtils = new StdUtilsMock();
|
||||
|
||||
// The UniswapV2Factory contract has neither a `balanceOf` function nor a fallback function,
|
||||
// so the `balanceOf` call should revert.
|
||||
address token = address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
|
||||
address[] memory addresses = new address[](1);
|
||||
addresses[0] = USDC_HOLDER_0;
|
||||
|
||||
vm.expectRevert("Multicall3: call failed");
|
||||
stdUtils.getTokenBalances_(token, addresses);
|
||||
}
|
||||
|
||||
function testCannotGetTokenBalances_EOA() external {
|
||||
address eoa = vm.addr({privateKey: 1});
|
||||
address[] memory addresses = new address[](1);
|
||||
addresses[0] = USDC_HOLDER_0;
|
||||
vm.expectRevert("StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
|
||||
getTokenBalances(eoa, addresses);
|
||||
}
|
||||
|
||||
function testGetTokenBalances_Empty() external {
|
||||
address[] memory addresses = new address[](0);
|
||||
uint256[] memory balances = getTokenBalances(USDC, addresses);
|
||||
assertEq(balances.length, 0);
|
||||
}
|
||||
|
||||
function testGetTokenBalances_USDC() external {
|
||||
address[] memory addresses = new address[](2);
|
||||
addresses[0] = USDC_HOLDER_0;
|
||||
addresses[1] = USDC_HOLDER_1;
|
||||
uint256[] memory balances = getTokenBalances(USDC, addresses);
|
||||
assertEq(balances[0], 159_000_000_000_000);
|
||||
assertEq(balances[1], 131_350_000_000_000);
|
||||
}
|
||||
|
||||
function testGetTokenBalances_SHIB() external {
|
||||
address[] memory addresses = new address[](3);
|
||||
addresses[0] = SHIB_HOLDER_0;
|
||||
addresses[1] = SHIB_HOLDER_1;
|
||||
addresses[2] = SHIB_HOLDER_2;
|
||||
uint256[] memory balances = getTokenBalances(SHIB, addresses);
|
||||
assertEq(balances[0], 3_323_256_285_484.42e18);
|
||||
assertEq(balances[1], 1_271_702_771_149.99999928e18);
|
||||
assertEq(balances[2], 606_357_106_247e18);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.6.2 <0.9.0;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../src/Script.sol";
|
||||
|
||||
// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
|
||||
// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
|
||||
contract CompilationScript is Script {}
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.6.2 <0.9.0;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../src/Script.sol";
|
||||
|
||||
// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
|
||||
// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
|
||||
contract CompilationScriptBase is ScriptBase {}
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.6.2 <0.9.0;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../src/Test.sol";
|
||||
|
||||
// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
|
||||
// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
|
||||
contract CompilationTest is Test {}
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.6.2 <0.9.0;
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../src/Test.sol";
|
||||
|
||||
// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
|
||||
// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
|
||||
contract CompilationTestBase is TestBase {}
|
187
advanced_expert/foundry_exploits/lib/forge-std/test/fixtures/broadcast.log.json
vendored
Normal file
187
advanced_expert/foundry_exploits/lib/forge-std/test/fixtures/broadcast.log.json
vendored
Normal file
|
@ -0,0 +1,187 @@
|
|||
{
|
||||
"transactions": [
|
||||
{
|
||||
"hash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
|
||||
"type": "CALL",
|
||||
"contractName": "Test",
|
||||
"contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"function": "multiple_arguments(uint256,address,uint256[]):(uint256)",
|
||||
"arguments": ["1", "0000000000000000000000000000000000001337", "[3,4]"],
|
||||
"tx": {
|
||||
"type": "0x02",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"gas": "0x73b9",
|
||||
"value": "0x0",
|
||||
"data": "0x23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004",
|
||||
"nonce": "0x3",
|
||||
"accessList": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"hash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
|
||||
"type": "CALL",
|
||||
"contractName": "Test",
|
||||
"contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"function": "inc():(uint256)",
|
||||
"arguments": [],
|
||||
"tx": {
|
||||
"type": "0x02",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"gas": "0xdcb2",
|
||||
"value": "0x0",
|
||||
"data": "0x371303c0",
|
||||
"nonce": "0x4",
|
||||
"accessList": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"hash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
|
||||
"type": "CALL",
|
||||
"contractName": "Test",
|
||||
"contractAddress": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
|
||||
"function": "t(uint256):(uint256)",
|
||||
"arguments": ["1"],
|
||||
"tx": {
|
||||
"type": "0x02",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
|
||||
"gas": "0x8599",
|
||||
"value": "0x0",
|
||||
"data": "0xafe29f710000000000000000000000000000000000000000000000000000000000000001",
|
||||
"nonce": "0x5",
|
||||
"accessList": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"receipts": [
|
||||
{
|
||||
"transactionHash": "0x481dc86e40bba90403c76f8e144aa9ff04c1da2164299d0298573835f0991181",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0xef0730448490304e5403be0fa8f8ce64f118e9adcca60c07a2ae1ab921d748af",
|
||||
"blockNumber": "0x1",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": null,
|
||||
"cumulativeGasUsed": "0x13f3a",
|
||||
"gasUsed": "0x13f3a",
|
||||
"contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0x6a187183545b8a9e7f1790e847139379bf5622baff2cb43acf3f5c79470af782",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0xf3acb96a90071640c2a8c067ae4e16aad87e634ea8d8bbbb5b352fba86ba0148",
|
||||
"blockNumber": "0x2",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": null,
|
||||
"cumulativeGasUsed": "0x45d80",
|
||||
"gasUsed": "0x45d80",
|
||||
"contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0x064ad173b4867bdef2fb60060bbdaf01735fbf10414541ea857772974e74ea9d",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0x8373d02109d3ee06a0225f23da4c161c656ccc48fe0fcee931d325508ae73e58",
|
||||
"blockNumber": "0x3",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0x4e59b44847b379578588920ca78fbf26c0b4956c",
|
||||
"cumulativeGasUsed": "0x45feb",
|
||||
"gasUsed": "0x45feb",
|
||||
"contractAddress": null,
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0x16712fae5c0e18f75045f84363fb6b4d9a9fe25e660c4ce286833a533c97f629",
|
||||
"blockNumber": "0x4",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"cumulativeGasUsed": "0x5905",
|
||||
"gasUsed": "0x5905",
|
||||
"contractAddress": null,
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0x156b88c3eb9a1244ba00a1834f3f70de735b39e3e59006dd03af4fe7d5480c11",
|
||||
"blockNumber": "0x5",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
|
||||
"cumulativeGasUsed": "0xa9c4",
|
||||
"gasUsed": "0xa9c4",
|
||||
"contractAddress": null,
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
|
||||
"blockNumber": "0x6",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
|
||||
"cumulativeGasUsed": "0x66c5",
|
||||
"gasUsed": "0x66c5",
|
||||
"contractAddress": null,
|
||||
"logs": [
|
||||
{
|
||||
"address": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
|
||||
"topics": [
|
||||
"0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b"
|
||||
],
|
||||
"data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000",
|
||||
"blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
|
||||
"blockNumber": "0x6",
|
||||
"transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
|
||||
"transactionIndex": "0x1",
|
||||
"logIndex": "0x0",
|
||||
"transactionLogIndex": "0x0",
|
||||
"removed": false
|
||||
}
|
||||
],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
},
|
||||
{
|
||||
"transactionHash": "0x11fbb10230c168ca1e36a7e5c69a6dbcd04fd9e64ede39d10a83e36ee8065c16",
|
||||
"transactionIndex": "0x0",
|
||||
"blockHash": "0xf1e0ed2eda4e923626ec74621006ed50b3fc27580dc7b4cf68a07ca77420e29c",
|
||||
"blockNumber": "0x7",
|
||||
"from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
|
||||
"to": "0x0000000000000000000000000000000000001337",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"gasUsed": "0x5208",
|
||||
"contractAddress": null,
|
||||
"logs": [],
|
||||
"status": "0x1",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"effectiveGasPrice": "0xee6b2800"
|
||||
}
|
||||
],
|
||||
"libraries": [
|
||||
"src/Broadcast.t.sol:F:0x5fbdb2315678afecb367f032d93f642f64180aa3"
|
||||
],
|
||||
"pending": [],
|
||||
"path": "broadcast/Broadcast.t.sol/31337/run-latest.json",
|
||||
"returns": {},
|
||||
"timestamp": 1655140035
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue