From de497a8a290af19844af27ef8efe495b618ef888 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Wed, 22 Nov 2023 13:22:46 +0200 Subject: [PATCH 1/6] carbon pol eth conversion - deployment scripts --- deploy/scripts/0009-CarbonPOL-upgrade.ts | 19 ++++++++++++++++++- deploy/tests/0009-carbon-pol.ts | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/deploy/scripts/0009-CarbonPOL-upgrade.ts b/deploy/scripts/0009-CarbonPOL-upgrade.ts index 27fbee08..58f30ce4 100644 --- a/deploy/scripts/0009-CarbonPOL-upgrade.ts +++ b/deploy/scripts/0009-CarbonPOL-upgrade.ts @@ -1,6 +1,7 @@ -import { upgradeProxy, InstanceName, setDeploymentMetadata } from '../../utils/Deploy'; import { DeployFunction } from 'hardhat-deploy/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { upgradeProxy, InstanceName, setDeploymentMetadata, execute } from '../../utils/Deploy'; +import { toWei } from '../../utils/Types'; const func: DeployFunction = async ({ getNamedAccounts }: HardhatRuntimeEnvironment) => { const { deployer, bnt } = await getNamedAccounts(); @@ -11,6 +12,22 @@ const func: DeployFunction = async ({ getNamedAccounts }: HardhatRuntimeEnvironm args: [bnt] }); + // Set ETH sale amount to 100 ether + await execute({ + name: InstanceName.CarbonPOL, + methodName: 'setEthSaleAmount', + args: [toWei(100)], + from: deployer + }); + + // Set min ETH sale amount to 10 ether + await execute({ + name: InstanceName.CarbonPOL, + methodName: 'setMinEthSaleAmount', + args: [toWei(10)], + from: deployer + }); + return true; }; diff --git a/deploy/tests/0009-carbon-pol.ts b/deploy/tests/0009-carbon-pol.ts index 0924b727..ece4a04f 100644 --- a/deploy/tests/0009-carbon-pol.ts +++ b/deploy/tests/0009-carbon-pol.ts @@ -1,3 +1,4 @@ +import { toWei } from '../../utils/Types'; import { CarbonPOL, ProxyAdmin } from '../../components/Contracts'; import { DeployedContracts } from '../../utils/Deploy'; import { describeDeployment } from '../../utils/helpers/Deploy'; @@ -21,6 +22,10 @@ describeDeployment(__filename, () => { expect(await carbonPOL.marketPriceMultiply()).to.equal(2); // check price decay half-life is configured correctly expect(await carbonPOL.priceDecayHalfLife()).to.equal(864000); + // check eth sale amount is configured correctly + expect((await carbonPOL.ethSaleAmount()).initial).to.equal(toWei(100)); + // check min eth sale amount is configured correctly + expect((await carbonPOL.minEthSaleAmount())).to.equal(toWei(10)); }); it('carbon pol implementation should be initialized', async () => { From a2bc3a48643d0aeb410fd6779db534532a83f206 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Thu, 23 Nov 2023 09:45:28 +0200 Subject: [PATCH 2/6] carbon pol eth conversion - price reset fix --- contracts/pol/CarbonPOL.sol | 2 +- deploy/tests/0009-carbon-pol.ts | 2 +- test/forge/CarbonPOL.t.sol | 24 +++++++++++++----------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index 604bfbc3..88d2eff7 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -354,8 +354,8 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils : uint128(address(this).balance); // reset the price to double the current one Price memory price = tokenPrice(NATIVE_TOKEN); - price.sourceAmount *= _marketPriceMultiply; _initialPrice[NATIVE_TOKEN] = price; + _tradingStartTimes[NATIVE_TOKEN] = uint32(block.timestamp); // emit price updated event emit PriceUpdated(NATIVE_TOKEN, price); } diff --git a/deploy/tests/0009-carbon-pol.ts b/deploy/tests/0009-carbon-pol.ts index ece4a04f..d5cdf556 100644 --- a/deploy/tests/0009-carbon-pol.ts +++ b/deploy/tests/0009-carbon-pol.ts @@ -25,7 +25,7 @@ describeDeployment(__filename, () => { // check eth sale amount is configured correctly expect((await carbonPOL.ethSaleAmount()).initial).to.equal(toWei(100)); // check min eth sale amount is configured correctly - expect((await carbonPOL.minEthSaleAmount())).to.equal(toWei(10)); + expect(await carbonPOL.minEthSaleAmount()).to.equal(toWei(10)); }); it('carbon pol implementation should be initialized', async () => { diff --git a/test/forge/CarbonPOL.t.sol b/test/forge/CarbonPOL.t.sol index 230ce739..fc03297b 100644 --- a/test/forge/CarbonPOL.t.sol +++ b/test/forge/CarbonPOL.t.sol @@ -838,7 +838,9 @@ contract CarbonPOLTest is TestFixture { } /// @dev test trading eth below the 10 ether sale amount threshold should reset the price and current eth amount - function testTradingETHBelowTheSaleThreshholdShouldResetThePriceAndCurrentEthAmount() public { + function testTradingETHBelowTheSaleThreshholdShouldResetThePriceAndCurrentEthAmount(uint256 timestamp) public { + // test with different timestamps + timestamp = bound(timestamp, 1, 100 days); // enable trading and set price for the native token vm.prank(admin); Token token = NATIVE_TOKEN; @@ -849,8 +851,8 @@ contract CarbonPOLTest is TestFixture { vm.startPrank(user1); - // set timestamp to 10 days - vm.warp(10 days); + // set timestamp + vm.warp(timestamp); uint128 initialSaleAmount = carbonPOL.ethSaleAmount().initial; uint128 currentSaleAmount = carbonPOL.ethSaleAmount().current; @@ -885,7 +887,6 @@ contract CarbonPOLTest is TestFixture { currentSaleAmount = carbonPOL.ethSaleAmount().current; assertEq(currentSaleAmount, initialSaleAmount); - vm.warp(block.timestamp + 1); // get the price after the threshold trade ICarbonPOL.Price memory newPrice = carbonPOL.tokenPrice(NATIVE_TOKEN); @@ -897,7 +898,9 @@ contract CarbonPOLTest is TestFixture { } /// @dev test trading eth below the 10 ether sale amount threshold should emit price updated event - function testTradingETHBelowTheSaleThreshholdShouldEmitEvent() public { + function testTradingETHBelowTheSaleThreshholdShouldEmitEvent(uint256 timestamp) public { + // test with different timestamps + timestamp = bound(timestamp, 1, 100 days); // enable trading and set price for the native token vm.prank(admin); Token token = NATIVE_TOKEN; @@ -908,8 +911,8 @@ contract CarbonPOLTest is TestFixture { vm.startPrank(user1); - // set timestamp to 10 days - vm.warp(10 days); + // set timestamp + vm.warp(timestamp); uint128 initialSaleAmount = carbonPOL.ethSaleAmount().initial; uint128 currentSaleAmount = carbonPOL.ethSaleAmount().current; @@ -926,15 +929,14 @@ contract CarbonPOLTest is TestFixture { // get the price before the threshold trade ICarbonPOL.Price memory prevPrice = carbonPOL.tokenPrice(NATIVE_TOKEN); - uint128 newExpectedSourceAmount = prevPrice.sourceAmount * carbonPOL.marketPriceMultiply(); - ICarbonPOL.Price memory newExpectedPrice = ICarbonPOL.Price({ - sourceAmount: newExpectedSourceAmount, + ICarbonPOL.Price memory expectedPrice = ICarbonPOL.Price({ + sourceAmount: prevPrice.sourceAmount, targetAmount: prevPrice.targetAmount }); // trade vm.expectEmit(); - emit PriceUpdated(token, newExpectedPrice); + emit PriceUpdated(token, expectedPrice); carbonPOL.trade(token, amountToSell); vm.stopPrank(); From 7640d904aaafb4d7dd848874aae9327aa24ef5d9 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Thu, 23 Nov 2023 13:07:32 +0200 Subject: [PATCH 3/6] carbon pol eth conversion - minor fix --- contracts/pol/CarbonPOL.sol | 8 ++++++-- test/forge/CarbonPOL.t.sol | 12 ++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index 88d2eff7..5a7b41a4 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -191,7 +191,9 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils function enableTradingETH(Price memory price) external onlyAdmin validPrice(price) { _tradingStartTimes[NATIVE_TOKEN] = uint32(block.timestamp); _initialPrice[NATIVE_TOKEN] = price; - _ethSaleAmount.current = _ethSaleAmount.initial; + _ethSaleAmount.current = address(this).balance > _ethSaleAmount.initial + ? _ethSaleAmount.initial + : uint128(address(this).balance); emit TradingEnabled(NATIVE_TOKEN, price); } @@ -410,7 +412,9 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if the new sale amount is below the current available eth sale amount if (newEthSaleAmount < _ethSaleAmount.current) { - _ethSaleAmount.current = newEthSaleAmount; + _ethSaleAmount.current = address(this).balance > newEthSaleAmount + ? newEthSaleAmount + : uint128(address(this).balance); } emit EthSaleAmountUpdated(prevEthSaleAmount, newEthSaleAmount); diff --git a/test/forge/CarbonPOL.t.sol b/test/forge/CarbonPOL.t.sol index fc03297b..ca6c8c82 100644 --- a/test/forge/CarbonPOL.t.sol +++ b/test/forge/CarbonPOL.t.sol @@ -379,6 +379,18 @@ contract CarbonPOLTest is TestFixture { carbonPOL.enableTradingETH(price); } + /// @dev test enabling trading for eth should set the current sale amount properly + function testEnablingTradingForETHShouldSetTheCurrentSaleAmountProperly() public { + vm.startPrank(admin); + // set the initial sale amount to a value higher than the pol balance + carbonPOL.setEthSaleAmount(uint128(address(carbonPOL).balance * 2)); + // enable trading for eth + carbonPOL.enableTradingETH(ICarbonPOL.Price({ sourceAmount: 100, targetAmount: 10000 })); + // check current eth sale amount is set to the contract balance + assertEq(carbonPOL.ethSaleAmount().current, address(carbonPOL).balance); + vm.stopPrank(); + } + /// @dev test should revert when setting invalid price for a token function testShouldRevertWhenSettingInvalidPriceForToken(uint256 i) public { // pick one of these tokens to test From 67bb9b543d7aa120222b94d654dac52ec8a55432 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Thu, 23 Nov 2023 14:54:54 +0200 Subject: [PATCH 4/6] carbon pol eth conversion - minor fix --- contracts/pol/CarbonPOL.sol | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index 5a7b41a4..5ae74797 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -191,9 +191,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils function enableTradingETH(Price memory price) external onlyAdmin validPrice(price) { _tradingStartTimes[NATIVE_TOKEN] = uint32(block.timestamp); _initialPrice[NATIVE_TOKEN] = price; - _ethSaleAmount.current = address(this).balance > _ethSaleAmount.initial - ? _ethSaleAmount.initial - : uint128(address(this).balance); + _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); emit TradingEnabled(NATIVE_TOKEN, price); } @@ -351,9 +349,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if remaining eth sale amount is below the min eth sale amount if (_ethSaleAmount.current < _minEthSaleAmount) { // top up the eth sale amount - _ethSaleAmount.current = address(this).balance > _ethSaleAmount.initial - ? _ethSaleAmount.initial - : uint128(address(this).balance); + _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); // reset the price to double the current one Price memory price = tokenPrice(NATIVE_TOKEN); _initialPrice[NATIVE_TOKEN] = price; @@ -412,9 +408,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if the new sale amount is below the current available eth sale amount if (newEthSaleAmount < _ethSaleAmount.current) { - _ethSaleAmount.current = address(this).balance > newEthSaleAmount - ? newEthSaleAmount - : uint128(address(this).balance); + _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); } emit EthSaleAmountUpdated(prevEthSaleAmount, newEthSaleAmount); From e42c4a05c6cdeb1e1f829b548db5bbad6468bc57 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Thu, 23 Nov 2023 15:12:30 +0200 Subject: [PATCH 5/6] carbon pol eth conversion - minor fix --- contracts/pol/CarbonPOL.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index 5ae74797..c364db6e 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.19; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { IVersioned } from "../utility/interfaces/IVersioned.sol"; import { ICarbonPOL } from "./interfaces/ICarbonPOL.sol"; @@ -191,7 +192,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils function enableTradingETH(Price memory price) external onlyAdmin validPrice(price) { _tradingStartTimes[NATIVE_TOKEN] = uint32(block.timestamp); _initialPrice[NATIVE_TOKEN] = price; - _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); + _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); emit TradingEnabled(NATIVE_TOKEN, price); } @@ -349,7 +350,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if remaining eth sale amount is below the min eth sale amount if (_ethSaleAmount.current < _minEthSaleAmount) { // top up the eth sale amount - _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); + _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); // reset the price to double the current one Price memory price = tokenPrice(NATIVE_TOKEN); _initialPrice[NATIVE_TOKEN] = price; @@ -408,7 +409,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if the new sale amount is below the current available eth sale amount if (newEthSaleAmount < _ethSaleAmount.current) { - _ethSaleAmount.current = MathEx.min(address(this).balance, _ethSaleAmount.initial); + _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); } emit EthSaleAmountUpdated(prevEthSaleAmount, newEthSaleAmount); From aa38cb13c7c70f77322b62f2bbc40f893b52fd16 Mon Sep 17 00:00:00 2001 From: Ivan Zhelyazkov Date: Thu, 23 Nov 2023 15:18:49 +0200 Subject: [PATCH 6/6] carbon pol eth conversion - minor fix --- contracts/pol/CarbonPOL.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/pol/CarbonPOL.sol b/contracts/pol/CarbonPOL.sol index c364db6e..c014a21b 100644 --- a/contracts/pol/CarbonPOL.sol +++ b/contracts/pol/CarbonPOL.sol @@ -192,7 +192,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils function enableTradingETH(Price memory price) external onlyAdmin validPrice(price) { _tradingStartTimes[NATIVE_TOKEN] = uint32(block.timestamp); _initialPrice[NATIVE_TOKEN] = price; - _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); + _ethSaleAmount.current = Math.min(address(this).balance, _ethSaleAmount.initial).toUint128(); emit TradingEnabled(NATIVE_TOKEN, price); } @@ -350,7 +350,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if remaining eth sale amount is below the min eth sale amount if (_ethSaleAmount.current < _minEthSaleAmount) { // top up the eth sale amount - _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); + _ethSaleAmount.current = Math.min(address(this).balance, _ethSaleAmount.initial).toUint128(); // reset the price to double the current one Price memory price = tokenPrice(NATIVE_TOKEN); _initialPrice[NATIVE_TOKEN] = price; @@ -409,7 +409,7 @@ contract CarbonPOL is ICarbonPOL, Upgradeable, ReentrancyGuardUpgradeable, Utils // check if the new sale amount is below the current available eth sale amount if (newEthSaleAmount < _ethSaleAmount.current) { - _ethSaleAmount.current = uint128(Math.min(address(this).balance, _ethSaleAmount.initial)); + _ethSaleAmount.current = Math.min(address(this).balance, _ethSaleAmount.initial).toUint128(); } emit EthSaleAmountUpdated(prevEthSaleAmount, newEthSaleAmount);