From 17cb1d904896291e6a9d6042f00a7f3b747322bf Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:15:54 -0500 Subject: [PATCH 01/15] created test contract --- .../protocol/test-sol/common/GasPriceMinimum.t.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 packages/protocol/test-sol/common/GasPriceMinimum.t.sol diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol new file mode 100644 index 00000000000..c9793b934bd --- /dev/null +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.7 <0.8.20; + +import "celo-foundry/Test.sol"; +import "forge-std/console.sol"; + +// Contract to test +import "../../contracts-0.8/common/GasPriceMinimum.sol"; + +contract GasPriceMinimumTest is Test {} From 10e3970741a3a4c963e7b8055b6459d72ca9a33d Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:31:03 -0500 Subject: [PATCH 02/15] add openzeppelin-contracts < 0.8.20 --- .gitmodules | 3 +++ packages/protocol/lib/openzeppelin-contracts8 | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/protocol/lib/openzeppelin-contracts8 diff --git a/.gitmodules b/.gitmodules index 7eaacd704b8..8e41b2f2883 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "packages/protocol/lib/memview.sol"] path = packages/protocol/lib/memview.sol url = https://github.com/summa-tx/memview.sol +[submodule "packages/protocol/lib/openzeppelin-contracts8"] + path = packages/protocol/lib/openzeppelin-contracts8 + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/packages/protocol/lib/openzeppelin-contracts8 b/packages/protocol/lib/openzeppelin-contracts8 new file mode 160000 index 00000000000..b53c43242fc --- /dev/null +++ b/packages/protocol/lib/openzeppelin-contracts8 @@ -0,0 +1 @@ +Subproject commit b53c43242fc9c0e435b66178c3847c4a1b417cc1 From d9a9bcac0a4142a4997ba7c07b4e6a815bfb5bf1 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:11:30 -0500 Subject: [PATCH 03/15] added latest forge test submodule --- .gitmodules | 3 +++ packages/protocol/foundry.toml | 2 ++ packages/protocol/lib/forge-std | 1 + 3 files changed, 6 insertions(+) create mode 160000 packages/protocol/lib/forge-std diff --git a/.gitmodules b/.gitmodules index 8e41b2f2883..e8619f9d9b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "packages/protocol/lib/openzeppelin-contracts8"] path = packages/protocol/lib/openzeppelin-contracts8 url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "packages/protocol/lib/forge-std"] + path = packages/protocol/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/packages/protocol/foundry.toml b/packages/protocol/foundry.toml index 4ea48658d7e..e578060431b 100644 --- a/packages/protocol/foundry.toml +++ b/packages/protocol/foundry.toml @@ -4,9 +4,11 @@ out = 'out' test = 'test-sol' libs = ['lib', 'node_modules'] remappings = [ + '@openzeppelin/contracts8/=lib/openzeppelin-contracts8/contracts/', 'openzeppelin-solidity/=lib/openzeppelin-contracts/', 'solidity-bytes-utils/=lib/solidity-bytes-utils/', 'forge-std/=lib/celo-foundry/lib/forge-std/src/', + 'forge-std8/=lib/forge-std/src/', 'ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/', 'celo-foundry/=lib/celo-foundry/src/', '@summa-tx/memview.sol/=lib/memview.sol', diff --git a/packages/protocol/lib/forge-std b/packages/protocol/lib/forge-std new file mode 160000 index 00000000000..2f112697506 --- /dev/null +++ b/packages/protocol/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 2f112697506eab12d433a65fdc31a639548fe365 From 5fff5d65f248940d163c413abc6786a00782fd45 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:13:29 -0500 Subject: [PATCH 04/15] pragma 0.8 support celo in foundry test --- .../common/test/PrecompileHandler.sol | 180 ++++++++++++++++++ .../test-sol/common/test/Precompiles.sol | 15 ++ .../protocol/test-sol/common/test/Test.sol | 102 ++++++++++ 3 files changed, 297 insertions(+) create mode 100644 packages/protocol/test-sol/common/test/PrecompileHandler.sol create mode 100644 packages/protocol/test-sol/common/test/Precompiles.sol create mode 100644 packages/protocol/test-sol/common/test/Test.sol diff --git a/packages/protocol/test-sol/common/test/PrecompileHandler.sol b/packages/protocol/test-sol/common/test/PrecompileHandler.sol new file mode 100644 index 00000000000..5b19caf112f --- /dev/null +++ b/packages/protocol/test-sol/common/test/PrecompileHandler.sol @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.5.13 <0.8.20; + +import "forge-std8/Vm.sol"; +import "forge-std8/console2.sol"; +import "./Precompiles.sol"; + +contract PrecompileHandler is Precompiles { + address constant private VM_ADDRESS = + address(bytes20(uint160(uint256(keccak256('hevm cheat code'))))); + + Vm public constant vm = Vm(VM_ADDRESS); + + bytes4 constant TRANSFER_SIG = bytes4(keccak256("transfer(address,address,uint256)")); + bytes4 constant EPOCH_SIZE_SIG = bytes4(keccak256("epochSize()")); + bytes4 constant CATCHALL_SIG = bytes4(keccak256("catchAll()")); + + uint256 public epochSize = 17280; + bool public debug = false; + + struct Mock { + bool success; + bytes returnData; + bool exists; + } + + mapping(address => mapping(bytes32 => Mock)) private mockedCalls; + bytes private _empty; + Mock private successMock = Mock(true, _empty, true); + Mock private revertMock = Mock(true, _empty, true); + + constructor() public { + vm.etch(TRANSFER, proxyTo(TRANSFER_SIG)); + vm.label(TRANSFER, "TRANSFER"); + + vm.etch(EPOCH_SIZE, proxyTo(EPOCH_SIZE_SIG)); + vm.label(EPOCH_SIZE, "EPOCH_SIZE"); + + bytes memory catchAllProxy = proxyTo(CATCHALL_SIG); + vm.etch(FRACTION_MUL, catchAllProxy); + vm.label(FRACTION_MUL, "FRACTION_MUL"); + + vm.etch(PROOF_OF_POSSESSION, catchAllProxy); + vm.label(PROOF_OF_POSSESSION, "PROOF_OF_POSSESSION"); + + vm.etch(GET_VALIDATOR, catchAllProxy); + vm.label(GET_VALIDATOR, "GET_VALIDATOR"); + + vm.etch(NUMBER_VALIDATORS, catchAllProxy); + vm.label(NUMBER_VALIDATORS, "NUMBER_VALIDATORS"); + + vm.etch(BLOCK_NUMBER_FROM_HEADER, catchAllProxy); + vm.label(BLOCK_NUMBER_FROM_HEADER, "BLOCK_NUMBER_FROM_HEADER"); + + vm.etch(HASH_HEADER, catchAllProxy); + vm.label(HASH_HEADER, "HASH_HEADER"); + + vm.etch(GET_PARENT_SEAL_BITMAP, catchAllProxy); + vm.label(GET_PARENT_SEAL_BITMAP, "GET_PARENT_SEAL_BITMAP"); + + vm.etch(GET_VERIFIED_SEAL_BITMAP, catchAllProxy); + vm.label(GET_VERIFIED_SEAL_BITMAP, "GET_VERIFIED_SEAL_BITMAP"); + } + + function transfer(address from, address to, uint256 amount) public returns (bool) { + vm.deal(from, from.balance - amount); + vm.deal(to, to.balance + amount); + return true; + } + + function setEpochSize(uint256 epochSize_) public { + epochSize = epochSize_; + } + + function setDebug(bool debug_) public { + debug = debug_; + } + + function mockSuccess(address prec, bytes32 callHash) public { + setMock(prec, callHash, successMock); + + if (debug) { + console2.log("Mock success"); + console2.log(prec); + console2.logBytes32(callHash); + } + } + + function mockRevert(address prec, bytes32 callHash) public { + setMock(prec, callHash, revertMock); + + if (debug) { + console2.log("Mock revert"); + console2.log(prec); + console2.logBytes32(callHash); + } + } + + function mockReturn(address prec, bytes32 callHash, bytes memory returnData) public { + setMock(prec, callHash, Mock(true, returnData, true)); + + if (debug) { + console2.log("Mock success with data"); + console2.log(prec); + console2.logBytes32(callHash); + console2.logBytes(returnData); + } + } + + function clearMock(address prec, bytes32 callHash) public { + delete mockedCalls[prec][callHash]; + } + + function setMock(address prec, bytes32 callHash, Mock memory mock) internal { + require( + prec >= GET_VERIFIED_SEAL_BITMAP && + prec <= TRANSFER, + "precompile not supported" + ); + + mockedCalls[prec][callHash] = mock; + } + + function catchAll() public view { + bytes memory cd; + assembly { + cd := mload(0x40) + let cds := sub(calldatasize(), 0x4) + mstore(cd, cds) + calldatacopy(add(cd, 0x20), 0x4, cds) + mstore(0x40, add(cd, add(cds, 0x20))) + } + + bytes32 cdh = keccak256(cd); + Mock memory mock = mockedCalls[msg.sender][cdh]; + + if (mock.exists == false) { + console2.log(msg.sender); + console2.logBytes(cd); + console2.logBytes32(cdh); + revert("mock not defined for call"); + } + + if (mock.success == false) { + revert(); + } + + if (mock.returnData.length > 0) { + bytes memory returnData = mock.returnData; + assembly { + let rds := mload(returnData) + return(add(returnData, 0x20), rds) + } + } + } + + function proxyTo(bytes4 sig) internal view returns (bytes memory) { + address prec = address(this); + bytes memory ptr; + + assembly { + ptr := mload(0x40) + mstore(ptr, 0x60) + let mc := add(ptr, 0x20) + let addrPrefix := shl(0xf8, 0x73) + let addr := shl(0x58, prec) + let sigPrefix := shl(0x50, 0x63) + let shiftedSig := shl(0x30, shr(0xe0, sig)) + let suffix := 0x600060043601 + mstore(mc, or(addrPrefix, or(addr, or(sigPrefix, or(shiftedSig, suffix))))) + mc := add(mc, 0x20) + mstore(mc, 0x8260e01b82523660006004840137600080828434885af13d6000816000823e82) + mc := add(mc, 0x20) + mstore(mc, 0x60008114604a578282f35b8282fd000000000000000000000000000000000000) + mstore(0x40, add(ptr, 0x80)) + } + + return ptr; + } +} \ No newline at end of file diff --git a/packages/protocol/test-sol/common/test/Precompiles.sol b/packages/protocol/test-sol/common/test/Precompiles.sol new file mode 100644 index 00000000000..6f324a68331 --- /dev/null +++ b/packages/protocol/test-sol/common/test/Precompiles.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.5.13 <0.8.20; + +contract Precompiles { + address public constant TRANSFER = address(0xff - 2); + address public constant FRACTION_MUL = address(0xff - 3); + address public constant PROOF_OF_POSSESSION = address(0xff - 4); + address public constant GET_VALIDATOR = address(0xff - 5); + address public constant NUMBER_VALIDATORS = address(0xff - 6); + address public constant EPOCH_SIZE = address(0xff - 7); + address public constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8); + address public constant HASH_HEADER = address(0xff - 9); + address public constant GET_PARENT_SEAL_BITMAP = address(0xff - 10); + address public constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11); +} \ No newline at end of file diff --git a/packages/protocol/test-sol/common/test/Test.sol b/packages/protocol/test-sol/common/test/Test.sol new file mode 100644 index 00000000000..7281d746e3f --- /dev/null +++ b/packages/protocol/test-sol/common/test/Test.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.5.13 <0.8.20; + +import { Test as ForgeTest } from "forge-std8/Test.sol"; +import "./Precompiles.sol"; +import "./PrecompileHandler.sol"; + +contract Test is ForgeTest, Precompiles { + PrecompileHandler public ph; + address currentPrank; + + event log_named_array(string key, bytes32[] val); + event log_array(string key, address[] val); + event log_array(string key, bytes32[] val); + + constructor() public ForgeTest() { + ph = new PrecompileHandler(); + } + + /* Utility functions */ + + function changePrank(address who) internal virtual override { + // Record current prank so helper functions can revert + // if they need to prank + currentPrank = who; + super.changePrank(who); + } + + function actor(string memory name) public returns (address) { + uint256 pk = uint256(keccak256(bytes(name))); + address addr = vm.addr(pk); + vm.label(addr, name); + return addr; + } + + function actorWithPK(string memory name) public returns (address, uint256) { + uint256 pk = uint256(keccak256(bytes(name))); + address addr = vm.addr(pk); + vm.label(addr, name); + return (addr, pk); + } + + /* Extra assertions, extends forge-std/Test.sol */ + + function assertEq(address[] memory a, address[] memory b) internal virtual override { + if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { + emit log("Error: a == b not satisfied [address[]]"); + emit log_named_array(" Expected", b); + emit log_named_array(" Actual", a); + fail(); + } + } + + function assertEq( + address[] memory a, + address[] memory b, + string memory err + ) internal virtual override { + if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { + emit log_named_string("Error", err); + assertEq(a, b); + } + } + + function assertEq(bytes32[] memory a, bytes32[] memory b) internal { + if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { + emit log("Error: a == b not satisfied [bytes32[]]"); + emit log_named_array(" Expected", b); + emit log_named_array(" Actual", a); + fail(); + } + } + + function deployCodeTo(string memory what, address where) internal virtual override { + deployCodeTo(what, "", 0, where); + } + + function deployCodeTo( + string memory what, + bytes memory args, + address where + ) internal virtual override { + deployCodeTo(what, args, 0, where); + } + + function deployCodeTo( + string memory what, + bytes memory args, + uint256 value, + address where + ) internal virtual override { + bytes memory creationCode = vm.getCode(what); + vm.etch(where, abi.encodePacked(creationCode, args)); + // (bool success, bytes memory runtimeBytecode) = where.call.value(value)(""); + (bool success, bytes memory runtimeBytecode) = where.call{ value: value }(""); + require( + success, + "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode." + ); + vm.etch(where, runtimeBytecode); + } +} From eef733c001f4e2b45dc8615f8d8dfd16ea535424 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:13:56 -0500 Subject: [PATCH 05/15] first passing test --- .../contracts-0.8/common/Registry8.sol | 99 +++++++++++++++++++ .../test-sol/common/GasPriceMinimum.t.sol | 50 +++++++++- 2 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 packages/protocol/contracts-0.8/common/Registry8.sol diff --git a/packages/protocol/contracts-0.8/common/Registry8.sol b/packages/protocol/contracts-0.8/common/Registry8.sol new file mode 100644 index 00000000000..67b106c6102 --- /dev/null +++ b/packages/protocol/contracts-0.8/common/Registry8.sol @@ -0,0 +1,99 @@ +pragma solidity >=0.8.7 <0.8.20; + +import "@openzeppelin/contracts8/access/Ownable.sol"; + +import "../../contracts/common/interfaces/IRegistry.sol"; +import "../../contracts/common/Initializable.sol"; + +/** + * @title Routes identifiers to addresses. + */ +contract Registry8 is IRegistry, Ownable, Initializable { + + mapping(bytes32 => address) public registry; + + event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); + + /** + * @notice Sets initialized == true on implementation contracts + * @param test Set to true to skip implementation initialization + */ + constructor(bool test) public Initializable(test) {} + + /** + * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. + */ + function initialize() external initializer { + _transferOwnership(msg.sender); + } + + /** + * @notice Associates the given address with the given identifier. + * @param identifier Identifier of contract whose address we want to set. + * @param addr Address of contract. + */ + function setAddressFor(string calldata identifier, address addr) external onlyOwner { + bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); + registry[identifierHash] = addr; + emit RegistryUpdated(identifier, identifierHash, addr); + } + + /** + * @notice Gets address associated with the given identifierHash. + * @param identifierHash Identifier hash of contract whose address we want to look up. + * @dev Throws if address not set. + */ + function getAddressForOrDie(bytes32 identifierHash) external view returns (address) { + require(registry[identifierHash] != address(0), "identifier has no registry entry"); + return registry[identifierHash]; + } + + /** + * @notice Gets address associated with the given identifierHash. + * @param identifierHash Identifier hash of contract whose address we want to look up. + */ + function getAddressFor(bytes32 identifierHash) external view returns (address) { + return registry[identifierHash]; + } + + /** + * @notice Gets address associated with the given identifier. + * @param identifier Identifier of contract whose address we want to look up. + * @dev Throws if address not set. + */ + function getAddressForStringOrDie(string calldata identifier) external view returns (address) { + bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); + require(registry[identifierHash] != address(0), "identifier has no registry entry"); + return registry[identifierHash]; + } + + /** + * @notice Gets address associated with the given identifier. + * @param identifier Identifier of contract whose address we want to look up. + */ + function getAddressForString(string calldata identifier) external view returns (address) { + bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); + return registry[identifierHash]; + } + + /** + * @notice Iterates over provided array of identifiers, getting the address for each. + * Returns true if `sender` matches the address of one of the provided identifiers. + * @param identifierHashes Array of hashes of approved identifiers. + * @param sender Address in question to verify membership. + * @return True if `sender` corresponds to the address of any of `identifiers` + * registry entries. + */ + function isOneOf(bytes32[] calldata identifierHashes, address sender) + external + view + returns (bool) + { + for (uint256 i = 0; i < identifierHashes.length; i = i++) { + if (registry[identifierHashes[i]] == sender) { + return true; + } + } + return false; + } +} diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index c9793b934bd..7eb093eb74c 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -1,10 +1,54 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.7 <0.8.20; -import "celo-foundry/Test.sol"; -import "forge-std/console.sol"; +// import { Test as ForgeTest } from "forge-std/Test.sol"; +import "./test/Test.sol"; +import "forge-std8/console.sol"; +import "../../contracts/common/FixidityLib.sol"; +import "../../contracts-0.8/common/Registry8.sol"; // Contract to test import "../../contracts-0.8/common/GasPriceMinimum.sol"; -contract GasPriceMinimumTest is Test {} +contract GasPriceMinimumTest is Test { + using FixidityLib for FixidityLib.Fraction; + Registry8 registry; + GasPriceMinimum public gasPriceMinimum; + address owner; + + + + uint256 gasPriceMinimumFloor = 100; + uint256 initialGasPriceMinimum = gasPriceMinimumFloor; + uint256 targetDensity = FixidityLib.newFixedFraction(5, 10).unwrap(); + uint256 adjustmentSpeed = FixidityLib.newFixedFraction(5, 10).unwrap(); + + function setUp() public virtual { + owner = address(this); + address registryAddress = 0x000000000000000000000000000000000000ce10; + deployCodeTo("Registry8.sol", abi.encode(false), registryAddress); + gasPriceMinimum = new GasPriceMinimum(true); + + registry = Registry8(registryAddress); + + registry.setAddressFor("GasPriceMinimum", address(gasPriceMinimum)); + + gasPriceMinimum.initialize( + registryAddress, + gasPriceMinimumFloor, + targetDensity, + adjustmentSpeed, + 0 + ); + } +} + +contract GasPriceMinimumInitialize is GasPriceMinimumTest { + function setUp() public override { + super.setUp(); + } + + function test_shouldHaveSetOwner() public { + assertEq(gasPriceMinimum.owner(), owner); + } +} From 3c89b6218470d60ed2fd8de01d312a215b34b5f5 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 4 Dec 2023 19:28:59 -0500 Subject: [PATCH 06/15] fully migrated GasPriceMinimumTest --- .../test-sol/common/GasPriceMinimum.t.sol | 242 ++++++++++++++- .../protocol/test/common/gaspriceminimum.ts | 275 ------------------ 2 files changed, 237 insertions(+), 280 deletions(-) delete mode 100644 packages/protocol/test/common/gaspriceminimum.ts diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index 7eb093eb74c..204122b5f83 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.7 <0.8.20; -// import { Test as ForgeTest } from "forge-std/Test.sol"; import "./test/Test.sol"; -import "forge-std8/console.sol"; + import "../../contracts/common/FixidityLib.sol"; import "../../contracts-0.8/common/Registry8.sol"; @@ -12,20 +11,30 @@ import "../../contracts-0.8/common/GasPriceMinimum.sol"; contract GasPriceMinimumTest is Test { using FixidityLib for FixidityLib.Fraction; + Registry8 registry; GasPriceMinimum public gasPriceMinimum; address owner; - - + address nonOwner; uint256 gasPriceMinimumFloor = 100; uint256 initialGasPriceMinimum = gasPriceMinimumFloor; uint256 targetDensity = FixidityLib.newFixedFraction(5, 10).unwrap(); + FixidityLib.Fraction targetDensityFraction = FixidityLib.newFixedFraction(5, 10); uint256 adjustmentSpeed = FixidityLib.newFixedFraction(5, 10).unwrap(); + FixidityLib.Fraction adjustmentSpeedFraction = FixidityLib.newFixedFraction(5, 10); + address registryAddress = 0x000000000000000000000000000000000000ce10; + + event TargetDensitySet(uint256 targetDensity); + event GasPriceMinimumFloorSet(uint256 gasPriceMinimumFloor); + event AdjustmentSpeedSet(uint256 adjustmentSpeed); + event GasPriceMinimumUpdated(uint256 gasPriceMinimum); + event BaseFeeOpCodeActivationBlockSet(uint256 baseFeeOpCodeActivationBlock); function setUp() public virtual { owner = address(this); - address registryAddress = 0x000000000000000000000000000000000000ce10; + nonOwner = actor("nonOwner"); + deployCodeTo("Registry8.sol", abi.encode(false), registryAddress); gasPriceMinimum = new GasPriceMinimum(true); @@ -51,4 +60,227 @@ contract GasPriceMinimumInitialize is GasPriceMinimumTest { function test_shouldHaveSetOwner() public { assertEq(gasPriceMinimum.owner(), owner); } + + function test_shouldSetTheGasPriceMinimum() public { + assertEq(gasPriceMinimum.getGasPriceMinimum(address(0)), initialGasPriceMinimum); + } + + function test_shouldHaveTargetDensity() public { + assertEq(gasPriceMinimum.targetDensity(), targetDensity); + } + + function test_shouldHaveAdjustmentSpeed() public { + assertEq(gasPriceMinimum.adjustmentSpeed(), adjustmentSpeed); + } + + function test_shouldHaveGasPriceMinimumFloor() public { + assertEq(gasPriceMinimum.gasPriceMinimumFloor(), gasPriceMinimumFloor); + } + + function test_shouldRevertWhenCalledAgain() public { + vm.expectRevert("contract already initialized"); + gasPriceMinimum.initialize( + registryAddress, + gasPriceMinimumFloor, + targetDensity, + adjustmentSpeed, + 0 + ); + } +} + +contract GasPriceMinimumSetAdjustmentSpeed is GasPriceMinimumTest { + using FixidityLib for FixidityLib.Fraction; + + uint256 newAdjustmentSpeed = FixidityLib.newFixedFraction(1, 3).unwrap(); + + function setUp() public override { + super.setUp(); + } + + function test_shouldSetTheAdjustmentSpeed() public { + gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed); + + assertEq(gasPriceMinimum.adjustmentSpeed(), newAdjustmentSpeed); + } + + function test_shouldEmitAdjustmentSpeedSetEvent() public { + vm.expectEmit(true, false, false, false); + emit AdjustmentSpeedSet(newAdjustmentSpeed); + gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed); + } + + function test_shouldRevertWhenTheProvidedFractionIsGreaterThanOne() public { + vm.expectRevert("adjustment speed must be smaller than 1"); + gasPriceMinimum.setAdjustmentSpeed(FixidityLib.newFixedFraction(3, 2).unwrap()); + } + + function test_shouldRevertWhenCalledByNonOwner() public { + vm.prank(nonOwner); + vm.expectRevert("Ownable: caller is not the owner"); + gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed); + } +} + +contract GasPriceMinimumSetTargetDensity is GasPriceMinimumTest { + using FixidityLib for FixidityLib.Fraction; + + uint256 newTargetDensity = FixidityLib.newFixedFraction(1, 3).unwrap(); + + function test_shouldSetTargetDensity() public { + gasPriceMinimum.setTargetDensity(newTargetDensity); + assertEq(gasPriceMinimum.targetDensity(), newTargetDensity); + } + + function test_ShouldEmitTargetDensitySetEvent() public { + vm.expectEmit(true, true, true, true); + emit TargetDensitySet(newTargetDensity); + gasPriceMinimum.setTargetDensity(newTargetDensity); + } + + function test_ShouldRevertWhenProvidedFractionIsGreaterThanOne() public { + vm.expectRevert("target density must be smaller than 1"); + gasPriceMinimum.setTargetDensity(FixidityLib.newFixedFraction(3, 2).unwrap()); + } + + function test_ShouldRevertWhenCalledByNonOwner() public { + vm.prank(nonOwner); + vm.expectRevert("Ownable: caller is not the owner"); + gasPriceMinimum.setTargetDensity(newTargetDensity); + } +} + +contract GasPriceMinimumSetGasPriceMinimumFloor is GasPriceMinimumTest { + uint256 newGasPriceMinimumFloor = 150; + + function setUp() public override { + super.setUp(); + } + + function test_ShouldSetGasPriceMinimumFloor() public { + gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinimumFloor); + + assertEq(gasPriceMinimum.gasPriceMinimumFloor(), newGasPriceMinimumFloor); + } + + function test_emitsGasPriceMinimumFloorSet() public { + vm.expectEmit(true, true, true, true); + emit GasPriceMinimumFloorSet(newGasPriceMinimumFloor); + gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinimumFloor); + } + + function test_shouldRevertWhenProvidedFloorIsZero() public { + vm.expectRevert("gas price minimum floor must be greater than zero"); + gasPriceMinimum.setGasPriceMinimumFloor(0); + } + + function test_shouldRevertWhenCalledByNonOwner() public { + vm.prank(nonOwner); + vm.expectRevert("Ownable: caller is not the owner"); + gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinimumFloor); + } +} + +contract GasPriceMinimumGetUpdatedGasPriceMinimum is GasPriceMinimumTest { + using FixidityLib for FixidityLib.Fraction; + uint256 nonce = 0; + + function setUp() public override { + super.setUp(); + } + + function getExpectedUpdatedGasPriceMinimum( + uint256 gasPriceMinFloor, + uint256 previousGasPriceMinimum, + FixidityLib.Fraction memory density, + FixidityLib.Fraction memory _targetDensity, + FixidityLib.Fraction memory _adjustmentSpeed + ) public pure returns (uint256) { + uint256 one = 1; + uint256 newGasPriceMin = previousGasPriceMinimum * + one + + FixidityLib.fromFixed(_adjustmentSpeed) * + FixidityLib.fromFixed(density) - + FixidityLib.fromFixed(_targetDensity); + + return newGasPriceMin < gasPriceMinFloor ? gasPriceMinFloor : newGasPriceMin; + } + + function random(uint256 minNumber, uint256 maxNumber) public returns (uint256) { + nonce += 1; + if (minNumber > 0) { + return + (uint256(keccak256(abi.encodePacked(nonce, msg.sender, blockhash(block.number - 1)))) % + (maxNumber - 1)) + 1; + } + return (uint256(keccak256(abi.encodePacked(nonce, msg.sender, blockhash(block.number - 1)))) % + maxNumber); + } + + function test_shouldReturn25PercentMoreThanInitialMinimumAndShouldNotBeLimitedByGasPriceMinimumFloorAsAWhole_WhenTheBlockIsFull() + public + { + uint256 currentGasPriceMinimum = gasPriceMinimum.gasPriceMinimum(); + + gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum); + + uint256 expectedUpdatedGasPriceMinimum = (currentGasPriceMinimum * 5) / 4 + 1; + + assertEq(gasPriceMinimum.getUpdatedGasPriceMinimum(1, 1), expectedUpdatedGasPriceMinimum); + } + + function test_shouldReturn25PercentLessThanInitialMinimumButShouldBeLimitedByGasPriceMinimumFloorIfNewGasLiesBelowMinimum_WhenTheBlockIsEmtpy() + public + { + uint256 currentGasPriceMinimum = gasPriceMinimum.gasPriceMinimum(); + + gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum); + + uint256 expectedCappedUpdatedGasPriceMinimum = gasPriceMinimum.gasPriceMinimumFloor(); + + assertEq(gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1), expectedCappedUpdatedGasPriceMinimum); + } + + function test_shouldReturn25PercentLessThanInitialMinimumAndShouldNotBeLimitedByGasPriceMinimumFloorIfNewGasPriceLiesAboveMinimum_WhenTheBlockIsEmtpy() + public + { + uint256 currentGasPriceMinimum = gasPriceMinimum.gasPriceMinimum(); + + gasPriceMinimum.setGasPriceMinimumFloor(1); + + uint256 expectedUpdatedGasPriceMinimum = (currentGasPriceMinimum * 3) / 4 + 1; + + assertEq(gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1), expectedUpdatedGasPriceMinimum); + } + + function test_shouldReturnAnUpdatedGasPriceMinimumThatMatchesATypescriptImplementation_WhenTheFullnessOfTheBlockIsRandom() + public + { + uint256 numIterations = 100; + uint256 currentGasPriceMinimum = gasPriceMinimum.gasPriceMinimum(); + uint256 gasPriceMinFloor = currentGasPriceMinimum; + gasPriceMinimum.setGasPriceMinimumFloor(gasPriceMinFloor); + + for (uint256 i = 0; i < numIterations; i++) { + uint256 currGas = gasPriceMinimum.gasPriceMinimum(); + + uint256 blockGasLimit = random(1, 105); + uint256 gasUsed = random(0, 1) * blockGasLimit; + + uint256 actualUpdatedGasPriceMinimum = gasPriceMinimum.getUpdatedGasPriceMinimum( + gasUsed, + blockGasLimit + ); + + uint256 expectedUpdatedGasPriceMinimum = getExpectedUpdatedGasPriceMinimum( + gasPriceMinFloor, + currGas, + FixidityLib.newFixedFraction(gasUsed, blockGasLimit), + targetDensityFraction, + adjustmentSpeedFraction + ); + + assertEq(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum); + } + } } diff --git a/packages/protocol/test/common/gaspriceminimum.ts b/packages/protocol/test/common/gaspriceminimum.ts deleted file mode 100644 index 990e39607ce..00000000000 --- a/packages/protocol/test/common/gaspriceminimum.ts +++ /dev/null @@ -1,275 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { - assertEqualBN, - assertLogMatches2, - assertTransactionRevertWithReason, -} from '@celo/protocol/lib/test-utils' -import { fromFixed, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import { RegistryContract, RegistryInstance } from 'types' -import { GasPriceMinimumContract, GasPriceMinimumInstance } from 'types/08' -import { SOLIDITY_08_PACKAGE } from '../../contractPackages' -import { ArtifactsSingleton } from '../../lib/artifactsSingleton' - -const Registry: RegistryContract = artifacts.require('Registry') -const GasPriceMinimum: GasPriceMinimumContract = - ArtifactsSingleton.getInstance(SOLIDITY_08_PACKAGE).require('GasPriceMinimum') - -// @ts-ignore -// TODO(mcortesi): Use BN -GasPriceMinimum.numberFormat = 'BigNumber' - -contract('GasPriceMinimum', (accounts: string[]) => { - let gasPriceMinimum: GasPriceMinimumInstance - let registry: RegistryInstance - const nonOwner = accounts[1] - const gasPriceMinimumFloor = new BigNumber(100) - const initialGasPriceMinimum = gasPriceMinimumFloor - const targetDensity = toFixed(1 / 2) - const adjustmentSpeed = toFixed(1 / 2) - - beforeEach(async () => { - registry = await Registry.new(true) - gasPriceMinimum = await GasPriceMinimum.new(true) - - await gasPriceMinimum.initialize( - registry.address, - gasPriceMinimumFloor, - targetDensity, - adjustmentSpeed, - 0 - ) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await gasPriceMinimum.owner() - assert.equal(owner, accounts[0]) - }) - - it('should set the gas price minimum', async () => { - const actualGasPriceMinimum = await gasPriceMinimum.getGasPriceMinimum(NULL_ADDRESS) - assertEqualBN(actualGasPriceMinimum, initialGasPriceMinimum) - }) - - it('should set the target density', async () => { - const actualTargetDensity = await gasPriceMinimum.targetDensity() - assertEqualBN(actualTargetDensity, targetDensity) - }) - - it('should set the adjustment speed', async () => { - const actualAdjustmentSpeed = await gasPriceMinimum.adjustmentSpeed() - assertEqualBN(actualAdjustmentSpeed, adjustmentSpeed) - }) - - it('should set the gas price minimum floor', async () => { - const actualGasPriceMinimumFloor = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualGasPriceMinimumFloor, gasPriceMinimumFloor) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.initialize( - registry.address, - gasPriceMinimumFloor, - targetDensity, - adjustmentSpeed, - 0 - ), - 'contract already initialized' - ) - }) - }) - - describe('#setAdjustmentSpeed', () => { - const newAdjustmentSpeed = toFixed(1 / 3) - - it('should set the adjustment speed', async () => { - await gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed) - const actualAdjustmentSpeed = await gasPriceMinimum.adjustmentSpeed() - assertEqualBN(actualAdjustmentSpeed, newAdjustmentSpeed) - }) - - it('should emit the AdjustmentSpeedSet event', async () => { - const resp = await gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'AdjustmentSpeedSet', - args: { - adjustmentSpeed: newAdjustmentSpeed, - }, - }) - }) - - it('should revert when the provided fraction is greater than one', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setAdjustmentSpeed(toFixed(3 / 2)), - 'adjustment speed must be smaller than 1' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed, { from: nonOwner }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setTargetDensity', () => { - const newTargetDensity = toFixed(1 / 3) - - it('should set the adjustment speed', async () => { - await gasPriceMinimum.setTargetDensity(newTargetDensity) - const actualTargetDensity = await gasPriceMinimum.targetDensity() - assertEqualBN(actualTargetDensity, newTargetDensity) - }) - - it('should emit the TargetDensitySet event', async () => { - const resp = await gasPriceMinimum.setTargetDensity(newTargetDensity) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'TargetDensitySet', - args: { - targetDensity: newTargetDensity, - }, - }) - }) - - it('should revert when the provided fraction is greater than one', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setTargetDensity(toFixed(3 / 2)), - 'target density must be smaller than 1' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setTargetDensity(newTargetDensity, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setGasPriceMinimumFloor', () => { - const newGasPriceMinFloor = new BigNumber(150) - - it('should set the minimum gas price floor', async () => { - await gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor) - const actualFloor = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualFloor, newGasPriceMinFloor) - }) - - it('should emit the MinimumGasPriceFloorSet event', async () => { - const resp = await gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'GasPriceMinimumFloorSet', - args: { - gasPriceMinimumFloor: newGasPriceMinFloor, - }, - }) - }) - - it('should revert when the provided floor is zero', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setGasPriceMinimumFloor(0), - 'gas price minimum floor must be greater than zero' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinFloor, { - from: nonOwner, - }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#getUpdatedGasPriceMinimum', () => { - describe('when the block is full', () => { - it('should return 25% more than the initial minimum and should not be limited by the gas price minimum floor as a whole', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(1, 1) - const expectedUpdatedGasPriceMinimum = currentGasPriceMinimum.times(5).div(4).plus(1) - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - }) - }) - - describe('when the block is empty', () => { - it('should return 25% less than the initial minimum, but be limited by the gas price minimum floor if new gas price lies below minimum', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(currentGasPriceMinimum) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1) - const expectedCappedUpdatedGasPriceMinimum = await gasPriceMinimum.gasPriceMinimumFloor() - assertEqualBN(actualUpdatedGasPriceMinimum, expectedCappedUpdatedGasPriceMinimum) - }) - - it('should return 25% less than the initial minimum, but not be limited by the gas price minimum floor if new gas price lies above minimum', async () => { - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - await gasPriceMinimum.setGasPriceMinimumFloor(1) - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1) - const expectedUpdatedGasPriceMinimum = currentGasPriceMinimum.times(3).div(4).plus(1) - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - }) - }) - - describe('when the fullness of the block is random', () => { - const getUpdatedGasPriceMinimum = ( - gasPriceMinFloor, - previousGasPriceMinimum, - density, - _targetDensity, - _adjustmentSpeed - ) => { - const one = new BigNumber(1) - const newGasPriceMinimum = previousGasPriceMinimum - .times( - one.plus( - fromFixed(_adjustmentSpeed).times(fromFixed(density).minus(fromFixed(_targetDensity))) - ) - ) - .plus(one) - .integerValue(BigNumber.ROUND_DOWN) - - return newGasPriceMinimum.lt(gasPriceMinFloor) ? gasPriceMinFloor : newGasPriceMinimum - } - - it('should return an updated gas price minimum that matches a typescript implementation', async () => { - const numIterations = 100 - const currentGasPriceMinimum = await gasPriceMinimum.gasPriceMinimum() - const gasPriceMinFloor = currentGasPriceMinimum - await gasPriceMinimum.setGasPriceMinimumFloor(gasPriceMinFloor) - - for (let i = 0; i < numIterations; i++) { - const curGas = await gasPriceMinimum.gasPriceMinimum() - - const blockGasLimit = new BigNumber(web3.utils.randomHex(4)) - const gasUsed = BigNumber.random().times(blockGasLimit).integerValue() - const actualUpdatedGasPriceMinimum = await gasPriceMinimum.getUpdatedGasPriceMinimum( - gasUsed, - blockGasLimit - ) - - const expectedUpdatedGasPriceMinimum = getUpdatedGasPriceMinimum( - gasPriceMinFloor, - curGas, - toFixed(gasUsed.div(blockGasLimit)), - targetDensity, - adjustmentSpeed - ) - - assertEqualBN(actualUpdatedGasPriceMinimum, expectedUpdatedGasPriceMinimum) - } - }) - }) - }) -}) From 815b6f0b83d217a9f29f7afe48852b23b257a823 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:26:16 -0500 Subject: [PATCH 07/15] added Registry8 test --- .../protocol/test-sol/common/Registry8.t.sol | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 packages/protocol/test-sol/common/Registry8.t.sol diff --git a/packages/protocol/test-sol/common/Registry8.t.sol b/packages/protocol/test-sol/common/Registry8.t.sol new file mode 100644 index 00000000000..e9d35f7fe59 --- /dev/null +++ b/packages/protocol/test-sol/common/Registry8.t.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.7 <0.8.20; + +import "./test/Test.sol"; + +// Contract to test +import "../../contracts-0.8/common/Registry8.sol"; + +contract RegistryTest is Test { + event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); + + address constant SOME_ADDRESS = address(0x06012c8cf97BEaD5deAe237070F9587f8E7A266d); + string constant SOME_ID = "cryptokitties"; + // hash of SOME_ID + // hash is harcoded to avoid test and implementation chaing in at the same time + bytes32 constant ID_HASH = 0x05445421d7b4d4c2e571c5a4ccf9317ec68601449f752c75ddbcc61a16061004; + + Registry8 registry; + address owner; + + function setUp() public { + owner = address(this); + vm.prank(owner); + registry = new Registry8(true); + registry.initialize(); + } + + function test_initialize_has_right_owner() public { + assertEq(registry.owner(), owner); + } + + function test_initialize_cant_called_again() public { + vm.expectRevert("contract already initialized"); + registry.initialize(); + } + + function test_setAddressFor_set_address() public { + vm.prank(owner); + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + assertEq(registry.registry(ID_HASH), SOME_ADDRESS); + } + + function test_setAddressFor_reverts_other_user() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(msg.sender); + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + } + + function test_setAddressFor_emits() public { + vm.expectEmit(true, true, false, true); + emit RegistryUpdated(SOME_ID, ID_HASH, SOME_ADDRESS); + + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + } + + function test_getAddressForOrDie_gets_address() public { + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + assertEq(registry.getAddressForOrDie(ID_HASH), SOME_ADDRESS); + } + + function test_getAddressForOrDie_reverts_address_not_set() public { + vm.expectRevert("identifier has no registry entry"); + registry.getAddressForOrDie(ID_HASH); + } + + function test_getAddressFor_gets_address() public { + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + assertEq(registry.getAddressFor(ID_HASH), SOME_ADDRESS); + } + + function test_getAddressFor_doesnt_revert() public { + assertEq(registry.getAddressFor(ID_HASH), address(0)); + } + + function test_getAddressForStringOrDie_gets_address() public { + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + assertEq(registry.getAddressForStringOrDie(SOME_ID), SOME_ADDRESS); + } + + function test_getAddressForStringOrDie_reverts() public { + vm.expectRevert("identifier has no registry entry"); + registry.getAddressForStringOrDie(SOME_ID); + } + + function test_getAddressForString_gets_addres() public { + registry.setAddressFor(SOME_ID, SOME_ADDRESS); + assertEq(registry.getAddressForString(SOME_ID), SOME_ADDRESS); + } + + function test_getAddressForString_shoudlnt_revert() public view { + registry.getAddressForString(SOME_ID); + } +} From 47a9cf28b2cfa287808b49a2d35490b27c8b0237 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:12:47 -0500 Subject: [PATCH 08/15] Using Registry interface instead. Avoids upgrading the registry contract to pragma ^0.8.0 in the PR. --- .../contracts-0.8/common/Registry8.sol | 99 ------------------- .../test-sol/common/GasPriceMinimum.t.sol | 12 ++- .../protocol/test-sol/common/Registry8.t.sol | 93 ----------------- 3 files changed, 7 insertions(+), 197 deletions(-) delete mode 100644 packages/protocol/contracts-0.8/common/Registry8.sol delete mode 100644 packages/protocol/test-sol/common/Registry8.t.sol diff --git a/packages/protocol/contracts-0.8/common/Registry8.sol b/packages/protocol/contracts-0.8/common/Registry8.sol deleted file mode 100644 index 67b106c6102..00000000000 --- a/packages/protocol/contracts-0.8/common/Registry8.sol +++ /dev/null @@ -1,99 +0,0 @@ -pragma solidity >=0.8.7 <0.8.20; - -import "@openzeppelin/contracts8/access/Ownable.sol"; - -import "../../contracts/common/interfaces/IRegistry.sol"; -import "../../contracts/common/Initializable.sol"; - -/** - * @title Routes identifiers to addresses. - */ -contract Registry8 is IRegistry, Ownable, Initializable { - - mapping(bytes32 => address) public registry; - - event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); - - /** - * @notice Sets initialized == true on implementation contracts - * @param test Set to true to skip implementation initialization - */ - constructor(bool test) public Initializable(test) {} - - /** - * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. - */ - function initialize() external initializer { - _transferOwnership(msg.sender); - } - - /** - * @notice Associates the given address with the given identifier. - * @param identifier Identifier of contract whose address we want to set. - * @param addr Address of contract. - */ - function setAddressFor(string calldata identifier, address addr) external onlyOwner { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - registry[identifierHash] = addr; - emit RegistryUpdated(identifier, identifierHash, addr); - } - - /** - * @notice Gets address associated with the given identifierHash. - * @param identifierHash Identifier hash of contract whose address we want to look up. - * @dev Throws if address not set. - */ - function getAddressForOrDie(bytes32 identifierHash) external view returns (address) { - require(registry[identifierHash] != address(0), "identifier has no registry entry"); - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifierHash. - * @param identifierHash Identifier hash of contract whose address we want to look up. - */ - function getAddressFor(bytes32 identifierHash) external view returns (address) { - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifier. - * @param identifier Identifier of contract whose address we want to look up. - * @dev Throws if address not set. - */ - function getAddressForStringOrDie(string calldata identifier) external view returns (address) { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - require(registry[identifierHash] != address(0), "identifier has no registry entry"); - return registry[identifierHash]; - } - - /** - * @notice Gets address associated with the given identifier. - * @param identifier Identifier of contract whose address we want to look up. - */ - function getAddressForString(string calldata identifier) external view returns (address) { - bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); - return registry[identifierHash]; - } - - /** - * @notice Iterates over provided array of identifiers, getting the address for each. - * Returns true if `sender` matches the address of one of the provided identifiers. - * @param identifierHashes Array of hashes of approved identifiers. - * @param sender Address in question to verify membership. - * @return True if `sender` corresponds to the address of any of `identifiers` - * registry entries. - */ - function isOneOf(bytes32[] calldata identifierHashes, address sender) - external - view - returns (bool) - { - for (uint256 i = 0; i < identifierHashes.length; i = i++) { - if (registry[identifierHashes[i]] == sender) { - return true; - } - } - return false; - } -} diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index 204122b5f83..6cf95bd62bd 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -4,7 +4,8 @@ pragma solidity >=0.8.7 <0.8.20; import "./test/Test.sol"; import "../../contracts/common/FixidityLib.sol"; -import "../../contracts-0.8/common/Registry8.sol"; + +import "../../contracts/common/interfaces/IRegistry.sol"; // Contract to test import "../../contracts-0.8/common/GasPriceMinimum.sol"; @@ -12,7 +13,7 @@ import "../../contracts-0.8/common/GasPriceMinimum.sol"; contract GasPriceMinimumTest is Test { using FixidityLib for FixidityLib.Fraction; - Registry8 registry; + IRegistry registry; GasPriceMinimum public gasPriceMinimum; address owner; address nonOwner; @@ -35,10 +36,10 @@ contract GasPriceMinimumTest is Test { owner = address(this); nonOwner = actor("nonOwner"); - deployCodeTo("Registry8.sol", abi.encode(false), registryAddress); + deployCodeTo("Registry.sol", abi.encode(false), registryAddress); gasPriceMinimum = new GasPriceMinimum(true); - registry = Registry8(registryAddress); + registry = IRegistry(registryAddress); registry.setAddressFor("GasPriceMinimum", address(gasPriceMinimum)); @@ -211,7 +212,8 @@ contract GasPriceMinimumGetUpdatedGasPriceMinimum is GasPriceMinimumTest { if (minNumber > 0) { return (uint256(keccak256(abi.encodePacked(nonce, msg.sender, blockhash(block.number - 1)))) % - (maxNumber - 1)) + 1; + (maxNumber - 1)) + + 1; } return (uint256(keccak256(abi.encodePacked(nonce, msg.sender, blockhash(block.number - 1)))) % maxNumber); diff --git a/packages/protocol/test-sol/common/Registry8.t.sol b/packages/protocol/test-sol/common/Registry8.t.sol deleted file mode 100644 index e9d35f7fe59..00000000000 --- a/packages/protocol/test-sol/common/Registry8.t.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.7 <0.8.20; - -import "./test/Test.sol"; - -// Contract to test -import "../../contracts-0.8/common/Registry8.sol"; - -contract RegistryTest is Test { - event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); - - address constant SOME_ADDRESS = address(0x06012c8cf97BEaD5deAe237070F9587f8E7A266d); - string constant SOME_ID = "cryptokitties"; - // hash of SOME_ID - // hash is harcoded to avoid test and implementation chaing in at the same time - bytes32 constant ID_HASH = 0x05445421d7b4d4c2e571c5a4ccf9317ec68601449f752c75ddbcc61a16061004; - - Registry8 registry; - address owner; - - function setUp() public { - owner = address(this); - vm.prank(owner); - registry = new Registry8(true); - registry.initialize(); - } - - function test_initialize_has_right_owner() public { - assertEq(registry.owner(), owner); - } - - function test_initialize_cant_called_again() public { - vm.expectRevert("contract already initialized"); - registry.initialize(); - } - - function test_setAddressFor_set_address() public { - vm.prank(owner); - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.registry(ID_HASH), SOME_ADDRESS); - } - - function test_setAddressFor_reverts_other_user() public { - vm.expectRevert("Ownable: caller is not the owner"); - vm.prank(msg.sender); - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - } - - function test_setAddressFor_emits() public { - vm.expectEmit(true, true, false, true); - emit RegistryUpdated(SOME_ID, ID_HASH, SOME_ADDRESS); - - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - } - - function test_getAddressForOrDie_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForOrDie(ID_HASH), SOME_ADDRESS); - } - - function test_getAddressForOrDie_reverts_address_not_set() public { - vm.expectRevert("identifier has no registry entry"); - registry.getAddressForOrDie(ID_HASH); - } - - function test_getAddressFor_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressFor(ID_HASH), SOME_ADDRESS); - } - - function test_getAddressFor_doesnt_revert() public { - assertEq(registry.getAddressFor(ID_HASH), address(0)); - } - - function test_getAddressForStringOrDie_gets_address() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForStringOrDie(SOME_ID), SOME_ADDRESS); - } - - function test_getAddressForStringOrDie_reverts() public { - vm.expectRevert("identifier has no registry entry"); - registry.getAddressForStringOrDie(SOME_ID); - } - - function test_getAddressForString_gets_addres() public { - registry.setAddressFor(SOME_ID, SOME_ADDRESS); - assertEq(registry.getAddressForString(SOME_ID), SOME_ADDRESS); - } - - function test_getAddressForString_shoudlnt_revert() public view { - registry.getAddressForString(SOME_ID); - } -} From add4d1185c72037270c072d5203dc618e195ee6e Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 17:17:45 -0500 Subject: [PATCH 09/15] removed extra setUp --- .../test-sol/common/GasPriceMinimum.t.sol | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index 6cf95bd62bd..5f995edcc9a 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -54,10 +54,6 @@ contract GasPriceMinimumTest is Test { } contract GasPriceMinimumInitialize is GasPriceMinimumTest { - function setUp() public override { - super.setUp(); - } - function test_shouldHaveSetOwner() public { assertEq(gasPriceMinimum.owner(), owner); } @@ -95,10 +91,6 @@ contract GasPriceMinimumSetAdjustmentSpeed is GasPriceMinimumTest { uint256 newAdjustmentSpeed = FixidityLib.newFixedFraction(1, 3).unwrap(); - function setUp() public override { - super.setUp(); - } - function test_shouldSetTheAdjustmentSpeed() public { gasPriceMinimum.setAdjustmentSpeed(newAdjustmentSpeed); @@ -154,10 +146,6 @@ contract GasPriceMinimumSetTargetDensity is GasPriceMinimumTest { contract GasPriceMinimumSetGasPriceMinimumFloor is GasPriceMinimumTest { uint256 newGasPriceMinimumFloor = 150; - function setUp() public override { - super.setUp(); - } - function test_ShouldSetGasPriceMinimumFloor() public { gasPriceMinimum.setGasPriceMinimumFloor(newGasPriceMinimumFloor); @@ -186,10 +174,6 @@ contract GasPriceMinimumGetUpdatedGasPriceMinimum is GasPriceMinimumTest { using FixidityLib for FixidityLib.Fraction; uint256 nonce = 0; - function setUp() public override { - super.setUp(); - } - function getExpectedUpdatedGasPriceMinimum( uint256 gasPriceMinFloor, uint256 previousGasPriceMinimum, From afa2f01a1ecc1e86e5b41de30646f9cfd7084cb4 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 17:17:58 -0500 Subject: [PATCH 10/15] Pinned submodule to specific tag/commit --- packages/protocol/lib/celo-foundry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/lib/celo-foundry b/packages/protocol/lib/celo-foundry index e835793925b..26ebfdb505c 160000 --- a/packages/protocol/lib/celo-foundry +++ b/packages/protocol/lib/celo-foundry @@ -1 +1 @@ -Subproject commit e835793925bfaaa8ef7aa8d341a2256c29470731 +Subproject commit 26ebfdb505ccdd48591992a2739a6e6486e73626 From 0d492232c010d4d3e996238e31febbd181a82953 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:10:31 -0500 Subject: [PATCH 11/15] ++ celo-foundry with pragma 0.8 --- .gitmodules | 3 +++ packages/protocol/lib/celo-foundry-8 | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/protocol/lib/celo-foundry-8 diff --git a/.gitmodules b/.gitmodules index e8619f9d9b4..85147538ad0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "packages/protocol/lib/forge-std"] path = packages/protocol/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "packages/protocol/lib/celo-foundry-8"] + path = packages/protocol/lib/celo-foundry-8 + url = https://github.com/celo-org/celo-foundry diff --git a/packages/protocol/lib/celo-foundry-8 b/packages/protocol/lib/celo-foundry-8 new file mode 160000 index 00000000000..9ed2e49e093 --- /dev/null +++ b/packages/protocol/lib/celo-foundry-8 @@ -0,0 +1 @@ +Subproject commit 9ed2e49e0934614283d686ad19755912e2694e0f From f1eb5ed0137ceb370b7a702ecfa774bfe34c73c9 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:38:45 -0500 Subject: [PATCH 12/15] fixed import mappings --- packages/protocol/foundry.toml | 11 +- packages/protocol/lib/celo-foundry-8 | 2 +- .../test-sol/common/GasPriceMinimum.t.sol | 2 +- .../common/test/PrecompileHandler.sol | 180 ------------------ .../test-sol/common/test/Precompiles.sol | 15 -- .../protocol/test-sol/common/test/Test.sol | 102 ---------- 6 files changed, 8 insertions(+), 304 deletions(-) delete mode 100644 packages/protocol/test-sol/common/test/PrecompileHandler.sol delete mode 100644 packages/protocol/test-sol/common/test/Precompiles.sol delete mode 100644 packages/protocol/test-sol/common/test/Test.sol diff --git a/packages/protocol/foundry.toml b/packages/protocol/foundry.toml index e578060431b..6347022e32a 100644 --- a/packages/protocol/foundry.toml +++ b/packages/protocol/foundry.toml @@ -4,13 +4,14 @@ out = 'out' test = 'test-sol' libs = ['lib', 'node_modules'] remappings = [ - '@openzeppelin/contracts8/=lib/openzeppelin-contracts8/contracts/', - 'openzeppelin-solidity/=lib/openzeppelin-contracts/', - 'solidity-bytes-utils/=lib/solidity-bytes-utils/', - 'forge-std/=lib/celo-foundry/lib/forge-std/src/', - 'forge-std8/=lib/forge-std/src/', 'ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/', + 'forge-std/=lib/celo-foundry/lib/forge-std/src/', + 'forge-std-8/=lib/celo-foundry-8/lib/forge-std/src/', + 'openzeppelin-solidity/=lib/openzeppelin-contracts/', + '@openzeppelin/contracts8/=lib/openzeppelin-contracts8/contracts/', 'celo-foundry/=lib/celo-foundry/src/', + 'celo-foundry-8/=lib/celo-foundry-8/src/', + 'solidity-bytes-utils/=lib/solidity-bytes-utils/', '@summa-tx/memview.sol/=lib/memview.sol', ] diff --git a/packages/protocol/lib/celo-foundry-8 b/packages/protocol/lib/celo-foundry-8 index 9ed2e49e093..952cdca4f53 160000 --- a/packages/protocol/lib/celo-foundry-8 +++ b/packages/protocol/lib/celo-foundry-8 @@ -1 +1 @@ -Subproject commit 9ed2e49e0934614283d686ad19755912e2694e0f +Subproject commit 952cdca4f531e86ea2560c37a0c6ba230b000e86 diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index 5f995edcc9a..715be4886db 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.7 <0.8.20; -import "./test/Test.sol"; +import "celo-foundry-8/Test.sol"; import "../../contracts/common/FixidityLib.sol"; diff --git a/packages/protocol/test-sol/common/test/PrecompileHandler.sol b/packages/protocol/test-sol/common/test/PrecompileHandler.sol deleted file mode 100644 index 5b19caf112f..00000000000 --- a/packages/protocol/test-sol/common/test/PrecompileHandler.sol +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.5.13 <0.8.20; - -import "forge-std8/Vm.sol"; -import "forge-std8/console2.sol"; -import "./Precompiles.sol"; - -contract PrecompileHandler is Precompiles { - address constant private VM_ADDRESS = - address(bytes20(uint160(uint256(keccak256('hevm cheat code'))))); - - Vm public constant vm = Vm(VM_ADDRESS); - - bytes4 constant TRANSFER_SIG = bytes4(keccak256("transfer(address,address,uint256)")); - bytes4 constant EPOCH_SIZE_SIG = bytes4(keccak256("epochSize()")); - bytes4 constant CATCHALL_SIG = bytes4(keccak256("catchAll()")); - - uint256 public epochSize = 17280; - bool public debug = false; - - struct Mock { - bool success; - bytes returnData; - bool exists; - } - - mapping(address => mapping(bytes32 => Mock)) private mockedCalls; - bytes private _empty; - Mock private successMock = Mock(true, _empty, true); - Mock private revertMock = Mock(true, _empty, true); - - constructor() public { - vm.etch(TRANSFER, proxyTo(TRANSFER_SIG)); - vm.label(TRANSFER, "TRANSFER"); - - vm.etch(EPOCH_SIZE, proxyTo(EPOCH_SIZE_SIG)); - vm.label(EPOCH_SIZE, "EPOCH_SIZE"); - - bytes memory catchAllProxy = proxyTo(CATCHALL_SIG); - vm.etch(FRACTION_MUL, catchAllProxy); - vm.label(FRACTION_MUL, "FRACTION_MUL"); - - vm.etch(PROOF_OF_POSSESSION, catchAllProxy); - vm.label(PROOF_OF_POSSESSION, "PROOF_OF_POSSESSION"); - - vm.etch(GET_VALIDATOR, catchAllProxy); - vm.label(GET_VALIDATOR, "GET_VALIDATOR"); - - vm.etch(NUMBER_VALIDATORS, catchAllProxy); - vm.label(NUMBER_VALIDATORS, "NUMBER_VALIDATORS"); - - vm.etch(BLOCK_NUMBER_FROM_HEADER, catchAllProxy); - vm.label(BLOCK_NUMBER_FROM_HEADER, "BLOCK_NUMBER_FROM_HEADER"); - - vm.etch(HASH_HEADER, catchAllProxy); - vm.label(HASH_HEADER, "HASH_HEADER"); - - vm.etch(GET_PARENT_SEAL_BITMAP, catchAllProxy); - vm.label(GET_PARENT_SEAL_BITMAP, "GET_PARENT_SEAL_BITMAP"); - - vm.etch(GET_VERIFIED_SEAL_BITMAP, catchAllProxy); - vm.label(GET_VERIFIED_SEAL_BITMAP, "GET_VERIFIED_SEAL_BITMAP"); - } - - function transfer(address from, address to, uint256 amount) public returns (bool) { - vm.deal(from, from.balance - amount); - vm.deal(to, to.balance + amount); - return true; - } - - function setEpochSize(uint256 epochSize_) public { - epochSize = epochSize_; - } - - function setDebug(bool debug_) public { - debug = debug_; - } - - function mockSuccess(address prec, bytes32 callHash) public { - setMock(prec, callHash, successMock); - - if (debug) { - console2.log("Mock success"); - console2.log(prec); - console2.logBytes32(callHash); - } - } - - function mockRevert(address prec, bytes32 callHash) public { - setMock(prec, callHash, revertMock); - - if (debug) { - console2.log("Mock revert"); - console2.log(prec); - console2.logBytes32(callHash); - } - } - - function mockReturn(address prec, bytes32 callHash, bytes memory returnData) public { - setMock(prec, callHash, Mock(true, returnData, true)); - - if (debug) { - console2.log("Mock success with data"); - console2.log(prec); - console2.logBytes32(callHash); - console2.logBytes(returnData); - } - } - - function clearMock(address prec, bytes32 callHash) public { - delete mockedCalls[prec][callHash]; - } - - function setMock(address prec, bytes32 callHash, Mock memory mock) internal { - require( - prec >= GET_VERIFIED_SEAL_BITMAP && - prec <= TRANSFER, - "precompile not supported" - ); - - mockedCalls[prec][callHash] = mock; - } - - function catchAll() public view { - bytes memory cd; - assembly { - cd := mload(0x40) - let cds := sub(calldatasize(), 0x4) - mstore(cd, cds) - calldatacopy(add(cd, 0x20), 0x4, cds) - mstore(0x40, add(cd, add(cds, 0x20))) - } - - bytes32 cdh = keccak256(cd); - Mock memory mock = mockedCalls[msg.sender][cdh]; - - if (mock.exists == false) { - console2.log(msg.sender); - console2.logBytes(cd); - console2.logBytes32(cdh); - revert("mock not defined for call"); - } - - if (mock.success == false) { - revert(); - } - - if (mock.returnData.length > 0) { - bytes memory returnData = mock.returnData; - assembly { - let rds := mload(returnData) - return(add(returnData, 0x20), rds) - } - } - } - - function proxyTo(bytes4 sig) internal view returns (bytes memory) { - address prec = address(this); - bytes memory ptr; - - assembly { - ptr := mload(0x40) - mstore(ptr, 0x60) - let mc := add(ptr, 0x20) - let addrPrefix := shl(0xf8, 0x73) - let addr := shl(0x58, prec) - let sigPrefix := shl(0x50, 0x63) - let shiftedSig := shl(0x30, shr(0xe0, sig)) - let suffix := 0x600060043601 - mstore(mc, or(addrPrefix, or(addr, or(sigPrefix, or(shiftedSig, suffix))))) - mc := add(mc, 0x20) - mstore(mc, 0x8260e01b82523660006004840137600080828434885af13d6000816000823e82) - mc := add(mc, 0x20) - mstore(mc, 0x60008114604a578282f35b8282fd000000000000000000000000000000000000) - mstore(0x40, add(ptr, 0x80)) - } - - return ptr; - } -} \ No newline at end of file diff --git a/packages/protocol/test-sol/common/test/Precompiles.sol b/packages/protocol/test-sol/common/test/Precompiles.sol deleted file mode 100644 index 6f324a68331..00000000000 --- a/packages/protocol/test-sol/common/test/Precompiles.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.5.13 <0.8.20; - -contract Precompiles { - address public constant TRANSFER = address(0xff - 2); - address public constant FRACTION_MUL = address(0xff - 3); - address public constant PROOF_OF_POSSESSION = address(0xff - 4); - address public constant GET_VALIDATOR = address(0xff - 5); - address public constant NUMBER_VALIDATORS = address(0xff - 6); - address public constant EPOCH_SIZE = address(0xff - 7); - address public constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8); - address public constant HASH_HEADER = address(0xff - 9); - address public constant GET_PARENT_SEAL_BITMAP = address(0xff - 10); - address public constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11); -} \ No newline at end of file diff --git a/packages/protocol/test-sol/common/test/Test.sol b/packages/protocol/test-sol/common/test/Test.sol deleted file mode 100644 index 7281d746e3f..00000000000 --- a/packages/protocol/test-sol/common/test/Test.sol +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.5.13 <0.8.20; - -import { Test as ForgeTest } from "forge-std8/Test.sol"; -import "./Precompiles.sol"; -import "./PrecompileHandler.sol"; - -contract Test is ForgeTest, Precompiles { - PrecompileHandler public ph; - address currentPrank; - - event log_named_array(string key, bytes32[] val); - event log_array(string key, address[] val); - event log_array(string key, bytes32[] val); - - constructor() public ForgeTest() { - ph = new PrecompileHandler(); - } - - /* Utility functions */ - - function changePrank(address who) internal virtual override { - // Record current prank so helper functions can revert - // if they need to prank - currentPrank = who; - super.changePrank(who); - } - - function actor(string memory name) public returns (address) { - uint256 pk = uint256(keccak256(bytes(name))); - address addr = vm.addr(pk); - vm.label(addr, name); - return addr; - } - - function actorWithPK(string memory name) public returns (address, uint256) { - uint256 pk = uint256(keccak256(bytes(name))); - address addr = vm.addr(pk); - vm.label(addr, name); - return (addr, pk); - } - - /* Extra assertions, extends forge-std/Test.sol */ - - function assertEq(address[] memory a, address[] memory b) internal virtual override { - if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { - emit log("Error: a == b not satisfied [address[]]"); - emit log_named_array(" Expected", b); - emit log_named_array(" Actual", a); - fail(); - } - } - - function assertEq( - address[] memory a, - address[] memory b, - string memory err - ) internal virtual override { - if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { - emit log_named_string("Error", err); - assertEq(a, b); - } - } - - function assertEq(bytes32[] memory a, bytes32[] memory b) internal { - if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) { - emit log("Error: a == b not satisfied [bytes32[]]"); - emit log_named_array(" Expected", b); - emit log_named_array(" Actual", a); - fail(); - } - } - - function deployCodeTo(string memory what, address where) internal virtual override { - deployCodeTo(what, "", 0, where); - } - - function deployCodeTo( - string memory what, - bytes memory args, - address where - ) internal virtual override { - deployCodeTo(what, args, 0, where); - } - - function deployCodeTo( - string memory what, - bytes memory args, - uint256 value, - address where - ) internal virtual override { - bytes memory creationCode = vm.getCode(what); - vm.etch(where, abi.encodePacked(creationCode, args)); - // (bool success, bytes memory runtimeBytecode) = where.call.value(value)(""); - (bool success, bytes memory runtimeBytecode) = where.call{ value: value }(""); - require( - success, - "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode." - ); - vm.etch(where, runtimeBytecode); - } -} From d830dc4371b9cdf28b87846b9eb276a6c99996c5 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:51:42 -0500 Subject: [PATCH 13/15] removed unused submodule --- .gitmodules | 3 --- packages/protocol/lib/forge-std | 1 - 2 files changed, 4 deletions(-) delete mode 160000 packages/protocol/lib/forge-std diff --git a/.gitmodules b/.gitmodules index 85147538ad0..b26686ad5b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,9 +16,6 @@ [submodule "packages/protocol/lib/openzeppelin-contracts8"] path = packages/protocol/lib/openzeppelin-contracts8 url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "packages/protocol/lib/forge-std"] - path = packages/protocol/lib/forge-std - url = https://github.com/foundry-rs/forge-std [submodule "packages/protocol/lib/celo-foundry-8"] path = packages/protocol/lib/celo-foundry-8 url = https://github.com/celo-org/celo-foundry diff --git a/packages/protocol/lib/forge-std b/packages/protocol/lib/forge-std deleted file mode 160000 index 2f112697506..00000000000 --- a/packages/protocol/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2f112697506eab12d433a65fdc31a639548fe365 From 6779ee976d3ca4a3297522d98e51ce22f04c9e01 Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:56:14 -0500 Subject: [PATCH 14/15] added celo foundry contracts v8 --- packages/protocol/lib/celo-foundry-8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/lib/celo-foundry-8 b/packages/protocol/lib/celo-foundry-8 index 952cdca4f53..1bef01f5658 160000 --- a/packages/protocol/lib/celo-foundry-8 +++ b/packages/protocol/lib/celo-foundry-8 @@ -1 +1 @@ -Subproject commit 952cdca4f531e86ea2560c37a0c6ba230b000e86 +Subproject commit 1bef01f56581acc0b25501bfd4f0add1b5daecd3 From 3b6e82c535de7b9c06c56664ee056a5e0cc31e3c Mon Sep 17 00:00:00 2001 From: soloseng <102702451+soloseng@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:57:12 -0500 Subject: [PATCH 15/15] PR feedback --- packages/protocol/lib/celo-foundry | 2 +- packages/protocol/remappings.txt | 1 + packages/protocol/test-sol/common/GasPriceMinimum.t.sol | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/protocol/lib/celo-foundry b/packages/protocol/lib/celo-foundry index 26ebfdb505c..e835793925b 160000 --- a/packages/protocol/lib/celo-foundry +++ b/packages/protocol/lib/celo-foundry @@ -1 +1 @@ -Subproject commit 26ebfdb505ccdd48591992a2739a6e6486e73626 +Subproject commit e835793925bfaaa8ef7aa8d341a2256c29470731 diff --git a/packages/protocol/remappings.txt b/packages/protocol/remappings.txt index ade04c498d7..8722ca0c8b0 100644 --- a/packages/protocol/remappings.txt +++ b/packages/protocol/remappings.txt @@ -1,3 +1,4 @@ @celo-contracts=contracts/ +@celo-contracts-8=contracts-0.8/ @test-sol=test-sol @lib=lib \ No newline at end of file diff --git a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol index 715be4886db..ec3c67f6526 100644 --- a/packages/protocol/test-sol/common/GasPriceMinimum.t.sol +++ b/packages/protocol/test-sol/common/GasPriceMinimum.t.sol @@ -3,12 +3,12 @@ pragma solidity >=0.8.7 <0.8.20; import "celo-foundry-8/Test.sol"; -import "../../contracts/common/FixidityLib.sol"; +import "@celo-contracts/common/FixidityLib.sol"; -import "../../contracts/common/interfaces/IRegistry.sol"; +import "@celo-contracts/common/interfaces/IRegistry.sol"; // Contract to test -import "../../contracts-0.8/common/GasPriceMinimum.sol"; +import "@celo-contracts-8/common/GasPriceMinimum.sol"; contract GasPriceMinimumTest is Test { using FixidityLib for FixidityLib.Fraction; @@ -239,7 +239,7 @@ contract GasPriceMinimumGetUpdatedGasPriceMinimum is GasPriceMinimumTest { assertEq(gasPriceMinimum.getUpdatedGasPriceMinimum(0, 1), expectedUpdatedGasPriceMinimum); } - function test_shouldReturnAnUpdatedGasPriceMinimumThatMatchesATypescriptImplementation_WhenTheFullnessOfTheBlockIsRandom() + function test_shouldReturnAnUpdatedGasPriceMinimumThatMatchesARandomNumber_WhenTheFullnessOfTheBlockIsRandom() public { uint256 numIterations = 100;