From ac9c93dd26b5433491d28d805a91927b300e57cf Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Tue, 21 Nov 2023 18:37:50 +0200 Subject: [PATCH] carbon pol eth conversion - min sale amount --- contracts/pol/CarbonPOL.sol | 41 ++++++++++++++++++++- contracts/pol/interfaces/ICarbonPOL.sol | 10 +++++ test/forge/CarbonPOL.t.sol | 49 +++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index 6ae346f1..4eb81994 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -39,8 +39,11 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // initial and current eth sale amount - for ETH->BNT trades EthSaleAmount private _ethSaleAmount; + // min eth sale amount - resets the current eth sale amount if below this amount after a trade + uint128 private _minEthSaleAmount; + // upgrade forward-compatibility storage gap - uint256[MAX_GAP - 4] private __gap; + uint256[MAX_GAP - 5] private __gap; /** * @dev used to initialize the implementation @@ -81,6 +84,8 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils _setPriceDecayHalfLife(10 days); // set initial eth sale amount to 100 eth _setEthSaleAmount(100 ether); + // set min eth sale amount to 10 eth + _setMinEthSaleAmount(10 ether); } /** @@ -148,6 +153,17 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils _setEthSaleAmount(newEthSaleAmount); } + /** + * @notice sets the min eth sale amount + * + * requirements: + * + * - the caller must be the admin of the contract + */ + function setMinEthSaleAmount(uint128 newMinEthSaleAmount) external onlyAdmin greaterThanZero(newMinEthSaleAmount) { + _setMinEthSaleAmount(newMinEthSaleAmount); + } + /** * @notice enable trading for TKN->ETH and set the initial price * @@ -200,6 +216,13 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils return _ethSaleAmount; } + /** + * @inheritdoc ICarbonPOL + */ + function minEthSaleAmount() external view returns (uint128) { + return _minEthSaleAmount; + } + /** * @inheritdoc ICarbonPOL */ @@ -393,6 +416,22 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils emit EthSaleAmountUpdated(prevEthSaleAmount, newEthSaleAmount); } + /** + * @dev set min eth sale amount helper + */ + function _setMinEthSaleAmount(uint128 newMinEthSaleAmount) private { + uint128 prevMinEthSaleAmount = _minEthSaleAmount; + + // return if the min eth sale amount is the same + if (prevMinEthSaleAmount == newMinEthSaleAmount) { + return; + } + + _minEthSaleAmount = newMinEthSaleAmount; + + emit MinEthSaleAmountUpdated(prevMinEthSaleAmount, newMinEthSaleAmount); + } + /** * @dev returns the token amount available for trading */ diff --git a/contracts/pol/interfaces/ICarbonPOL.sol b/contracts/pol/interfaces/ICarbonPOL.sol index c4368c28..58b93080 100644 --- a/contracts/pol/interfaces/ICarbonPOL.sol +++ b/contracts/pol/interfaces/ICarbonPOL.sol @@ -55,6 +55,11 @@ interface ICarbonPOL is IUpgradeable { */ event EthSaleAmountUpdated(uint128 prevEthSaleAmount, uint128 newEthSaleAmount); + /** + * @notice triggered when the min eth sale amount is updated + */ + event MinEthSaleAmountUpdated(uint128 prevMinEthSaleAmount, uint128 newMinEthSaleAmount); + /** * @notice returns the market price multiplier */ @@ -70,6 +75,11 @@ interface ICarbonPOL is IUpgradeable { */ function ethSaleAmount() external view returns (EthSaleAmount memory); + /** + * @notice returns the min eth sale amount - resets the current eth sale amount if below this amount after a trade + */ + function minEthSaleAmount() external view returns (uint128); + /** * @notice returns true if trading is enabled for token */ diff --git a/test/forge/CarbonPOL.t.sol b/test/forge/CarbonPOL.t.sol index a72f2aeb..230ce739 100644 --- a/test/forge/CarbonPOL.t.sol +++ b/test/forge/CarbonPOL.t.sol @@ -28,6 +28,9 @@ contract CarbonPOLTest is TestFixture { uint128 private constant ETH_SALE_AMOUNT_DEFAULT = 100 ether; uint128 private constant ETH_SALE_AMOUNT_UPDATED = 150 ether; + uint128 private constant MIN_ETH_SALE_AMOUNT_DEFAULT = 10 ether; + uint128 private constant MIN_ETH_SALE_AMOUNT_UPDATED = 15 ether; + // Events /** @@ -60,6 +63,11 @@ contract CarbonPOLTest is TestFixture { */ event EthSaleAmountUpdated(uint128 prevEthSaleAmount, uint128 newEthSaleAmount); + /** + * @notice triggered when the min eth sale amount is updated + */ + event MinEthSaleAmountUpdated(uint128 prevMinEthSaleAmount, uint128 newMinEthSaleAmount); + /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. @@ -221,6 +229,47 @@ contract CarbonPOLTest is TestFixture { vm.stopPrank(); } + /** + * @dev min eth sale amount tests + */ + + /// @dev test that setMinEthSaleAmount should revert when a non-admin calls it + function testShouldRevertWhenNonAdminAttemptsToSetTheMinEthSaleAmount() public { + vm.prank(user1); + vm.expectRevert(AccessDenied.selector); + carbonPOL.setMinEthSaleAmount(MIN_ETH_SALE_AMOUNT_UPDATED); + } + + /// @dev test that setMinEthSaleAmount should revert when setting to an invalid value + function testShouldRevertSettingTheMinEthSaleAmountWithAnInvalidValue() public { + vm.prank(admin); + vm.expectRevert(ZeroValue.selector); + carbonPOL.setMinEthSaleAmount(0); + } + + /// @dev test that setMinEthSaleAmount with the same value should be ignored + function testFailShouldIgnoreSettingTheSameMinEthSaleAmount() public { + vm.prank(admin); + vm.expectEmit(false, false, false, false); + emit MinEthSaleAmountUpdated(MIN_ETH_SALE_AMOUNT_DEFAULT, MIN_ETH_SALE_AMOUNT_DEFAULT); + carbonPOL.setMinEthSaleAmount(MIN_ETH_SALE_AMOUNT_DEFAULT); + } + + /// @dev test that admin should be able to update the min eth sale amount + function testShouldBeAbleToSetAndUpdateTheMinEthSaleAmount() public { + vm.startPrank(admin); + uint128 minEthSaleAmount = carbonPOL.minEthSaleAmount(); + assertEq(minEthSaleAmount, MIN_ETH_SALE_AMOUNT_DEFAULT); + + vm.expectEmit(); + emit MinEthSaleAmountUpdated(MIN_ETH_SALE_AMOUNT_DEFAULT, MIN_ETH_SALE_AMOUNT_UPDATED); + carbonPOL.setMinEthSaleAmount(MIN_ETH_SALE_AMOUNT_UPDATED); + + minEthSaleAmount = carbonPOL.minEthSaleAmount(); + assertEq(minEthSaleAmount, MIN_ETH_SALE_AMOUNT_UPDATED); + vm.stopPrank(); + } + /// @dev test that setting the eth sale amount to an amount below the current eth sale amount reset the current amount function testCurrentEthSaleAmountIsUpdatedWhenAboveTheNewEthSaleAmount() public { vm.startPrank(admin);