-
Notifications
You must be signed in to change notification settings - Fork 375
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GasPriceMinimum Foundry Migration (#10811)
* created test contract * add openzeppelin-contracts < 0.8.20 * added latest forge test submodule * pragma 0.8 support celo in foundry test * first passing test * fully migrated GasPriceMinimumTest * added Registry8 test * Using Registry interface instead. Avoids upgrading the registry contract to pragma ^0.8.0 in the PR. * removed extra setUp * Pinned submodule to specific tag/commit * ++ celo-foundry with pragma 0.8 * fixed import mappings * removed unused submodule * added celo foundry contracts v8 * PR feedback --------- Co-authored-by: Martín Volpe <[email protected]>
- Loading branch information
Showing
7 changed files
with
287 additions
and
278 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule celo-foundry-8
added at
1bef01
Submodule openzeppelin-contracts8
added at
b53c43
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
@celo-contracts=contracts/ | ||
@celo-contracts-8=contracts-0.8/ | ||
@test-sol=test-sol | ||
@lib=lib |
272 changes: 272 additions & 0 deletions
272
packages/protocol/test-sol/common/GasPriceMinimum.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.8.7 <0.8.20; | ||
|
||
import "celo-foundry-8/Test.sol"; | ||
|
||
import "@celo-contracts/common/FixidityLib.sol"; | ||
|
||
import "@celo-contracts/common/interfaces/IRegistry.sol"; | ||
|
||
// Contract to test | ||
import "@celo-contracts-8/common/GasPriceMinimum.sol"; | ||
|
||
contract GasPriceMinimumTest is Test { | ||
using FixidityLib for FixidityLib.Fraction; | ||
|
||
IRegistry 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); | ||
nonOwner = actor("nonOwner"); | ||
|
||
deployCodeTo("Registry.sol", abi.encode(false), registryAddress); | ||
gasPriceMinimum = new GasPriceMinimum(true); | ||
|
||
registry = IRegistry(registryAddress); | ||
|
||
registry.setAddressFor("GasPriceMinimum", address(gasPriceMinimum)); | ||
|
||
gasPriceMinimum.initialize( | ||
registryAddress, | ||
gasPriceMinimumFloor, | ||
targetDensity, | ||
adjustmentSpeed, | ||
0 | ||
); | ||
} | ||
} | ||
|
||
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 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 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 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_shouldReturnAnUpdatedGasPriceMinimumThatMatchesARandomNumber_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); | ||
} | ||
} | ||
} |
Oops, something went wrong.