From 8f1a3359fbeb85a1b5f0d63f730733f635f5d1ff Mon Sep 17 00:00:00 2001 From: RickGriff Date: Sat, 20 Jan 2024 13:19:45 +0700 Subject: [PATCH 1/6] Rip out borrow fees --- contracts/src/BorrowerOperations.sol | 19 +------ .../src/Interfaces/IPriceFeedTestnet.sol | 9 ++++ .../src/OldTestContracts/PriceFeedTestnet.sol | 4 +- contracts/src/test/TestContracts/BaseTest.sol | 2 - .../src/test/TestContracts/DevTestSetup.sol | 5 ++ contracts/src/test/basicOps.t.sol | 50 +++++++++++++++++++ 6 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 contracts/src/Interfaces/IPriceFeedTestnet.sol create mode 100644 contracts/src/test/basicOps.t.sol diff --git a/contracts/src/BorrowerOperations.sol b/contracts/src/BorrowerOperations.sol index 68e43fbc..e83b6c38 100644 --- a/contracts/src/BorrowerOperations.sol +++ b/contracts/src/BorrowerOperations.sol @@ -165,8 +165,7 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe vars.netDebt = _boldAmount; if (!isRecoveryMode) { - vars.BoldFee = _triggerBorrowingFee(contractsCache.troveManager, contractsCache.boldToken, _boldAmount, _maxFeePercentage); - vars.netDebt = vars.netDebt + vars.BoldFee; + // TODO: implement interest rate charges } _requireAtLeastMinNetDebt(vars.netDebt); @@ -271,8 +270,7 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe // If the adjustment incorporates a debt increase and system is in Normal Mode, then trigger a borrowing fee if (_isDebtIncrease && !isRecoveryMode) { - vars.BoldFee = _triggerBorrowingFee(contractsCache.troveManager, contractsCache.boldToken, _boldChange, _maxFeePercentage); - vars.netDebtChange = vars.netDebtChange + vars.BoldFee; // The raw debt change includes the fee + // TODO: implement interest rate charges } vars.debt = contractsCache.troveManager.getTroveDebt(_borrower); @@ -358,19 +356,6 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe // --- Helper functions --- - function _triggerBorrowingFee(ITroveManager _troveManager, IBoldToken _boldToken, uint _boldAmount, uint _maxFeePercentage) internal returns (uint) { - _troveManager.decayBaseRateFromBorrowing(); // decay the baseRate state variable - uint BoldFee = _troveManager.getBorrowingFee(_boldAmount); - - _requireUserAcceptsFee(BoldFee, _boldAmount, _maxFeePercentage); - - // Send fee to LQTY staking contract - lqtyStaking.increaseF_bold(BoldFee); - _boldToken.mint(lqtyStakingAddress, BoldFee); - - return BoldFee; - } - function _getUSDValue(uint _coll, uint _price) internal pure returns (uint) { uint usdValue = _price * _coll / DECIMAL_PRECISION; diff --git a/contracts/src/Interfaces/IPriceFeedTestnet.sol b/contracts/src/Interfaces/IPriceFeedTestnet.sol new file mode 100644 index 00000000..5db7d1df --- /dev/null +++ b/contracts/src/Interfaces/IPriceFeedTestnet.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "./IPriceFeed.sol"; + +interface IPriceFeedTestnet is IPriceFeed { + function setPrice(uint256 _price) external returns (bool); +} \ No newline at end of file diff --git a/contracts/src/OldTestContracts/PriceFeedTestnet.sol b/contracts/src/OldTestContracts/PriceFeedTestnet.sol index 2f220196..c85eb6c1 100644 --- a/contracts/src/OldTestContracts/PriceFeedTestnet.sol +++ b/contracts/src/OldTestContracts/PriceFeedTestnet.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.18; -import "../Interfaces/IPriceFeed.sol"; +import "../Interfaces/IPriceFeedTestnet.sol"; /* * PriceFeed placeholder for testnet and development. The price is simply set manually and saved in a state * variable. The contract does not connect to a live Chainlink price feed. */ -contract PriceFeedTestnet is IPriceFeed { +contract PriceFeedTestnet is IPriceFeedTestnet { event LastGoodPriceUpdated(uint _lastGoodPrice); uint256 private _price = 200 * 1e18; diff --git a/contracts/src/test/TestContracts/BaseTest.sol b/contracts/src/test/TestContracts/BaseTest.sol index 8973d834..f2657ae0 100644 --- a/contracts/src/test/TestContracts/BaseTest.sol +++ b/contracts/src/test/TestContracts/BaseTest.sol @@ -37,7 +37,6 @@ contract BaseTest is Test { IBorrowerOperations borrowerOperations; ICollSurplusPool collSurplusPool; IDefaultPool defaultPool; - IPriceFeed priceFeed; ISortedTroves sortedTroves; IStabilityPool stabilityPool; ITroveManager troveManager; @@ -60,7 +59,6 @@ contract BaseTest is Test { console.log("CollSurplusPool addr: ", address(collSurplusPool)); console.log("DefaultPool addr: ", address(defaultPool)); console.log("GasPool addr: ", address(gasPool)); - console.log("PriceFeed addr: ", address(priceFeed)); console.log("SortedTroves addr: ", address(sortedTroves)); console.log("StabilityPool addr: ", address(stabilityPool)); console.log("TroveManager addr: ", address(troveManager)); diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol index f44f6ed9..8b3f0a86 100644 --- a/contracts/src/test/TestContracts/DevTestSetup.sol +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; +import "../../Interfaces/IPriceFeedTestnet.sol"; + import "../../ActivePool.sol"; import "../../BoldToken.sol"; import "../../BorrowerOperations.sol"; @@ -18,6 +20,9 @@ import "../../TroveManager.sol"; import "./BaseTest.sol"; contract DevTestSetup is BaseTest { + + IPriceFeedTestnet priceFeed; + function setUp() public virtual { // Start tests at a non-zero timestamp vm.warp(block.timestamp + 600); diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol new file mode 100644 index 00000000..cdeb9200 --- /dev/null +++ b/contracts/src/test/basicOps.t.sol @@ -0,0 +1,50 @@ +pragma solidity 0.8.18; + +import "./TestContracts/DevTestSetup.sol"; + +contract BasicOps is DevTestSetup { + + function testOpenTrove() public { + uint256 trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 0); + + vm.startPrank(A); + priceFeed.setPrice(2000e18); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 1); + } + + function testCloseTrove() public { + vm.startPrank(A); + priceFeed.setPrice(2000e18); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + vm.stopPrank(); + + vm.startPrank(B); + priceFeed.setPrice(2000e18); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + uint256 trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 2); + + vm.startPrank(B); + borrowerOperations.closeTrove(); + vm.stopPrank(); + + // Check Troves count reduced by 1 + trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 1); + } + + // adjustTrove + + // redeem + + // liquidate + + // SP deposit + + // SP withdraw +} \ No newline at end of file From 53af23238d3f2397b452986af32d9e8eb4ffb556 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Mon, 22 Jan 2024 09:54:11 +0700 Subject: [PATCH 2/6] Rip out redemption fees --- contracts/src/BoldToken.sol | 4 ++ contracts/src/Interfaces/IBoldToken.sol | 2 + contracts/src/Interfaces/ITroveManager.sol | 2 + contracts/src/TroveManager.sol | 8 +-- .../src/test/TestContracts/DevTestSetup.sol | 2 +- contracts/src/test/basicOps.t.sol | 67 +++++++++++++++++-- 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/contracts/src/BoldToken.sol b/contracts/src/BoldToken.sol index 3227cf6f..8467cc65 100644 --- a/contracts/src/BoldToken.sol +++ b/contracts/src/BoldToken.sol @@ -46,6 +46,8 @@ contract BoldToken is CheckContract, IBoldToken { mapping (address => uint256) private _nonces; + uint256 public deploymentStartTime; + // User data for Bold token mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; @@ -88,6 +90,8 @@ contract BoldToken is CheckContract, IBoldToken { _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = _chainID(); _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(_TYPE_HASH, hashedName, hashedVersion); + + deploymentStartTime = block.timestamp; } // --- Functions for intra-Liquity calls --- diff --git a/contracts/src/Interfaces/IBoldToken.sol b/contracts/src/Interfaces/IBoldToken.sol index 64127c10..08d6116a 100644 --- a/contracts/src/Interfaces/IBoldToken.sol +++ b/contracts/src/Interfaces/IBoldToken.sol @@ -6,6 +6,8 @@ import "../Dependencies/IERC20.sol"; import "../Dependencies/IERC2612.sol"; interface IBoldToken is IERC20, IERC2612 { + function deploymentStartTime() external view returns (uint256); + function mint(address _account, uint256 _amount) external; function burn(address _account, uint256 _amount) external; diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index f5ed1f3c..e17dc849 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -33,6 +33,8 @@ interface ITroveManager is ILiquityBase { function sortedTroves() external view returns(ISortedTroves); function borrowerOperationsAddress() external view returns (address); + function BOOTSTRAP_PERIOD() external view returns (uint256); + function getTroveOwnersCount() external view returns (uint); function getTroveFromTroveOwnersArray(uint _index) external view returns (address); diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index c023d45b..087b0f4d 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -13,6 +13,7 @@ import "./Dependencies/LiquityBase.sol"; import "./Dependencies/Ownable.sol"; import "./Dependencies/CheckContract.sol"; +import "forge-std/console2.sol"; contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { string constant public NAME = "TroveManager"; @@ -1005,10 +1006,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { _requireUserAcceptsFee(totals.ETHFee, totals.totalETHDrawn, _maxFeePercentage); - // Send the ETH fee to the LQTY staking contract - contractsCache.activePool.sendETH(address(contractsCache.lqtyStaking), totals.ETHFee); - contractsCache.lqtyStaking.increaseF_ETH(totals.ETHFee); - + // Do nothing with the fee - the funds remain in ActivePool. TODO: replace with new redemption fee scheme totals.ETHToSendToRedeemer = totals.totalETHDrawn - totals.ETHFee; emit Redemption(_boldamount, totals.totalBoldToRedeem, totals.totalETHDrawn, totals.ETHFee); @@ -1496,7 +1494,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { } function _requireAfterBootstrapPeriod() internal view { - uint systemDeploymentTime = lqtyToken.getDeploymentStartTime(); + uint systemDeploymentTime = boldToken.deploymentStartTime(); require(block.timestamp >= systemDeploymentTime + BOOTSTRAP_PERIOD, "TroveManager: Redemptions are not allowed during bootstrap phase"); } diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol index 8b3f0a86..a535adbc 100644 --- a/contracts/src/test/TestContracts/DevTestSetup.sol +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -34,7 +34,7 @@ contract DevTestSetup is BaseTest { (accountsList[0], accountsList[1], accountsList[2], accountsList[3], accountsList[4], accountsList[5]); // Give some StETH to test accounts - uint256 initialETHAmount = 2000e18; + uint256 initialETHAmount = 10_000e18; deal(A, initialETHAmount); deal(B, initialETHAmount); deal(C, initialETHAmount); diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index cdeb9200..f9f78ce8 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -5,11 +5,11 @@ import "./TestContracts/DevTestSetup.sol"; contract BasicOps is DevTestSetup { function testOpenTrove() public { + priceFeed.setPrice(2000e18); uint256 trovesCount = troveManager.getTroveOwnersCount(); assertEq(trovesCount, 0); vm.startPrank(A); - priceFeed.setPrice(2000e18); borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); trovesCount = troveManager.getTroveOwnersCount(); @@ -17,13 +17,12 @@ contract BasicOps is DevTestSetup { } function testCloseTrove() public { - vm.startPrank(A); priceFeed.setPrice(2000e18); + vm.startPrank(A); borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); vm.stopPrank(); vm.startPrank(B); - priceFeed.setPrice(2000e18); borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); uint256 trovesCount = troveManager.getTroveOwnersCount(); @@ -40,7 +39,67 @@ contract BasicOps is DevTestSetup { // adjustTrove - // redeem + function testAdjustTrove() public { + priceFeed.setPrice(2000e18); + vm.startPrank(A); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + // Check Trove coll and debt + uint256 debt_1 = troveManager.getTroveDebt(A); + assertGt(debt_1, 0); + uint256 coll_1 = troveManager.getTroveColl(A); + assertGt(coll_1, 0); + + // Adjust trove + borrowerOperations.adjustTrove{value: 1 ether}(1e18, 0, 500e18, true, ZERO_ADDRESS, ZERO_ADDRESS); + + // Check coll and debt altered + uint256 debt_2 = troveManager.getTroveDebt(A); + assertGt(debt_2, debt_1); + uint256 coll_2 = troveManager.getTroveColl(A); + assertGt(coll_2, coll_1); + } + + function testRedeem() public { + priceFeed.setPrice(2000e18); + vm.startPrank(A); + borrowerOperations.openTrove{value: 5 ether}(1e18, 5_000e18, ZERO_ADDRESS, ZERO_ADDRESS); + vm.stopPrank(); + + uint256 debt_1 = troveManager.getTroveDebt(A); + assertGt(debt_1, 0); + uint256 coll_1 = troveManager.getTroveColl(A); + assertGt(coll_1, 0); + + vm.startPrank(B); + borrowerOperations.openTrove{value: 5 ether}(1e18, 4_000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + vm.warp(block.timestamp + troveManager.BOOTSTRAP_PERIOD() + 1); + + uint256 redemptionAmount = 1000e18; // 1k BOLD + uint256 expectedCollReduction = redemptionAmount * 1e18 / priceFeed.fetchPrice(); + + uint256 expectedColl_A = troveManager.getTroveColl(A) - expectedCollReduction; + uint256 expectedDebt_A = troveManager.getTroveDebt(A) - redemptionAmount; + uint256 expectedNICR = LiquityMath._computeNominalCR(expectedColl_A,expectedDebt_A); + + // B redeems 1k BOLD + troveManager.redeemCollateral( + redemptionAmount, + ZERO_ADDRESS, + ZERO_ADDRESS, + ZERO_ADDRESS, + expectedNICR, + 10, + 1e18 + ); + + // Check A's coll and debt reduced + uint256 debt_2 = troveManager.getTroveDebt(A); + assertLt(debt_2, debt_1); + uint256 coll_2 = troveManager.getTroveColl(A); + assertLt(coll_2, coll_1); + } // liquidate From 9469ee124071ebd2b5de9c05062076989ddbdfaf Mon Sep 17 00:00:00 2001 From: RickGriff Date: Mon, 22 Jan 2024 10:08:52 +0700 Subject: [PATCH 3/6] Test liquidation --- contracts/src/test/TestContracts/BaseTest.sol | 3 ++ contracts/src/test/basicOps.t.sol | 30 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/contracts/src/test/TestContracts/BaseTest.sol b/contracts/src/test/TestContracts/BaseTest.sol index f2657ae0..bc6e8257 100644 --- a/contracts/src/test/TestContracts/BaseTest.sol +++ b/contracts/src/test/TestContracts/BaseTest.sol @@ -30,8 +30,11 @@ contract BaseTest is Test { uint256 public constant MAX_UINT256 = type(uint256).max; uint256 public constant SECONDS_IN_1_YEAR = 31536000; // 60*60*24*365 + uint256 MCR = 110e16; + uint256 CCR = 150e16; address public constant ZERO_ADDRESS = address(0); + // Core contracts IActivePool activePool; IBorrowerOperations borrowerOperations; diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index f9f78ce8..f5da72e9 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -101,7 +101,35 @@ contract BasicOps is DevTestSetup { assertLt(coll_2, coll_1); } - // liquidate + function testLiquidation() public { + priceFeed.setPrice(2000e18); + vm.startPrank(A); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + vm.stopPrank(); + + vm.startPrank(B); + borrowerOperations.openTrove{value: 10 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + // Price drops + priceFeed.setPrice(1200e18); + uint256 price = priceFeed.fetchPrice(); + + // Check CR_A < MCR and TCR > CCR + console.log(troveManager.getCurrentICR(A, price), "A ICR"); + assertLt(troveManager.getCurrentICR(A, price), MCR); + + console.log(troveManager.getTCR(price) , "TCR"); + assertGt(troveManager.getTCR(price), CCR); + + uint256 trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 2); + + troveManager.liquidate(A); + + // Check Troves count reduced by 1 + trovesCount = troveManager.getTroveOwnersCount(); + assertEq(trovesCount, 1); + } // SP deposit From c1513c10a32b946390aea1d18f74ec2bd58f9a76 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Mon, 22 Jan 2024 10:49:34 +0700 Subject: [PATCH 4/6] Rip out SP LQTY issuance --- contracts/src/Interfaces/IStabilityPool.sol | 40 +--- contracts/src/StabilityPool.sol | 216 +----------------- .../src/test/TestContracts/DevTestSetup.sol | 3 +- contracts/src/test/basicOps.t.sol | 40 ++++ 4 files changed, 57 insertions(+), 242 deletions(-) diff --git a/contracts/src/Interfaces/IStabilityPool.sol b/contracts/src/Interfaces/IStabilityPool.sol index 2f5dc63d..e9cdb115 100644 --- a/contracts/src/Interfaces/IStabilityPool.sol +++ b/contracts/src/Interfaces/IStabilityPool.sol @@ -27,18 +27,7 @@ import "./ITroveManager.sol"; * Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations: * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf * - * --- LQTY ISSUANCE TO STABILITY POOL DEPOSITORS --- - * - * An LQTY issuance event occurs at every deposit operation, and every liquidation. - * - * Each deposit is tagged with the address of the front end through which it was made. - * - * All deposits earn a share of the issued LQTY in proportion to the deposit as a share of total deposits. The LQTY earned - * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate. - * - * Please see the system Readme for an overview: - * https://github.com/liquity/dev/blob/main/README.md#lqty-issuance-to-stability-providers - */ +*/ interface IStabilityPool is ILiquityBase { function borrowerOperations() external view returns (IBorrowerOperations); function boldToken() external view returns (IBoldToken); @@ -54,8 +43,7 @@ interface IStabilityPool is ILiquityBase { address _activePoolAddress, address _boldTokenAddress, address _sortedTrovesAddress, - address _priceFeedAddress, - address _communityIssuanceAddress + address _priceFeedAddress ) external; /* @@ -64,10 +52,8 @@ interface IStabilityPool is ILiquityBase { * - Sender is not a registered frontend * - _amount is not zero * --- - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends * - Tags the deposit with the provided front end tag param, if it's a new deposit - * - Sends depositor's accumulated gains (LQTY, ETH) to depositor - * - Sends the tagged front end's accumulated LQTY gains to the tagged front end + * - Sends depositor's accumulated ETH gains to depositor * - Increases deposit and tagged front end's stake, and takes new snapshots for each. */ function provideToSP(uint _amount, address _frontEndTag) external; @@ -77,10 +63,8 @@ interface IStabilityPool is ILiquityBase { * - _amount is zero or there are no under collateralized troves left in the system * - User has a non zero deposit * --- - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends * - Removes the deposit's front end tag if it is a full withdrawal - * - Sends all depositor's accumulated gains (LQTY, ETH) to depositor - * - Sends the tagged front end's accumulated LQTY gains to the tagged front end + * - Sends all depositor's accumulated ETH gains to depositor * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. * * If _amount > userDeposit, the user withdraws all of their compounded deposit. @@ -93,9 +77,6 @@ interface IStabilityPool is ILiquityBase { * - User has an open trove * - User has some ETH gain * --- - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends - * - Sends all depositor's LQTY gain to depositor - * - Sends all tagged front end's LQTY gain to the tagged front end * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove * - Leaves their compounded deposit in the Stability Pool * - Updates snapshots for deposit and tagged front end stake @@ -138,19 +119,6 @@ interface IStabilityPool is ILiquityBase { */ function getDepositorETHGain(address _depositor) external view returns (uint); - /* - * Calculate the LQTY gain earned by a deposit since its last snapshots were taken. - * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned. - * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through - * which they made their deposit. - */ - function getDepositorLQTYGain(address _depositor) external view returns (uint); - - /* - * Return the LQTY gain earned by the front end. - */ - function getFrontEndLQTYGain(address _frontEnd) external view returns (uint); - /* * Return the user's compounded deposit. */ diff --git a/contracts/src/StabilityPool.sol b/contracts/src/StabilityPool.sol index aa90762c..777ab57e 100644 --- a/contracts/src/StabilityPool.sol +++ b/contracts/src/StabilityPool.sol @@ -8,7 +8,6 @@ import './Interfaces/IBorrowerOperations.sol'; import './Interfaces/ITroveManager.sol'; import './Interfaces/IBoldToken.sol'; import './Interfaces/ISortedTroves.sol'; -import "./Interfaces/ICommunityIssuance.sol"; import "./Dependencies/LiquityBase.sol"; import "./Dependencies/Ownable.sol"; import "./Dependencies/CheckContract.sol"; @@ -126,21 +125,6 @@ import "./Dependencies/CheckContract.sol"; * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf * * - * --- LQTY ISSUANCE TO STABILITY POOL DEPOSITORS --- - * - * An LQTY issuance event occurs at every deposit operation, and every liquidation. - * - * Each deposit is tagged with the address of the front end through which it was made. - * - * All deposits earn a share of the issued LQTY in proportion to the deposit as a share of total deposits. The LQTY earned - * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate. - * - * Please see the system Readme for an overview: - * https://github.com/liquity/dev/blob/main/README.md#lqty-issuance-to-stability-providers - * - * We use the same mathematical product-sum approach to track LQTY gains for depositors, where 'G' is the sum corresponding to LQTY gains. - * The product P (and snapshot P_t) is re-used, as the ratio P/P_t tracks a deposit's depletion due to liquidations. - * */ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { string constant public NAME = "StabilityPool"; @@ -154,8 +138,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { // Needed to check if there are pending liquidations ISortedTroves public sortedTroves; - ICommunityIssuance public communityIssuance; - uint256 internal ETH; // deposited ether tracker // Tracker for Bold held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset. @@ -214,17 +196,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { */ mapping (uint128 => mapping(uint128 => uint)) public epochToScaleToSum; - /* - * Similarly, the sum 'G' is used to calculate LQTY gains. During it's lifetime, each deposit d_t earns a LQTY gain of - * ( d_t * [G - G_t] )/P_t, where G_t is the depositor's snapshot of G taken at time t when the deposit was made. - * - * LQTY reward events occur are triggered by depositor operations (new deposit, topup, withdrawal), and liquidations. - * In each case, the LQTY reward is issued (i.e. G is updated), before other state changes are made. - */ - mapping (uint128 => mapping(uint128 => uint)) public epochToScaleToG; - - // Error tracker for the error correction in the LQTY issuance calculation - uint public lastLQTYError; // Error trackers for the error correction in the offset calculation uint public lastETHError_Offset; uint public lastBoldLossError_Offset; @@ -241,7 +212,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { event BoldTokenAddressChanged(address _newBoldTokenAddress); event SortedTrovesAddressChanged(address _newSortedTrovesAddress); event PriceFeedAddressChanged(address _newPriceFeedAddress); - event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress); event P_Updated(uint _P); event S_Updated(uint _S, uint128 _epoch, uint128 _scale); @@ -252,14 +222,12 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate); event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd); - event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S, uint _G); - event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P, uint _G); + event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S); + event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P); event UserDepositChanged(address indexed _depositor, uint _newDeposit); event FrontEndStakeChanged(address indexed _frontEnd, uint _newFrontEndStake, address _depositor); event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _boldLoss); - event LQTYPaidToDepositor(address indexed _depositor, uint _LQTY); - event LQTYPaidToFrontEnd(address indexed _frontEnd, uint _LQTY); event EtherSent(address _to, uint _amount); // --- Contract setters --- @@ -270,8 +238,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { address _activePoolAddress, address _boldTokenAddress, address _sortedTrovesAddress, - address _priceFeedAddress, - address _communityIssuanceAddress + address _priceFeedAddress ) external override @@ -290,7 +257,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { boldToken = IBoldToken(_boldTokenAddress); sortedTroves = ISortedTroves(_sortedTrovesAddress); priceFeed = IPriceFeed(_priceFeedAddress); - communityIssuance = ICommunityIssuance(_communityIssuanceAddress); emit BorrowerOperationsAddressChanged(_borrowerOperationsAddress); emit TroveManagerAddressChanged(_troveManagerAddress); @@ -298,7 +264,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { emit BoldTokenAddressChanged(_boldTokenAddress); emit SortedTrovesAddressChanged(_sortedTrovesAddress); emit PriceFeedAddressChanged(_priceFeedAddress); - emit CommunityIssuanceAddressChanged(_communityIssuanceAddress); _renounceOwnership(); } @@ -317,10 +282,8 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { /* provideToSP(): * - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends * - Tags the deposit with the provided front end tag param, if it's a new deposit - * - Sends depositor's accumulated gains (LQTY, ETH) to depositor - * - Sends the tagged front end's accumulated LQTY gains to the tagged front end + * - Sends depositor's accumulated ETH to depositor * - Increases deposit and tagged front end's stake, and takes new snapshots for each. */ function provideToSP(uint _amount, address _frontEndTag) external override { @@ -330,18 +293,12 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint initialDeposit = deposits[msg.sender].initialValue; - ICommunityIssuance communityIssuanceCached = communityIssuance; - - _triggerLQTYIssuance(communityIssuanceCached); - if (initialDeposit == 0) {_setFrontEndTag(msg.sender, _frontEndTag);} uint depositorETHGain = getDepositorETHGain(msg.sender); uint compoundedBoldDeposit = getCompoundedBoldDeposit(msg.sender); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - // First pay out any LQTY gains address frontEnd = deposits[msg.sender].frontEndTag; - _payOutLQTYGains(communityIssuanceCached, msg.sender, frontEnd); // Update front end stake uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); @@ -362,10 +319,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { /* withdrawFromSP(): * - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends * - Removes the deposit's front end tag if it is a full withdrawal - * - Sends all depositor's accumulated gains (LQTY, ETH) to depositor - * - Sends the tagged front end's accumulated LQTY gains to the tagged front end * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. * * If _amount > userDeposit, the user withdraws all of their compounded deposit. @@ -375,19 +329,13 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint initialDeposit = deposits[msg.sender].initialValue; _requireUserHasDeposit(initialDeposit); - ICommunityIssuance communityIssuanceCached = communityIssuance; - - _triggerLQTYIssuance(communityIssuanceCached); - uint depositorETHGain = getDepositorETHGain(msg.sender); uint compoundedBoldDeposit = getCompoundedBoldDeposit(msg.sender); uint BoldtoWithdraw = LiquityMath._min(_amount, compoundedBoldDeposit); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - // First pay out any LQTY gains address frontEnd = deposits[msg.sender].frontEndTag; - _payOutLQTYGains(communityIssuanceCached, msg.sender, frontEnd); // Update front end stake uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); @@ -408,9 +356,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { } /* withdrawETHGainToTrove: - * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends - * - Sends all depositor's LQTY gain to depositor - * - Sends all tagged front end's LQTY gain to the tagged front end * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove * - Leaves their compounded deposit in the Stability Pool * - Updates snapshots for deposit and tagged front end stake */ @@ -420,18 +365,12 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { _requireUserHasTrove(msg.sender); _requireUserHasETHGain(msg.sender); - ICommunityIssuance communityIssuanceCached = communityIssuance; - - _triggerLQTYIssuance(communityIssuanceCached); - uint depositorETHGain = getDepositorETHGain(msg.sender); uint compoundedBoldDeposit = getCompoundedBoldDeposit(msg.sender); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - // First pay out any LQTY gains address frontEnd = deposits[msg.sender].frontEndTag; - _payOutLQTYGains(communityIssuanceCached, msg.sender, frontEnd); // Update front end stake uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); @@ -454,51 +393,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { borrowerOperations.moveETHGainToTrove{ value: depositorETHGain }(msg.sender, _upperHint, _lowerHint); } - // --- LQTY issuance functions --- - - function _triggerLQTYIssuance(ICommunityIssuance _communityIssuance) internal { - uint LQTYIssuance = _communityIssuance.issueLQTY(); - _updateG(LQTYIssuance); - } - - function _updateG(uint _LQTYIssuance) internal { - uint totalBold = totalBoldDeposits; // cached to save an SLOAD - /* - * When total deposits is 0, G is not updated. In this case, the LQTY issued can not be obtained by later - * depositors - it is missed out on, and remains in the balanceof the CommunityIssuance contract. - * - */ - if (totalBold == 0 || _LQTYIssuance == 0) {return;} - - uint LQTYPerUnitStaked; - LQTYPerUnitStaked =_computeLQTYPerUnitStaked(_LQTYIssuance, totalBold); - - uint marginalLQTYGain = LQTYPerUnitStaked * P; - epochToScaleToG[currentEpoch][currentScale] = epochToScaleToG[currentEpoch][currentScale] + marginalLQTYGain; - - emit G_Updated(epochToScaleToG[currentEpoch][currentScale], currentEpoch, currentScale); - } - - function _computeLQTYPerUnitStaked(uint _LQTYIssuance, uint _totalBoldDeposits) internal returns (uint) { - /* - * Calculate the LQTY-per-unit staked. Division uses a "feedback" error correction, to keep the - * cumulative error low in the running total G: - * - * 1) Form a numerator which compensates for the floor division error that occurred the last time this - * function was called. - * 2) Calculate "per-unit-staked" ratio. - * 3) Multiply the ratio back by its denominator, to reveal the current floor division error. - * 4) Store this error for use in the next correction when this function is called. - * 5) Note: static analysis tools complain about this "division before multiplication", however, it is intended. - */ - uint LQTYNumerator = _LQTYIssuance * DECIMAL_PRECISION + lastLQTYError; - - uint LQTYPerUnitStaked = LQTYNumerator / _totalBoldDeposits; - lastLQTYError = LQTYNumerator - LQTYPerUnitStaked * _totalBoldDeposits; - - return LQTYPerUnitStaked; - } - // --- Liquidation functions --- /* @@ -511,8 +405,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint totalBold = totalBoldDeposits; // cached to save an SLOAD if (totalBold == 0 || _debtToOffset == 0) { return; } - _triggerLQTYIssuance(communityIssuance); - (uint ETHGainPerUnitStaked, uint boldLossPerUnitStaked) = _computeRewardsPerUnitStaked(_collToAdd, _debtToOffset, totalBold); @@ -671,70 +563,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { return ETHGain; } - /* - * Calculate the LQTY gain earned by a deposit since its last snapshots were taken. - * Given by the formula: LQTY = d0 * (G - G(0))/P(0) - * where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. - * d0 is the last recorded deposit value. - */ - function getDepositorLQTYGain(address _depositor) public view override returns (uint) { - uint initialDeposit = deposits[_depositor].initialValue; - if (initialDeposit == 0) {return 0;} - - address frontEndTag = deposits[_depositor].frontEndTag; - - /* - * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned. - * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through - * which they made their deposit. - */ - uint kickbackRate = frontEndTag == address(0) ? DECIMAL_PRECISION : frontEnds[frontEndTag].kickbackRate; - - Snapshots memory snapshots = depositSnapshots[_depositor]; - - uint LQTYGain = kickbackRate * _getLQTYGainFromSnapshots(initialDeposit, snapshots) / DECIMAL_PRECISION; - - return LQTYGain; - } - - /* - * Return the LQTY gain earned by the front end. Given by the formula: E = D0 * (G - G(0))/P(0) - * where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. - * - * D0 is the last recorded value of the front end's total tagged deposits. - */ - function getFrontEndLQTYGain(address _frontEnd) public view override returns (uint) { - uint frontEndStake = frontEndStakes[_frontEnd]; - if (frontEndStake == 0) { return 0; } - - uint kickbackRate = frontEnds[_frontEnd].kickbackRate; - uint frontEndShare = uint(DECIMAL_PRECISION) - kickbackRate; - - Snapshots memory snapshots = frontEndSnapshots[_frontEnd]; - - uint LQTYGain = frontEndShare * _getLQTYGainFromSnapshots(frontEndStake, snapshots) / DECIMAL_PRECISION; - return LQTYGain; - } - - function _getLQTYGainFromSnapshots(uint initialStake, Snapshots memory snapshots) internal view returns (uint) { - /* - * Grab the sum 'G' from the epoch at which the stake was made. The LQTY gain may span up to one scale change. - * If it does, the second portion of the LQTY gain is scaled by 1e9. - * If the gain spans no scale change, the second portion will be 0. - */ - uint128 epochSnapshot = snapshots.epoch; - uint128 scaleSnapshot = snapshots.scale; - uint G_Snapshot = snapshots.G; - uint P_Snapshot = snapshots.P; - - uint firstPortion = epochToScaleToG[epochSnapshot][scaleSnapshot] - G_Snapshot; - uint secondPortion = epochToScaleToG[epochSnapshot][scaleSnapshot + 1] / SCALE_FACTOR; - - uint LQTYGain = initialStake * (firstPortion + secondPortion) / P_Snapshot / DECIMAL_PRECISION; - - return LQTYGain; - } - // --- Compounded deposit and compounded front end stake --- /* @@ -813,7 +641,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { return compoundedStake; } - // --- Sender functions for Bold deposit, ETH gains and LQTY gains --- + // --- Sender functions for Bold deposit and ETH gains --- // Transfer the Bold tokens from the user to the Stability Pool's address, and update its recorded Bold function _sendBoldtoStabilityPool(address _address, uint _amount) internal { @@ -870,25 +698,23 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { if (_newValue == 0) { delete deposits[_depositor].frontEndTag; delete depositSnapshots[_depositor]; - emit DepositSnapshotUpdated(_depositor, 0, 0, 0); + emit DepositSnapshotUpdated(_depositor, 0, 0); return; } uint128 currentScaleCached = currentScale; uint128 currentEpochCached = currentEpoch; uint currentP = P; - // Get S and G for the current epoch and current scale + // Get S for the current epoch and current scale uint currentS = epochToScaleToSum[currentEpochCached][currentScaleCached]; - uint currentG = epochToScaleToG[currentEpochCached][currentScaleCached]; - // Record new snapshots of the latest running product P, sum S, and sum G, for the depositor + // Record new snapshots of the latest running product P and sum S for the depositor depositSnapshots[_depositor].P = currentP; depositSnapshots[_depositor].S = currentS; - depositSnapshots[_depositor].G = currentG; depositSnapshots[_depositor].scale = currentScaleCached; depositSnapshots[_depositor].epoch = currentEpochCached; - emit DepositSnapshotUpdated(_depositor, currentP, currentS, currentG); + emit DepositSnapshotUpdated(_depositor, currentP, currentS); } function _updateFrontEndStakeAndSnapshots(address _frontEnd, uint _newValue) internal { @@ -896,7 +722,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { if (_newValue == 0) { delete frontEndSnapshots[_frontEnd]; - emit FrontEndSnapshotUpdated(_frontEnd, 0, 0); + emit FrontEndSnapshotUpdated(_frontEnd, 0); return; } @@ -904,30 +730,12 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint128 currentEpochCached = currentEpoch; uint currentP = P; - // Get G for the current epoch and current scale - uint currentG = epochToScaleToG[currentEpochCached][currentScaleCached]; - - // Record new snapshots of the latest running product P and sum G for the front end + // Record new snapshots of the latest running product P frontEndSnapshots[_frontEnd].P = currentP; - frontEndSnapshots[_frontEnd].G = currentG; frontEndSnapshots[_frontEnd].scale = currentScaleCached; frontEndSnapshots[_frontEnd].epoch = currentEpochCached; - emit FrontEndSnapshotUpdated(_frontEnd, currentP, currentG); - } - - function _payOutLQTYGains(ICommunityIssuance _communityIssuance, address _depositor, address _frontEnd) internal { - // Pay out front end's LQTY gain - if (_frontEnd != address(0)) { - uint frontEndLQTYGain = getFrontEndLQTYGain(_frontEnd); - _communityIssuance.sendLQTY(_frontEnd, frontEndLQTYGain); - emit LQTYPaidToFrontEnd(_frontEnd, frontEndLQTYGain); - } - - // Pay out depositor's LQTY gain - uint depositorLQTYGain = getDepositorLQTYGain(_depositor); - _communityIssuance.sendLQTY(_depositor, depositorLQTYGain); - emit LQTYPaidToDepositor(_depositor, depositorLQTYGain); + emit FrontEndSnapshotUpdated(_frontEnd, currentP); } // --- 'require' functions --- diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol index a535adbc..0313326a 100644 --- a/contracts/src/test/TestContracts/DevTestSetup.sol +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -107,8 +107,7 @@ contract DevTestSetup is BaseTest { address(activePool), address(boldToken), address(sortedTroves), - address(priceFeed), - ZERO_ADDRESS // No Community Issuance + address(priceFeed) ); activePool.setAddresses( diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index f5da72e9..f8625469 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -132,6 +132,46 @@ contract BasicOps is DevTestSetup { } // SP deposit + function testSPDeposit() public { + priceFeed.setPrice(2000e18); + vm.startPrank(A); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + // A makes an SP deposit + stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + + // time passes + vm.warp(block.timestamp + 7 days); + + // A tops up their SP deposit + stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + + // Check A's balance decreased and SP deposit increased + assertEq(boldToken.balanceOf(A), 1800e18); + assertEq(stabilityPool.getCompoundedBoldDeposit(A), 200e18); + } // SP withdraw + function testSPWithdrawal() public { + priceFeed.setPrice(2000e18); + vm.startPrank(A); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + + // A makes an SP deposit + stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + + // time passes + vm.warp(block.timestamp + 7 days); + + // Check A's balance decreased and SP deposit increased + assertEq(boldToken.balanceOf(A), 1900e18); + assertEq(stabilityPool.getCompoundedBoldDeposit(A), 100e18); + + // A tops up their SP deposit + stabilityPool.withdrawFromSP(100e18); + + // Check A's balance increased and SP deposit decreased to 0 + assertEq(boldToken.balanceOf(A), 2000e18); + assertEq(stabilityPool.getCompoundedBoldDeposit(A), 0); + } } \ No newline at end of file From 505d474d55c50197f8f3cd9684e450ece5ed7585 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Mon, 22 Jan 2024 14:06:24 +0700 Subject: [PATCH 5/6] Rip out SP front end logic --- contracts/src/Interfaces/IStabilityPool.sol | 71 +++------- contracts/src/StabilityPool.sol | 139 +++----------------- contracts/src/test/basicOps.t.sol | 13 +- 3 files changed, 39 insertions(+), 184 deletions(-) diff --git a/contracts/src/Interfaces/IStabilityPool.sol b/contracts/src/Interfaces/IStabilityPool.sol index e9cdb115..96c6f413 100644 --- a/contracts/src/Interfaces/IStabilityPool.sol +++ b/contracts/src/Interfaces/IStabilityPool.sol @@ -45,54 +45,32 @@ interface IStabilityPool is ILiquityBase { address _sortedTrovesAddress, address _priceFeedAddress ) external; + + /* provideToSP(): + * - Calculates depositor's ETH gain + * - Calculates the compounded deposit + * - Increases deposit, and takes new snapshots of accumulators P and S + * - Sends depositor's accumulated ETH gains to depositor + */ + function provideToSP(uint _amount) external; - /* - * Initial checks: - * - Frontend is registered or zero address - * - Sender is not a registered frontend - * - _amount is not zero - * --- - * - Tags the deposit with the provided front end tag param, if it's a new deposit - * - Sends depositor's accumulated ETH gains to depositor - * - Increases deposit and tagged front end's stake, and takes new snapshots for each. - */ - function provideToSP(uint _amount, address _frontEndTag) external; - - /* - * Initial checks: - * - _amount is zero or there are no under collateralized troves left in the system - * - User has a non zero deposit - * --- - * - Removes the deposit's front end tag if it is a full withdrawal - * - Sends all depositor's accumulated ETH gains to depositor - * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. - * - * If _amount > userDeposit, the user withdraws all of their compounded deposit. - */ + + /* withdrawFromSP(): + * - Calculates depositor's ETH gain + * - Calculates the compounded deposit + * - Sends the requested BOLD withdrawal to depositor + * - (If _amount > userDeposit, the user withdraws all of their compounded deposit) + * - Decreases deposit by withdrawn amount and takes new snapshots of accumulators P and S + */ function withdrawFromSP(uint _amount) external; - /* - * Initial checks: - * - User has a non zero deposit - * - User has an open trove - * - User has some ETH gain - * --- - * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove - * - Leaves their compounded deposit in the Stability Pool - * - Updates snapshots for deposit and tagged front end stake - */ + /* withdrawETHGainToTrove(): + * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove + * - Leaves their compounded deposit in the Stability Pool + * - Takes new snapshots of accumulators P and S + */ function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external; - /* - * Initial checks: - * - Frontend (sender) not already registered - * - User (sender) has no deposit - * - _kickbackRate is in the range [0, 100%] - * --- - * Front end makes a one-time selection of kickback rate upon registering - */ - function registerFrontEnd(uint _kickbackRate) external; - /* * Initial checks: * - Caller is TroveManager @@ -124,13 +102,6 @@ interface IStabilityPool is ILiquityBase { */ function getCompoundedBoldDeposit(address _depositor) external view returns (uint); - /* - * Return the front end's compounded stake. - * - * The front end's compounded stake is equal to the sum of its depositors' compounded deposits. - */ - function getCompoundedFrontEndStake(address _frontEnd) external view returns (uint); - /* * Fallback function * Only callable by Active Pool, it just accounts for ETH received diff --git a/contracts/src/StabilityPool.sol b/contracts/src/StabilityPool.sol index 777ab57e..550ff4e5 100644 --- a/contracts/src/StabilityPool.sol +++ b/contracts/src/StabilityPool.sol @@ -145,14 +145,8 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { // --- Data structures --- - struct FrontEnd { - uint kickbackRate; - bool registered; - } - struct Deposit { uint initialValue; - address frontEndTag; } struct Snapshots { @@ -166,10 +160,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { mapping (address => Deposit) public deposits; // depositor address -> Deposit struct mapping (address => Snapshots) public depositSnapshots; // depositor address -> snapshots struct - mapping (address => FrontEnd) public frontEnds; // front end address -> FrontEnd struct - mapping (address => uint) public frontEndStakes; // front end address -> last recorded total deposits, tagged with that front end - mapping (address => Snapshots) public frontEndSnapshots; // front end address -> snapshots struct - /* Product 'P': Running product by which to multiply an initial deposit, in order to find the current compounded deposit, * after a series of liquidations have occurred, each of which cancel some Bold debt with the deposit. * @@ -219,13 +209,8 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { event EpochUpdated(uint128 _currentEpoch); event ScaleUpdated(uint128 _currentScale); - event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate); - event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd); - event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S); - event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P); event UserDepositChanged(address indexed _depositor, uint _newDeposit); - event FrontEndStakeChanged(address indexed _frontEnd, uint _newFrontEndStake, address _depositor); event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _boldLoss); event EtherSent(address _to, uint _amount); @@ -281,31 +266,20 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { // --- External Depositor Functions --- /* provideToSP(): - * - * - Tags the deposit with the provided front end tag param, if it's a new deposit - * - Sends depositor's accumulated ETH to depositor - * - Increases deposit and tagged front end's stake, and takes new snapshots for each. + * - Calculates depositor's ETH gain + * - Calculates the compounded deposit + * - Increases deposit, and takes new snapshots of accumulators P and S + * - Sends depositor's accumulated ETH gains to depositor */ - function provideToSP(uint _amount, address _frontEndTag) external override { - _requireFrontEndIsRegisteredOrZero(_frontEndTag); - _requireFrontEndNotRegistered(msg.sender); + function provideToSP(uint _amount) external override { _requireNonZeroAmount(_amount); uint initialDeposit = deposits[msg.sender].initialValue; - if (initialDeposit == 0) {_setFrontEndTag(msg.sender, _frontEndTag);} uint depositorETHGain = getDepositorETHGain(msg.sender); uint compoundedBoldDeposit = getCompoundedBoldDeposit(msg.sender); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - address frontEnd = deposits[msg.sender].frontEndTag; - - // Update front end stake - uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); - uint newFrontEndStake = compoundedFrontEndStake + _amount; - _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake); - emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender); - _sendBoldtoStabilityPool(msg.sender, _amount); uint newDeposit = compoundedBoldDeposit + _amount; @@ -318,11 +292,11 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { } /* withdrawFromSP(): - * - * - Removes the deposit's front end tag if it is a full withdrawal - * - Decreases deposit and tagged front end's stake, and takes new snapshots for each. - * - * If _amount > userDeposit, the user withdraws all of their compounded deposit. + * - Calculates depositor's ETH gain + * - Calculates the compounded deposit + * - Sends the requested BOLD withdrawal to depositor + * - (If _amount > userDeposit, the user withdraws all of their compounded deposit) + * - Decreases deposit by withdrawn amount and takes new snapshots of accumulators P and S */ function withdrawFromSP(uint _amount) external override { if (_amount !=0) {_requireNoUnderCollateralizedTroves();} @@ -335,14 +309,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint BoldtoWithdraw = LiquityMath._min(_amount, compoundedBoldDeposit); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - address frontEnd = deposits[msg.sender].frontEndTag; - - // Update front end stake - uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); - uint newFrontEndStake = compoundedFrontEndStake - BoldtoWithdraw; - _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake); - emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender); - _sendBoldToDepositor(msg.sender, BoldtoWithdraw); // Update deposit @@ -355,10 +321,11 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { _sendETHGainToDepositor(depositorETHGain); } - /* withdrawETHGainToTrove: + /* withdrawETHGainToTrove(): * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove * - Leaves their compounded deposit in the Stability Pool - * - Updates snapshots for deposit and tagged front end stake */ + * - Takes new snapshots of accumulators P and S + */ function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external override { uint initialDeposit = deposits[msg.sender].initialValue; _requireUserHasDeposit(initialDeposit); @@ -370,14 +337,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { uint compoundedBoldDeposit = getCompoundedBoldDeposit(msg.sender); uint boldLoss = initialDeposit - compoundedBoldDeposit; // Needed only for event log - address frontEnd = deposits[msg.sender].frontEndTag; - - // Update front end stake - uint compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd); - uint newFrontEndStake = compoundedFrontEndStake; - _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake); - emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender); - _updateDepositAndSnapshots(msg.sender, compoundedBoldDeposit); /* Emit events before transferring ETH gain to Trove. @@ -526,7 +485,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { emit StabilityPoolBoldBalanceUpdated(newTotalBoldDeposits); } - // --- Reward calculator functions for depositor and front end --- + // --- Reward calculator functions for depositor --- /* Calculates the ETH gain earned by the deposit since its last snapshots were taken. * Given by the formula: E = d0 * (S - S(0))/P(0) @@ -563,7 +522,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { return ETHGain; } - // --- Compounded deposit and compounded front end stake --- + // --- Compounded deposit --- /* * Return the user's compounded deposit. Given by the formula: d = d0 * P/P(0) @@ -579,23 +538,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { return compoundedDeposit; } - /* - * Return the front end's compounded stake. Given by the formula: D = D0 * P/P(0) - * where P(0) is the depositor's snapshot of the product P, taken at the last time - * when one of the front end's tagged deposits updated their deposit. - * - * The front end's compounded stake is equal to the sum of its depositors' compounded deposits. - */ - function getCompoundedFrontEndStake(address _frontEnd) public view override returns (uint) { - uint frontEndStake = frontEndStakes[_frontEnd]; - if (frontEndStake == 0) { return 0; } - - Snapshots memory snapshots = frontEndSnapshots[_frontEnd]; - - uint compoundedFrontEndStake = _getCompoundedStakeFromSnapshots(frontEndStake, snapshots); - return compoundedFrontEndStake; - } - // Internal function, used to calculcate compounded deposits and compounded front end stakes. function _getCompoundedStakeFromSnapshots( uint initialStake, @@ -670,33 +612,12 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { _decreaseBold(BoldWithdrawal); } - // --- External Front End functions --- - - // Front end makes a one-time selection of kickback rate upon registering - function registerFrontEnd(uint _kickbackRate) external override { - _requireFrontEndNotRegistered(msg.sender); - _requireUserHasNoDeposit(msg.sender); - _requireValidKickbackRate(_kickbackRate); - - frontEnds[msg.sender].kickbackRate = _kickbackRate; - frontEnds[msg.sender].registered = true; - - emit FrontEndRegistered(msg.sender, _kickbackRate); - } - // --- Stability Pool Deposit Functionality --- - function _setFrontEndTag(address _depositor, address _frontEndTag) internal { - deposits[_depositor].frontEndTag = _frontEndTag; - emit FrontEndTagSet(_depositor, _frontEndTag); - } - - function _updateDepositAndSnapshots(address _depositor, uint _newValue) internal { deposits[_depositor].initialValue = _newValue; if (_newValue == 0) { - delete deposits[_depositor].frontEndTag; delete depositSnapshots[_depositor]; emit DepositSnapshotUpdated(_depositor, 0, 0); return; @@ -717,27 +638,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { emit DepositSnapshotUpdated(_depositor, currentP, currentS); } - function _updateFrontEndStakeAndSnapshots(address _frontEnd, uint _newValue) internal { - frontEndStakes[_frontEnd] = _newValue; - - if (_newValue == 0) { - delete frontEndSnapshots[_frontEnd]; - emit FrontEndSnapshotUpdated(_frontEnd, 0); - return; - } - - uint128 currentScaleCached = currentScale; - uint128 currentEpochCached = currentEpoch; - uint currentP = P; - - // Record new snapshots of the latest running product P - frontEndSnapshots[_frontEnd].P = currentP; - frontEndSnapshots[_frontEnd].scale = currentScaleCached; - frontEndSnapshots[_frontEnd].epoch = currentEpochCached; - - emit FrontEndSnapshotUpdated(_frontEnd, currentP); - } - // --- 'require' functions --- function _requireCallerIsActivePool() internal view { @@ -777,15 +677,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { require(ETHGain > 0, "StabilityPool: caller must have non-zero ETH Gain"); } - function _requireFrontEndNotRegistered(address _address) internal view { - require(!frontEnds[_address].registered, "StabilityPool: must not already be a registered front end"); - } - - function _requireFrontEndIsRegisteredOrZero(address _address) internal view { - require(frontEnds[_address].registered || _address == address(0), - "StabilityPool: Tag must be a registered front end, or the zero address"); - } - function _requireValidKickbackRate(uint _kickbackRate) internal pure { require (_kickbackRate <= DECIMAL_PRECISION, "StabilityPool: Kickback rate must be in range [0,1]"); } diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index f8625469..0fc8b51c 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -37,8 +37,6 @@ contract BasicOps is DevTestSetup { assertEq(trovesCount, 1); } - // adjustTrove - function testAdjustTrove() public { priceFeed.setPrice(2000e18); vm.startPrank(A); @@ -115,10 +113,7 @@ contract BasicOps is DevTestSetup { uint256 price = priceFeed.fetchPrice(); // Check CR_A < MCR and TCR > CCR - console.log(troveManager.getCurrentICR(A, price), "A ICR"); assertLt(troveManager.getCurrentICR(A, price), MCR); - - console.log(troveManager.getTCR(price) , "TCR"); assertGt(troveManager.getTCR(price), CCR); uint256 trovesCount = troveManager.getTroveOwnersCount(); @@ -131,34 +126,32 @@ contract BasicOps is DevTestSetup { assertEq(trovesCount, 1); } - // SP deposit function testSPDeposit() public { priceFeed.setPrice(2000e18); vm.startPrank(A); borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); // A makes an SP deposit - stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + stabilityPool.provideToSP(100e18); // time passes vm.warp(block.timestamp + 7 days); // A tops up their SP deposit - stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + stabilityPool.provideToSP(100e18); // Check A's balance decreased and SP deposit increased assertEq(boldToken.balanceOf(A), 1800e18); assertEq(stabilityPool.getCompoundedBoldDeposit(A), 200e18); } - // SP withdraw function testSPWithdrawal() public { priceFeed.setPrice(2000e18); vm.startPrank(A); borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); // A makes an SP deposit - stabilityPool.provideToSP(100e18, ZERO_ADDRESS); + stabilityPool.provideToSP(100e18); // time passes vm.warp(block.timestamp + 7 days); From e715e292d8938a46105db7feb72ddd11eeb6b46f Mon Sep 17 00:00:00 2001 From: RickGriff Date: Tue, 23 Jan 2024 14:55:45 +0700 Subject: [PATCH 6/6] Move IPriceFeedTestnet and delete redundant test contracts --- .../src/OldTestContracts/ActivePoolTester.sol | 16 ----- .../src/OldTestContracts/BoldTokenCaller.sol | 29 -------- .../src/OldTestContracts/BoldTokenTester.sol | 66 ------------------- .../BorrowerOperationsTester.sol | 63 ------------------ .../src/OldTestContracts/CDPManagerTester.sol | 60 ----------------- .../OldTestContracts/DefaultPoolTester.sol | 16 ----- .../src/OldTestContracts/Destructible.sol | 12 ---- .../src/OldTestContracts/FunctionCaller.sol | 49 -------------- .../OldTestContracts/LiquityMathTester.sol | 24 ------- contracts/src/OldTestContracts/MockTellor.sol | 51 -------------- contracts/src/OldTestContracts/NonPayable.sol | 24 ------- .../src/OldTestContracts/PriceFeedTester.sol | 16 ----- .../src/OldTestContracts/PriceFeedTestnet.sol | 35 ---------- .../OldTestContracts/SortedTrovesTester.sol | 34 ---------- .../OldTestContracts/StabilityPoolTester.sol | 20 ------ .../src/TestContracts/PriceFeedTestnet.sol | 4 +- contracts/src/TroveManager.sol | 2 +- .../src/test/TestContracts/DevTestSetup.sol | 4 +- .../Interfaces/IPriceFeedTestnet.sol | 2 +- contracts/src/test/basicOps.t.sol | 2 +- 20 files changed, 7 insertions(+), 522 deletions(-) delete mode 100644 contracts/src/OldTestContracts/ActivePoolTester.sol delete mode 100644 contracts/src/OldTestContracts/BoldTokenCaller.sol delete mode 100644 contracts/src/OldTestContracts/BoldTokenTester.sol delete mode 100644 contracts/src/OldTestContracts/BorrowerOperationsTester.sol delete mode 100644 contracts/src/OldTestContracts/CDPManagerTester.sol delete mode 100644 contracts/src/OldTestContracts/DefaultPoolTester.sol delete mode 100644 contracts/src/OldTestContracts/Destructible.sol delete mode 100644 contracts/src/OldTestContracts/FunctionCaller.sol delete mode 100644 contracts/src/OldTestContracts/LiquityMathTester.sol delete mode 100644 contracts/src/OldTestContracts/MockTellor.sol delete mode 100644 contracts/src/OldTestContracts/NonPayable.sol delete mode 100644 contracts/src/OldTestContracts/PriceFeedTester.sol delete mode 100644 contracts/src/OldTestContracts/PriceFeedTestnet.sol delete mode 100644 contracts/src/OldTestContracts/SortedTrovesTester.sol delete mode 100644 contracts/src/OldTestContracts/StabilityPoolTester.sol rename contracts/src/{ => test/TestContracts}/Interfaces/IPriceFeedTestnet.sol (78%) diff --git a/contracts/src/OldTestContracts/ActivePoolTester.sol b/contracts/src/OldTestContracts/ActivePoolTester.sol deleted file mode 100644 index 75cee9b5..00000000 --- a/contracts/src/OldTestContracts/ActivePoolTester.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../ActivePool.sol"; - -contract ActivePoolTester is ActivePool { - - function unprotectedIncreaseBoldDebt(uint _amount) external { - boldDebt = boldDebt + _amount; - } - - function unprotectedPayable() external payable { - ETH = ETH + msg.value; - } -} diff --git a/contracts/src/OldTestContracts/BoldTokenCaller.sol b/contracts/src/OldTestContracts/BoldTokenCaller.sol deleted file mode 100644 index 613b41a3..00000000 --- a/contracts/src/OldTestContracts/BoldTokenCaller.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../Interfaces/IBoldToken.sol"; - -contract BoldTokenCaller { - IBoldToken Bold; - - function setBold(IBoldToken _bold) external { - Bold = _bold; - } - - function boldMint(address _account, uint _amount) external { - Bold.mint(_account, _amount); - } - - function boldBurn(address _account, uint _amount) external { - Bold.burn(_account, _amount); - } - - function boldSendToPool(address _sender, address _poolAddress, uint256 _amount) external { - Bold.sendToPool(_sender, _poolAddress, _amount); - } - - function boldReturnFromPool(address _poolAddress, address _receiver, uint256 _amount ) external { - Bold.returnFromPool(_poolAddress, _receiver, _amount); - } -} diff --git a/contracts/src/OldTestContracts/BoldTokenTester.sol b/contracts/src/OldTestContracts/BoldTokenTester.sol deleted file mode 100644 index 446299e6..00000000 --- a/contracts/src/OldTestContracts/BoldTokenTester.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../BoldToken.sol"; - -contract BoldTokenTester is BoldToken { - - bytes32 private immutable _PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - - constructor( - address _troveManagerAddress, - address _stabilityPoolAddress, - address _borrowerOperationsAddress - ) public BoldToken(_troveManagerAddress, - _stabilityPoolAddress, - _borrowerOperationsAddress) {} - - function unprotectedMint(address _account, uint256 _amount) external { - // No check on caller here - - _mint(_account, _amount); - } - - function unprotectedBurn(address _account, uint _amount) external { - // No check on caller here - - _burn(_account, _amount); - } - - function unprotectedSendToPool(address _sender, address _poolAddress, uint256 _amount) external { - // No check on caller here - - _transfer(_sender, _poolAddress, _amount); - } - - function unprotectedReturnFromPool(address _poolAddress, address _receiver, uint256 _amount ) external { - // No check on caller here - - _transfer(_poolAddress, _receiver, _amount); - } - - function callInternalApprove(address owner, address spender, uint256 amount) external returns (bool) { - _approve(owner, spender, amount); - } - - function getChainId() external view returns (uint256 chainID) { - //return _chainID(); // it’s private - assembly { - chainID := chainid() - } - } - - function getDigest(address owner, address spender, uint amount, uint nonce, uint deadline) external view returns (bytes32) { - return keccak256(abi.encodePacked( - uint16(0x1901), - domainSeparator(), - keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, amount, nonce, deadline)) - ) - ); - } - - function recoverAddress(bytes32 digest, uint8 v, bytes32 r, bytes32 s) external pure returns (address) { - return ecrecover(digest, v, r, s); - } -} diff --git a/contracts/src/OldTestContracts/BorrowerOperationsTester.sol b/contracts/src/OldTestContracts/BorrowerOperationsTester.sol deleted file mode 100644 index 142cbdad..00000000 --- a/contracts/src/OldTestContracts/BorrowerOperationsTester.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../BorrowerOperations.sol"; - -/* Tester contract inherits from BorrowerOperations, and provides external functions -for testing the parent's internal functions. */ -contract BorrowerOperationsTester is BorrowerOperations { - - function getNewICRFromTroveChange - ( - uint _coll, - uint _debt, - uint _collChange, - bool isCollIncrease, - uint _debtChange, - bool isDebtIncrease, - uint _price - ) - external - pure - returns (uint) - { - return _getNewICRFromTroveChange(_coll, _debt, _collChange, isCollIncrease, _debtChange, isDebtIncrease, _price); - } - - function getNewTCRFromTroveChange - ( - uint _collChange, - bool isCollIncrease, - uint _debtChange, - bool isDebtIncrease, - uint _price - ) - external - view - returns (uint) - { - return _getNewTCRFromTroveChange(_collChange, isCollIncrease, _debtChange, isDebtIncrease, _price); - } - - function getUSDValue(uint _coll, uint _price) external pure returns (uint) { - return _getUSDValue(_coll, _price); - } - - function callInternalAdjustLoan - ( - address _borrower, - uint _collWithdrawal, - uint _debtChange, - bool _isDebtIncrease, - address _upperHint, - address _lowerHint) - external - { - _adjustTrove(_borrower, _collWithdrawal, _debtChange, _isDebtIncrease, _upperHint, _lowerHint, 0); - } - - - // Payable fallback function - receive() external payable { } -} diff --git a/contracts/src/OldTestContracts/CDPManagerTester.sol b/contracts/src/OldTestContracts/CDPManagerTester.sol deleted file mode 100644 index 02eee294..00000000 --- a/contracts/src/OldTestContracts/CDPManagerTester.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../TroveManager.sol"; - -/* Tester contract inherits from TroveManager, and provides external functions -for testing the parent's internal functions. */ - -contract TroveManagerTester is TroveManager { - - function computeICR(uint _coll, uint _debt, uint _price) external pure returns (uint) { - return LiquityMath._computeCR(_coll, _debt, _price); - } - - function getCollGasCompensation(uint _coll) external pure returns (uint) { - return _getCollGasCompensation(_coll); - } - - function getBoldGasCompensation() external pure returns (uint) { - return BOLD_GAS_COMPENSATION; - } - - function getCompositeDebt(uint _debt) external pure returns (uint) { - return _getCompositeDebt(_debt); - } - - function unprotectedDecayBaseRateFromBorrowing() external returns (uint) { - baseRate = _calcDecayedBaseRate(); - assert(baseRate >= 0 && baseRate <= DECIMAL_PRECISION); - - _updateLastFeeOpTime(); - return baseRate; - } - - function minutesPassedSinceLastFeeOp() external view returns (uint) { - return _minutesPassedSinceLastFeeOp(); - } - - function setLastFeeOpTimeToNow() external { - lastFeeOperationTime = block.timestamp; - } - - function setBaseRate(uint _baseRate) external { - baseRate = _baseRate; - } - - function callGetRedemptionFee(uint _ETHDrawn) external view returns (uint) { - _getRedemptionFee(_ETHDrawn); - } - - function getActualDebtFromComposite(uint _debtVal) external pure returns (uint) { - return _getNetDebt(_debtVal); - } - - function callInternalRemoveTroveOwner(address _troveOwner) external { - uint troveOwnersArrayLength = TroveOwners.length; - _removeTroveOwner(_troveOwner, troveOwnersArrayLength); - } -} diff --git a/contracts/src/OldTestContracts/DefaultPoolTester.sol b/contracts/src/OldTestContracts/DefaultPoolTester.sol deleted file mode 100644 index a81c3f47..00000000 --- a/contracts/src/OldTestContracts/DefaultPoolTester.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../DefaultPool.sol"; - -contract DefaultPoolTester is DefaultPool { - - function unprotectedIncreaseBoldDebt(uint _amount) external { - BoldDebt = BoldDebt + _amount; - } - - function unprotectedPayable() external payable { - ETH = ETH + msg.value; - } -} diff --git a/contracts/src/OldTestContracts/Destructible.sol b/contracts/src/OldTestContracts/Destructible.sol deleted file mode 100644 index 2146a9ff..00000000 --- a/contracts/src/OldTestContracts/Destructible.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -contract Destructible { - - receive() external payable {} - - function destruct(address payable _receiver) external { - selfdestruct(_receiver); - } -} diff --git a/contracts/src/OldTestContracts/FunctionCaller.sol b/contracts/src/OldTestContracts/FunctionCaller.sol deleted file mode 100644 index 04929ae6..00000000 --- a/contracts/src/OldTestContracts/FunctionCaller.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import '../Interfaces/ITroveManager.sol'; -import '../Interfaces/ISortedTroves.sol'; -import '../Interfaces/IPriceFeed.sol'; -import '../Dependencies/LiquityMath.sol'; - -/* Wrapper contract - used for calculating gas of read-only and internal functions. -Not part of the Liquity application. */ -contract FunctionCaller { - - ITroveManager troveManager; - address public troveManagerAddress; - - ISortedTroves sortedTroves; - address public sortedTrovesAddress; - - IPriceFeed priceFeed; - address public priceFeedAddress; - - // --- Dependency setters --- - - function setTroveManagerAddress(address _troveManagerAddress) external { - troveManagerAddress = _troveManagerAddress; - troveManager = ITroveManager(_troveManagerAddress); - } - - function setSortedTrovesAddress(address _sortedTrovesAddress) external { - troveManagerAddress = _sortedTrovesAddress; - sortedTroves = ISortedTroves(_sortedTrovesAddress); - } - - function setPriceFeedAddress(address _priceFeedAddress) external { - priceFeedAddress = _priceFeedAddress; - priceFeed = IPriceFeed(_priceFeedAddress); - } - - // --- Non-view wrapper functions used for calculating gas --- - - function troveManager_getCurrentICR(address _address, uint _price) external returns (uint) { - return troveManager.getCurrentICR(_address, _price); - } - - function sortedTroves_findInsertPosition(uint _NICR, address _prevId, address _nextId) external returns (address, address) { - return sortedTroves.findInsertPosition(_NICR, _prevId, _nextId); - } -} diff --git a/contracts/src/OldTestContracts/LiquityMathTester.sol b/contracts/src/OldTestContracts/LiquityMathTester.sol deleted file mode 100644 index 627bf788..00000000 --- a/contracts/src/OldTestContracts/LiquityMathTester.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../Dependencies/LiquityMath.sol"; - -/* Tester contract for math functions in Math.sol library. */ - -contract LiquityMathTester { - - function callMax(uint _a, uint _b) external pure returns (uint) { - return LiquityMath._max(_a, _b); - } - - // Non-view wrapper for gas test - function callDecPowTx(uint _base, uint _n) external returns (uint) { - return LiquityMath._decPow(_base, _n); - } - - // External wrapper - function callDecPow(uint _base, uint _n) external pure returns (uint) { - return LiquityMath._decPow(_base, _n); - } -} diff --git a/contracts/src/OldTestContracts/MockTellor.sol b/contracts/src/OldTestContracts/MockTellor.sol deleted file mode 100644 index be039b47..00000000 --- a/contracts/src/OldTestContracts/MockTellor.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - - -contract MockTellor { - - // --- Mock price data --- - - bool didRetrieve = true; // default to a positive retrieval - uint private price; - uint private updateTime; - - bool private revertRequest; - - // --- Setters for mock price data --- - - function setPrice(uint _price) external { - price = _price; - } - - function setDidRetrieve(bool _didRetrieve) external { - didRetrieve = _didRetrieve; - } - - function setUpdateTime(uint _updateTime) external { - updateTime = _updateTime; - } - - function setRevertRequest() external { - revertRequest = !revertRequest; - } - - // --- Mock data reporting functions --- - - function getTimestampbyRequestIDandIndex(uint, uint) external view returns (uint) { - return updateTime; - } - - function getNewValueCountbyRequestId(uint) external view returns (uint) { - if (revertRequest) {require (1 == 0, "Tellor request reverted");} - return 1; - } - - function retrieveData(uint256, uint256) external view returns (uint256) { - return price; - } - - - -} diff --git a/contracts/src/OldTestContracts/NonPayable.sol b/contracts/src/OldTestContracts/NonPayable.sol deleted file mode 100644 index 6539427c..00000000 --- a/contracts/src/OldTestContracts/NonPayable.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -//import "../Dependencies/console.sol"; - - -contract NonPayable { - bool isPayable; - - function setPayable(bool _isPayable) external { - isPayable = _isPayable; - } - - function forward(address _dest, bytes calldata _data) external payable { - (bool success, bytes memory returnData) = _dest.call{ value: msg.value }(_data); - //console.logBytes(returnData); - require(success, string(returnData)); - } - - receive() external payable { - require(isPayable); - } -} diff --git a/contracts/src/OldTestContracts/PriceFeedTester.sol b/contracts/src/OldTestContracts/PriceFeedTester.sol deleted file mode 100644 index aec017ef..00000000 --- a/contracts/src/OldTestContracts/PriceFeedTester.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../PriceFeed.sol"; - -contract PriceFeedTester is PriceFeed { - - function setLastGoodPrice(uint _lastGoodPrice) external { - lastGoodPrice = _lastGoodPrice; - } - - function setStatus(Status _status) external { - status = _status; - } -} \ No newline at end of file diff --git a/contracts/src/OldTestContracts/PriceFeedTestnet.sol b/contracts/src/OldTestContracts/PriceFeedTestnet.sol deleted file mode 100644 index c85eb6c1..00000000 --- a/contracts/src/OldTestContracts/PriceFeedTestnet.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../Interfaces/IPriceFeedTestnet.sol"; - -/* -* PriceFeed placeholder for testnet and development. The price is simply set manually and saved in a state -* variable. The contract does not connect to a live Chainlink price feed. -*/ -contract PriceFeedTestnet is IPriceFeedTestnet { - event LastGoodPriceUpdated(uint _lastGoodPrice); - - uint256 private _price = 200 * 1e18; - - // --- Functions --- - - // View price getter for simplicity in tests - function getPrice() external view returns (uint256) { - return _price; - } - - function fetchPrice() external override returns (uint256) { - // Fire an event just like the mainnet version would. - // This lets the subgraph rely on events to get the latest price even when developing locally. - emit LastGoodPriceUpdated(_price); - return _price; - } - - // Manual external price setter. - function setPrice(uint256 price) external returns (bool) { - _price = price; - return true; - } -} diff --git a/contracts/src/OldTestContracts/SortedTrovesTester.sol b/contracts/src/OldTestContracts/SortedTrovesTester.sol deleted file mode 100644 index 3a373d16..00000000 --- a/contracts/src/OldTestContracts/SortedTrovesTester.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../Interfaces/ISortedTroves.sol"; - - -contract SortedTrovesTester { - ISortedTroves sortedTroves; - - function setSortedTroves(address _sortedTrovesAddress) external { - sortedTroves = ISortedTroves(_sortedTrovesAddress); - } - - function insert(address _id, uint256 _NICR, address _prevId, address _nextId) external { - sortedTroves.insert(_id, _NICR, _prevId, _nextId); - } - - function remove(address _id) external { - sortedTroves.remove(_id); - } - - function reInsert(address _id, uint256 _newNICR, address _prevId, address _nextId) external { - sortedTroves.reInsert(_id, _newNICR, _prevId, _nextId); - } - - function getNominalICR(address) external pure returns (uint) { - return 1; - } - - function getCurrentICR(address, uint) external pure returns (uint) { - return 1; - } -} diff --git a/contracts/src/OldTestContracts/StabilityPoolTester.sol b/contracts/src/OldTestContracts/StabilityPoolTester.sol deleted file mode 100644 index 57f503ce..00000000 --- a/contracts/src/OldTestContracts/StabilityPoolTester.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "../StabilityPool.sol"; - -contract StabilityPoolTester is StabilityPool { - - function unprotectedPayable() external payable { - ETH = ETH + msg.value; - } - - function setCurrentScale(uint128 _currentScale) external { - currentScale = _currentScale; - } - - function setTotalDeposits(uint _totalBoldDeposits) external { - totalBoldDeposits = _totalBoldDeposits; - } -} diff --git a/contracts/src/TestContracts/PriceFeedTestnet.sol b/contracts/src/TestContracts/PriceFeedTestnet.sol index 2f220196..3c57c514 100644 --- a/contracts/src/TestContracts/PriceFeedTestnet.sol +++ b/contracts/src/TestContracts/PriceFeedTestnet.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.18; -import "../Interfaces/IPriceFeed.sol"; +import "../test/TestContracts/Interfaces/IPriceFeedTestnet.sol"; /* * PriceFeed placeholder for testnet and development. The price is simply set manually and saved in a state * variable. The contract does not connect to a live Chainlink price feed. */ -contract PriceFeedTestnet is IPriceFeed { +contract PriceFeedTestnet is IPriceFeedTestnet { event LastGoodPriceUpdated(uint _lastGoodPrice); uint256 private _price = 200 * 1e18; diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 087b0f4d..03d5da9f 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -13,7 +13,7 @@ import "./Dependencies/LiquityBase.sol"; import "./Dependencies/Ownable.sol"; import "./Dependencies/CheckContract.sol"; -import "forge-std/console2.sol"; +// import "forge-std/console2.sol"; contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { string constant public NAME = "TroveManager"; diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol index 0313326a..ec44f378 100644 --- a/contracts/src/test/TestContracts/DevTestSetup.sol +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import "../../Interfaces/IPriceFeedTestnet.sol"; +import "./Interfaces/IPriceFeedTestnet.sol"; import "../../ActivePool.sol"; import "../../BoldToken.sol"; @@ -12,7 +12,7 @@ import "../../DefaultPool.sol"; import "../../GasPool.sol"; import "../../HintHelpers.sol"; import "../../MultiTroveGetter.sol"; -import "../../OldTestContracts/PriceFeedTestnet.sol"; +import "../../TestContracts/PriceFeedTestnet.sol"; import "../../SortedTroves.sol"; import "../../StabilityPool.sol"; import "../../TroveManager.sol"; diff --git a/contracts/src/Interfaces/IPriceFeedTestnet.sol b/contracts/src/test/TestContracts/Interfaces/IPriceFeedTestnet.sol similarity index 78% rename from contracts/src/Interfaces/IPriceFeedTestnet.sol rename to contracts/src/test/TestContracts/Interfaces/IPriceFeedTestnet.sol index 5db7d1df..06325aa0 100644 --- a/contracts/src/Interfaces/IPriceFeedTestnet.sol +++ b/contracts/src/test/TestContracts/Interfaces/IPriceFeedTestnet.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.18; -import "./IPriceFeed.sol"; +import "../../../Interfaces/IPriceFeed.sol"; interface IPriceFeedTestnet is IPriceFeed { function setPrice(uint256 _price) external returns (bool); diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index 0fc8b51c..f5644b2a 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -160,7 +160,7 @@ contract BasicOps is DevTestSetup { assertEq(boldToken.balanceOf(A), 1900e18); assertEq(stabilityPool.getCompoundedBoldDeposit(A), 100e18); - // A tops up their SP deposit + // A withdraws their full SP deposit stabilityPool.withdrawFromSP(100e18); // Check A's balance increased and SP deposit decreased to 0