From e52315ad1bc147506e22917f9051872b4a0fb3ba Mon Sep 17 00:00:00 2001 From: RickGriff Date: Thu, 25 Jan 2024 14:58:14 +0700 Subject: [PATCH 1/9] Add borrower-chosen interest rate ordering --- contracts/src/BorrowerOperations.sol | 96 ++++----- contracts/src/Dependencies/LiquityBase.sol | 2 + .../src/Interfaces/IBorrowerOperations.sol | 16 +- contracts/src/Interfaces/IStabilityPool.sol | 2 +- contracts/src/Interfaces/ITroveManager.sol | 8 +- contracts/src/MultiTroveGetter.sol | 6 +- contracts/src/SortedTroves.sol | 131 +++++------ contracts/src/StabilityPool.sol | 4 +- .../BorrowerOperationsTester.sol | 24 +-- contracts/src/TroveManager.sol | 29 ++- contracts/src/test/TestContracts/BaseTest.sol | 41 +++- contracts/src/test/basicOps.t.sol | 22 +- contracts/src/test/interestRateBasic.t.sol | 204 ++++++++++++++++++ 13 files changed, 409 insertions(+), 176 deletions(-) create mode 100644 contracts/src/test/interestRateBasic.t.sol diff --git a/contracts/src/BorrowerOperations.sol b/contracts/src/BorrowerOperations.sol index 3bd4ef75..ed03b14c 100644 --- a/contracts/src/BorrowerOperations.sol +++ b/contracts/src/BorrowerOperations.sol @@ -59,7 +59,6 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe uint netDebt; uint compositeDebt; uint ICR; - uint NICR; uint stake; uint arrayIndex; } @@ -145,16 +144,19 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe // --- Borrower Trove Operations --- - function openTrove(uint _maxFeePercentage, uint _boldAmount, address _upperHint, address _lowerHint) external payable override { + function openTrove(uint _maxFeePercentage, uint _boldAmount, address _upperHint, address _lowerHint, uint256 _annualInterestRate) external payable override { ContractsCache memory contractsCache = ContractsCache(troveManager, activePool, boldToken); LocalVariables_openTrove memory vars; vars.price = priceFeed.fetchPrice(); bool isRecoveryMode = _checkRecoveryMode(vars.price); + _requireValidAnnualInterestRate(_annualInterestRate); _requireValidMaxFeePercentage(_maxFeePercentage, isRecoveryMode); _requireTroveisNotActive(contractsCache.troveManager, msg.sender); + // TODO: apply aggregate pending interest, and take snapshot of current timestamp. + vars.BoldFee; vars.netDebt = _boldAmount; @@ -168,7 +170,6 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe assert(vars.compositeDebt > 0); vars.ICR = LiquityMath._computeCR(msg.value, vars.compositeDebt, vars.price); - vars.NICR = LiquityMath._computeNominalCR(msg.value, vars.compositeDebt); if (isRecoveryMode) { _requireICRisAboveCCR(vars.ICR); @@ -178,15 +179,15 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe _requireNewTCRisAboveCCR(newTCR); } - // Set the trove struct's properties - contractsCache.troveManager.setTroveStatus(msg.sender, 1); - contractsCache.troveManager.increaseTroveColl(msg.sender, msg.value); - contractsCache.troveManager.increaseTroveDebt(msg.sender, vars.compositeDebt); - - contractsCache.troveManager.updateTroveRewardSnapshots(msg.sender); - vars.stake = contractsCache.troveManager.updateStakeAndTotalStakes(msg.sender); + // Set the stored Trove properties + vars.stake = contractsCache.troveManager.setTrovePropertiesOnOpen( + msg.sender, + msg.value, + vars.compositeDebt, + _annualInterestRate + ); - sortedTroves.insert(msg.sender, vars.NICR, _upperHint, _lowerHint); + sortedTroves.insert(msg.sender, _annualInterestRate, _upperHint, _lowerHint); vars.arrayIndex = contractsCache.troveManager.addTroveOwnerToArray(msg.sender); emit TroveCreated(msg.sender, vars.arrayIndex); @@ -201,33 +202,48 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe } // Send ETH as collateral to a trove - function addColl(address _upperHint, address _lowerHint) external payable override { - _adjustTrove(msg.sender, 0, 0, false, _upperHint, _lowerHint, 0); + function addColl() external payable override { + _adjustTrove(msg.sender, 0, 0, false, 0); } // Send ETH as collateral to a trove. Called by only the Stability Pool. - function moveETHGainToTrove(address _borrower, address _upperHint, address _lowerHint) external payable override { + function moveETHGainToTrove(address _borrower) external payable override { _requireCallerIsStabilityPool(); - _adjustTrove(_borrower, 0, 0, false, _upperHint, _lowerHint, 0); + _adjustTrove(_borrower, 0, 0, false, 0); } // Withdraw ETH collateral from a trove - function withdrawColl(uint _collWithdrawal, address _upperHint, address _lowerHint) external override { - _adjustTrove(msg.sender, _collWithdrawal, 0, false, _upperHint, _lowerHint, 0); + function withdrawColl(uint _collWithdrawal) external override { + _adjustTrove(msg.sender, _collWithdrawal, 0, false, 0); } // Withdraw Bold tokens from a trove: mint new Bold tokens to the owner, and increase the trove's debt accordingly - function withdrawBold(uint _maxFeePercentage, uint _boldAmount, address _upperHint, address _lowerHint) external override { - _adjustTrove(msg.sender, 0, _boldAmount, true, _upperHint, _lowerHint, _maxFeePercentage); + function withdrawBold(uint _maxFeePercentage, uint _boldAmount ) external override { + _adjustTrove(msg.sender, 0, _boldAmount, true, _maxFeePercentage); } // Repay Bold tokens to a Trove: Burn the repaid Bold tokens, and reduce the trove's debt accordingly - function repayBold(uint _boldAmount, address _upperHint, address _lowerHint) external override { - _adjustTrove(msg.sender, 0, _boldAmount, false, _upperHint, _lowerHint, 0); + function repayBold(uint _boldAmount) external override { + _adjustTrove(msg.sender, 0, _boldAmount, false, 0); } - function adjustTrove(uint _maxFeePercentage, uint _collWithdrawal, uint _boldChange, bool _isDebtIncrease, address _upperHint, address _lowerHint) external payable override { - _adjustTrove(msg.sender, _collWithdrawal, _boldChange, _isDebtIncrease, _upperHint, _lowerHint, _maxFeePercentage); + function adjustTrove(uint _maxFeePercentage, uint _collWithdrawal, uint _boldChange, bool _isDebtIncrease) external payable override { + _adjustTrove(msg.sender, _collWithdrawal, _boldChange, _isDebtIncrease, _maxFeePercentage); + } + + function adjustTroveInterestRate(uint _newAnnualInterestRate, address _upperHint, address _lowerHint) external { + _requireValidAnnualInterestRate(_newAnnualInterestRate); + ITroveManager troveManagerCached = troveManager; + _requireTroveisActive(troveManagerCached, msg.sender); + + // TODO: apply individual and aggregate pending interest, and take snapshots of current timestamp. + // TODO: determine how applying pending interest should interact / be sequenced with applying pending rewards from redistributions. + + troveManagerCached.applyPendingRewards(msg.sender); + + sortedTroves.reInsert(msg.sender, _newAnnualInterestRate, _upperHint, _lowerHint); + + troveManagerCached.changeAnnualInterestRate(msg.sender, _newAnnualInterestRate); } /* @@ -237,7 +253,7 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe * * If both are positive, it will revert. */ - function _adjustTrove(address _borrower, uint _collWithdrawal, uint _boldChange, bool _isDebtIncrease, address _upperHint, address _lowerHint, uint _maxFeePercentage) internal { + function _adjustTrove(address _borrower, uint _collWithdrawal, uint _boldChange, bool _isDebtIncrease, uint _maxFeePercentage) internal { ContractsCache memory contractsCache = ContractsCache(troveManager, activePool, boldToken); LocalVariables_adjustTrove memory vars; @@ -255,6 +271,8 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe // Confirm the operation is either a borrower adjusting their own trove, or a pure ETH transfer from the Stability Pool to a trove assert(msg.sender == _borrower || (msg.sender == stabilityPoolAddress && msg.value > 0 && _boldChange == 0)); + // TODO: apply individual and aggregate pending interest, and take snapshots of current timestamp. + contractsCache.troveManager.applyPendingRewards(_borrower); // Get the collChange based on whether or not ETH was sent in the transaction @@ -288,10 +306,6 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe (vars.newColl, vars.newDebt) = _updateTroveFromAdjustment(contractsCache.troveManager, _borrower, vars.collChange, vars.isCollIncrease, vars.netDebtChange, _isDebtIncrease); vars.stake = contractsCache.troveManager.updateStakeAndTotalStakes(_borrower); - // Re-insert trove in to the sorted list - uint newNICR = _getNewNominalICRFromTroveChange(vars.coll, vars.debt, vars.collChange, vars.isCollIncrease, vars.netDebtChange, _isDebtIncrease); - sortedTroves.reInsert(_borrower, newNICR, _upperHint, _lowerHint); - emit TroveUpdated(_borrower, vars.newDebt, vars.newColl, vars.stake, BorrowerOperation.adjustTrove); emit BoldBorrowingFeePaid(msg.sender, vars.BoldFee); @@ -317,6 +331,8 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe uint price = priceFeed.fetchPrice(); _requireNotInRecoveryMode(price); + // TODO: apply individual and aggregate pending interest, and take snapshots of current timestamp. + troveManagerCached.applyPendingRewards(msg.sender); uint coll = troveManagerCached.getTroveColl(msg.sender); @@ -551,28 +567,12 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe } } - // --- ICR and TCR getters --- - - // Compute the new collateral ratio, considering the change in coll and debt. Assumes 0 pending rewards. - function _getNewNominalICRFromTroveChange - ( - uint _coll, - uint _debt, - uint _collChange, - bool _isCollIncrease, - uint _debtChange, - bool _isDebtIncrease - ) - pure - internal - returns (uint) - { - (uint newColl, uint newDebt) = _getNewTroveAmounts(_coll, _debt, _collChange, _isCollIncrease, _debtChange, _isDebtIncrease); - - uint newNICR = LiquityMath._computeNominalCR(newColl, newDebt); - return newNICR; + function _requireValidAnnualInterestRate(uint256 _annualInterestRate) internal pure { + require(_annualInterestRate <= MAX_ANNUAL_INTEREST_RATE, "Interest rate must not be greater than max"); } + // --- ICR and TCR getters --- + // Compute the new collateral ratio, considering the change in coll and debt. Assumes 0 pending rewards. function _getNewICRFromTroveChange ( diff --git a/contracts/src/Dependencies/LiquityBase.sol b/contracts/src/Dependencies/LiquityBase.sol index 36f7c4d9..e30187c2 100644 --- a/contracts/src/Dependencies/LiquityBase.sol +++ b/contracts/src/Dependencies/LiquityBase.sol @@ -29,6 +29,8 @@ contract LiquityBase is BaseMath, ILiquityBase { uint constant public MIN_NET_DEBT = 1800e18; // uint constant public MIN_NET_DEBT = 0; + uint256 constant public MAX_ANNUAL_INTEREST_RATE = 1e18; // 100% + uint constant public PERCENT_DIVISOR = 200; // dividing by 200 yields 0.5% uint constant public BORROWING_FEE_FLOOR = DECIMAL_PRECISION / 1000 * 5; // 0.5% diff --git a/contracts/src/Interfaces/IBorrowerOperations.sol b/contracts/src/Interfaces/IBorrowerOperations.sol index 1555cba5..588cacd9 100644 --- a/contracts/src/Interfaces/IBorrowerOperations.sol +++ b/contracts/src/Interfaces/IBorrowerOperations.sol @@ -24,23 +24,25 @@ interface IBorrowerOperations is ILiquityBase { address _boldTokenAddress ) external; - function openTrove(uint _maxFee, uint _boldAmount, address _upperHint, address _lowerHint) external payable; + function openTrove(uint _maxFee, uint _boldAmount, address _upperHint, address _lowerHint, uint256 _annualInterestRate) external payable; - function addColl(address _upperHint, address _lowerHint) external payable; + function addColl() external payable; - function moveETHGainToTrove(address _user, address _upperHint, address _lowerHint) external payable; + function moveETHGainToTrove(address _user) external payable; - function withdrawColl(uint _amount, address _upperHint, address _lowerHint) external; + function withdrawColl(uint _amount) external; - function withdrawBold(uint _maxFee, uint _amount, address _upperHint, address _lowerHint) external; + function withdrawBold(uint _maxFee, uint _amount) external; - function repayBold(uint _amount, address _upperHint, address _lowerHint) external; + function repayBold(uint _amount) external; function closeTrove() external; - function adjustTrove(uint _maxFee, uint _collWithdrawal, uint _debtChange, bool isDebtIncrease, address _upperHint, address _lowerHint) external payable; + function adjustTrove(uint _maxFee, uint _collWithdrawal, uint _debtChange, bool isDebtIncrease) external payable; function claimCollateral() external; function getCompositeDebt(uint _debt) external pure returns (uint); + + function adjustTroveInterestRate(uint _newAnnualInterestRate, address _upperHint, address _lowerHint) external; } diff --git a/contracts/src/Interfaces/IStabilityPool.sol b/contracts/src/Interfaces/IStabilityPool.sol index 96c6f413..efa8477c 100644 --- a/contracts/src/Interfaces/IStabilityPool.sol +++ b/contracts/src/Interfaces/IStabilityPool.sol @@ -69,7 +69,7 @@ interface IStabilityPool is ILiquityBase { * - Leaves their compounded deposit in the Stability Pool * - Takes new snapshots of accumulators P and S */ - function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external; + function withdrawETHGainToTrove() external; /* * Initial checks: diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index 1e188162..8c22dde5 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -53,8 +53,6 @@ interface ITroveManager is ILiquityBase { function updateStakeAndTotalStakes(address _borrower) external returns (uint); - function updateTroveRewardSnapshots(address _borrower) external; - function addTroveOwnerToArray(address _borrower) external returns (uint index); function applyPendingRewards(address _borrower) external; @@ -97,7 +95,9 @@ interface ITroveManager is ILiquityBase { function getTroveColl(address _borrower) external view returns (uint); - function setTroveStatus(address _borrower, uint num) external; + function getTroveAnnualInterestRate(address _borrower) external view returns (uint); + + function setTrovePropertiesOnOpen(address _borrower, uint256 _coll, uint256 _debt, uint256 _annualInterestRate) external returns (uint256); function increaseTroveColl(address _borrower, uint _collIncrease) external returns (uint); @@ -107,6 +107,8 @@ interface ITroveManager is ILiquityBase { function decreaseTroveDebt(address _borrower, uint _collDecrease) external returns (uint); + function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external returns (uint256); + function getTCR(uint _price) external view returns (uint); function checkRecoveryMode(uint _price) external view returns (bool); diff --git a/contracts/src/MultiTroveGetter.sol b/contracts/src/MultiTroveGetter.sol index 6c08d3f6..61bd9b8e 100644 --- a/contracts/src/MultiTroveGetter.sol +++ b/contracts/src/MultiTroveGetter.sol @@ -78,7 +78,8 @@ contract MultiTroveGetter { _troves[idx].coll, _troves[idx].stake, /* status */, - /* arrayIndex */ + /* arrayIndex */, + /* annualInterestRate */ ) = troveManager.Troves(currentTroveowner); ( _troves[idx].snapshotETH, @@ -107,7 +108,8 @@ contract MultiTroveGetter { _troves[idx].coll, _troves[idx].stake, /* status */, - /* arrayIndex */ + /* arrayIndex */, + /* annualInterestRate */ ) = troveManager.Troves(currentTroveowner); ( _troves[idx].snapshotETH, diff --git a/contracts/src/SortedTroves.sol b/contracts/src/SortedTroves.sol index 23195c76..f87ada42 100644 --- a/contracts/src/SortedTroves.sol +++ b/contracts/src/SortedTroves.sol @@ -12,32 +12,23 @@ import "./Dependencies/CheckContract.sol"; * A sorted doubly linked list with nodes sorted in descending order. * * Nodes map to active Troves in the system - the ID property is the address of a Trove owner. -* Nodes are ordered according to their current nominal individual collateral ratio (NICR), -* which is like the ICR but without the price, i.e., just collateral / debt. +* Nodes are ordered according to the borrower's chosen annual interest rate. * * The list optionally accepts insert position hints. * -* NICRs are computed dynamically at runtime, and not stored on the Node. This is because NICRs of active Troves -* change dynamically as liquidation events occur. +* The annual interest rate is stored on the Trove struct in TroveManager, not directly on the Node. * -* The list relies on the fact that liquidation events preserve ordering: a liquidation decreases the NICRs of all active Troves, -* but maintains their order. A node inserted based on current NICR will maintain the correct position, -* relative to it's peers, as rewards accumulate, as long as it's raw collateral and debt have not changed. -* Thus, Nodes remain sorted by current NICR. -* -* Nodes need only be re-inserted upon a Trove operation - when the owner adds or removes collateral or debt -* to their position. +* A node need only be re-inserted when the borrower adjusts their interest rate. Interest rate order is preserved +* under all other system operations. * * The list is a modification of the following audited SortedDoublyLinkedList: * https://github.com/livepeer/protocol/blob/master/contracts/libraries/SortedDoublyLL.sol * -* -* Changes made in the Liquity implementation: +* Changes made in the Bold implementation: * * - Keys have been removed from nodes * -* - Ordering checks for insertion are performed by comparing an NICR argument to the current NICR, calculated at runtime. -* The list relies on the property that ordering by ICR is maintained as the ETH:USD price varies. +* - Ordering checks for insertion are performed by comparing an interest rate argument to the Trove's current interest rate. * * - Public functions with parameters have been made internal to save gas, and given an external wrapper function for external access */ @@ -46,7 +37,7 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { event TroveManagerAddressChanged(address _troveManagerAddress); event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress); - event NodeAdded(address _id, uint _NICR); + event NodeAdded(address _id, uint _annualInterestRate); event NodeRemoved(address _id); address public borrowerOperationsAddress; @@ -56,14 +47,14 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { // Information for a node in the list struct Node { bool exists; - address nextId; // Id of next node (smaller NICR) in the list - address prevId; // Id of previous node (larger NICR) in the list + address nextId; // Id of next node (smaller interest rate) in the list + address prevId; // Id of previous node (larger interest rate) in the list } // Information for the list struct Data { - address head; // Head of the list. Also the node in the list with the largest NICR - address tail; // Tail of the list. Also the node in the list with the smallest NICR + address head; // Head of the list. Also the node in the list with the largest interest rate + address tail; // Tail of the list. Also the node in the list with the smallest interest rate uint256 maxSize; // Maximum size of the list uint256 size; // Current size of the list mapping (address => Node) nodes; // Track the corresponding ids for each node in the list @@ -92,35 +83,33 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { /* * @dev Add a node to the list * @param _id Node's id - * @param _NICR Node's NICR + * @param _annualInterestRate Node's annual interest rate * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ - function insert (address _id, uint256 _NICR, address _prevId, address _nextId) external override { + function insert (address _id, uint256 _annualInterestRate, address _prevId, address _nextId) external override { ITroveManager troveManagerCached = troveManager; _requireCallerIsBOorTroveM(troveManagerCached); - _insert(troveManagerCached, _id, _NICR, _prevId, _nextId); + _insert(troveManagerCached, _id, _annualInterestRate, _prevId, _nextId); } - function _insert(ITroveManager _troveManager, address _id, uint256 _NICR, address _prevId, address _nextId) internal { + function _insert(ITroveManager _troveManager, address _id, uint256 _annualInterestRate, address _prevId, address _nextId) internal { // List must not be full require(!isFull(), "SortedTroves: List is full"); // List must not already contain node require(!contains(_id), "SortedTroves: List already contains the node"); // Node id must not be null require(_id != address(0), "SortedTroves: Id cannot be zero"); - // NICR must be non-zero - require(_NICR > 0, "SortedTroves: NICR must be positive"); address prevId = _prevId; address nextId = _nextId; - if (!_validInsertPosition(_troveManager, _NICR, prevId, nextId)) { + if (!_validInsertPosition(_troveManager, _annualInterestRate, prevId, nextId)) { // Sender's hint was not a valid insert position // Use sender's hint to find a valid insert position - (prevId, nextId) = _findInsertPosition(_troveManager, _NICR, prevId, nextId); + (prevId, nextId) = _findInsertPosition(_troveManager, _annualInterestRate, prevId, nextId); } data.nodes[_id].exists = true; @@ -148,7 +137,7 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } data.size = data.size + 1; - emit NodeAdded(_id, _NICR); + emit NodeAdded(_id, _annualInterestRate); } function remove(address _id) external override { @@ -198,25 +187,23 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Re-insert the node at a new position, based on its new NICR + * @dev Re-insert the node at a new position, based on its new annual interest rate * @param _id Node's id - * @param _newNICR Node's new NICR + * @param _newAnnualInterestRate Node's new annual interest rate * @param _prevId Id of previous node for the new insert position * @param _nextId Id of next node for the new insert position */ - function reInsert(address _id, uint256 _newNICR, address _prevId, address _nextId) external override { + function reInsert(address _id, uint256 _newAnnualInterestRate, address _prevId, address _nextId) external override { ITroveManager troveManagerCached = troveManager; _requireCallerIsBOorTroveM(troveManagerCached); // List must contain the node require(contains(_id), "SortedTroves: List does not contain the id"); - // NICR must be non-zero - require(_newNICR > 0, "SortedTroves: NICR must be positive"); // Remove node from the list _remove(_id); - _insert(troveManagerCached, _id, _newNICR, _prevId, _nextId); + _insert(troveManagerCached, _id, _newAnnualInterestRate, _prevId, _nextId); } /* @@ -255,21 +242,21 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Returns the first node in the list (node with the largest NICR) + * @dev Returns the first node in the list (node with the largest annual interest rate) */ function getFirst() external view override returns (address) { return data.head; } /* - * @dev Returns the last node in the list (node with the smallest NICR) + * @dev Returns the last node in the list (node with the smallest annual interest rate) */ function getLast() external view override returns (address) { return data.tail; } /* - * @dev Returns the next node (with a smaller NICR) in the list for a given node + * @dev Returns the next node (with a smaller interest rate) in the list for a given node * @param _id Node's id */ function getNext(address _id) external view override returns (address) { @@ -277,7 +264,7 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Returns the previous node (with a larger NICR) in the list for a given node + * @dev Returns the previous node (with a larger interest rate) in the list for a given node * @param _id Node's id */ function getPrev(address _id) external view override returns (address) { @@ -285,42 +272,42 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Check if a pair of nodes is a valid insertion point for a new node with the given NICR - * @param _NICR Node's NICR + * @dev Check if a pair of nodes is a valid insertion point for a new node with the given interest rate + * @param _annualInterestRate Node's annual interest rate * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ - function validInsertPosition(uint256 _NICR, address _prevId, address _nextId) external view override returns (bool) { - return _validInsertPosition(troveManager, _NICR, _prevId, _nextId); + function validInsertPosition(uint256 _annualInterestRate, address _prevId, address _nextId) external view override returns (bool) { + return _validInsertPosition(troveManager, _annualInterestRate, _prevId, _nextId); } - function _validInsertPosition(ITroveManager _troveManager, uint256 _NICR, address _prevId, address _nextId) internal view returns (bool) { + function _validInsertPosition(ITroveManager _troveManager, uint256 _annualInterestRate, address _prevId, address _nextId) internal view returns (bool) { if (_prevId == address(0) && _nextId == address(0)) { // `(null, null)` is a valid insert position if the list is empty return isEmpty(); } else if (_prevId == address(0)) { // `(null, _nextId)` is a valid insert position if `_nextId` is the head of the list - return data.head == _nextId && _NICR >= _troveManager.getNominalICR(_nextId); + return data.head == _nextId && _annualInterestRate >= _troveManager.getTroveAnnualInterestRate(_nextId); } else if (_nextId == address(0)) { // `(_prevId, null)` is a valid insert position if `_prevId` is the tail of the list - return data.tail == _prevId && _NICR <= _troveManager.getNominalICR(_prevId); + return data.tail == _prevId && _annualInterestRate <= _troveManager.getTroveAnnualInterestRate(_prevId); } else { - // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_NICR` falls between the two nodes' NICRs + // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_annualInterestRate` falls between the two nodes' interest rates return data.nodes[_prevId].nextId == _nextId && - _troveManager.getNominalICR(_prevId) >= _NICR && - _NICR >= _troveManager.getNominalICR(_nextId); + _troveManager.getTroveAnnualInterestRate(_prevId) >= _annualInterestRate && + _annualInterestRate >= _troveManager.getTroveAnnualInterestRate(_nextId); } } /* - * @dev Descend the list (larger NICRs to smaller NICRs) to find a valid insert position + * @dev Descend the list (larger interest rates to smaller interest rates) to find a valid insert position * @param _troveManager TroveManager contract, passed in as param to save SLOAD’s - * @param _NICR Node's NICR + * @param _annualInterestRate Node's annual interest rate * @param _startId Id of node to start descending the list from */ - function _descendList(ITroveManager _troveManager, uint256 _NICR, address _startId) internal view returns (address, address) { + function _descendList(ITroveManager _troveManager, uint256 _annualInterestRate, address _startId) internal view returns (address, address) { // If `_startId` is the head, check if the insert position is before the head - if (data.head == _startId && _NICR >= _troveManager.getNominalICR(_startId)) { + if (data.head == _startId && _annualInterestRate >= _troveManager.getTroveAnnualInterestRate(_startId)) { return (address(0), _startId); } @@ -328,7 +315,7 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { address nextId = data.nodes[prevId].nextId; // Descend the list until we reach the end or until we find a valid insert position - while (prevId != address(0) && !_validInsertPosition(_troveManager, _NICR, prevId, nextId)) { + while (prevId != address(0) && !_validInsertPosition(_troveManager, _annualInterestRate, prevId, nextId)) { prevId = data.nodes[prevId].nextId; nextId = data.nodes[prevId].nextId; } @@ -337,14 +324,14 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Ascend the list (smaller NICRs to larger NICRs) to find a valid insert position + * @dev Ascend the list (smaller interest rates to larger interest rates) to find a valid insert position * @param _troveManager TroveManager contract, passed in as param to save SLOAD’s - * @param _NICR Node's NICR + * @param _annualInterestRate Node's annual interest rate * @param _startId Id of node to start ascending the list from */ - function _ascendList(ITroveManager _troveManager, uint256 _NICR, address _startId) internal view returns (address, address) { + function _ascendList(ITroveManager _troveManager, uint256 _annualInterestRate, address _startId) internal view returns (address, address) { // If `_startId` is the tail, check if the insert position is after the tail - if (data.tail == _startId && _NICR <= _troveManager.getNominalICR(_startId)) { + if (data.tail == _startId && _annualInterestRate <= _troveManager.getTroveAnnualInterestRate(_startId)) { return (_startId, address(0)); } @@ -352,7 +339,7 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { address prevId = data.nodes[nextId].prevId; // Ascend the list until we reach the end or until we find a valid insertion point - while (nextId != address(0) && !_validInsertPosition(_troveManager, _NICR, prevId, nextId)) { + while (nextId != address(0) && !_validInsertPosition(_troveManager, _annualInterestRate, prevId, nextId)) { nextId = data.nodes[nextId].prevId; prevId = data.nodes[nextId].prevId; } @@ -361,45 +348,45 @@ contract SortedTroves is Ownable, CheckContract, ISortedTroves { } /* - * @dev Find the insert position for a new node with the given NICR - * @param _NICR Node's NICR + * @dev Find the insert position for a new node with the given interest rate + * @param _annualInterestRate Node's annual interest rate * @param _prevId Id of previous node for the insert position * @param _nextId Id of next node for the insert position */ - function findInsertPosition(uint256 _NICR, address _prevId, address _nextId) external view override returns (address, address) { - return _findInsertPosition(troveManager, _NICR, _prevId, _nextId); + function findInsertPosition(uint256 _annualInterestRate, address _prevId, address _nextId) external view override returns (address, address) { + return _findInsertPosition(troveManager, _annualInterestRate, _prevId, _nextId); } - function _findInsertPosition(ITroveManager _troveManager, uint256 _NICR, address _prevId, address _nextId) internal view returns (address, address) { + function _findInsertPosition(ITroveManager _troveManager, uint256 _annualInterestRate, address _prevId, address _nextId) internal view returns (address, address) { address prevId = _prevId; address nextId = _nextId; if (prevId != address(0)) { - if (!contains(prevId) || _NICR > _troveManager.getNominalICR(prevId)) { - // `prevId` does not exist anymore or now has a smaller NICR than the given NICR + if (!contains(prevId) || _annualInterestRate > _troveManager.getTroveAnnualInterestRate(prevId)) { + // `prevId` does not exist anymore or now has a smaller interest rate than the given interest rate prevId = address(0); } } if (nextId != address(0)) { - if (!contains(nextId) || _NICR < _troveManager.getNominalICR(nextId)) { - // `nextId` does not exist anymore or now has a larger NICR than the given NICR + if (!contains(nextId) || _annualInterestRate < _troveManager.getTroveAnnualInterestRate(nextId)) { + // `nextId` does not exist anymore or now has a larger interest rate than the given interest rate nextId = address(0); } } if (prevId == address(0) && nextId == address(0)) { // No hint - descend list starting from head - return _descendList(_troveManager, _NICR, data.head); + return _descendList(_troveManager, _annualInterestRate, data.head); } else if (prevId == address(0)) { // No `prevId` for hint - ascend list starting from `nextId` - return _ascendList(_troveManager, _NICR, nextId); + return _ascendList(_troveManager, _annualInterestRate, nextId); } else if (nextId == address(0)) { // No `nextId` for hint - descend list starting from `prevId` - return _descendList(_troveManager, _NICR, prevId); + return _descendList(_troveManager, _annualInterestRate, prevId); } else { // Descend list starting from `prevId` - return _descendList(_troveManager, _NICR, prevId); + return _descendList(_troveManager, _annualInterestRate, prevId); } } diff --git a/contracts/src/StabilityPool.sol b/contracts/src/StabilityPool.sol index 550ff4e5..0a1455ed 100644 --- a/contracts/src/StabilityPool.sol +++ b/contracts/src/StabilityPool.sol @@ -326,7 +326,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { * - Leaves their compounded deposit in the Stability Pool * - Takes new snapshots of accumulators P and S */ - function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external override { + function withdrawETHGainToTrove() external override { uint initialDeposit = deposits[msg.sender].initialValue; _requireUserHasDeposit(initialDeposit); _requireUserHasTrove(msg.sender); @@ -349,7 +349,7 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { emit StabilityPoolETHBalanceUpdated(ETH); emit EtherSent(msg.sender, depositorETHGain); - borrowerOperations.moveETHGainToTrove{ value: depositorETHGain }(msg.sender, _upperHint, _lowerHint); + borrowerOperations.moveETHGainToTrove{ value: depositorETHGain }(msg.sender); } // --- Liquidation functions --- diff --git a/contracts/src/TestContracts/BorrowerOperationsTester.sol b/contracts/src/TestContracts/BorrowerOperationsTester.sol index 142cbdad..67296a41 100644 --- a/contracts/src/TestContracts/BorrowerOperationsTester.sol +++ b/contracts/src/TestContracts/BorrowerOperationsTester.sol @@ -8,23 +8,6 @@ import "../BorrowerOperations.sol"; 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, @@ -49,12 +32,11 @@ contract BorrowerOperationsTester is BorrowerOperations { address _borrower, uint _collWithdrawal, uint _debtChange, - bool _isDebtIncrease, - address _upperHint, - address _lowerHint) + bool _isDebtIncrease + ) external { - _adjustTrove(_borrower, _collWithdrawal, _debtChange, _isDebtIncrease, _upperHint, _lowerHint, 0); + _adjustTrove(_borrower, _collWithdrawal, _debtChange, _isDebtIncrease, 0); } diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index fe57b795..1358283f 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -71,6 +71,8 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { uint stake; Status status; uint128 arrayIndex; + uint256 annualInterestRate; + // TODO: optimize this struct packing for gas reduction, which may break v1 tests that assume a certain order of properties } mapping (address => Trove) public Troves; @@ -1062,12 +1064,6 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { } } - // Update borrower's snapshots of L_ETH and L_boldDebt to reflect the current values - function updateTroveRewardSnapshots(address _borrower) external override { - _requireCallerIsBorrowerOperations(); - return _updateTroveRewardSnapshots(_borrower); - } - function _updateTroveRewardSnapshots(address _borrower) internal { rewardSnapshots[_borrower].ETH = L_ETH; rewardSnapshots[_borrower].boldDebt = L_boldDebt; @@ -1229,6 +1225,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { Troves[_borrower].status = closedStatus; Troves[_borrower].coll = 0; Troves[_borrower].debt = 0; + Troves[_borrower].annualInterestRate = 0; rewardSnapshots[_borrower].ETH = 0; rewardSnapshots[_borrower].boldDebt = 0; @@ -1507,11 +1504,22 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { return Troves[_borrower].coll; } + function getTroveAnnualInterestRate(address _borrower) external view returns (uint) { + return Troves[_borrower].annualInterestRate; + } + // --- Trove property setters, called by BorrowerOperations --- - function setTroveStatus(address _borrower, uint _num) external override { + function setTrovePropertiesOnOpen(address _borrower, uint256 _coll, uint256 _debt, uint256 _annualInterestRate) external returns (uint256) { _requireCallerIsBorrowerOperations(); - Troves[_borrower].status = Status(_num); + // TODO: optimize gas for writing to this struct + Troves[_borrower].status = Status.active; + Troves[_borrower].coll = _coll; + Troves[_borrower].debt = _debt; + Troves[_borrower].annualInterestRate = _annualInterestRate; + + _updateTroveRewardSnapshots(_borrower); + return _updateStakeAndTotalStakes(_borrower); } function increaseTroveColl(address _borrower, uint _collIncrease) external override returns (uint) { @@ -1541,4 +1549,9 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { Troves[_borrower].debt = newDebt; return newDebt; } + + function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external returns (uint256) { + _requireCallerIsBorrowerOperations(); + Troves[_borrower].annualInterestRate = _newAnnualInterestRate; + } } diff --git a/contracts/src/test/TestContracts/BaseTest.sol b/contracts/src/test/TestContracts/BaseTest.sol index de45e071..f057578f 100644 --- a/contracts/src/test/TestContracts/BaseTest.sol +++ b/contracts/src/test/TestContracts/BaseTest.sol @@ -56,7 +56,46 @@ contract BaseTest is Test { accountsList = tempAccounts; } - function logContractAddresses() view public { + function openTroveNoHints100pctMaxFee( + address _account, + uint256 _coll, + uint256 _boldAmount, + uint256 _annualInterestRate + ) + public + { + vm.startPrank(_account); + borrowerOperations.openTrove{value: _coll}(1e18, _boldAmount, ZERO_ADDRESS, ZERO_ADDRESS, _annualInterestRate); + vm.stopPrank(); + } + + + // (uint _maxFeePercentage, uint _collWithdrawal, uint _boldChange, bool _isDebtIncrease) + function adjustTrove100pctMaxFee( + address _account, + uint256 _collChange, + uint256 _boldChange, + bool _isCollIncrease, + bool _isDebtIncrease + ) + public + { + vm.startPrank(_account); + if (_isCollIncrease) { + borrowerOperations.adjustTrove{value: _collChange}(1e18, 0, _boldChange, _isDebtIncrease); + } else { + borrowerOperations.adjustTrove(1e18, _collChange, _boldChange, _isDebtIncrease); + } + vm.stopPrank(); + } + + function changeInterestRateNoHints(address _account, uint256 _newAnnualInterestRate) public { + vm.startPrank(_account); + borrowerOperations.adjustTroveInterestRate(_newAnnualInterestRate, ZERO_ADDRESS, ZERO_ADDRESS); + vm.stopPrank(); + } + + function logContractAddresses() public view { console.log("ActivePool addr: ", address(activePool)); console.log("BorrowerOps addr: ", address(borrowerOperations)); console.log("CollSurplusPool addr: ", address(collSurplusPool)); diff --git a/contracts/src/test/basicOps.t.sol b/contracts/src/test/basicOps.t.sol index f5644b2a..328bd9f8 100644 --- a/contracts/src/test/basicOps.t.sol +++ b/contracts/src/test/basicOps.t.sol @@ -10,7 +10,7 @@ contract BasicOps is DevTestSetup { assertEq(trovesCount, 0); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); trovesCount = troveManager.getTroveOwnersCount(); assertEq(trovesCount, 1); @@ -19,11 +19,11 @@ contract BasicOps is DevTestSetup { function testCloseTrove() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); vm.stopPrank(); vm.startPrank(B); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); uint256 trovesCount = troveManager.getTroveOwnersCount(); assertEq(trovesCount, 2); @@ -40,7 +40,7 @@ contract BasicOps is DevTestSetup { function testAdjustTrove() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); // Check Trove coll and debt uint256 debt_1 = troveManager.getTroveDebt(A); @@ -49,7 +49,7 @@ contract BasicOps is DevTestSetup { assertGt(coll_1, 0); // Adjust trove - borrowerOperations.adjustTrove{value: 1 ether}(1e18, 0, 500e18, true, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.adjustTrove{value: 1 ether}(1e18, 0, 500e18, true); // Check coll and debt altered uint256 debt_2 = troveManager.getTroveDebt(A); @@ -61,7 +61,7 @@ contract BasicOps is DevTestSetup { function testRedeem() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 5 ether}(1e18, 5_000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 5 ether}(1e18, 5_000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); vm.stopPrank(); uint256 debt_1 = troveManager.getTroveDebt(A); @@ -70,7 +70,7 @@ contract BasicOps is DevTestSetup { assertGt(coll_1, 0); vm.startPrank(B); - borrowerOperations.openTrove{value: 5 ether}(1e18, 4_000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 5 ether}(1e18, 4_000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); vm.warp(block.timestamp + troveManager.BOOTSTRAP_PERIOD() + 1); @@ -102,11 +102,11 @@ contract BasicOps is DevTestSetup { function testLiquidation() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); vm.stopPrank(); vm.startPrank(B); - borrowerOperations.openTrove{value: 10 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 10 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); // Price drops priceFeed.setPrice(1200e18); @@ -129,7 +129,7 @@ contract BasicOps is DevTestSetup { function testSPDeposit() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); // A makes an SP deposit stabilityPool.provideToSP(100e18); @@ -148,7 +148,7 @@ contract BasicOps is DevTestSetup { function testSPWithdrawal() public { priceFeed.setPrice(2000e18); vm.startPrank(A); - borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 0); // A makes an SP deposit stabilityPool.provideToSP(100e18); diff --git a/contracts/src/test/interestRateBasic.t.sol b/contracts/src/test/interestRateBasic.t.sol new file mode 100644 index 00000000..e2962fe0 --- /dev/null +++ b/contracts/src/test/interestRateBasic.t.sol @@ -0,0 +1,204 @@ +pragma solidity 0.8.18; + +import "./TestContracts/DevTestSetup.sol"; + +contract InterestRateBasic is DevTestSetup { + + function testOpenTroveSetsInterestRate() public { + priceFeed.setPrice(2000e18); + assertEq(troveManager.getTroveAnnualInterestRate(A), 0); + assertEq(troveManager.getTroveAnnualInterestRate(B), 0); + assertEq(troveManager.getTroveAnnualInterestRate(C), 0); + assertEq(troveManager.getTroveAnnualInterestRate(D), 0); + + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 0); + assertEq(troveManager.getTroveAnnualInterestRate(A), 0); + + openTroveNoHints100pctMaxFee(B, 2 ether, 2000e18, 1); + assertEq(troveManager.getTroveAnnualInterestRate(B), 1); + + openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, 37e16); + assertEq(troveManager.getTroveAnnualInterestRate(C), 37e16); + + openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, 1e18); + assertEq(troveManager.getTroveAnnualInterestRate(D), 1e18); + } + + function testOpenTroveInsertsToCorrectPositionInSortedList() public { + priceFeed.setPrice(2000e18); + + // Users A, B, C, D, E will open Troves with interest rates ascending in the alphabetical order of their names + uint256 interestRate_A = 0; + uint256 interestRate_B = 1e17; + uint256 interestRate_C = 2e17; + uint256 interestRate_D = 3e17; + uint256 interestRate_E = 4e17; + + // B and D open + openTroveNoHints100pctMaxFee(B, 2 ether, 2000e18, interestRate_B); + openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, interestRate_D); + + // Check initial list order - expect [B, D] + // B + assertEq(sortedTroves.getNext(B), ZERO_ADDRESS); // tail + assertEq(sortedTroves.getPrev(B), D); + // D + assertEq(sortedTroves.getNext(D), B); + assertEq(sortedTroves.getPrev(D), ZERO_ADDRESS); // head + + + // C opens. Expect to be inserted between B and D + openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, interestRate_C); + assertEq(sortedTroves.getNext(C), B); + assertEq(sortedTroves.getPrev(C), D); + + // A opens. Expect to be inserted at the tail, below B + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, interestRate_A); + assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); + assertEq(sortedTroves.getPrev(A), B); + + // E opens. Expect to be inserted at the head, above D + openTroveNoHints100pctMaxFee(E, 2 ether, 2000e18, interestRate_E); + assertEq(sortedTroves.getNext(E), D); + assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); + } + + + function testRevertWhenOpenTroveWithInterestRateGreaterThanMax() public { + priceFeed.setPrice(2000e18); + + vm.startPrank(A); + vm.expectRevert(); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 1e18 + 1); + + vm.expectRevert(); + borrowerOperations.openTrove{value: 2 ether}(1e18, 2000e18, ZERO_ADDRESS, ZERO_ADDRESS, 42e18); + } + + function testRevertWhenAdjustInterestRateGreaterThanMax() public { + priceFeed.setPrice(2000e18); + + // A opens Trove with valid annual interest rate ... + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 37e16); + assertEq(troveManager.getTroveAnnualInterestRate(A), 37e16); + + // ... then tries to adjust it to an invalid value + vm.startPrank(A); + vm.expectRevert(); + borrowerOperations.adjustTroveInterestRate(1e18 + 1, ZERO_ADDRESS, ZERO_ADDRESS); + + vm.expectRevert(); + borrowerOperations.adjustTroveInterestRate(42e18, ZERO_ADDRESS, ZERO_ADDRESS); + } + + function testAdjustTroveInterestRateSetsCorrectNewRate() public { + priceFeed.setPrice(2000e18); + + // A, B, C opens Troves with valid annual interest rates + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 5e17); + openTroveNoHints100pctMaxFee(B, 2 ether, 2000e18, 5e17); + openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, 5e17); + assertEq(troveManager.getTroveAnnualInterestRate(A), 5e17); + assertEq(troveManager.getTroveAnnualInterestRate(B), 5e17); + assertEq(troveManager.getTroveAnnualInterestRate(C), 5e17); + + + changeInterestRateNoHints(A, 0); + assertEq(troveManager.getTroveAnnualInterestRate(A), 0); + + changeInterestRateNoHints(B, 6e17); + assertEq(troveManager.getTroveAnnualInterestRate(B), 6e17); + + changeInterestRateNoHints(C, 1e18); + assertEq(troveManager.getTroveAnnualInterestRate(C), 1e18); + } + + // TODO: test adjusting interest rates correctly orders sorted list + function testAdjustTroveInterestRateInsertsToCorrectPositionInSortedList() public { + priceFeed.setPrice(2000e18); + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 1e17); + openTroveNoHints100pctMaxFee(B, 2 ether, 2000e18, 2e17); + openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, 3e17); + openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, 4e17); + openTroveNoHints100pctMaxFee(E, 2 ether, 2000e18, 5e17); + + // Check initial sorted list order - expect [A:1%, B:2%, C:3%, D:4%, E:5%] + // A + assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail + assertEq(sortedTroves.getPrev(A), B); + // B + assertEq(sortedTroves.getNext(B), A); + assertEq(sortedTroves.getPrev(B), C); + // C + assertEq(sortedTroves.getNext(C), B); + assertEq(sortedTroves.getPrev(C), D); + // D + assertEq(sortedTroves.getNext(D), C); + assertEq(sortedTroves.getPrev(D), E); + // E + assertEq(sortedTroves.getNext(E), D); + assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); // head + + // C sets rate to 0%, moves to tail - expect [C:0%, A:1%, B:2%, D:4%, E:5%] + changeInterestRateNoHints(C, 0); + assertEq(sortedTroves.getNext(C), ZERO_ADDRESS); + assertEq(sortedTroves.getPrev(C), A); + + // D sets rate to 7%, moves to head - expect [C:0%, A:1%, B:2%, E:5%, D:7%] + changeInterestRateNoHints(D, 7e17); + assertEq(sortedTroves.getNext(D), E); + assertEq(sortedTroves.getPrev(D), ZERO_ADDRESS); + + + // A sets rate to 6%, moves up 2 positions - expect [C:0%, B:2%, E:5%, A:6%, D:7%] + changeInterestRateNoHints(A, 6e17); + assertEq(sortedTroves.getNext(A), E); + assertEq(sortedTroves.getPrev(A), D); + } + + function testAdjustTroveDoesNotChangeListPositions() public { + priceFeed.setPrice(2000e18); + + // Troves opened in ascending order of interest rate + openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 1e17); + openTroveNoHints100pctMaxFee(B, 2 ether, 2000e18, 2e17); + openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, 3e17); + openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, 4e17); + openTroveNoHints100pctMaxFee(E, 2 ether, 2000e18, 5e17); + + + // Check A's neighbors + assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail + assertEq(sortedTroves.getPrev(A), B); + + // Adjust A's coll + debt + adjustTrove100pctMaxFee(A, 10 ether, 5000e18, true, true); + + // Check A's neighbors unchanged + assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail + assertEq(sortedTroves.getPrev(A), B); + + + // Check C's neighbors + assertEq(sortedTroves.getNext(C), B); + assertEq(sortedTroves.getPrev(C), D); + + // Adjust C's coll + debt + adjustTrove100pctMaxFee(C, 10 ether, 5000e18, true, true); + + // Check C's neighbors unchanged + assertEq(sortedTroves.getNext(C), B); + assertEq(sortedTroves.getPrev(C), D); + + // Check E's neighbors + assertEq(sortedTroves.getNext(E), D); + assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); // head + + // Adjust E's coll + debt + adjustTrove100pctMaxFee(E, 10 ether, 5000e18, true, true); + + // Check C's neighbors unchanged + assertEq(sortedTroves.getNext(E), D); + assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); // head + } +} \ No newline at end of file From cbe9d8005eab1e224bd4b8afac925f018daecbe2 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Thu, 25 Jan 2024 19:27:31 +0700 Subject: [PATCH 2/9] Remove extra empty lines --- contracts/src/test/interestRateBasic.t.sol | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contracts/src/test/interestRateBasic.t.sol b/contracts/src/test/interestRateBasic.t.sol index e2962fe0..26f9f38b 100644 --- a/contracts/src/test/interestRateBasic.t.sol +++ b/contracts/src/test/interestRateBasic.t.sol @@ -46,7 +46,6 @@ contract InterestRateBasic is DevTestSetup { assertEq(sortedTroves.getNext(D), B); assertEq(sortedTroves.getPrev(D), ZERO_ADDRESS); // head - // C opens. Expect to be inserted between B and D openTroveNoHints100pctMaxFee(C, 2 ether, 2000e18, interestRate_C); assertEq(sortedTroves.getNext(C), B); @@ -102,7 +101,6 @@ contract InterestRateBasic is DevTestSetup { assertEq(troveManager.getTroveAnnualInterestRate(B), 5e17); assertEq(troveManager.getTroveAnnualInterestRate(C), 5e17); - changeInterestRateNoHints(A, 0); assertEq(troveManager.getTroveAnnualInterestRate(A), 0); @@ -149,7 +147,6 @@ contract InterestRateBasic is DevTestSetup { assertEq(sortedTroves.getNext(D), E); assertEq(sortedTroves.getPrev(D), ZERO_ADDRESS); - // A sets rate to 6%, moves up 2 positions - expect [C:0%, B:2%, E:5%, A:6%, D:7%] changeInterestRateNoHints(A, 6e17); assertEq(sortedTroves.getNext(A), E); @@ -166,7 +163,6 @@ contract InterestRateBasic is DevTestSetup { openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, 4e17); openTroveNoHints100pctMaxFee(E, 2 ether, 2000e18, 5e17); - // Check A's neighbors assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail assertEq(sortedTroves.getPrev(A), B); @@ -178,7 +174,6 @@ contract InterestRateBasic is DevTestSetup { assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail assertEq(sortedTroves.getPrev(A), B); - // Check C's neighbors assertEq(sortedTroves.getNext(C), B); assertEq(sortedTroves.getPrev(C), D); From f6a5f85482457323a3eaf083b10c5ae280c6d980 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Sun, 4 Feb 2024 10:31:37 +0700 Subject: [PATCH 3/9] Adapt v1 tests to accommodate ordering by interest rate --- .../BorrowerOperationsTester.sol | 18 +- .../src/TestContracts/SortedTrovesTester.sol | 20 +- contracts/src/TroveManager.sol | 2 + contracts/test/AccessControlTest.js | 28 - contracts/test/BorrowerOperationsTest.js | 281 ++++----- contracts/test/CollSurplusPool.js | 4 +- contracts/test/GasCompensationTest.js | 8 +- contracts/test/SP_P_TruncationTest.js | 10 + contracts/test/SortedTrovesTest.js | 46 +- contracts/test/StabilityPoolTest.js | 60 +- .../test/StabilityPool_SPWithdrawalTest.js | 220 +++---- .../StabilityPool_SPWithdrawalToCDPTest.js | 578 +++++++++--------- contracts/test/TroveManagerTest.js | 90 +-- .../TroveManager_LiquidationRewardsTest.js | 48 +- .../test/TroveManager_RecoveryModeTest.js | 73 +-- contracts/test/stakeDeclineTest.js | 11 +- contracts/utils/testHelpers.js | 9 +- 17 files changed, 714 insertions(+), 792 deletions(-) diff --git a/contracts/src/TestContracts/BorrowerOperationsTester.sol b/contracts/src/TestContracts/BorrowerOperationsTester.sol index 67296a41..66b5b623 100644 --- a/contracts/src/TestContracts/BorrowerOperationsTester.sol +++ b/contracts/src/TestContracts/BorrowerOperationsTester.sol @@ -8,6 +8,23 @@ import "../BorrowerOperations.sol"; 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, @@ -39,7 +56,6 @@ contract BorrowerOperationsTester is BorrowerOperations { _adjustTrove(_borrower, _collWithdrawal, _debtChange, _isDebtIncrease, 0); } - // Payable fallback function receive() external payable { } } diff --git a/contracts/src/TestContracts/SortedTrovesTester.sol b/contracts/src/TestContracts/SortedTrovesTester.sol index 3a373d16..c66f70a8 100644 --- a/contracts/src/TestContracts/SortedTrovesTester.sol +++ b/contracts/src/TestContracts/SortedTrovesTester.sol @@ -4,31 +4,33 @@ pragma solidity 0.8.18; import "../Interfaces/ISortedTroves.sol"; - +// Used as both a wrapper for SortedTroves functions and a mock TroveManager. contract SortedTrovesTester { ISortedTroves sortedTroves; + // --- SortedTroves external wrapper functions -- 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 insert(address _id, uint256 _annualInterestRate, address _prevId, address _nextId) external { + sortedTroves.insert(_id, _annualInterestRate, _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 reInsert(address _id, uint256 _newAnnualInterestRate, address _prevId, address _nextId) external { + sortedTroves.reInsert(_id, _newAnnualInterestRate, _prevId, _nextId); } - function getNominalICR(address) external pure returns (uint) { + // --- Mock TroveManager functions --- + function getTroveAnnualInterestRate(address) external pure returns (uint) { return 1; } - function getCurrentICR(address, uint) external pure returns (uint) { - return 1; - } + // function getCurrentICR(address, uint) external pure returns (uint) { + // return 1; + // } } diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 1358283f..94d35dd5 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -478,6 +478,8 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { * Liquidate a sequence of troves. Closes a maximum number of n under-collateralized Troves, * starting from the one with the lowest collateral ratio in the system, and moving upwards */ + // TODO: remove this liquidation function, since with ordering by interest rate, it is now redundant: there's no guarantee + // the bottom of the list has Troves with CR < MCR. function liquidateTroves(uint _n) external override { ContractsCache memory contractsCache = ContractsCache( activePool, diff --git a/contracts/test/AccessControlTest.js b/contracts/test/AccessControlTest.js index 1a985ae5..5c7976f6 100644 --- a/contracts/test/AccessControlTest.js +++ b/contracts/test/AccessControlTest.js @@ -67,8 +67,6 @@ contract( // Attempt call from alice try { const tx1 = await borrowerOperations.moveETHGainToTrove( - bob, - bob, bob, { from: bob } ); @@ -93,19 +91,6 @@ contract( } }); - // updateRewardSnapshots - it("updateRewardSnapshots(): reverts when called by an account that is not BorrowerOperations", async () => { - // Attempt call from alice - try { - const txAlice = await troveManager.updateTroveRewardSnapshots(bob, { - from: alice, - }); - } catch (err) { - assert.include(err.message, "revert"); - // assert.include(err.message, "Caller is not the BorrowerOperations contract") - } - }); - // removeStake it("removeStake(): reverts when called by an account that is not BorrowerOperations", async () => { // Attempt call from alice @@ -154,19 +139,6 @@ contract( } }); - // setTroveStatus - it("setTroveStatus(): reverts when called by an account that is not BorrowerOperations", async () => { - // Attempt call from alice - try { - const txAlice = await troveManager.setTroveStatus(bob, 1, { - from: alice, - }); - } catch (err) { - assert.include(err.message, "revert"); - // assert.include(err.message, "Caller is not the BorrowerOperations contract") - } - }); - // increaseTroveColl it("increaseTroveColl(): reverts when called by an account that is not BorrowerOperations", async () => { // Attempt call from alice diff --git a/contracts/test/BorrowerOperationsTest.js b/contracts/test/BorrowerOperationsTest.js index 740613db..8231ab56 100644 --- a/contracts/test/BorrowerOperationsTest.js +++ b/contracts/test/BorrowerOperationsTest.js @@ -136,7 +136,7 @@ contract("BorrowerOperations", async (accounts) => { const collTopUp = 1; // 1 wei top up await assertRevert( - borrowerOperations.addColl(alice, alice, { + borrowerOperations.addColl( { from: alice, value: collTopUp, }), @@ -158,7 +158,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(activePool_ETH_Before.eq(aliceColl)); assert.isTrue(activePool_RawEther_Before.eq(aliceColl)); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: dec(1, "ether"), }); @@ -187,7 +187,7 @@ contract("BorrowerOperations", async (accounts) => { assert.equal(status_Before, 1); // Alice adds second collateral - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: dec(1, "ether"), }); @@ -211,7 +211,7 @@ contract("BorrowerOperations", async (accounts) => { assert.equal(aliceTroveInList_Before, true); assert.equal(listIsEmpty_Before, false); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: dec(1, "ether"), }); @@ -234,7 +234,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(totalStakes_Before.eq(alice_Stake_Before)); // Alice tops up Trove collateral with 2 ether - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: dec(2, "ether"), }); @@ -324,11 +324,11 @@ contract("BorrowerOperations", async (accounts) => { const aliceTopUp = toBN(dec(5, "ether")); const bobTopUp = toBN(dec(1, "ether")); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: aliceTopUp, }); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl( { from: bob, value: bobTopUp, }); @@ -430,7 +430,7 @@ contract("BorrowerOperations", async (accounts) => { // Carol attempts to add collateral to her non-existent trove try { - const txCarol = await borrowerOperations.addColl(carol, carol, { + const txCarol = await borrowerOperations.addColl( { from: carol, value: dec(1, "ether"), }); @@ -450,7 +450,7 @@ contract("BorrowerOperations", async (accounts) => { // Bob attempts to add collateral to his closed trove try { - const txBob = await borrowerOperations.addColl(bob, bob, { + const txBob = await borrowerOperations.addColl( { from: bob, value: dec(1, "ether"), }); @@ -471,7 +471,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(await th.checkRecoveryMode(contracts)); const collTopUp = toBN(dec(1, "ether")); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: collTopUp, }); @@ -500,7 +500,7 @@ contract("BorrowerOperations", async (accounts) => { const collWithdrawal = 1; // 1 wei withdrawal await assertRevert( - borrowerOperations.withdrawColl(1, alice, alice, { from: alice }), + borrowerOperations.withdrawColl(1, { from: alice }), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" ); }); @@ -521,8 +521,7 @@ contract("BorrowerOperations", async (accounts) => { // Bob successfully withdraws some coll const txBob = await borrowerOperations.withdrawColl( dec(100, "finney"), - bob, - bob, + { from: bob } ); assert.isTrue(txBob.receipt.status); @@ -531,8 +530,7 @@ contract("BorrowerOperations", async (accounts) => { try { const txCarol = await borrowerOperations.withdrawColl( dec(1, "ether"), - carol, - carol, + { from: carol } ); assert.isFalse(txCarol.receipt.status); @@ -550,8 +548,7 @@ contract("BorrowerOperations", async (accounts) => { // Withdrawal possible when recoveryMode == false const txAlice = await borrowerOperations.withdrawColl( 1000, - alice, - alice, + { from: alice } ); assert.isTrue(txAlice.receipt.status); @@ -562,7 +559,7 @@ contract("BorrowerOperations", async (accounts) => { //Check withdrawal impossible when recoveryMode == true try { - const txBob = await borrowerOperations.withdrawColl(1000, bob, bob, { + const txBob = await borrowerOperations.withdrawColl(1000, { from: bob, }); assert.isFalse(txBob.receipt.status); @@ -580,7 +577,7 @@ contract("BorrowerOperations", async (accounts) => { const bobColl = await getTroveEntireColl(bob); // Carol withdraws exactly all her collateral await assertRevert( - borrowerOperations.withdrawColl(carolColl, carol, carol, { + borrowerOperations.withdrawColl(carolColl, { from: carol, }), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -590,8 +587,7 @@ contract("BorrowerOperations", async (accounts) => { try { const txBob = await borrowerOperations.withdrawColl( bobColl.add(toBN(1)), - bob, - bob, + { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -608,7 +604,7 @@ contract("BorrowerOperations", async (accounts) => { // Bob attempts to withdraws 1 wei, Which would leave him with < 110% ICR. try { - const txBob = await borrowerOperations.withdrawColl(1, bob, bob, { + const txBob = await borrowerOperations.withdrawColl(1, { from: bob, }); assert.isFalse(txBob.receipt.status); @@ -636,8 +632,6 @@ contract("BorrowerOperations", async (accounts) => { try { const txData = await borrowerOperations.withdrawColl( "1", - alice, - alice, { from: alice } ); assert.isFalse(txData.receipt.status); @@ -660,7 +654,7 @@ contract("BorrowerOperations", async (accounts) => { // Alice attempts to withdraw all collateral await assertRevert( - borrowerOperations.withdrawColl(aliceColl, alice, alice, { + borrowerOperations.withdrawColl(aliceColl, { from: alice, }), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -678,7 +672,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(await sortedTroves.contains(alice)); // Withdraw some collateral - await borrowerOperations.withdrawColl(dec(100, "finney"), alice, alice, { + await borrowerOperations.withdrawColl(dec(100, "finney"), { from: alice, }); @@ -694,7 +688,7 @@ contract("BorrowerOperations", async (accounts) => { const aliceCollBefore = await getTroveEntireColl(alice); // Alice withdraws 1 ether - await borrowerOperations.withdrawColl(dec(1, "ether"), alice, alice, { + await borrowerOperations.withdrawColl(dec(1, "ether"), { from: alice, }); @@ -717,7 +711,7 @@ contract("BorrowerOperations", async (accounts) => { await web3.eth.getBalance(activePool.address) ); - await borrowerOperations.withdrawColl(dec(1, "ether"), alice, alice, { + await borrowerOperations.withdrawColl(dec(1, "ether"), { from: alice, }); @@ -755,7 +749,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(totalStakes_Before.eq(aliceColl)); // Alice withdraws 1 ether - await borrowerOperations.withdrawColl(dec(1, "ether"), alice, alice, { + await borrowerOperations.withdrawColl(dec(1, "ether"), { from: alice, }); @@ -781,7 +775,7 @@ contract("BorrowerOperations", async (accounts) => { const alice_ETHBalance_Before = toBN( web3.utils.toBN(await web3.eth.getBalance(alice)) ); - await borrowerOperations.withdrawColl(dec(1, "ether"), alice, alice, { + await borrowerOperations.withdrawColl(dec(1, "ether"), { from: alice, gasPrice: 0, }); @@ -866,10 +860,10 @@ contract("BorrowerOperations", async (accounts) => { const aliceCollWithdrawal = toBN(dec(5, "ether")); const bobCollWithdrawal = toBN(dec(1, "ether")); - await borrowerOperations.withdrawColl(aliceCollWithdrawal, alice, alice, { + await borrowerOperations.withdrawColl(aliceCollWithdrawal, { from: alice, }); - await borrowerOperations.withdrawColl(bobCollWithdrawal, bob, bob, { + await borrowerOperations.withdrawColl(bobCollWithdrawal, { from: bob, }); @@ -953,8 +947,6 @@ contract("BorrowerOperations", async (accounts) => { borrowerOperations.withdrawBold( th._100pct, Boldwithdrawal, - alice, - alice, { from: alice } ), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -969,8 +961,6 @@ contract("BorrowerOperations", async (accounts) => { const txBob = await borrowerOperations.withdrawBold( th._100pct, dec(100, 18), - bob, - bob, { from: bob } ); assert.isTrue(txBob.receipt.status); @@ -980,8 +970,7 @@ contract("BorrowerOperations", async (accounts) => { const txCarol = await borrowerOperations.withdrawBold( th._100pct, dec(100, 18), - carol, - carol, + { from: carol } ); assert.isFalse(txCarol.receipt.status); @@ -998,8 +987,6 @@ contract("BorrowerOperations", async (accounts) => { const txBob = await borrowerOperations.withdrawBold( th._100pct, 1, - bob, - bob, { from: bob } ); assert.isTrue(txBob.receipt.status); @@ -1009,8 +996,6 @@ contract("BorrowerOperations", async (accounts) => { const txAlice = await borrowerOperations.withdrawBold( th._100pct, 0, - alice, - alice, { from: alice } ); assert.isFalse(txAlice.receipt.status); @@ -1030,8 +1015,6 @@ contract("BorrowerOperations", async (accounts) => { const txAlice = await borrowerOperations.withdrawBold( th._100pct, dec(100, 18), - alice, - alice, { from: alice } ); assert.isTrue(txAlice.receipt.status); @@ -1044,9 +1027,7 @@ contract("BorrowerOperations", async (accounts) => { try { const txBob = await borrowerOperations.withdrawBold( th._100pct, - 1, - bob, - bob, + 1, { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -1064,8 +1045,7 @@ contract("BorrowerOperations", async (accounts) => { const txBob = await borrowerOperations.withdrawBold( th._100pct, 1, - bob, - bob, + { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -1091,8 +1071,7 @@ contract("BorrowerOperations", async (accounts) => { const txBob = await borrowerOperations.withdrawBold( th._100pct, dec(1, 18), - bob, - bob, + { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -1116,8 +1095,7 @@ contract("BorrowerOperations", async (accounts) => { const txData = await borrowerOperations.withdrawBold( th._100pct, "200", - alice, - alice, + { from: alice } ); assert.isFalse(txData.receipt.status); @@ -1136,8 +1114,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.withdrawBold( th._100pct, await getNetBorrowingAmount(100), - alice, - alice, + { from: alice } ); @@ -1165,8 +1142,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.withdrawBold( th._100pct, await getNetBorrowingAmount(dec(10000, 18)), - alice, - alice, + { from: alice } ); @@ -1190,8 +1166,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.withdrawBold( th._100pct, dec(10000, 18), - alice, - alice, + { from: alice } ); @@ -1222,7 +1197,7 @@ contract("BorrowerOperations", async (accounts) => { const BoldRepayment = 1; // 1 wei repayment await assertRevert( - borrowerOperations.repayBold(BoldRepayment, alice, alice, { + borrowerOperations.repayBold(BoldRepayment, { from: alice, }), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -1236,18 +1211,19 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT.add(toBN("2"))), A, A, + 0, { from: A, value: dec(100, 30) } ); - const repayTxA = await borrowerOperations.repayBold(1, A, A, { from: A }); + const repayTxA = await borrowerOperations.repayBold(1, { from: A }); assert.isTrue(repayTxA.receipt.status); - await borrowerOperations.openTrove(th._100pct, dec(20, 25), B, B, { + await borrowerOperations.openTrove(th._100pct, dec(20, 25), B, B, 0, { from: B, value: dec(100, 30), }); - const repayTxB = await borrowerOperations.repayBold(dec(19, 25), B, B, { + const repayTxB = await borrowerOperations.repayBold(dec(19, 25),{ from: B, }); assert.isTrue(repayTxB.receipt.status); @@ -1260,6 +1236,7 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT.add(toBN("1"))), A, A, + 0, { from: A, value: dec(100, 30) } ); @@ -1268,7 +1245,7 @@ contract("BorrowerOperations", async (accounts) => { assert.isTrue(debt.eq(th.toBN(dec(2000, 18)).add(th.toBN("1")))) // Try to repay 2 wei to bring Trove debt to 1 wei below minimum, and expect revert - const repayTxAPromise = borrowerOperations.repayBold(2, A, A, { + const repayTxAPromise = borrowerOperations.repayBold(2, { from: A, }); await assertRevert( @@ -1299,8 +1276,6 @@ contract("BorrowerOperations", async (accounts) => { 0, repayAmount, false, - alice, - alice, { from: alice } ), "SafeMath: subtraction overflow" @@ -1319,7 +1294,7 @@ contract("BorrowerOperations", async (accounts) => { extraParams: { from: bob }, }); // Bob successfully repays some Bold - const txBob = await borrowerOperations.repayBold(dec(10, 18), bob, bob, { + const txBob = await borrowerOperations.repayBold(dec(10, 18), { from: bob, }); assert.isTrue(txBob.receipt.status); @@ -1328,8 +1303,7 @@ contract("BorrowerOperations", async (accounts) => { try { const txCarol = await borrowerOperations.repayBold( dec(10, 18), - carol, - carol, + { from: carol } ); assert.isFalse(txCarol.receipt.status); @@ -1352,7 +1326,7 @@ contract("BorrowerOperations", async (accounts) => { const aliceDebt = await getTroveEntireDebt(alice); // Bob successfully repays some Bold - const txBob = await borrowerOperations.repayBold(dec(10, 18), bob, bob, { + const txBob = await borrowerOperations.repayBold(dec(10, 18), { from: bob, }); assert.isTrue(txBob.receipt.status); @@ -1361,8 +1335,6 @@ contract("BorrowerOperations", async (accounts) => { try { const txAlice = await borrowerOperations.repayBold( aliceDebt.add(toBN(dec(1, 18))), - alice, - alice, { from: alice } ); assert.isFalse(txAlice.receipt.status); @@ -1388,8 +1360,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.repayBold( aliceDebtBefore.div(toBN(10)), - alice, - alice, + { from: alice } ); // Repays 1/10 her debt @@ -1422,8 +1393,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.repayBold( aliceDebtBefore.div(toBN(10)), - alice, - alice, + { from: alice } ); // Repays 1/10 her debt @@ -1455,8 +1425,7 @@ contract("BorrowerOperations", async (accounts) => { await borrowerOperations.repayBold( aliceDebtBefore.div(toBN(10)), - alice, - alice, + { from: alice } ); // Repays 1/10 her debt @@ -1490,8 +1459,7 @@ contract("BorrowerOperations", async (accounts) => { const tx = await borrowerOperations.repayBold( aliceDebtBefore.div(toBN(10)), - alice, - alice, + { from: alice } ); assert.isTrue(tx.receipt.status); @@ -1531,8 +1499,6 @@ contract("BorrowerOperations", async (accounts) => { // Bob tries to repay 6 Bold const repayBoldPromise_B = borrowerOperations.repayBold( toBN(dec(6, 18)), - B, - B, { from: B } ); @@ -1567,8 +1533,6 @@ contract("BorrowerOperations", async (accounts) => { 0, BoldRepayment, false, - alice, - alice, { from: alice, value: collTopUp } ), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -1593,8 +1557,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -1604,8 +1567,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - carol, - carol, + { from: carol, value: dec(1, "ether") } ); assert.isFalse(txCarol.receipt.status); @@ -1633,8 +1595,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); assert.isTrue(txAlice.receipt.status); @@ -1650,8 +1611,6 @@ contract("BorrowerOperations", async (accounts) => { dec(1, "ether"), 0, false, - alice, - alice, { from: alice } ); assert.isFalse(txAlice.receipt.status); @@ -1666,8 +1625,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - bob, - bob, + { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -1681,9 +1639,7 @@ contract("BorrowerOperations", async (accounts) => { th._100pct, 0, dec(111, 18), - true, - bob, - bob, + true, { from: bob, value: dec(1, "ether") } ); assert.isFalse(txBob.receipt.status); @@ -1717,8 +1673,6 @@ contract("BorrowerOperations", async (accounts) => { 1, dec(5000, 18), false, - alice, - alice, { from: alice } ), "BorrowerOps: Collateral withdrawal not permitted Recovery Mode" @@ -1767,8 +1721,6 @@ contract("BorrowerOperations", async (accounts) => { 0, debtIncrease, true, - alice, - alice, { from: alice, value: collIncrease } ), "BorrowerOps: Operation must leave trove with ICR >= CCR" @@ -1822,8 +1774,6 @@ contract("BorrowerOperations", async (accounts) => { 0, aliceDebtIncrease, true, - alice, - alice, { from: alice, value: aliceCollIncrease } ), "BorrowerOps: Cannot decrease your Trove's ICR in Recovery Mode" @@ -1856,8 +1806,7 @@ contract("BorrowerOperations", async (accounts) => { 0, bobDebtIncrease, true, - bob, - bob, + { from: bob, value: bobCollIncrease } ), " BorrowerOps: Operation must leave trove with ICR >= CCR" @@ -1907,8 +1856,7 @@ contract("BorrowerOperations", async (accounts) => { 0, debtIncrease, true, - alice, - alice, + { from: alice, value: collIncrease } ); assert.isTrue(tx.receipt.status); @@ -1960,8 +1908,7 @@ contract("BorrowerOperations", async (accounts) => { 0, debtIncrease, true, - alice, - alice, + { from: alice, value: collIncrease } ); assert.isTrue(tx.receipt.status); @@ -1988,8 +1935,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(1, 18), true, - bob, - bob, + { from: bob } ); assert.isFalse(txBob.receipt.status); @@ -2021,8 +1967,7 @@ contract("BorrowerOperations", async (accounts) => { 0, remainingDebt.add(toBN(1)), false, - bob, - bob, + { from: bob, value: dec(1, "ether") } ), "revert" @@ -2043,8 +1988,7 @@ contract("BorrowerOperations", async (accounts) => { carolColl.add(toBN(1)), 0, true, - carol, - carol, + { from: carol } ); assert.isFalse(txCarol.receipt.status); @@ -2081,8 +2025,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(100, 18), true, - bob, - bob, + { from: bob, value: dec(1, "ether") } ); assert.isFalse(txBob.receipt.status); @@ -2110,8 +2053,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - alice, - alice, + { from: alice, value: 0 } ); @@ -2141,8 +2083,7 @@ contract("BorrowerOperations", async (accounts) => { 0, 0, false, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2177,8 +2118,7 @@ contract("BorrowerOperations", async (accounts) => { 0, await getNetBorrowingAmount(dec(50, 18)), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2221,8 +2161,7 @@ contract("BorrowerOperations", async (accounts) => { dec(500, "finney"), dec(50, 18), false, - alice, - alice, + { from: alice } ); @@ -2257,8 +2196,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), false, - alice, - alice, + { from: alice, value: dec(500, "finney") } ); @@ -2301,8 +2239,7 @@ contract("BorrowerOperations", async (accounts) => { dec(1, 17), await getNetBorrowingAmount(dec(1, 18)), true, - alice, - alice, + { from: alice } ); @@ -2345,8 +2282,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(50, 18), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2383,8 +2319,7 @@ contract("BorrowerOperations", async (accounts) => { dec(500, "finney"), dec(50, 18), false, - alice, - alice, + { from: alice } ); @@ -2419,8 +2354,7 @@ contract("BorrowerOperations", async (accounts) => { dec(100, "finney"), dec(10, 18), false, - alice, - alice, + { from: alice } ); @@ -2455,8 +2389,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(100, 18), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2495,8 +2428,7 @@ contract("BorrowerOperations", async (accounts) => { dec(100, "finney"), dec(10, 18), false, - alice, - alice, + { from: alice } ); @@ -2540,8 +2472,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(100, 18), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2581,8 +2512,7 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(30, 18), false, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2615,8 +2545,7 @@ contract("BorrowerOperations", async (accounts) => { 0, await getNetBorrowingAmount(dec(100, 18)), true, - alice, - alice, + { from: alice, value: dec(1, "ether") } ); @@ -2654,8 +2583,6 @@ contract("BorrowerOperations", async (accounts) => { aliceColl, aliceDebt, true, - alice, - alice, { from: alice } ), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" @@ -2675,7 +2602,7 @@ contract("BorrowerOperations", async (accounts) => { }); await assertRevert( - borrowerOperations.adjustTrove(th._100pct, 0, 0, true, alice, alice, { + borrowerOperations.adjustTrove(th._100pct, 0, 0, true, { from: alice, }), "BorrowerOps: Debt increase requires non-zero debtChange" @@ -2700,8 +2627,6 @@ contract("BorrowerOperations", async (accounts) => { dec(1, "ether"), dec(100, 18), true, - alice, - alice, { from: alice, value: dec(3, "ether") } ), "BorrowerOperations: Cannot withdraw and add coll" @@ -2716,7 +2641,7 @@ contract("BorrowerOperations", async (accounts) => { }); await assertRevert( - borrowerOperations.adjustTrove(th._100pct, 0, 0, false, alice, alice, { + borrowerOperations.adjustTrove(th._100pct, 0, 0, false, { from: alice, }), "BorrowerOps: There must be either a collateral change or a debt change" @@ -2744,8 +2669,6 @@ contract("BorrowerOperations", async (accounts) => { aliceColl.add(toBN(1)), 0, false, - alice, - alice, { from: alice } ) ); @@ -2754,9 +2677,7 @@ contract("BorrowerOperations", async (accounts) => { th._100pct, aliceColl.add(toBN(dec(37, "ether"))), 0, - false, - bob, - bob, + false, { from: bob } ) ); @@ -2787,8 +2708,6 @@ contract("BorrowerOperations", async (accounts) => { 0, bobDebt, false, - B, - B, { from: B } ); @@ -2816,8 +2735,7 @@ contract("BorrowerOperations", async (accounts) => { dec(1, 18), dec(1, 18), true, - alice, - alice, + { from: bob } ); await assertRevert( @@ -2829,8 +2747,7 @@ contract("BorrowerOperations", async (accounts) => { dec(1, 18), dec(1, 18), true, - alice, - alice, + { from: owner } ); await assertRevert( @@ -2842,8 +2759,7 @@ contract("BorrowerOperations", async (accounts) => { dec(1, 18), dec(1, 18), true, - alice, - alice, + { from: bob } ); await assertRevert( @@ -3489,8 +3405,6 @@ contract("BorrowerOperations", async (accounts) => { 0, dec(1, 18), true, - whale, - whale, { from: whale } ); @@ -3636,7 +3550,6 @@ contract("BorrowerOperations", async (accounts) => { const D_emittedColl = toBN( th.getEventArgByName(txD, "TroveUpdated", "_coll") ); - const E_emittedDebt = toBN( th.getEventArgByName(txE, "TroveUpdated", "_debt") ); @@ -3660,6 +3573,7 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT.add(toBN(1))), A, A, + 0, { from: A, value: dec(100, 30) } ); assert.isTrue(txA.receipt.status); @@ -3670,6 +3584,7 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT.add(toBN(dec(47789898, 22)))), A, A, + 0, { from: C, value: dec(100, 30) } ); assert.isTrue(txC.receipt.status); @@ -3677,7 +3592,7 @@ contract("BorrowerOperations", async (accounts) => { }); it("openTrove(): reverts if net debt < minimum net debt", async () => { - const txAPromise = borrowerOperations.openTrove(th._100pct, 0, A, A, { + const txAPromise = borrowerOperations.openTrove(th._100pct, 0, A, A, 0, { from: A, value: dec(100, 30), }); @@ -3688,6 +3603,7 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT.sub(toBN(1))), B, B, + 0, { from: B, value: dec(100, 30) } ); await assertRevert(txBPromise, "revert"); @@ -3697,6 +3613,7 @@ contract("BorrowerOperations", async (accounts) => { MIN_NET_DEBT.sub(toBN(dec(173, 18))), C, C, + 0, { from: C, value: dec(100, 30) } ); await assertRevert(txCPromise, "revert"); @@ -3917,6 +3834,7 @@ contract("BorrowerOperations", async (accounts) => { await getNetBorrowingAmount(MIN_NET_DEBT), carol, carol, + 0, { from: carol, value: dec(1, "ether") } ) ); @@ -3935,7 +3853,7 @@ contract("BorrowerOperations", async (accounts) => { assert.equal(status_Before, 0); const BoldRequest = MIN_NET_DEBT; - await borrowerOperations.openTrove(th._100pct, MIN_NET_DEBT, carol, carol, { + await borrowerOperations.openTrove(th._100pct, MIN_NET_DEBT, carol, carol, 0, { from: alice, value: dec(100, "ether"), }); @@ -4157,6 +4075,7 @@ contract("BorrowerOperations", async (accounts) => { await getOpenTroveBoldAmount(dec(10000, 18)), alice, alice, + 0, { from: alice, value: dec(100, "ether") } ); @@ -4192,6 +4111,7 @@ contract("BorrowerOperations", async (accounts) => { dec(10000, 18), alice, alice, + 0, { from: alice, value: dec(100, "ether") } ); @@ -4437,6 +4357,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4444,6 +4365,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4488,6 +4410,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4495,6 +4418,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4539,6 +4463,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4546,6 +4471,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4589,6 +4515,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4596,6 +4523,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4640,6 +4568,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4647,6 +4576,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4692,6 +4622,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4699,6 +4630,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4744,6 +4676,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4751,6 +4684,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4796,6 +4730,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4803,6 +4738,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4848,6 +4784,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, alice, alice, + 0, { from: alice, value: troveColl } ); await borrowerOperations.openTrove( @@ -4855,6 +4792,7 @@ contract("BorrowerOperations", async (accounts) => { troveBoldAmount, bob, bob, + 0, { from: bob, value: troveColl } ); @@ -4899,6 +4837,7 @@ contract("BorrowerOperations", async (accounts) => { dec(100000, 18), alice, alice, + 0, { from: alice, value: dec(1000, 18) } ); @@ -4911,8 +4850,8 @@ contract("BorrowerOperations", async (accounts) => { const _100pctHex = "0xde0b6b3a7640000"; const _1e25Hex = "0xd3c21bcecceda1000000"; const openTroveData = th.getTransactionData( - "openTrove(uint256,uint256,address,address)", - [_100pctHex, _1e25Hex, "0x0", "0x0"] + "openTrove(uint256,uint256,address,address,uint256)", + [_100pctHex, _1e25Hex, "0x0", "0x0", "0x0"] ); await nonPayable.forward(borrowerOperations.address, openTroveData, { value: dec(10000, "ether"), diff --git a/contracts/test/CollSurplusPool.js b/contracts/test/CollSurplusPool.js index 85c31249..1278a776 100644 --- a/contracts/test/CollSurplusPool.js +++ b/contracts/test/CollSurplusPool.js @@ -103,8 +103,8 @@ contract("CollSurplusPool", async (accounts) => { B_boldAmount ); const openTroveData = th.getTransactionData( - "openTrove(uint256,uint256,address,address)", - ["0xde0b6b3a7640000", web3.utils.toHex(B_boldAmount), B, B] + "openTrove(uint256,uint256,address,address,uint256)", + ["0xde0b6b3a7640000", web3.utils.toHex(B_boldAmount), B, B, "0x0"] ); await nonPayable.forward(borrowerOperations.address, openTroveData, { value: B_coll, diff --git a/contracts/test/GasCompensationTest.js b/contracts/test/GasCompensationTest.js index 523f5bcf..da5dca5a 100644 --- a/contracts/test/GasCompensationTest.js +++ b/contracts/test/GasCompensationTest.js @@ -1283,7 +1283,7 @@ contract("Gas compensation tests", async (accounts) => { }); // liquidateTroves - full offset - it("liquidateTroves(): full offset. Compensates the correct amount, and liquidates the remainder", async () => { + it.skip("liquidateTroves(): full offset. Compensates the correct amount, and liquidates the remainder", async () => { await priceFeed.setPrice(dec(1000, 18)); await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); @@ -1411,7 +1411,7 @@ contract("Gas compensation tests", async (accounts) => { }); // liquidateTroves - full redistribution - it("liquidateTroves(): full redistribution. Compensates the correct amount, and liquidates the remainder", async () => { + it.skip("liquidateTroves(): full redistribution. Compensates the correct amount, and liquidates the remainder", async () => { await priceFeed.setPrice(dec(1000, 18)); await openTrove({ ICR: toBN(dec(200, 18)), extraParams: { from: whale } }); @@ -1527,7 +1527,7 @@ contract("Gas compensation tests", async (accounts) => { }); // --- event emission in liquidation sequence --- - it("liquidateTroves(): full offset. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { + it.skip("liquidateTroves(): full offset. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { await priceFeed.setPrice(dec(1000, 18)); await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); @@ -1643,7 +1643,7 @@ contract("Gas compensation tests", async (accounts) => { assert.isAtMost(th.getDifference(expectedGasComp, loggedGasComp), 1000); }); - it("liquidateTroves(): full redistribution. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { + it.skip("liquidateTroves(): full redistribution. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { await priceFeed.setPrice(dec(1000, 18)); await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); diff --git a/contracts/test/SP_P_TruncationTest.js b/contracts/test/SP_P_TruncationTest.js index 1c5e56ed..e006f924 100644 --- a/contracts/test/SP_P_TruncationTest.js +++ b/contracts/test/SP_P_TruncationTest.js @@ -150,6 +150,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, + 0, { from: whale, value: dec(100000, "ether") } ); await boldToken.transfer(A, dec(50000, 18), { from: whale }); @@ -161,6 +162,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getBoldAmountForDesiredDebt(2000), account, account, + 0, { from: account, value: dec(15, "ether") } ); assert.isTrue( @@ -245,6 +247,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, + 0, { from: whale, value: dec(100000, "ether") } ); await boldToken.transfer(A, dec(50000, 18), { from: whale }); @@ -256,6 +259,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getBoldAmountForDesiredDebt(2000), account, account, + 0, { from: account, value: dec(15, "ether") } ); assert.isTrue( @@ -351,6 +355,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, + 0, { from: whale, value: dec(100000, "ether") } ); await boldToken.transfer(A, dec(50000, 18), { from: whale }); @@ -362,6 +367,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getBoldAmountForDesiredDebt(2000), account, account, + 0, { from: account, value: dec(15, "ether") } ); assert.isTrue( @@ -459,6 +465,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, + 0, { from: whale, value: dec(100000, "ether") } ); await boldToken.transfer(A, dec(50000, 18), { from: whale }); @@ -470,6 +477,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getBoldAmountForDesiredDebt(2000), account, account, + 0, { from: account, value: dec(15, "ether") } ); assert.isTrue( @@ -576,6 +584,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, + 0, { from: whale, value: dec(100000, "ether") } ); await boldToken.transfer(A, dec(50000, 18), { from: whale }); @@ -587,6 +596,7 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { await getBoldAmountForDesiredDebt(2000), account, account, + 0, { from: account, value: dec(15, "ether") } ); assert.isTrue( diff --git a/contracts/test/SortedTrovesTest.js b/contracts/test/SortedTrovesTest.js index e776fad6..ec0e86b9 100644 --- a/contracts/test/SortedTrovesTest.js +++ b/contracts/test/SortedTrovesTest.js @@ -306,22 +306,22 @@ contract("SortedTroves", async (accounts) => { it("Finds the correct insert position given two addresses that loosely bound the correct position", async () => { await priceFeed.setPrice(dec(100, 18)); - // NICR sorted in descending order + // Inserted in descending order of interest rate await openTrove({ ICR: toBN(dec(500, 18)), extraParams: { from: whale }, }); - await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: A } }); - await openTrove({ ICR: toBN(dec(5, 18)), extraParams: { from: B } }); - await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: C } }); - await openTrove({ ICR: toBN(dec(166, 16)), extraParams: { from: D } }); - await openTrove({ ICR: toBN(dec(125, 16)), extraParams: { from: E } }); + await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: A, annualInterestRate: toBN(dec(1,18))}}); // 100% interest rate + await openTrove({ ICR: toBN(dec(5, 18)), extraParams: { from: B , annualInterestRate: toBN(dec(75, 16))}}); // 75% interest rate + await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: C, annualInterestRate: toBN(dec(5, 17))}}); // 50% interest rate + await openTrove({ ICR: toBN(dec(166, 16)), extraParams: { from: D, annualInterestRate: toBN(dec(25,16))}}); // 25% interest rate + await openTrove({ ICR: toBN(dec(125, 16)), extraParams: { from: E, annualInterestRate: toBN(dec(1, 16))}}); // 1% interest rate - // Expect a trove with NICR 300% to be inserted between B and C - const targetNICR = dec(3, 18); + // Expect a trove with 60% interest rate to be inserted between B and C + const targetAnnualIRate = toBN(dec(60, 16)); // Pass addresses that loosely bound the right postiion - const hints = await sortedTroves.findInsertPosition(targetNICR, A, E); + const hints = await sortedTroves.findInsertPosition(targetAnnualIRate, A, E); // Expect the exact correct insert hints have been returned assert.equal(hints[0], B); @@ -329,7 +329,7 @@ contract("SortedTroves", async (accounts) => { // The price doesn’t affect the hints await priceFeed.setPrice(dec(500, 18)); - const hints2 = await sortedTroves.findInsertPosition(targetNICR, A, E); + const hints2 = await sortedTroves.findInsertPosition(targetAnnualIRate, A, E); // Expect the exact correct insert hints have been returned assert.equal(hints2[0], B); @@ -338,7 +338,7 @@ contract("SortedTroves", async (accounts) => { }); describe("SortedTroves with mock dependencies", () => { - let sortedTrovesTester; + let sortedTrovesTester; beforeEach(async () => { sortedTroves = await SortedTroves.new(); @@ -352,6 +352,7 @@ contract("SortedTroves", async (accounts) => { await th.assertRevert( sortedTroves.setParams( 0, + // The SortedTrovesTester is being used here as both a wrapper for SortedTroves and a mock TroveManager. sortedTrovesTester.address, sortedTrovesTester.address ), @@ -393,13 +394,6 @@ contract("SortedTroves", async (accounts) => { ); }); - it("insert(): fails if NICR is zero", async () => { - await th.assertRevert( - sortedTrovesTester.insert(alice, 0, alice, alice), - "SortedTroves: NICR must be positive" - ); - }); - it("remove(): fails if id is not in the list", async () => { await th.assertRevert( sortedTrovesTester.remove(alice), @@ -414,22 +408,6 @@ contract("SortedTroves", async (accounts) => { ); }); - it("reInsert(): fails if new NICR is zero", async () => { - await sortedTrovesTester.insert(alice, 1, alice, alice); - assert.isTrue( - await sortedTroves.contains(alice), - "list should contain element" - ); - await th.assertRevert( - sortedTrovesTester.reInsert(alice, 0, alice, alice), - "SortedTroves: NICR must be positive" - ); - assert.isTrue( - await sortedTroves.contains(alice), - "list should contain element" - ); - }); - it("findInsertPosition(): No prevId for hint - ascend list starting from nextId, result is after the tail", async () => { await sortedTrovesTester.insert(alice, 1, alice, alice); const pos = await sortedTroves.findInsertPosition( diff --git a/contracts/test/StabilityPoolTest.js b/contracts/test/StabilityPoolTest.js index 9219a7e9..d12a94cd 100644 --- a/contracts/test/StabilityPoolTest.js +++ b/contracts/test/StabilityPoolTest.js @@ -1603,7 +1603,7 @@ contract("StabilityPool", async (accounts) => { assert.equal(await stabilityPool.getDepositorETHGain(alice), 0); // Alice attempts third withdrawal (this time, frm SP to Trove) - const txPromise_A = stabilityPool.withdrawETHGainToTrove(alice, alice, { + const txPromise_A = stabilityPool.withdrawETHGainToTrove({ from: alice, }); await th.assertRevert(txPromise_A); @@ -1803,6 +1803,7 @@ contract("StabilityPool", async (accounts) => { await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, + 0, { from: defaulter_1, value: dec(100, "ether") } ); @@ -1842,8 +1843,6 @@ contract("StabilityPool", async (accounts) => { await borrowerOperations.withdrawBold( th._100pct, dec(5000, 18), - bob, - bob, { from: bob } ); @@ -2613,6 +2612,7 @@ contract("StabilityPool", async (accounts) => { await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, + 0, { from: defaulter_1, value: dec(100, "ether") } ); @@ -3100,12 +3100,12 @@ contract("StabilityPool", async (accounts) => { await troveManager.liquidate(defaulter_1); assert.isFalse(await sortedTroves.contains(defaulter_1)); - const txAlice = await stabilityPool.withdrawETHGainToTrove(alice, alice, { + const txAlice = await stabilityPool.withdrawETHGainToTrove( { from: alice, }); assert.isTrue(txAlice.receipt.status); - const txPromise_B = stabilityPool.withdrawETHGainToTrove(bob, bob, { + const txPromise_B = stabilityPool.withdrawETHGainToTrove( { from: bob, }); await th.assertRevert(txPromise_B); @@ -3178,7 +3178,7 @@ contract("StabilityPool", async (accounts) => { ); // Alice sends her ETH Gains to her Trove - await stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }); + await stabilityPool.withdrawETHGainToTrove( { from: alice }); // check Alice's BoldLoss has been applied to her deposit expectedCompoundedDeposit_A alice_deposit_afterDefault = (await stabilityPool.deposits(alice)); @@ -3244,7 +3244,7 @@ contract("StabilityPool", async (accounts) => { // Alice attempts to her ETH Gains to her Trove await assertRevert( - stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }), + stabilityPool.withdrawETHGainToTrove( { from: alice }), "BorrowerOps: An operation that would result in ICR < MCR is not permitted" ); }); @@ -3294,14 +3294,14 @@ contract("StabilityPool", async (accounts) => { await priceFeed.setPrice(dec(200, 18)); // Alice sends her ETH Gains to her Trove - await stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }); + await stabilityPool.withdrawETHGainToTrove( { from: alice }); assert.equal(await stabilityPool.getDepositorETHGain(alice), 0); const ETHinSP_Before = (await stabilityPool.getETH()).toString(); // Alice attempts second withdrawal from SP to Trove - reverts, due to 0 ETH Gain - const txPromise_A = stabilityPool.withdrawETHGainToTrove(alice, alice, { + const txPromise_A = stabilityPool.withdrawETHGainToTrove( { from: alice, }); await th.assertRevert(txPromise_A); @@ -3373,7 +3373,7 @@ contract("StabilityPool", async (accounts) => { const stability_ETH_Before = await stabilityPool.getETH(); // Alice retrieves redirects ETH gain to her Trove - await stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }); + await stabilityPool.withdrawETHGainToTrove({ from: alice }); const active_ETH_After = await activePool.getETH(); const stability_ETH_After = await stabilityPool.getETH(); @@ -3427,27 +3427,27 @@ contract("StabilityPool", async (accounts) => { await priceFeed.setPrice(dec(200, 18)); // All depositors attempt to withdraw - const tx1 = await stabilityPool.withdrawETHGainToTrove(alice, alice, { + const tx1 = await stabilityPool.withdrawETHGainToTrove({ from: alice, }); assert.isTrue(tx1.receipt.status); - const tx2 = await stabilityPool.withdrawETHGainToTrove(bob, bob, { + const tx2 = await stabilityPool.withdrawETHGainToTrove({ from: bob, }); assert.isTrue(tx1.receipt.status); - const tx3 = await stabilityPool.withdrawETHGainToTrove(carol, carol, { + const tx3 = await stabilityPool.withdrawETHGainToTrove({ from: carol, }); assert.isTrue(tx1.receipt.status); - const tx4 = await stabilityPool.withdrawETHGainToTrove(dennis, dennis, { + const tx4 = await stabilityPool.withdrawETHGainToTrove({ from: dennis, }); assert.isTrue(tx1.receipt.status); - const tx5 = await stabilityPool.withdrawETHGainToTrove(erin, erin, { + const tx5 = await stabilityPool.withdrawETHGainToTrove({ from: erin, }); assert.isTrue(tx1.receipt.status); - const tx6 = await stabilityPool.withdrawETHGainToTrove(flyn, flyn, { + const tx6 = await stabilityPool.withdrawETHGainToTrove({ from: flyn, }); assert.isTrue(tx1.receipt.status); @@ -3497,28 +3497,28 @@ contract("StabilityPool", async (accounts) => { await priceFeed.setPrice(dec(200, 18)); - await stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }); + await stabilityPool.withdrawETHGainToTrove({ from: alice }); const aliceCollAfter = (await troveManager.Troves(alice))[1]; assert.isAtMost( th.getDifference(aliceCollAfter.sub(collBefore), expectedCollGain), 10000 ); - await stabilityPool.withdrawETHGainToTrove(bob, bob, { from: bob }); + await stabilityPool.withdrawETHGainToTrove({ from: bob }); const bobCollAfter = (await troveManager.Troves(bob))[1]; assert.isAtMost( th.getDifference(bobCollAfter.sub(collBefore), expectedCollGain), 10000 ); - await stabilityPool.withdrawETHGainToTrove(carol, carol, { from: carol }); + await stabilityPool.withdrawETHGainToTrove({ from: carol }); const carolCollAfter = (await troveManager.Troves(carol))[1]; assert.isAtMost( th.getDifference(carolCollAfter.sub(collBefore), expectedCollGain), 10000 ); - await stabilityPool.withdrawETHGainToTrove(dennis, dennis, { + await stabilityPool.withdrawETHGainToTrove( { from: dennis, }); const dennisCollAfter = (await troveManager.Troves(dennis))[1]; @@ -3527,14 +3527,14 @@ contract("StabilityPool", async (accounts) => { 10000 ); - await stabilityPool.withdrawETHGainToTrove(erin, erin, { from: erin }); + await stabilityPool.withdrawETHGainToTrove({ from: erin }); const erinCollAfter = (await troveManager.Troves(erin))[1]; assert.isAtMost( th.getDifference(erinCollAfter.sub(collBefore), expectedCollGain), 10000 ); - await stabilityPool.withdrawETHGainToTrove(flyn, flyn, { from: flyn }); + await stabilityPool.withdrawETHGainToTrove({ from: flyn }); const flynCollAfter = (await troveManager.Troves(flyn))[1]; assert.isAtMost( th.getDifference(flynCollAfter.sub(collBefore), expectedCollGain), @@ -3608,9 +3608,9 @@ contract("StabilityPool", async (accounts) => { ); // A, B, C withdraw their full ETH gain from the Stability Pool to their trove - await stabilityPool.withdrawETHGainToTrove(alice, alice, { from: alice }); - await stabilityPool.withdrawETHGainToTrove(bob, bob, { from: bob }); - await stabilityPool.withdrawETHGainToTrove(carol, carol, { from: carol }); + await stabilityPool.withdrawETHGainToTrove( { from: alice }); + await stabilityPool.withdrawETHGainToTrove({ from: bob }); + await stabilityPool.withdrawETHGainToTrove({ from: carol }); // Check collateral of troves A, B, C has increased by the value of their ETH gain from liquidations, respectively const alice_expectedCollateral = alice_Collateral_Before @@ -3685,7 +3685,7 @@ contract("StabilityPool", async (accounts) => { // D attempts to withdraw his ETH gain to Trove await th.assertRevert( - stabilityPool.withdrawETHGainToTrove(dennis, dennis, { from: dennis }), + stabilityPool.withdrawETHGainToTrove( { from: dennis }), "caller must have an active trove to withdraw ETHGain to" ); }); @@ -3737,16 +3737,16 @@ contract("StabilityPool", async (accounts) => { assert.equal(await stabilityPool.getDepositorETHGain(C), "0"); // Check withdrawETHGainToTrove reverts for A, B, C - const txPromise_A = stabilityPool.withdrawETHGainToTrove(A, A, { + const txPromise_A = stabilityPool.withdrawETHGainToTrove({ from: A, }); - const txPromise_B = stabilityPool.withdrawETHGainToTrove(B, B, { + const txPromise_B = stabilityPool.withdrawETHGainToTrove({ from: B, }); - const txPromise_C = stabilityPool.withdrawETHGainToTrove(C, C, { + const txPromise_C = stabilityPool.withdrawETHGainToTrove({ from: C, }); - const txPromise_D = stabilityPool.withdrawETHGainToTrove(D, D, { + const txPromise_D = stabilityPool.withdrawETHGainToTrove({ from: D, }); diff --git a/contracts/test/StabilityPool_SPWithdrawalTest.js b/contracts/test/StabilityPool_SPWithdrawalTest.js index 696df6f5..8d5eeb9b 100644 --- a/contracts/test/StabilityPool_SPWithdrawalTest.js +++ b/contracts/test/StabilityPool_SPWithdrawalTest.js @@ -81,7 +81,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Identical deposits, identical liquidation amounts--- it("withdrawFromSP(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -91,7 +91,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulter opens trove with 200% ICR and 10k Bold net debt - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -120,7 +120,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after two identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -130,8 +130,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -160,7 +160,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after three identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -170,9 +170,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -204,7 +204,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Identical deposits, increasing liquidation amounts --- it("withdrawFromSP(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after two liquidations of increasing Bold", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -214,8 +214,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '70000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: '70000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -246,7 +246,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after three liquidations of increasing Bold", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -256,9 +256,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(6000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '60000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: '70000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(6000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: '60000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: '70000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -291,7 +291,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Increasing deposits, identical liquidation amounts --- it("withdrawFromSP(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after two identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k, 20k, 30k Bold to A, B and C respectively who then deposit it to the SP await boldToken.transfer(alice, dec(10000, 18), { from: whale }) @@ -302,8 +302,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await stabilityPool.provideToSP(dec(30000, 18), { from: carol }) // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -333,7 +333,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after three identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k, 20k, 30k Bold to A, B and C respectively who then deposit it to the SP await boldToken.transfer(alice, dec(10000, 18), { from: whale }) @@ -344,9 +344,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await stabilityPool.provideToSP(dec(30000, 18), { from: carol }) // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -378,7 +378,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Varied deposits and varied liquidation amount --- it("withdrawFromSP(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after three varying liquidations", async () => { // Whale opens Trove with 1m ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, { from: whale, value: dec(1000000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, 0,{ from: whale, value: dec(1000000, 'ether') }) /* Depositors provide:- Alice: 2000 Bold @@ -398,9 +398,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 2: 5000 Bold & 50 ETH Defaulter 3: 46700 Bold & 500 ETH */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('207000000000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(2160, 18) }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5, 21)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(50, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('46700000000000000000000'), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(500, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('207000000000000000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(2160, 18) }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5, 21)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(50, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('46700000000000000000000'), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(500, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -435,7 +435,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): A, B, C Deposit -> 2 liquidations -> D deposits -> 1 liquidation. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -445,9 +445,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -490,7 +490,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): A, B, C Deposit -> 2 liquidations -> D deposits -> 2 liquidations. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -500,10 +500,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -544,7 +544,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): A, B, C Deposit -> 2 liquidations -> D deposits -> 2 liquidations. Various deposit and liquidation vals. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 1m ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, { from: whale, value: dec(1000000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, 0,{ from: whale, value: dec(1000000, 'ether') }) /* Depositors open troves and make SP deposit: Alice: 60000 Bold @@ -565,10 +565,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 3: 5000 Bold, 50 ETH Defaulter 4: 40000 Bold, 400 ETH */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(25000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '250000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(40000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(400, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(25000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: '250000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(40000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(400, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -613,7 +613,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): A, B, C, D deposit -> 2 liquidations -> D withdraws -> 2 liquidations. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol, dennis] @@ -623,10 +623,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -669,7 +669,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): A, B, C, D deposit -> 2 liquidations -> D withdraws -> 2 liquidations. Various deposit and liquidation vals. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) /* Initial deposits: Alice: 20000 Bold @@ -693,10 +693,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 3: 30000 Bold Defaulter 4: 5000 Bold */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(30000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(300, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(30000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(300, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: '50000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -742,7 +742,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- One deposit enters at t > 0, and another leaves later --- it("withdrawFromSP(): A, B, D deposit -> 2 liquidations -> C makes deposit -> 1 liquidation -> D withdraws -> 1 liquidation. All deposits: 100 Bold. Liquidations: 100,100,100,50. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B and D who then deposit it to the SP const depositors = [alice, bob, dennis] @@ -752,10 +752,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: '50000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -811,7 +811,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // C, D withdraw 5000Bold & 500e it("withdrawFromSP(): Depositor withdraws correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -821,8 +821,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -878,7 +878,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // L2 20000, 200 empties Pool it("withdrawFromSP(): Pool-emptying liquidation increases epoch by one, resets scaleFactor to 0, and resets P to 1e18", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -888,10 +888,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 4 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -970,7 +970,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // C, D withdraw 5000 Bold & 50e it("withdrawFromSP(): Depositors withdraw correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -980,8 +980,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1037,15 +1037,15 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Expect A to withdraw 0 deposit and ether only from reward L1 it("withdrawFromSP(): single deposit fully offset. After subsequent liquidations, depositor withdraws 0 deposit and *only* the ETH Gain from one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1,2,3 withdraw 10000 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1079,13 +1079,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Depositor withdraws correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // 4 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(200, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -1188,18 +1188,18 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): deposit spans one scale factor change: Single depositor withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 withdraws 'almost' 10000 Bold: 9999.99991 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) assert.equal(await stabilityPool.currentScale(), '0') // Defaulter 2 withdraws 9900 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(9900, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(60, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(9900, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(60, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1245,16 +1245,16 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): Several deposits of varying amounts span one scale factor change. Depositors withdraw correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 withdraws 'almost' 10k Bold. - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) // Defaulter 2 withdraws 59400 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59400000000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(330, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59400000000000000000000'), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(330, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1327,14 +1327,14 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): deposit spans one scale factor change: Single depositor withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 and default 2 each withdraw 9999.999999999 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter 1 ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -1383,14 +1383,14 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): Several deposits of varying amounts span one scale factor change. Depositors withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 and default 2 withdraw up to debt of 9999.9 Bold and 59999.4 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59999400000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(600, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59999400000000000000000'), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(600, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1447,10 +1447,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Expect A to withdraw 0 deposit it("withdrawFromSP(): Deposit that decreases to less than 1e-9 of it's original value is reduced to 0", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Defaulters 1 withdraws 9999.9999999 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999999900000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999999900000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) // Price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1483,13 +1483,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): Several deposits of 10000 Bold span one scale factor change. Depositors withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Defaulters 1-4 each withdraw 9999.9 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1561,12 +1561,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): 2 depositors can withdraw after each receiving half of a pool-emptying liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Defaulters 1-3 each withdraw 24100, 24300, 24500 Bold (inc gas comp) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24100, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24300, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24500, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24100, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24300, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24500, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(200, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1689,14 +1689,14 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): Depositor's ETH gain stops increasing after two scale changes", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // Defaulters 1-5 each withdraw up to debt of 9999.9999999 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_5, defaulter_5, { from: defaulter_5, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_5, defaulter_5, 0, { from: defaulter_5, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1765,19 +1765,19 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawFromSP(): Large liquidated coll/debt, deposits and ETH price", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // ETH:USD price is $2 billion per ETH await priceFeed.setPrice(dec(2, 27)); const depositors = [alice, bob] for (account of depositors) { - await borrowerOperations.openTrove(th._100pct, dec(1, 36), account, account, { from: account, value: dec(2, 27) }) + await borrowerOperations.openTrove(th._100pct, dec(1, 36), account, account, 0, { from: account, value: dec(2, 27) }) await stabilityPool.provideToSP(dec(1, 36), { from: account }) } // Defaulter opens trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1, 36)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(1, 27) }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1, 36)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: dec(1, 27) }) // ETH:USD price drops to $1 billion per ETH await priceFeed.setPrice(dec(1, 27)); @@ -1822,7 +1822,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawFromSP(): Small liquidated coll/debt, large deposits and ETH price", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0,{ from: whale, value: dec(100000, 'ether') }) // ETH:USD price is $2 billion per ETH await priceFeed.setPrice(dec(2, 27)); @@ -1835,7 +1835,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulter opens trove with 50e-7 ETH and 5000 Bold. 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '5000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0,{ from: defaulter_1, value: '5000000000000' }) // ETH:USD price drops to $1 billion per ETH await priceFeed.setPrice(dec(1, 27)); diff --git a/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js b/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js index 119c7f42..a1081657 100644 --- a/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js +++ b/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js @@ -81,12 +81,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Identical deposits, identical liquidation amounts--- it("withdrawETHGainToTrove(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -96,7 +96,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulter opens trove with 200% ICR and 10k Bold net debt - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -105,9 +105,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_1, { from: owner }); // Check depositors' compounded deposit is 6666.66 Bold and ETH Gain is 33.16 ETH - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -125,12 +125,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after two identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -140,8 +140,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -151,9 +151,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_2, { from: owner }); // Check depositors' compounded deposit is 3333.33 Bold and ETH Gain is 66.33 ETH - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() const bob_ETHWithdrawn = th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() @@ -170,12 +170,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after three identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -185,9 +185,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -198,9 +198,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); // Check depositors' compounded deposit is 0 Bold and ETH Gain is 99.5 ETH - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -219,12 +219,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Identical deposits, increasing liquidation amounts --- it("withdrawETHGainToTrove(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after two liquidations of increasing Bold", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -234,8 +234,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '70000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: '70000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -245,9 +245,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_2, { from: owner }); // Check depositors' compounded deposit - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -266,12 +266,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Depositors with equal initial deposit withdraw correct compounded deposit and ETH Gain after three liquidations of increasing Bold", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -281,9 +281,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(6000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '60000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: '70000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(6000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: '60000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(7000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: '70000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -294,9 +294,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); // Check depositors' compounded deposit - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -316,12 +316,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Increasing deposits, identical liquidation amounts --- it("withdrawETHGainToTrove(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after two identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k, 20k, 30k Bold to A, B and C respectively who then deposit it to the SP await boldToken.transfer(alice, dec(10000, 18), { from: whale }) @@ -332,8 +332,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await stabilityPool.provideToSP(dec(30000, 18), { from: carol }) // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -343,9 +343,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_2, { from: owner }); // Depositors attempt to withdraw everything - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -363,12 +363,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after three identical liquidations", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k, 20k, 30k Bold to A, B and C respectively who then deposit it to the SP await boldToken.transfer(alice, dec(10000, 18), { from: whale }) @@ -379,9 +379,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await stabilityPool.provideToSP(dec(30000, 18), { from: carol }) // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -392,9 +392,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); // Depositors attempt to withdraw everything - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -413,12 +413,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- Varied deposits and varied liquidation amount --- it("withdrawETHGainToTrove(): Depositors with varying deposits withdraw correct compounded deposit and ETH Gain after three varying liquidations", async () => { // Whale opens Trove with 1m ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, { from: whale, value: dec(1000000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, 0, { from: whale, value: dec(1000000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) /* Depositors provide:- Alice: 2000 Bold @@ -438,9 +438,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 2: 5000 Bold & 50 ETH Defaulter 3: 46700 Bold & 500 ETH */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('207000000000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(2160, 18) }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5, 21)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(50, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('46700000000000000000000'), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(500, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('207000000000000000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(2160, 18) }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5, 21)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(50, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('46700000000000000000000'), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(500, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -451,9 +451,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); // Depositors attempt to withdraw everything - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -475,13 +475,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): A, B, C Deposit -> 2 liquidations -> D deposits -> 1 liquidation. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -491,9 +491,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -509,10 +509,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Third defaulter liquidated await troveManager.liquidate(defaulter_3, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -536,13 +536,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): A, B, C Deposit -> 2 liquidations -> D deposits -> 2 liquidations. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol] @@ -552,10 +552,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -572,10 +572,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); await troveManager.liquidate(defaulter_4, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -596,13 +596,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): A, B, C Deposit -> 2 liquidations -> D deposits -> 2 liquidations. Various deposit and liquidation vals. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 1m ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, { from: whale, value: dec(1000000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1000000, 18)), whale, whale, 0, { from: whale, value: dec(1000000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) /* Depositors open troves and make SP deposit: Alice: 60000 Bold @@ -623,10 +623,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 3: 5000 Bold, 50 ETH Defaulter 4: 40000 Bold, 400 ETH */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(25000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: '250000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: '50000000000000000000' }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(40000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(400, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(25000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: '250000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(40000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(400, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -644,10 +644,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_4, { from: owner }); // Each depositor withdraws as much as possible - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -671,13 +671,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): A, B, C, D deposit -> 2 liquidations -> D withdraws -> 2 liquidations. All deposits and liquidations = 100 Bold. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and C who then deposit it to the SP const depositors = [alice, bob, carol, dennis] @@ -687,10 +687,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -702,7 +702,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Dennis withdraws his deposit and ETH gain // Increasing the price for a moment to avoid pending liquidations to block withdrawal await priceFeed.setPrice(dec(200, 18)) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) await priceFeed.setPrice(dec(100, 18)) const dennis_ETHWithdrawn = th.getEventArgByName(txD, 'ETHGainWithdrawn', '_ETH').toString() @@ -713,9 +713,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); await troveManager.liquidate(defaulter_4, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -733,12 +733,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): A, B, C, D deposit -> 2 liquidations -> D withdraws -> 2 liquidations. Various deposit and liquidation vals. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) /* Initial deposits: Alice: 20000 Bold @@ -762,10 +762,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' Defaulter 3: 30000 Bold Defaulter 4: 5000 Bold */ - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(30000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(300, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(30000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(300, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: '50000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -789,9 +789,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_3, { from: owner }); await troveManager.liquidate(defaulter_4, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -811,12 +811,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // --- One deposit enters at t > 0, and another leaves later --- it("withdrawETHGainToTrove(): A, B, D deposit -> 2 liquidations -> C makes deposit -> 1 liquidation -> D withdraws -> 1 liquidation. All deposits: 100 Bold. Liquidations: 100,100,100,50. A, B, C, D withdraw correct Bold deposit and ETH Gain", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B and D who then deposit it to the SP const depositors = [alice, bob, dennis] @@ -826,10 +826,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulters open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: '50000000000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_4, defaulter_4, 0, { from: defaulter_4, value: '50000000000000000000' }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -856,9 +856,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_4, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -885,13 +885,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // C, D withdraw 5000Bold & 500e it("withdrawETHGainToTrove(): Depositor withdraws correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -901,8 +901,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -923,10 +923,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // await borrowerOperations.openTrove(th._100pct, dec(1, 18), account, account, { from: erin, value: dec(2, 'ether') }) // await stabilityPool.provideToSP(dec(1, 18), { from: erin }) - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() const bob_ETHWithdrawn = th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() @@ -958,13 +958,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // L2 20000, 200 empties Pool it("withdrawETHGainToTrove(): Pool-emptying liquidation increases epoch by one, resets scaleFactor to 0, and resets P to 1e18", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -974,10 +974,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 4 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -1056,14 +1056,14 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // C, D withdraw 5000 Bold & 50e it("withdrawETHGainToTrove(): Depositors withdraw correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: erin, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: erin, value: dec(10000, 'ether') }) // Whale transfers 10k Bold to A, B who then deposit it to the SP const depositors = [alice, bob] @@ -1073,8 +1073,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // 2 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1095,11 +1095,11 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Defaulter 2 liquidated. 10000 Bold offset await troveManager.liquidate(defaulter_2, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) - const txE = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: erin }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) + const txE = await stabilityPool.withdrawETHGainToTrove({ from: erin }) const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() const bob_ETHWithdrawn = th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() @@ -1130,21 +1130,21 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Expect A to withdraw 0 deposit and ether only from reward L1 it("withdrawETHGainToTrove(): single deposit fully offset. After subsequent liquidations, depositor withdraws 0 deposit and *only* the ETH Gain from one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1,2,3 withdraw 10000 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1154,7 +1154,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' await troveManager.liquidate(defaulter_2, { from: owner }); await troveManager.liquidate(defaulter_3, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() @@ -1178,23 +1178,23 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Depositor withdraws correct compounded deposit after liquidation empties the pool", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // A, B, C, D, E, F, G, H open troves - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: erin, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: flyn, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: harriet, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: graham, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: erin, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: flyn, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: harriet, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: graham, value: dec(10000, 'ether') }) // 4 Defaulters open trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_3, defaulter_3, 0,{ from: defaulter_3, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(20000, 18)), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(200, 'ether') }) // price drops by 50%: defaulter ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -1239,14 +1239,14 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Defaulter 4 liquidated. 10k Bold offset await troveManager.liquidate(defaulter_4, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) - const txE = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: erin }) - const txF = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: flyn }) - const txG = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: graham }) - const txH = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: harriet }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) + const txE = await stabilityPool.withdrawETHGainToTrove({ from: erin }) + const txF = await stabilityPool.withdrawETHGainToTrove({ from: flyn }) + const txG = await stabilityPool.withdrawETHGainToTrove({ from: graham }) + const txH = await stabilityPool.withdrawETHGainToTrove({ from: harriet }) const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() const bob_ETHWithdrawn = th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() @@ -1297,21 +1297,21 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): deposit spans one scale factor change: Single depositor withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 withdraws 'almost' 10000 Bold: 9999.99991 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) assert.equal(await stabilityPool.currentScale(), '0') // Defaulter 2 withdraws 9900 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(9900, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(60, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(9900, 18)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(60, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1337,7 +1337,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(await stabilityPool.currentScale(), '1') - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) const bob_ETHWithdrawn = await th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() // Expect Bob to retain 1% of initial deposit (100 Bold) and all the liquidated ETH (60 ether) @@ -1359,21 +1359,21 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): Several deposits of varying amounts span one scale factor change. Depositors withdraw correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 withdraws 'almost' 10k Bold. - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999910000000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) // Defaulter 2 withdraws 59400 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59400000000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(330, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59400000000000000000000'), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(330, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1406,9 +1406,9 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(await stabilityPool.currentScale(), '1') - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) /* Expect depositors to retain 1% of their initial deposit, and an ETH gain in proportion to their initial deposit: @@ -1447,18 +1447,18 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): deposit spans one scale factor change: Single depositor withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 and default 2 each withdraw 9999.999999999 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(99999, 17)), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) // price drops by 50%: defaulter 1 ICR falls to 100% await priceFeed.setPrice(dec(100, 18)); @@ -1486,7 +1486,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(await stabilityPool.P(), dec(1, 17)) // Scale changes and P changes. P = 1e(13-5+9) = 1e17 assert.equal(await stabilityPool.currentScale(), '1') - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) const bob_ETHWithdrawn = await th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() // Bob should withdraw 1e-5 of initial deposit: 0.1 Bold and the full ETH gain of 100 ether @@ -1507,19 +1507,19 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): Several deposits of varying amounts span one scale factor change. Depositors withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) await boldToken.transfer(alice, dec(10000, 18), { from: whale }) await stabilityPool.provideToSP(dec(10000, 18), { from: alice }) // Defaulter 1 and default 2 withdraw up to debt of 9999.9 Bold and 59999.4 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59999400000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(600, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('59999400000000000000000'), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(600, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1552,13 +1552,13 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(await stabilityPool.P(), dec(1, 17)) // P decreases. P = 1e(13-5+9) = 1e17 assert.equal(await stabilityPool.currentScale(), '1') - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) const bob_ETHWithdrawn = await th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) const carol_ETHWithdrawn = await th.getEventArgByName(txC, 'ETHGainWithdrawn', '_ETH').toString() - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) const dennis_ETHWithdrawn = await th.getEventArgByName(txD, 'ETHGainWithdrawn', '_ETH').toString() // {B, C, D} should have a compounded deposit of {0.1, 0.2, 0.3} Bold @@ -1576,15 +1576,15 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Expect A to withdraw 0 deposit it("withdrawETHGainToTrove(): Deposit that decreases to less than 1e-9 of it's original value is reduced to 0", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Defaulters 1 withdraws 9999.9999999 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999999900000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999999999900000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) // Price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1618,18 +1618,18 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // in helper functon getOpenTroveBoldAmount due to now-zero borrow fees. Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): Several deposits of 10000 Bold span one scale factor change. Depositors withdraws correct compounded deposit and ETH Gain after one liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: alice, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: bob, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: carol, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: alice, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: bob, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: carol, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: dennis, value: dec(10000, 'ether') }) // Defaulters 1-4 each withdraw 9999.9 Bold - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(100, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_4, defaulter_4, { from: defaulter_4, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_2, defaulter_2, 0,{ from: defaulter_2, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_3, defaulter_3, 0,0,{ from: defaulter_3, value: dec(100, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount('9999900000000000000000'), defaulter_4, defaulter_4, 0,{ from: defaulter_4, value: dec(100, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1674,10 +1674,10 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(await stabilityPool.P(), dec(1, 16)) // Scale changes and P changes to 1e(12-5+9) = 1e16 assert.equal(await stabilityPool.currentScale(), '2') - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: carol }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: dennis }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: carol }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: dennis }) const alice_ETHWithdrawn = await th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH').toString() const bob_ETHWithdrawn = await th.getEventArgByName(txB, 'ETHGainWithdrawn', '_ETH').toString() @@ -1701,19 +1701,19 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): 2 depositors can withdraw after each receiving half of a pool-emptying liquidation", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) - - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: A, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: B, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: C, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: D, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: E, value: dec(10000, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, { from: F, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) + + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: A, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: B, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: C, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: D, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: E, value: dec(10000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), ZERO_ADDRESS, ZERO_ADDRESS, 0, { from: F, value: dec(10000, 'ether') }) // Defaulters 1-3 each withdraw 24100, 24300, 24500 Bold (inc gas comp) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24100, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24300, 18)), defaulter_2, defaulter_2, { from: defaulter_2, value: dec(200, 'ether') }) - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24500, 18)), defaulter_3, defaulter_3, { from: defaulter_3, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24100, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24300, 18)), defaulter_2, defaulter_2, 0, { from: defaulter_2, value: dec(200, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(24500, 18)), defaulter_3, defaulter_3, 0, { from: defaulter_3, value: dec(200, 'ether') }) // price drops by 50% await priceFeed.setPrice(dec(100, 18)); @@ -1749,8 +1749,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Attempt withdrawals // Increasing the price for a moment to avoid pending liquidations to block withdrawal await priceFeed.setPrice(dec(200, 18)) - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: A }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: B }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: A }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: B }) await priceFeed.setPrice(dec(100, 18)) assert.isTrue(txA.receipt.status) @@ -1789,8 +1789,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Attempt withdrawals // Increasing the price for a moment to avoid pending liquidations to block withdrawal await priceFeed.setPrice(dec(200, 18)) - const txC = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: C }) - const txD = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: D }) + const txC = await stabilityPool.withdrawETHGainToTrove({ from: C }) + const txD = await stabilityPool.withdrawETHGainToTrove({ from: D }) await priceFeed.setPrice(dec(100, 18)) assert.isTrue(txC.receipt.status) @@ -1826,8 +1826,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.equal(SPBoldBalance_3, '0') // Attempt withdrawals - const txE = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: E }) - const txF = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: F }) + const txE = await stabilityPool.withdrawETHGainToTrove({ from: E }) + const txF = await stabilityPool.withdrawETHGainToTrove({ from: F }) assert.isTrue(txE.receipt.status) assert.isTrue(txF.receipt.status) }) @@ -1836,19 +1836,19 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' it("withdrawETHGainToTrove(): Large liquidated coll/debt, deposits and ETH price", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // ETH:USD price is $2 billion per ETH await priceFeed.setPrice(dec(2, 27)); const depositors = [alice, bob] for (account of depositors) { - await borrowerOperations.openTrove(th._100pct, dec(1, 36), account, account, { from: account, value: dec(2, 27) }) + await borrowerOperations.openTrove(th._100pct, dec(1, 36), account, account, 0, { from: account, value: dec(2, 27) }) await stabilityPool.provideToSP(dec(1, 36), { from: account }) } // Defaulter opens trove with 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1, 36)), defaulter_1, defaulter_1, { from: defaulter_1, value: dec(1, 27) }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(1, 36)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: dec(1, 27) }) // ETH:USD price drops to $1 billion per ETH await priceFeed.setPrice(dec(1, 27)); @@ -1856,8 +1856,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Defaulter liquidated await troveManager.liquidate(defaulter_1, { from: owner }); - const txA = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txB = await stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) + const txA = await stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txB = await stabilityPool.withdrawETHGainToTrove({ from: bob }) // Grab the ETH gain from the emitted event in the tx log const alice_ETHWithdrawn = th.getEventArgByName(txA, 'ETHGainWithdrawn', '_ETH') @@ -1893,7 +1893,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Double-check this when we write new SP arithmetic tests and fix the "P" issue. it.skip("withdrawETHGainToTrove(): Small liquidated coll/debt, large deposits and ETH price", async () => { // Whale opens Trove with 100k ETH - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, { from: whale, value: dec(100000, 'ether') }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(100000, 18)), whale, whale, 0, { from: whale, value: dec(100000, 'ether') }) // ETH:USD price is $2 billion per ETH await priceFeed.setPrice(dec(2, 27)); @@ -1906,7 +1906,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' } // Defaulter opens trove with 50e-7 ETH and 5000 Bold. 200% ICR - await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, { from: defaulter_1, value: '5000000000000' }) + await borrowerOperations.openTrove(th._100pct, await getOpenTroveBoldAmount(dec(5000, 18)), defaulter_1, defaulter_1, 0, { from: defaulter_1, value: '5000000000000' }) // ETH:USD price drops to $1 billion per ETH await priceFeed.setPrice(dec(1, 27)); @@ -1914,8 +1914,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' // Defaulter liquidated await troveManager.liquidate(defaulter_1, { from: owner }); - const txAPromise = stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: alice }) - const txBPromise = stabilityPool.withdrawETHGainToTrove(ZERO_ADDRESS, ZERO_ADDRESS, { from: bob }) + const txAPromise = stabilityPool.withdrawETHGainToTrove({ from: alice }) + const txBPromise = stabilityPool.withdrawETHGainToTrove({ from: bob }) // Expect ETH gain per depositor of ~1e11 wei to be rounded to 0 by the ETHGainedPerUnitStaked calculation (e / D), where D is ~1e36. await th.assertRevert(txAPromise, 'StabilityPool: caller must have non-zero ETH Gain') diff --git a/contracts/test/TroveManagerTest.js b/contracts/test/TroveManagerTest.js index f675d90f..9e25888b 100644 --- a/contracts/test/TroveManagerTest.js +++ b/contracts/test/TroveManagerTest.js @@ -1238,8 +1238,9 @@ contract("TroveManager", async (accounts) => { }); // --- liquidateTroves() --- - - it("liquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { + // TODO: likely remove liquidateTroves() function and all tests for it, since it no longer works due to the + // new list ordering by interest rates + it.skip("liquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { // A, B, C, D, E open troves await openTrove({ ICR: toBN(dec(333, 16)), extraParams: { from: D } }); await openTrove({ ICR: toBN(dec(333, 16)), extraParams: { from: E } }); @@ -1324,7 +1325,7 @@ contract("TroveManager", async (accounts) => { assert.isTrue((await sortedTroves.getSize()).eq(toBN("1"))); }); - it("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { + it.skip("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); @@ -1400,7 +1401,7 @@ contract("TroveManager", async (accounts) => { assert.equal((await sortedTroves.getSize()).toString(), "4"); }); - it("liquidateTroves(): liquidates up to the requested number of undercollateralized troves", async () => { + it.skip("liquidateTroves(): liquidates up to the requested number of undercollateralized troves", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); @@ -1465,7 +1466,7 @@ contract("TroveManager", async (accounts) => { assert.isTrue(erin_isInSortedList); }); - it("liquidateTroves(): does nothing if all troves have ICR > 110%", async () => { + it.skip("liquidateTroves(): does nothing if all troves have ICR > 110%", async () => { await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: bob } }); @@ -1516,7 +1517,7 @@ contract("TroveManager", async (accounts) => { assert.equal(listSize_Before, listSize_After); }); - it("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { + it.skip("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { await openTrove({ ICR: toBN(dec(400, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(221, 16)), extraParams: { from: bob } }); await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); @@ -1592,7 +1593,7 @@ contract("TroveManager", async (accounts) => { assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); }); - it("liquidateTroves(): reverts if n = 0", async () => { + it.skip("liquidateTroves(): reverts if n = 0", async () => { await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: bob } }); @@ -1632,7 +1633,7 @@ contract("TroveManager", async (accounts) => { assert.equal(TCR_Before, TCR_After); }); - it("liquidateTroves(): liquidates troves with ICR < MCR", async () => { + it.skip("liquidateTroves(): liquidates troves with ICR < MCR", async () => { await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); // A, B, C open troves that will remain active when price drops to 100 @@ -1690,7 +1691,7 @@ contract("TroveManager", async (accounts) => { assert.isFalse(await sortedTroves.contains(flyn)); }); - it("liquidateTroves(): does not affect the liquidated user's token balances", async () => { + it.skip("liquidateTroves(): does not affect the liquidated user's token balances", async () => { await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); // D, E, F open troves that will fall below MCR when price drops to 100 @@ -1735,7 +1736,7 @@ contract("TroveManager", async (accounts) => { assert.equal((await boldToken.balanceOf(flyn)).toString(), F_balanceBefore); }); - it("liquidateTroves(): A liquidation sequence containing Pool offsets increases the TCR", async () => { + it.skip("liquidateTroves(): A liquidation sequence containing Pool offsets increases the TCR", async () => { // Whale provides 500 Bold to SP await openTrove({ ICR: toBN(dec(100, 18)), @@ -1809,7 +1810,7 @@ contract("TroveManager", async (accounts) => { assert.isTrue(TCR_After.gte(TCR_Before)); }); - it("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { + it.skip("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { const { collateral: W_coll, totalDebt: W_debt } = await openTrove({ ICR: toBN(dec(100, 18)), extraParams: { from: whale }, @@ -1915,7 +1916,7 @@ contract("TroveManager", async (accounts) => { assert.isTrue(TCR_After.gte(TCR_Before.mul(toBN(995)).div(toBN(1000)))); }); - it("liquidateTroves(): Liquidating troves with SP deposits correctly impacts their SP deposit and ETH gain", async () => { + it.skip("liquidateTroves(): Liquidating troves with SP deposits correctly impacts their SP deposit and ETH gain", async () => { // Whale provides 400 Bold to the SP const whaleDeposit = toBN(dec(40000, 18)); await openTrove({ @@ -2082,8 +2083,10 @@ contract("TroveManager", async (accounts) => { }); // --- batchLiquidateTroves() --- + // TODO: revisit the relevance of this test since it relies on liquidateTroves(), which now no longer works due to ordering by interest rate. + // Can we achieve / test the same thing using another liquidation function? - it("batchLiquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { + it.skip("batchLiquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { // A, B, C, D, E open troves await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: C } }); await openTrove({ ICR: toBN(dec(364, 16)), extraParams: { from: D } }); @@ -2585,7 +2588,10 @@ contract("TroveManager", async (accounts) => { // --- redemptions --- - it("getRedemptionHints(): gets the address of the first Trove and the final ICR of the last Trove involved in a redemption", async () => { + // TODO: Revisit all redemption tests when implementing redeeming by interest rate ordering, and leaving fully redeemed Troves open. + // Many of these tests rely on specific ICR ordering in the setup, and close fully redeemed. + // It may be more efficient to write wholly new redemption tests in Solidity for Foundry. + it.skip("getRedemptionHints(): gets the address of the first Trove and the final ICR of the last Trove involved in a redemption", async () => { // --- SETUP --- const partialRedemptionAmount = toBN(dec(100, 18)); const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ @@ -2620,7 +2626,7 @@ contract("TroveManager", async (accounts) => { th.assertIsApproximatelyEqual(partialRedemptionHintNICR, expectedICR); }); - it("getRedemptionHints(): returns 0 as partialRedemptionHintNICR when reaching _maxIterations", async () => { + it.skip("getRedemptionHints(): returns 0 as partialRedemptionHintNICR when reaching _maxIterations", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(310, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(290, 16)), extraParams: { from: bob } }); @@ -2642,7 +2648,7 @@ contract("TroveManager", async (accounts) => { assert.equal(partialRedemptionHintNICR, "0"); }); - it("redeemCollateral(): cancels the provided Bold with debt from Troves with the lowest ICRs and sends an equivalent amount of Ether", async () => { + it.skip("redeemCollateral(): cancels the provided Bold with debt from Troves with the lowest ICRs and sends an equivalent amount of Ether", async () => { // --- SETUP --- const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(310, 16)), @@ -2763,7 +2769,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): with invalid first hint, zero address", async () => { + it.skip("redeemCollateral(): with invalid first hint, zero address", async () => { // --- SETUP --- const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(310, 16)), @@ -2874,7 +2880,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): with invalid first hint, non-existent trove", async () => { + it.skip("redeemCollateral(): with invalid first hint, non-existent trove", async () => { // --- SETUP --- const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(310, 16)), @@ -2985,7 +2991,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): with invalid first hint, trove below MCR", async () => { + it.skip("redeemCollateral(): with invalid first hint, trove below MCR", async () => { // --- SETUP --- const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(310, 16)), @@ -3101,7 +3107,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): ends the redemption sequence when the token redemption request has been filled", async () => { + it.skip("redeemCollateral(): ends the redemption sequence when the token redemption request has been filled", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(100, 18)), extraParams: { from: whale } }); @@ -3198,7 +3204,7 @@ contract("TroveManager", async (accounts) => { assert.equal(erin_Coll.toString(), E_coll.toString()); }); - it("redeemCollateral(): ends the redemption sequence when max iterations have been reached", async () => { + it.skip("redeemCollateral(): ends the redemption sequence when max iterations have been reached", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(100, 18)), extraParams: { from: whale } }); @@ -3273,7 +3279,7 @@ contract("TroveManager", async (accounts) => { assert.equal(carol_Status, 1); }); - it("redeemCollateral(): performs partial redemption if resultant debt is > minimum net debt", async () => { + it.skip("redeemCollateral(): performs partial redemption if resultant debt is > minimum net debt", async () => { await borrowerOperations.openTrove( th._100pct, await getOpenTroveBoldAmount(dec(10000, 18)), @@ -3327,7 +3333,7 @@ contract("TroveManager", async (accounts) => { await th.assertIsApproximatelyEqual(A_debt, dec(4600, 18), 1000); }); - it("redeemCollateral(): doesn't perform partial redemption if resultant debt would be < minimum net debt", async () => { + it.skip("redeemCollateral(): doesn't perform partial redemption if resultant debt would be < minimum net debt", async () => { await borrowerOperations.openTrove( th._100pct, await getOpenTroveBoldAmount(dec(6000, 18)), @@ -3382,7 +3388,7 @@ contract("TroveManager", async (accounts) => { await th.assertIsApproximatelyEqual(A_debt, dec(6000, 18)); }); - it("redeemCollateral(): doesnt perform the final partial redemption in the sequence if the hint is out-of-date", async () => { + it.skip("redeemCollateral(): doesnt perform the final partial redemption in the sequence if the hint is out-of-date", async () => { // --- SETUP --- const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(363, 16)), @@ -3573,7 +3579,7 @@ contract("TroveManager", async (accounts) => { assert.equal(carol_BoldBalance_After, "0"); }); - it("redeemCollateral(): doesn't touch Troves with ICR < 110%", async () => { + it.skip("redeemCollateral(): doesn't touch Troves with ICR < 110%", async () => { // --- SETUP --- const { netDebt: A_debt } = await openTrove({ @@ -3621,7 +3627,7 @@ contract("TroveManager", async (accounts) => { th.assertIsApproximatelyEqual(bob_Debt_After, B_totalDebt); }); - it("redeemCollateral(): finds the last Trove with ICR == 110% even if there is more than one", async () => { + it.skip("redeemCollateral(): finds the last Trove with ICR == 110% even if there is more than one", async () => { // --- SETUP --- const amount1 = toBN(dec(100, 18)); const { totalDebt: A_totalDebt } = await openTrove({ @@ -3697,7 +3703,7 @@ contract("TroveManager", async (accounts) => { th.assertIsApproximatelyEqual(dennis_Debt_After, D_totalDebt); }); - it("redeemCollateral(): reverts when TCR < MCR", async () => { + it.skip("redeemCollateral(): reverts when TCR < MCR", async () => { await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: bob } }); await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); @@ -3723,7 +3729,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): reverts when argument _amount is 0", async () => { + it.skip("redeemCollateral(): reverts when argument _amount is 0", async () => { await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); // Alice opens trove and transfers 500Bold to Erin, the would-be redeemer @@ -3762,7 +3768,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): reverts if max fee > 100%", async () => { + it.skip("redeemCollateral(): reverts if max fee > 100%", async () => { await openTrove({ ICR: toBN(dec(400, 16)), extraBoldAmount: dec(10, 18), @@ -3812,7 +3818,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): reverts if max fee < 0.5%", async () => { + it.skip("redeemCollateral(): reverts if max fee < 0.5%", async () => { await openTrove({ ICR: toBN(dec(400, 16)), extraBoldAmount: dec(10, 18), @@ -3872,7 +3878,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): reverts if fee exceeds max fee percentage", async () => { + it.skip("redeemCollateral(): reverts if fee exceeds max fee percentage", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(400, 16)), extraBoldAmount: dec(80, 18), @@ -3957,7 +3963,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): doesn't affect the Stability Pool deposits or ETH gain of redeemed-from troves", async () => { + it.skip("redeemCollateral(): doesn't affect the Stability Pool deposits or ETH gain of redeemed-from troves", async () => { await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); // B, C, D, F open trove @@ -4094,7 +4100,7 @@ contract("TroveManager", async (accounts) => { assert.equal(dennis_ETHGain_before, dennis_ETHGain_after); }); - it("redeemCollateral(): caller can redeem their entire BoldToken balance", async () => { + it.skip("redeemCollateral(): caller can redeem their entire BoldToken balance", async () => { const { collateral: W_coll, totalDebt: W_totalDebt } = await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale }, @@ -4194,7 +4200,7 @@ contract("TroveManager", async (accounts) => { assert.equal(erin_balance_after, "0"); }); - it("redeemCollateral(): reverts when requested redemption amount exceeds caller's Bold token balance", async () => { + it.skip("redeemCollateral(): reverts when requested redemption amount exceeds caller's Bold token balance", async () => { const { collateral: W_coll, totalDebt: W_totalDebt } = await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale }, @@ -4403,7 +4409,7 @@ contract("TroveManager", async (accounts) => { } }); - it("redeemCollateral(): value of issued ETH == face value of redeemed Bold (assuming 1 Bold has value of $1)", async () => { + it.skip("redeemCollateral(): value of issued ETH == face value of redeemed Bold (assuming 1 Bold has value of $1)", async () => { const { collateral: W_coll } = await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale }, @@ -4560,7 +4566,7 @@ contract("TroveManager", async (accounts) => { // it doesn’t make much sense as there’s now min debt enforced and at least one trove must remain active // the only way to test it is before any trove is opened - it("redeemCollateral(): reverts if there is zero outstanding system debt", async () => { + it.skip("redeemCollateral(): reverts if there is zero outstanding system debt", async () => { // --- SETUP --- illegally mint Bold to Bob await boldToken.unprotectedMint(bob, dec(100, 18)); @@ -4600,7 +4606,7 @@ contract("TroveManager", async (accounts) => { // assert.isFalse(redemptionTx.receipt.status); }); - it("redeemCollateral(): reverts if caller's tries to redeem more than the outstanding system debt", async () => { + it.skip("redeemCollateral(): reverts if caller's tries to redeem more than the outstanding system debt", async () => { // --- SETUP --- illegally mint Bold to Bob await boldToken.unprotectedMint(bob, "101000000000000000000"); @@ -4660,7 +4666,7 @@ contract("TroveManager", async (accounts) => { } }); - it("redeemCollateral(): a redemption sends the ETH remainder (ETHDrawn - gas) to the redeemer", async () => { + it.skip("redeemCollateral(): a redemption sends the ETH remainder (ETHDrawn - gas) to the redeemer", async () => { // time fast-forwards 1 year, and multisig stakes 1 LQTY await th.fastForwardTime( timeValues.SECONDS_IN_ONE_YEAR, @@ -4726,7 +4732,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): a full redemption (leaving trove with 0 debt), closes the trove", async () => { + it.skip("redeemCollateral(): a full redemption (leaving trove with 0 debt), closes the trove", async () => { // time fast-forwards 1 year, and multisig stakes 1 LQTY await th.fastForwardTime( timeValues.SECONDS_IN_ONE_YEAR, @@ -4891,7 +4897,7 @@ contract("TroveManager", async (accounts) => { }; }; - it("redeemCollateral(): emits correct debt and coll values in each redeemed trove's TroveUpdated event", async () => { + it.skip("redeemCollateral(): emits correct debt and coll values in each redeemed trove's TroveUpdated event", async () => { const { netDebt: W_netDebt } = await openTrove({ ICR: toBN(dec(20, 18)), extraBoldAmount: dec(10000, 18), @@ -4982,7 +4988,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): a redemption that closes a trove leaves the trove's ETH surplus (collateral - ETH drawn) available for the trove owner to claim", async () => { + it.skip("redeemCollateral(): a redemption that closes a trove leaves the trove's ETH surplus (collateral - ETH drawn) available for the trove owner to claim", async () => { const { A_netDebt, A_coll, B_netDebt, B_coll, C_netDebt, C_coll } = await redeemCollateral3Full1Partial(); @@ -5030,7 +5036,7 @@ contract("TroveManager", async (accounts) => { ); }); - it("redeemCollateral(): a redemption that closes a trove leaves the trove's ETH surplus (collateral - ETH drawn) available for the trove owner after re-opening trove", async () => { + it.skip("redeemCollateral(): a redemption that closes a trove leaves the trove's ETH surplus (collateral - ETH drawn) available for the trove owner after re-opening trove", async () => { const { A_netDebt, A_coll: A_collBefore, diff --git a/contracts/test/TroveManager_LiquidationRewardsTest.js b/contracts/test/TroveManager_LiquidationRewardsTest.js index 85cd2557..a0e96068 100644 --- a/contracts/test/TroveManager_LiquidationRewardsTest.js +++ b/contracts/test/TroveManager_LiquidationRewardsTest.js @@ -523,7 +523,7 @@ contract( // Bob adds 1 ETH to his trove const addedColl1 = toBN(dec(1, "ether")); - await borrowerOperations.addColl(B, B, { from: B, value: addedColl1 }); + await borrowerOperations.addColl({ from: B, value: addedColl1 }); // Liquidate C const txC = await troveManager.liquidate(C); @@ -566,7 +566,7 @@ contract( // Bob adds 1 ETH to his trove const addedColl2 = toBN(dec(1, "ether")); - await borrowerOperations.addColl(B, B, { from: B, value: addedColl2 }); + await borrowerOperations.addColl({ from: B, value: addedColl2 }); // Liquidate E const txE = await troveManager.liquidate(E); @@ -681,7 +681,7 @@ contract( assert.isAtMost(getDifference(E_expectedPendingETH_1, E_ETHGain_1), 1e8); // // Bob adds 1 ETH to his trove - await borrowerOperations.addColl(B, B, { + await borrowerOperations.addColl( { from: B, value: dec(1, "ether"), }); @@ -733,7 +733,7 @@ contract( assert.isAtMost(getDifference(E_expectedPendingETH_2, E_ETHGain_2), 1e8); // // Bob adds 1 ETH to his trove - await borrowerOperations.addColl(B, B, { + await borrowerOperations.addColl( { from: B, value: dec(1, "ether"), }); @@ -807,7 +807,7 @@ contract( //Bob adds ETH to his trove const addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl({ from: bob, value: addedColl, }); @@ -816,8 +816,6 @@ contract( await borrowerOperations.withdrawBold( th._100pct, await getNetBorrowingAmount(A_totalDebt), - alice, - alice, { from: alice } ); @@ -886,7 +884,7 @@ contract( //Bob adds ETH to his trove const addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl({ from: bob, value: addedColl, }); @@ -1033,7 +1031,7 @@ contract( //Carol adds 1 ETH to her trove, brings it to 1992.01 total coll const C_addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(carol, carol, { + await borrowerOperations.addColl({ from: carol, value: dec(1, "ether"), }); @@ -1201,15 +1199,15 @@ contract( bringing them to 2.995, 2.995, 1992.01 total coll each. */ const addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl( { from: alice, value: addedColl, }); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl( { from: bob, value: addedColl, }); - await borrowerOperations.addColl(carol, carol, { + await borrowerOperations.addColl({ from: carol, value: addedColl, }); @@ -1346,7 +1344,7 @@ contract( //Bob withdraws 0.5 ETH from his trove const withdrawnColl = toBN(dec(500, "finney")); - await borrowerOperations.withdrawColl(withdrawnColl, bob, bob, { + await borrowerOperations.withdrawColl(withdrawnColl, { from: bob, }); @@ -1354,8 +1352,6 @@ contract( await borrowerOperations.withdrawBold( th._100pct, await getNetBorrowingAmount(A_totalDebt), - alice, - alice, { from: alice } ); @@ -1428,7 +1424,7 @@ contract( //Bob withdraws 0.5 ETH from his trove const withdrawnColl = toBN(dec(500, "finney")); - await borrowerOperations.withdrawColl(withdrawnColl, bob, bob, { + await borrowerOperations.withdrawColl(withdrawnColl, { from: bob, }); @@ -1595,7 +1591,7 @@ contract( //Carol wthdraws 1 ETH from her trove, brings it to 1990.01 total coll const C_withdrawnColl = toBN(dec(1, "ether")); - await borrowerOperations.withdrawColl(C_withdrawnColl, carol, carol, { + await borrowerOperations.withdrawColl(C_withdrawnColl, { from: carol, }); @@ -1758,13 +1754,13 @@ contract( /* Alice, Bob, Carol each withdraw 0.5 ETH to their troves, bringing them to 1.495, 1.495, 1990.51 total coll each. */ const withdrawnColl = toBN(dec(500, "finney")); - await borrowerOperations.withdrawColl(withdrawnColl, alice, alice, { + await borrowerOperations.withdrawColl(withdrawnColl, { from: alice, }); - await borrowerOperations.withdrawColl(withdrawnColl, bob, bob, { + await borrowerOperations.withdrawColl(withdrawnColl, { from: bob, }); - await borrowerOperations.withdrawColl(withdrawnColl, carol, carol, { + await borrowerOperations.withdrawColl(withdrawnColl, { from: carol, }); @@ -1983,14 +1979,14 @@ contract( //Bob adds 1 ETH to his trove const B_addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl( { from: bob, value: B_addedColl, }); //Carol withdraws 1 ETH from her trove const C_withdrawnColl = toBN(dec(1, "ether")); - await borrowerOperations.withdrawColl(C_withdrawnColl, carol, carol, { + await borrowerOperations.withdrawColl(C_withdrawnColl, { from: carol, }); @@ -2077,7 +2073,7 @@ contract( // D tops up const D_addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(dennis, dennis, { + await borrowerOperations.addColl({ from: dennis, value: D_addedColl, }); @@ -2274,14 +2270,14 @@ contract( // Bob adds 11.33909 ETH to his trove const B_addedColl = toBN("11339090000000000000"); - await borrowerOperations.addColl(bob, bob, { + await borrowerOperations.addColl( { from: bob, value: B_addedColl, }); // Carol withdraws 15 ETH from her trove const C_withdrawnColl = toBN(dec(15, "ether")); - await borrowerOperations.withdrawColl(C_withdrawnColl, carol, carol, { + await borrowerOperations.withdrawColl(C_withdrawnColl, { from: carol, }); @@ -2370,7 +2366,7 @@ contract( // D tops up const D_addedColl = toBN(dec(1, "ether")); - await borrowerOperations.addColl(dennis, dennis, { + await borrowerOperations.addColl({ from: dennis, value: D_addedColl, }); diff --git a/contracts/test/TroveManager_RecoveryModeTest.js b/contracts/test/TroveManager_RecoveryModeTest.js index 93dc9adf..a174d4b1 100644 --- a/contracts/test/TroveManager_RecoveryModeTest.js +++ b/contracts/test/TroveManager_RecoveryModeTest.js @@ -139,7 +139,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { const recoveryMode_Before = await th.checkRecoveryMode(contracts); assert.isTrue(recoveryMode_Before); - await borrowerOperations.addColl(alice, alice, { from: alice, value: "1" }); + await borrowerOperations.addColl({ from: alice, value: "1" }); const recoveryMode_After = await th.checkRecoveryMode(contracts); assert.isTrue(recoveryMode_After); @@ -154,9 +154,9 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { const recoveryMode_Before = await th.checkRecoveryMode(contracts); assert.isFalse(recoveryMode_Before); - await borrowerOperations.withdrawColl(_1_Ether, alice, alice, { + await borrowerOperations.withdrawColl(_1_Ether, { from: alice, - }); + }); const recoveryMode_After = await th.checkRecoveryMode(contracts); assert.isFalse(recoveryMode_After); @@ -180,7 +180,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { const recoveryMode_Before = await th.checkRecoveryMode(contracts); assert.isTrue(recoveryMode_Before); - await borrowerOperations.addColl(alice, alice, { + await borrowerOperations.addColl({ from: alice, value: A_coll, }); @@ -1663,8 +1663,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { const bob_Coll_Before = (await troveManager.Troves(bob))[1]; const bob_Debt_Before = (await troveManager.Troves(bob))[0]; - // confirm Bob is last trove in list, and has >110% ICR - assert.equal((await sortedTroves.getLast()).toString(), bob); + // confirm Bob has >110% ICR assert.isTrue((await troveManager.getCurrentICR(bob, price)).gt(mv._MCR)); // L1: Try to liquidate Bob. Nothing happens @@ -1712,8 +1711,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { const carol_Coll_Before = (await troveManager.Troves(carol))[1]; const carol_Debt_Before = (await troveManager.Troves(carol))[0]; - // Confirm Carol is last trove in list, and has >110% ICR - assert.equal(await sortedTroves.getLast(), carol); + // Confirm Carol has >110% ICR assert.isTrue((await troveManager.getCurrentICR(carol, price)).gt(mv._MCR)); // L2: Try to liquidate Carol. Nothing happens @@ -2216,19 +2214,20 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal((await boldToken.balanceOf(carol)).toString(), C_boldAmount); }); - it("liquidate(), with 110% < ICR < TCR, can claim collateral, re-open, be reedemed and claim again", async () => { + // TODO: test relies on specific redemption behavior, so rewrite in Solidity after we've finalized new redemption logic + it.skip("liquidate(), with 110% < ICR < TCR, can claim collateral, re-open, be reedemed and claim again", async () => { // --- SETUP --- // Alice withdraws up to 1500 Bold of debt, resulting in ICRs of 266%. - // Bob withdraws up to 480 Bold of debt, resulting in ICR of 240%. Bob has lowest ICR. + // Bob withdraws up to 480 Bold of debt, resulting in ICR of 240%. Bob has lowest interest rate. const { collateral: B_coll, totalDebt: B_totalDebt } = await openTrove({ ICR: toBN(dec(240, 16)), extraBoldAmount: dec(480, 18), - extraParams: { from: bob }, + extraParams: { from: bob, annualInterestRate: 0 }, }); const { collateral: A_coll } = await openTrove({ ICR: toBN(dec(266, 16)), extraBoldAmount: B_totalDebt, - extraParams: { from: alice }, + extraParams: { from: alice }, annualInterestRate: th.toBN(dec(5,17)) // 50% interest rate }); // Alice deposits Bold in the Stability Pool @@ -2281,18 +2280,18 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { web3.currentProvider ); - // Bob re-opens the trove, price 200, total debt 80 Bold, ICR = 120% (lowest one) + // Bob re-opens the trove, price 200, total debt 80 Bold, ICR = 120%, 0 interest rate (lowest one) // Dennis redeems 30, so Bob has a surplus of (200 * 0.48 - 30) / 200 = 0.33 ETH await priceFeed.setPrice("200000000000000000000"); const { collateral: B_coll_2, netDebt: B_netDebt_2 } = await openTrove({ ICR: toBN(dec(150, 16)), extraBoldAmount: dec(480, 18), - extraParams: { from: bob, value: bob_remainingCollateral }, + extraParams: { from: bob, value: bob_remainingCollateral, annualInterestRate: 0} }); const { collateral: D_coll } = await openTrove({ ICR: toBN(dec(266, 16)), extraBoldAmount: B_netDebt_2, - extraParams: { from: dennis }, + extraParams: { from: dennis }, annualInterestRate: th.toBN(dec(5,17)) }); await th.redeemCollateral(dennis, contracts, B_netDebt_2, GAS_PRICE); price = await priceFeed.getPrice(); @@ -2428,7 +2427,9 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { // --- liquidateTroves --- - it("liquidateTroves(): With all ICRs > 110%, Liquidates Troves until system leaves recovery mode", async () => { + // TODO: delete these tests when we delete liquidateTroves(), since we no will no longer liquidate sequentially + + it.skip("liquidateTroves(): With all ICRs > 110%, Liquidates Troves until system leaves recovery mode", async () => { // make 8 Troves accordingly // --- SETUP --- @@ -2577,7 +2578,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isFalse(await sortedTroves.contains(harry)); }); - it("liquidateTroves(): Liquidates Troves until 1) system has left recovery mode AND 2) it reaches a Trove with ICR >= 110%", async () => { + it.skip("liquidateTroves(): Liquidates Troves until 1) system has left recovery mode AND 2) it reaches a Trove with ICR >= 110%", async () => { // make 6 Troves accordingly // --- SETUP --- const { totalDebt: B_totalDebt } = await openTrove({ @@ -2702,7 +2703,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isFalse(await sortedTroves.contains(freddy)); }); - it("liquidateTroves(): liquidates only up to the requested number of undercollateralized troves", async () => { + it.skip("liquidateTroves(): liquidates only up to the requested number of undercollateralized troves", async () => { await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: whale, value: dec(300, "ether") }, @@ -2777,7 +2778,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isTrue(erin_isInSortedList); }); - it("liquidateTroves(): does nothing if n = 0", async () => { + it.skip("liquidateTroves(): does nothing if n = 0", async () => { await openTrove({ ICR: toBN(dec(200, 16)), extraBoldAmount: dec(100, 18), @@ -2827,7 +2828,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal(TCR_Before, TCR_After); }); - it("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { + it.skip("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { // --- SETUP --- await openTrove({ ICR: toBN(dec(300, 16)), @@ -2895,7 +2896,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal((await troveManager.Troves(freddy))[3].toString(), "3"); }); - it("liquidateTroves(): a liquidation sequence containing Pool offsets increases the TCR", async () => { + it.skip("liquidateTroves(): a liquidation sequence containing Pool offsets increases the TCR", async () => { // Whale provides 500 Bold to SP await openTrove({ ICR: toBN(dec(200, 16)), @@ -2979,7 +2980,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isTrue(TCR_After.gte(TCR_Before)); }); - it("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { + it.skip("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { const { collateral: W_coll, totalDebt: W_totalDebt } = await openTrove({ ICR: toBN(dec(250, 16)), extraBoldAmount: dec(500, 18), @@ -3097,7 +3098,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { + it.skip("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { await openTrove({ ICR: toBN(dec(400, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(220, 16)), extraParams: { from: bob } }); await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); @@ -3171,7 +3172,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); }); - it("liquidateTroves(): does nothing if all troves have ICR > 110% and Stability Pool is empty", async () => { + it.skip("liquidateTroves(): does nothing if all troves have ICR > 110% and Stability Pool is empty", async () => { await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: alice } }); await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: bob } }); await openTrove({ ICR: toBN(dec(285, 16)), extraParams: { from: carol } }); @@ -3219,7 +3220,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal(listSize_Before, listSize_After); }); - it("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves", async () => { + it.skip("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves", async () => { // Troves to be absorbed by SP const { collateral: F_coll, totalDebt: F_totalDebt } = await openTrove({ ICR: toBN(dec(222, 16)), @@ -3350,7 +3351,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves, including a partial", async () => { + it.skip("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves, including a partial", async () => { // Troves to be absorbed by SP const { collateral: F_coll, totalDebt: F_totalDebt } = await openTrove({ ICR: toBN(dec(222, 16)), @@ -3508,7 +3509,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves(): does not affect the liquidated user's token balances", async () => { + it.skip("liquidateTroves(): does not affect the liquidated user's token balances", async () => { await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: whale } }); // D, E, F open troves that will fall below MCR when price drops to 100 @@ -3556,7 +3557,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal((await boldToken.balanceOf(freddy)).toString(), boldAmountF); }); - it("liquidateTroves(): Liquidating troves at 100 < ICR < 110 with SP deposits correctly impacts their SP deposit and ETH gain", async () => { + it.skip("liquidateTroves(): Liquidating troves at 100 < ICR < 110 with SP deposits correctly impacts their SP deposit and ETH gain", async () => { // Whale provides Bold to the SP const { boldAmount: W_boldAmount } = await openTrove({ ICR: toBN(dec(300, 16)), @@ -3756,7 +3757,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves(): Liquidating troves at ICR <=100% with SP deposits does not alter their deposit or ETH gain", async () => { + it.skip("liquidateTroves(): Liquidating troves at ICR <=100% with SP deposits does not alter their deposit or ETH gain", async () => { // Whale provides 400 Bold to the SP await openTrove({ ICR: toBN(dec(300, 16)), @@ -3862,7 +3863,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal(bob_ETHGain_After, "0"); }); - it("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains active", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains active", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(196, 16)), extraParams: { from: alice }, @@ -3920,7 +3921,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal((await troveManager.Troves(carol))[3].toString(), "1"); // check Status is active }); - it("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains in TroveOwners Array", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains in TroveOwners Array", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: alice }, @@ -3989,7 +3990,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.equal(addressIdx.toString(), idxOnStruct); }); - it("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, emptied pool", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, emptied pool", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(196, 16)), extraParams: { from: alice }, @@ -4059,7 +4060,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isTrue(await sortedTroves.contains(erin)); }); - it("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, non emptied pool", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, non emptied pool", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(196, 16)), extraParams: { from: alice }, @@ -4130,7 +4131,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { assert.isTrue(await sortedTroves.contains(erin)); }); - it("liquidateTroves() with a non fullfilled liquidation: total liquidated coll and debt is correct", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: total liquidated coll and debt is correct", async () => { const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(196, 16)), extraParams: { from: alice }, @@ -4200,7 +4201,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves() with a non fullfilled liquidation: emits correct liquidation event values", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: emits correct liquidation event values", async () => { const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: alice }, @@ -4314,7 +4315,7 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - it("liquidateTroves() with a non fullfilled liquidation: ICR of non liquidated trove does not change", async () => { + it.skip("liquidateTroves() with a non fullfilled liquidation: ICR of non liquidated trove does not change", async () => { const { totalDebt: A_totalDebt } = await openTrove({ ICR: toBN(dec(196, 16)), extraParams: { from: alice }, diff --git a/contracts/test/stakeDeclineTest.js b/contracts/test/stakeDeclineTest.js index fa1ab383..41c70221 100644 --- a/contracts/test/stakeDeclineTest.js +++ b/contracts/test/stakeDeclineTest.js @@ -79,6 +79,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(1, 31)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: A, value: dec(2, 29) } ); @@ -88,6 +89,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(2, 30)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: B, value: dec(4, 28) } ); await borrowerOperations.openTrove( @@ -95,6 +97,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(2, 30)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: C, value: dec(4, 28) } ); await borrowerOperations.openTrove( @@ -102,6 +105,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(2, 30)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: D, value: dec(4, 28) } ); await borrowerOperations.openTrove( @@ -109,6 +113,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(2, 30)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: E, value: dec(4, 28) } ); await borrowerOperations.openTrove( @@ -116,6 +121,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(2, 30)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: F, value: dec(4, 28) } ); @@ -127,6 +133,7 @@ contract("TroveManager", async (accounts) => { await getOpenTroveBoldAmount(dec(1, 22)), ZERO_ADDRESS, ZERO_ADDRESS, + 0, { from: account, value: dec(2, 20) } ); } @@ -158,8 +165,6 @@ contract("TroveManager", async (accounts) => { 0, 1, false, - ZERO_ADDRESS, - ZERO_ADDRESS, { from: B } ); // B repays 1 wei console.log(`B stake after A1: ${(await troveManager.Troves(B))[2]}`); @@ -181,8 +186,6 @@ contract("TroveManager", async (accounts) => { 0, 1, false, - ZERO_ADDRESS, - ZERO_ADDRESS, { from: B } ); // A repays 1 wei console.log( diff --git a/contracts/utils/testHelpers.js b/contracts/utils/testHelpers.js index 42e36db3..05f5ee20 100644 --- a/contracts/utils/testHelpers.js +++ b/contracts/utils/testHelpers.js @@ -851,7 +851,7 @@ class TestHelper { extraBoldAmount = this.toBN(extraBoldAmount); if (!upperHint) upperHint = this.ZERO_ADDRESS; if (!lowerHint) lowerHint = this.ZERO_ADDRESS; - + if (!extraParams.annualInterestRate) extraParams.annualInterestRate = 0; const MIN_DEBT = ( await this.getNetBorrowingAmount( @@ -885,6 +885,7 @@ class TestHelper { //extraParams.value, // TODO: this is the stETH value - ensure its still working upperHint, lowerHint, + extraParams.annualInterestRate, { from: extraParams.from, value: extraParams.value, @@ -903,11 +904,9 @@ class TestHelper { static async withdrawBold( contracts, - { maxFeePercentage, boldAmount, ICR, upperHint, lowerHint, extraParams } + { maxFeePercentage, boldAmount, ICR, extraParams } ) { if (!maxFeePercentage) maxFeePercentage = this._100pct; - if (!upperHint) upperHint = this.ZERO_ADDRESS; - if (!lowerHint) lowerHint = this.ZERO_ADDRESS; assert( !(boldAmount && ICR) && (boldAmount || ICR), @@ -941,8 +940,6 @@ class TestHelper { await contracts.borrowerOperations.withdrawBold( maxFeePercentage, boldAmount, - upperHint, - lowerHint, extraParams ); From b62169ac7124e8bf9bc6a2ca8f1f171fe49904f9 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Sun, 4 Feb 2024 11:28:12 +0700 Subject: [PATCH 4/9] Remove redundant borrow fee getters --- contracts/src/Interfaces/ITroveManager.sol | 8 - contracts/src/TroveManager.sol | 43 ----- contracts/test/BorrowerOperationsTest.js | 4 +- contracts/test/FeeArithmeticTest.js | 202 --------------------- contracts/utils/testHelpers.js | 12 +- 5 files changed, 4 insertions(+), 265 deletions(-) diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index 8c22dde5..033dcaf4 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -79,14 +79,6 @@ interface ITroveManager is ILiquityBase { function getRedemptionFeeWithDecay(uint _ETHDrawn) external view returns (uint); - function getBorrowingRate() external view returns (uint); - function getBorrowingRateWithDecay() external view returns (uint); - - function getBorrowingFee(uint BoldDebt) external view returns (uint); - function getBorrowingFeeWithDecay(uint _boldDebt) external view returns (uint); - - function decayBaseRateFromBorrowing() external; - function getTroveStatus(address _borrower) external view returns (uint); function getTroveStake(address _borrower) external view returns (uint); diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 94d35dd5..d81ac368 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -1386,49 +1386,6 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { // return redemptionFee; } - // --- Borrowing fee functions --- - - function getBorrowingRate() public view override returns (uint) { - return _calcBorrowingRate(baseRate); - } - - function getBorrowingRateWithDecay() public view override returns (uint) { - return _calcBorrowingRate(_calcDecayedBaseRate()); - } - - function _calcBorrowingRate(uint _baseRate) internal pure returns (uint) { - return 0; - // return LiquityMath._min( - // BORROWING_FEE_FLOOR + _baseRate, - // MAX_BORROWING_FEE - // ); - } - - function getBorrowingFee(uint _boldDebt) external view override returns (uint) { - return _calcBorrowingFee(getBorrowingRate(), _boldDebt); - } - - function getBorrowingFeeWithDecay(uint _boldDebt) external view override returns (uint) { - return _calcBorrowingFee(getBorrowingRateWithDecay(), _boldDebt); - } - - function _calcBorrowingFee(uint _borrowingRate, uint _boldDebt) internal pure returns (uint) { - return _borrowingRate * _boldDebt / DECIMAL_PRECISION; - } - - // Updates the baseRate state variable based on time elapsed since the last redemption or Bold borrowing operation. - function decayBaseRateFromBorrowing() external override { - _requireCallerIsBorrowerOperations(); - - uint decayedBaseRate = _calcDecayedBaseRate(); - assert(decayedBaseRate <= DECIMAL_PRECISION); // The baseRate can decay to 0 - - baseRate = decayedBaseRate; - emit BaseRateUpdated(decayedBaseRate); - - _updateLastFeeOpTime(); - } - // --- Internal fee functions --- // Update the last fee operation time only if time passed >= decay interval. This prevents base rate griefing. diff --git a/contracts/test/BorrowerOperationsTest.js b/contracts/test/BorrowerOperationsTest.js index 8231ab56..f49e5fd3 100644 --- a/contracts/test/BorrowerOperationsTest.js +++ b/contracts/test/BorrowerOperationsTest.js @@ -3859,9 +3859,7 @@ contract("BorrowerOperations", async (accounts) => { }); // Get the expected debt based on the Bold request (adding fee and liq. reserve on top) - const expectedDebt = BoldRequest.add( - await troveManager.getBorrowingFee(BoldRequest) - ).add(BOLD_GAS_COMPENSATION); + const expectedDebt = BoldRequest.add(BOLD_GAS_COMPENSATION); const debt_After = await getTroveEntireDebt(alice); const coll_After = await getTroveEntireColl(alice); diff --git a/contracts/test/FeeArithmeticTest.js b/contracts/test/FeeArithmeticTest.js index 18b56c85..8b7f7528 100644 --- a/contracts/test/FeeArithmeticTest.js +++ b/contracts/test/FeeArithmeticTest.js @@ -365,208 +365,6 @@ contract('Fee arithmetic tests', async accounts => { } }) - it("decayBaseRateFromBorrowing(): returns the initial base rate for no time increase", async () => { - await troveManagerTester.setBaseRate(dec(5, 17)) - await troveManagerTester.setLastFeeOpTimeToNow() - - const baseRateBefore = await troveManagerTester.baseRate() - assert.equal(baseRateBefore, dec(5, 17)) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const baseRateAfter = await troveManagerTester.baseRate() - - assert.isTrue(baseRateBefore.eq(baseRateAfter)) - }) - - it("decayBaseRateFromBorrowing(): returns the initial base rate for less than one minute passed ", async () => { - await troveManagerTester.setBaseRate(dec(5, 17)) - await troveManagerTester.setLastFeeOpTimeToNow() - - // 1 second - const baseRateBefore_1 = await troveManagerTester.baseRate() - assert.equal(baseRateBefore_1, dec(5, 17)) - - await th.fastForwardTime(1, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const baseRateAfter_1 = await troveManagerTester.baseRate() - - assert.isTrue(baseRateBefore_1.eq(baseRateAfter_1)) - - // 17 seconds - await troveManagerTester.setLastFeeOpTimeToNow() - - const baseRateBefore_2 = await troveManagerTester.baseRate() - await th.fastForwardTime(17, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const baseRateAfter_2 = await troveManagerTester.baseRate() - - assert.isTrue(baseRateBefore_2.eq(baseRateAfter_2)) - - // 29 seconds - await troveManagerTester.setLastFeeOpTimeToNow() - - const baseRateBefore_3 = await troveManagerTester.baseRate() - await th.fastForwardTime(29, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const baseRateAfter_3 = await troveManagerTester.baseRate() - - assert.isTrue(baseRateBefore_3.eq(baseRateAfter_3)) - - // 50 seconds - await troveManagerTester.setLastFeeOpTimeToNow() - - const baseRateBefore_4 = await troveManagerTester.baseRate() - await th.fastForwardTime(50, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const baseRateAfter_4 = await troveManagerTester.baseRate() - - assert.isTrue(baseRateBefore_4.eq(baseRateAfter_4)) - - // (cant quite test up to 59 seconds, as execution of the final tx takes >1 second before the block is mined) - }) - - it("decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.01", async () => { - // baseRate = 0.01 - for (i = 0; i < decayBaseRateResults.seconds.length; i++) { - // Set base rate to 0.01 in TroveManager - await troveManagerTester.setBaseRate(dec(1, 16)) - const contractBaseRate = await troveManagerTester.baseRate() - assert.equal(contractBaseRate, dec(1, 16)) - - const startBaseRate = '0.01' - - const secondsPassed = decayBaseRateResults.seconds[i] - const expectedDecayedBaseRate = decayBaseRateResults[startBaseRate][i] - await troveManagerTester.setLastFeeOpTimeToNow() - - // Progress time - await th.fastForwardTime(secondsPassed, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const decayedBaseRate = await troveManagerTester.baseRate() - - const minutesPassed = secondsPassed / 60 - - const error = decayedBaseRate.sub(toBN(expectedDecayedBaseRate)) - // console.log( - // `starting baseRate: ${startBaseRate}, - // minutesPassed: ${minutesPassed}, - // expectedDecayedBaseRate: ${expectedDecayedBaseRate}, - // decayedBaseRate: ${decayedBaseRate}, - // error: ${error}` - // ) - assert.isAtMost(getDifference(expectedDecayedBaseRate.toString(), decayedBaseRate.toString()), 100000) // allow absolute error tolerance of 1e-13 - } - }) - - it("decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.1", async () => { - // baseRate = 0.1 - for (i = 0; i < decayBaseRateResults.seconds.length; i++) { - // Set base rate to 0.1 in TroveManager - await troveManagerTester.setBaseRate(dec(1, 17)) - const contractBaseRate = await troveManagerTester.baseRate() - assert.equal(contractBaseRate, dec(1, 17)) - - const startBaseRate = '0.1' - - const secondsPassed = decayBaseRateResults.seconds[i] - const expectedDecayedBaseRate = decayBaseRateResults['0.1'][i] - await troveManagerTester.setLastFeeOpTimeToNow() - - // Progress time - await th.fastForwardTime(secondsPassed, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const decayedBaseRate = await troveManagerTester.baseRate() - - const minutesPassed = secondsPassed / 60 - - const error = decayedBaseRate.sub(toBN(expectedDecayedBaseRate)) - // console.log( - // `starting baseRate: ${startBaseRate}, - // minutesPassed: ${minutesPassed}, - // expectedDecayedBaseRate: ${expectedDecayedBaseRate}, - // decayedBaseRate: ${decayedBaseRate}, - // error: ${error}` - // ) - assert.isAtMost(getDifference(expectedDecayedBaseRate.toString(), decayedBaseRate.toString()), 1000000) // allow absolute error tolerance of 1e-12 - } - }) - - it("decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.34539284", async () => { - // baseRate = 0.34539284 - for (i = 0; i < decayBaseRateResults.seconds.length; i++) { - // Set base rate to 0.1 in TroveManager - await troveManagerTester.setBaseRate('345392840000000000') - const contractBaseRate = await troveManagerTester.baseRate() - await troveManagerTester.setBaseRate('345392840000000000') - - const startBaseRate = '0.34539284' - - const secondsPassed = decayBaseRateResults.seconds[i] - const expectedDecayedBaseRate = decayBaseRateResults[startBaseRate][i] - await troveManagerTester.setLastFeeOpTimeToNow() - - // Progress time - await th.fastForwardTime(secondsPassed, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const decayedBaseRate = await troveManagerTester.baseRate() - - const minutesPassed = secondsPassed / 60 - - const error = decayedBaseRate.sub(toBN(expectedDecayedBaseRate)) - // console.log( - // `starting baseRate: ${startBaseRate}, - // minutesPassed: ${minutesPassed}, - // expectedDecayedBaseRate: ${expectedDecayedBaseRate}, - // decayedBaseRate: ${decayedBaseRate}, - // error: ${error}` - // ) - - assert.isAtMost(getDifference(expectedDecayedBaseRate.toString(), decayedBaseRate.toString()), 1000000) // allow absolute error tolerance of 1e-12 - } - }) - - it("decayBaseRateFromBorrowing(): returns correctly decayed base rate, for various durations. Initial baseRate = 0.9976", async () => { - // baseRate = 0.9976 - for (i = 0; i < decayBaseRateResults.seconds.length; i++) { - // Set base rate to 0.9976 in TroveManager - await troveManagerTester.setBaseRate('997600000000000000') - await troveManagerTester.setBaseRate('997600000000000000') - - const startBaseRate = '0.9976' - - const secondsPassed = decayBaseRateResults.seconds[i] - const expectedDecayedBaseRate = decayBaseRateResults[startBaseRate][i] - await troveManagerTester.setLastFeeOpTimeToNow() - - // progress time - await th.fastForwardTime(secondsPassed, web3.currentProvider) - - await troveManagerTester.unprotectedDecayBaseRateFromBorrowing() - const decayedBaseRate = await troveManagerTester.baseRate() - - const minutesPassed = secondsPassed / 60 - - const error = decayedBaseRate.sub(toBN(expectedDecayedBaseRate)) - - // console.log( - // `starting baseRate: ${startBaseRate}, - // minutesPassed: ${minutesPassed}, - // expectedDecayedBaseRate: ${expectedDecayedBaseRate}, - // decayedBaseRate: ${decayedBaseRate}, - // error: ${error}` - // ) - - assert.isAtMost(getDifference(expectedDecayedBaseRate.toString(), decayedBaseRate.toString()), 10000000) // allow absolute error tolerance of 1e-11 - } - }) - // --- Exponentiation tests --- describe('Basic exponentiation', async accounts => { diff --git a/contracts/utils/testHelpers.js b/contracts/utils/testHelpers.js index 05f5ee20..920198b7 100644 --- a/contracts/utils/testHelpers.js +++ b/contracts/utils/testHelpers.js @@ -336,7 +336,7 @@ class TestHelper { * So, it adds the gas compensation and the borrowing fee */ static async getOpenTroveTotalDebt(contracts, boldAmount) { - const fee = await contracts.troveManager.getBorrowingFee(boldAmount); + const fee = this.toBN(0); const compositeDebt = await this.getCompositeDebt(contracts, boldAmount); return compositeDebt.add(fee); } @@ -355,18 +355,12 @@ class TestHelper { // Subtracts the borrowing fee static async getNetBorrowingAmount(contracts, debtWithFee) { - const borrowingRate = - await contracts.troveManager.getBorrowingRateWithDecay(); - - return this.toBN(debtWithFee) - .mul(MoneyValues._1e18BN) - .div(MoneyValues._1e18BN.add(borrowingRate)); + return this.toBN(debtWithFee); } // Adds the borrowing fee static async getAmountWithBorrowingFee(contracts, boldAmount) { - const fee = await contracts.troveManager.getBorrowingFee(boldAmount); - return boldAmount.add(fee); + return boldAmount; } // Adds the redemption fee From 9fe10da2931e9035d18a65d991afdff8c5c74d2f Mon Sep 17 00:00:00 2001 From: RickGriff Date: Sun, 4 Feb 2024 23:32:36 +0700 Subject: [PATCH 5/9] Remove liquidateTroves functionality + tests --- contracts/src/Interfaces/ITroveManager.sol | 2 - contracts/src/TroveManager.sol | 54 +- contracts/test/GasCompensationTest.js | 464 ---- contracts/test/TroveManagerTest.js | 845 ------- .../test/TroveManager_RecoveryModeTest.js | 1945 ----------------- ...ager_RecoveryMode_Batch_Liqudation_Test.js | 72 - 6 files changed, 1 insertion(+), 3381 deletions(-) diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index 033dcaf4..9a346e91 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -37,8 +37,6 @@ interface ITroveManager is ILiquityBase { function liquidate(address _borrower) external; - function liquidateTroves(uint _n) external; - function batchLiquidateTroves(address[] calldata _troveArray) external; function redeemCollateral( diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index d81ac368..758ffebf 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -473,59 +473,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { singleLiquidation.debtToRedistribute = 0; singleLiquidation.collToRedistribute = 0; } - - /* - * Liquidate a sequence of troves. Closes a maximum number of n under-collateralized Troves, - * starting from the one with the lowest collateral ratio in the system, and moving upwards - */ - // TODO: remove this liquidation function, since with ordering by interest rate, it is now redundant: there's no guarantee - // the bottom of the list has Troves with CR < MCR. - function liquidateTroves(uint _n) external override { - ContractsCache memory contractsCache = ContractsCache( - activePool, - defaultPool, - IBoldToken(address(0)), - sortedTroves, - ICollSurplusPool(address(0)), - address(0) - ); - IStabilityPool stabilityPoolCached = stabilityPool; - - LocalVariables_OuterLiquidationFunction memory vars; - - LiquidationTotals memory totals; - - vars.price = priceFeed.fetchPrice(); - vars.boldInStabPool = stabilityPoolCached.getTotalBoldDeposits(); - vars.recoveryModeAtStart = _checkRecoveryMode(vars.price); - - // Perform the appropriate liquidation sequence - tally the values, and obtain their totals - if (vars.recoveryModeAtStart) { - totals = _getTotalsFromLiquidateTrovesSequence_RecoveryMode(contractsCache, vars.price, vars.boldInStabPool, _n); - } else { // if !vars.recoveryModeAtStart - totals = _getTotalsFromLiquidateTrovesSequence_NormalMode(contractsCache.activePool, contractsCache.defaultPool, vars.price, vars.boldInStabPool, _n); - } - - require(totals.totalDebtInSequence > 0, "TroveManager: nothing to liquidate"); - - // Move liquidated ETH and Bold to the appropriate pools - stabilityPoolCached.offset(totals.totalDebtToOffset, totals.totalCollToSendToSP); - _redistributeDebtAndColl(contractsCache.activePool, contractsCache.defaultPool, totals.totalDebtToRedistribute, totals.totalCollToRedistribute); - if (totals.totalCollSurplus > 0) { - contractsCache.activePool.sendETH(address(collSurplusPool), totals.totalCollSurplus); - } - - // Update system snapshots - _updateSystemSnapshots_excludeCollRemainder(contractsCache.activePool, totals.totalCollGasCompensation); - - vars.liquidatedDebt = totals.totalDebtInSequence; - vars.liquidatedColl = totals.totalCollInSequence - totals.totalCollGasCompensation - totals.totalCollSurplus; - emit Liquidation(vars.liquidatedDebt, vars.liquidatedColl, totals.totalCollGasCompensation, totals.totalBoldGasCompensation); - - // Send gas compensation to caller - _sendGasCompensation(contractsCache.activePool, msg.sender, totals.totalBoldGasCompensation, totals.totalCollGasCompensation); - } - + /* * This function is used when the liquidateTroves sequence starts during Recovery Mode. However, it * handle the case where the system *leaves* Recovery Mode, part way through the liquidation sequence diff --git a/contracts/test/GasCompensationTest.js b/contracts/test/GasCompensationTest.js index da5dca5a..d44ad4c5 100644 --- a/contracts/test/GasCompensationTest.js +++ b/contracts/test/GasCompensationTest.js @@ -1282,470 +1282,6 @@ contract("Gas compensation tests", async (accounts) => { assert.isAtMost(th.getDifference(expectedGasComp_B, loggedGasComp_B), 1000); }); - // liquidateTroves - full offset - it.skip("liquidateTroves(): full offset. Compensates the correct amount, and liquidates the remainder", async () => { - await priceFeed.setPrice(dec(1000, 18)); - - await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); - - // A-F open troves - await openTrove({ - ICR: toBN(dec(118, 16)), - extraBoldAmount: dec(2000, 18), - extraParams: { from: alice }, - }); - await openTrove({ - ICR: toBN(dec(526, 16)), - extraBoldAmount: dec(8000, 18), - extraParams: { from: bob }, - }); - await openTrove({ - ICR: toBN(dec(488, 16)), - extraBoldAmount: dec(600, 18), - extraParams: { from: carol }, - }); - await openTrove({ - ICR: toBN(dec(545, 16)), - extraBoldAmount: dec(1, 23), - extraParams: { from: dennis }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: erin }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: flyn }, - }); - - // D, E each provide 10000 Bold to SP - await stabilityPool.provideToSP(dec(1, 23), { from: erin }); - await stabilityPool.provideToSP(dec(1, 23), { from: flyn }); - - const BoldinSP_0 = await stabilityPool.getTotalBoldDeposits(); - - // price drops to 200 - await priceFeed.setPrice(dec(200, 18)); - const price = await priceFeed.getPrice(); - - // Check not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D have ICR < MCR - assert.isTrue((await troveManager.getCurrentICR(alice, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(carol, price)).lt(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(dennis, price)).lt(mv._MCR) - ); - - // Check E, F have ICR > MCR - assert.isTrue((await troveManager.getCurrentICR(erin, price)).gt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(flyn, price)).gt(mv._MCR)); - - // --- Check value of of A's collateral is < $10, and value of B,C,D collateral are > $10 --- - const aliceColl = (await troveManager.Troves(alice))[1]; - const bobColl = (await troveManager.Troves(bob))[1]; - const carolColl = (await troveManager.Troves(carol))[1]; - const dennisColl = (await troveManager.Troves(dennis))[1]; - - // --- Check value of 0.5% of A, B, and C's collateral is <$10, and value of 0.5% of D's collateral is > $10 --- - const _0pt5percent_aliceColl = aliceColl.div(web3.utils.toBN("200")); - const _0pt5percent_bobColl = bobColl.div(web3.utils.toBN("200")); - const _0pt5percent_carolColl = carolColl.div(web3.utils.toBN("200")); - const _0pt5percent_dennisColl = dennisColl.div(web3.utils.toBN("200")); - - const collGasCompensation = await troveManagerTester.getCollGasCompensation( - price - ); - assert.equal(collGasCompensation, dec(1, 18)); - - /* Expect total gas compensation = - 0.5% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedGasComp = _0pt5percent_aliceColl - .add(_0pt5percent_bobColl) - .add(_0pt5percent_carolColl) - .add(_0pt5percent_dennisColl); - - /* Expect liquidated coll = - 0.95% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedLiquidatedColl = aliceColl - .sub(_0pt5percent_aliceColl) - .add(bobColl.sub(_0pt5percent_bobColl)) - .add(carolColl.sub(_0pt5percent_carolColl)) - .add(dennisColl.sub(_0pt5percent_dennisColl)); - - // Liquidate troves A-D - - const liquidatorBalance_before = web3.utils.toBN( - await web3.eth.getBalance(liquidator) - ); - const GAS_Used_Liquidator = th.gasUsed( - await troveManager.liquidateTroves(4, { - from: liquidator, - gasPrice: GAS_PRICE, - }) - ); - const liquidatorBalance_after = web3.utils.toBN( - await web3.eth.getBalance(liquidator) - ); - - // Check Bold in SP has decreased - const BoldinSP_1 = await stabilityPool.getTotalBoldDeposits(); - assert.isTrue(BoldinSP_1.lt(BoldinSP_0)); - - // Check liquidator's balance has increased by the expected compensation amount - const compensationReceived = liquidatorBalance_after - .sub(liquidatorBalance_before) - .add(toBN(GAS_Used_Liquidator * GAS_PRICE)) - .toString(); - assert.equal(expectedGasComp, compensationReceived); - - // Check ETH in stability pool now equals the expected liquidated collateral - const ETHinSP = (await stabilityPool.getETH()).toString(); - assert.equal(expectedLiquidatedColl, ETHinSP); - }); - - // liquidateTroves - full redistribution - it.skip("liquidateTroves(): full redistribution. Compensates the correct amount, and liquidates the remainder", async () => { - await priceFeed.setPrice(dec(1000, 18)); - - await openTrove({ ICR: toBN(dec(200, 18)), extraParams: { from: whale } }); - - // A-D open troves - await openTrove({ - ICR: toBN(dec(118, 16)), - extraBoldAmount: dec(2000, 18), - extraParams: { from: alice }, - }); - await openTrove({ - ICR: toBN(dec(526, 16)), - extraBoldAmount: dec(8000, 18), - extraParams: { from: bob }, - }); - await openTrove({ - ICR: toBN(dec(488, 16)), - extraBoldAmount: dec(600, 18), - extraParams: { from: carol }, - }); - await openTrove({ - ICR: toBN(dec(545, 16)), - extraBoldAmount: dec(1, 23), - extraParams: { from: dennis }, - }); - - const BoldinDefaultPool_0 = await defaultPool.getBoldDebt(); - - // price drops to 200 - await priceFeed.setPrice(dec(200, 18)); - const price = await priceFeed.getPrice(); - - // Check not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D have ICR < MCR - assert.isTrue((await troveManager.getCurrentICR(alice, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(carol, price)).lt(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(dennis, price)).lt(mv._MCR) - ); - - // --- Check value of of A's collateral is < $10, and value of B,C,D collateral are > $10 --- - const aliceColl = (await troveManager.Troves(alice))[1]; - const bobColl = (await troveManager.Troves(bob))[1]; - const carolColl = (await troveManager.Troves(carol))[1]; - const dennisColl = (await troveManager.Troves(dennis))[1]; - - // --- Check value of 0.5% of A, B, and C's collateral is <$10, and value of 0.5% of D's collateral is > $10 --- - const _0pt5percent_aliceColl = aliceColl.div(web3.utils.toBN("200")); - const _0pt5percent_bobColl = bobColl.div(web3.utils.toBN("200")); - const _0pt5percent_carolColl = carolColl.div(web3.utils.toBN("200")); - const _0pt5percent_dennisColl = dennisColl.div(web3.utils.toBN("200")); - - const collGasCompensation = await troveManagerTester.getCollGasCompensation( - price - ); - assert.equal(collGasCompensation, dec(1, 18)); - - /* Expect total gas compensation = - 0.5% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedGasComp = _0pt5percent_aliceColl - .add(_0pt5percent_bobColl) - .add(_0pt5percent_carolColl) - .add(_0pt5percent_dennisColl); - - /* Expect liquidated coll = - 0.95% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedLiquidatedColl = aliceColl - .sub(_0pt5percent_aliceColl) - .add(bobColl.sub(_0pt5percent_bobColl)) - .add(carolColl.sub(_0pt5percent_carolColl)) - .add(dennisColl.sub(_0pt5percent_dennisColl)); - - // Liquidate troves A-D - const liquidatorBalance_before = web3.utils.toBN( - await web3.eth.getBalance(liquidator) - ); - const GAS_Used_Liquidator = th.gasUsed( - await troveManager.liquidateTroves(4, { - from: liquidator, - gasPrice: GAS_PRICE, - }) - ); - const liquidatorBalance_after = web3.utils.toBN( - await web3.eth.getBalance(liquidator) - ); - - // Check Bold in DefaultPool has decreased - const BoldinDefaultPool_1 = await defaultPool.getBoldDebt(); - assert.isTrue(BoldinDefaultPool_1.gt(BoldinDefaultPool_0)); - - // Check liquidator's balance has increased by the expected compensation amount - const compensationReceived = liquidatorBalance_after - .sub(liquidatorBalance_before) - .add(toBN(GAS_Used_Liquidator * GAS_PRICE)) - .toString(); - - assert.isAtMost( - th.getDifference(expectedGasComp, compensationReceived), - 1000 - ); - - // Check ETH in defaultPool now equals the expected liquidated collateral - const ETHinDefaultPool = (await defaultPool.getETH()).toString(); - assert.isAtMost( - th.getDifference(expectedLiquidatedColl, ETHinDefaultPool), - 1000 - ); - }); - - // --- event emission in liquidation sequence --- - it.skip("liquidateTroves(): full offset. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { - await priceFeed.setPrice(dec(1000, 18)); - - await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); - - // A-F open troves - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(118, 16)), - extraBoldAmount: dec(2000, 18), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(526, 16)), - extraBoldAmount: dec(8000, 18), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(488, 16)), - extraBoldAmount: dec(600, 18), - extraParams: { from: carol }, - }); - const { totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(545, 16)), - extraBoldAmount: dec(1, 23), - extraParams: { from: dennis }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: erin }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: flyn }, - }); - - // D, E each provide 10000 Bold to SP - await stabilityPool.provideToSP(dec(1, 23), { from: erin }); - await stabilityPool.provideToSP(dec(1, 23), { from: flyn }); - - const BoldinSP_0 = await stabilityPool.getTotalBoldDeposits(); - - // price drops to 200 - await priceFeed.setPrice(dec(200, 18)); - const price = await priceFeed.getPrice(); - - // Check not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D have ICR < MCR - assert.isTrue((await troveManager.getCurrentICR(alice, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(carol, price)).lt(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(dennis, price)).lt(mv._MCR) - ); - - // Check E, F have ICR > MCR - assert.isTrue((await troveManager.getCurrentICR(erin, price)).gt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(flyn, price)).gt(mv._MCR)); - - // --- Check value of of A's collateral is < $10, and value of B,C,D collateral are > $10 --- - const aliceColl = (await troveManager.Troves(alice))[1]; - const bobColl = (await troveManager.Troves(bob))[1]; - const carolColl = (await troveManager.Troves(carol))[1]; - const dennisColl = (await troveManager.Troves(dennis))[1]; - - // --- Check value of 0.5% of A, B, and C's collateral is <$10, and value of 0.5% of D's collateral is > $10 --- - const _0pt5percent_aliceColl = aliceColl.div(web3.utils.toBN("200")); - const _0pt5percent_bobColl = bobColl.div(web3.utils.toBN("200")); - const _0pt5percent_carolColl = carolColl.div(web3.utils.toBN("200")); - const _0pt5percent_dennisColl = dennisColl.div(web3.utils.toBN("200")); - - const collGasCompensation = await troveManagerTester.getCollGasCompensation( - price - ); - assert.equal(collGasCompensation, dec(1, 18)); - - /* Expect total gas compensation = - 0.5% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedGasComp = _0pt5percent_aliceColl - .add(_0pt5percent_bobColl) - .add(_0pt5percent_carolColl) - .add(_0pt5percent_dennisColl); - - /* Expect liquidated coll = - 0.95% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedLiquidatedColl = aliceColl - .sub(_0pt5percent_aliceColl) - .add(bobColl.sub(_0pt5percent_bobColl)) - .add(carolColl.sub(_0pt5percent_carolColl)) - .add(dennisColl.sub(_0pt5percent_dennisColl)); - - // Expect liquidatedDebt = 51 + 190 + 1025 + 13510 = 14646 Bold - const expectedLiquidatedDebt = A_totalDebt.add(B_totalDebt) - .add(C_totalDebt) - .add(D_totalDebt); - - // Liquidate troves A-D - const liquidationTxData = await troveManager.liquidateTroves(4, { - from: liquidator, - gasPrice: GAS_PRICE, - }); - - // Get data from the liquidation event logs - const [loggedDebt, loggedColl, loggedGasComp] = - th.getEmittedLiquidationValues(liquidationTxData); - - assert.isAtMost(th.getDifference(expectedLiquidatedDebt, loggedDebt), 1000); - assert.isAtMost(th.getDifference(expectedLiquidatedColl, loggedColl), 1000); - assert.isAtMost(th.getDifference(expectedGasComp, loggedGasComp), 1000); - }); - - it.skip("liquidateTroves(): full redistribution. Liquidation event emits the correct gas compensation and total liquidated coll and debt", async () => { - await priceFeed.setPrice(dec(1000, 18)); - - await openTrove({ ICR: toBN(dec(2000, 18)), extraParams: { from: whale } }); - - // A-F open troves - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(118, 16)), - extraBoldAmount: dec(2000, 18), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(526, 16)), - extraBoldAmount: dec(8000, 18), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(488, 16)), - extraBoldAmount: dec(600, 18), - extraParams: { from: carol }, - }); - const { totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(545, 16)), - extraBoldAmount: dec(1, 23), - extraParams: { from: dennis }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: erin }, - }); - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 23), - extraParams: { from: flyn }, - }); - - const BoldinDefaultPool_0 = await defaultPool.getBoldDebt(); - - // price drops to 200 - await priceFeed.setPrice(dec(200, 18)); - const price = await priceFeed.getPrice(); - - // Check not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D have ICR < MCR - assert.isTrue((await troveManager.getCurrentICR(alice, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lt(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(carol, price)).lt(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(dennis, price)).lt(mv._MCR) - ); - - const aliceColl = (await troveManager.Troves(alice))[1]; - const bobColl = (await troveManager.Troves(bob))[1]; - const carolColl = (await troveManager.Troves(carol))[1]; - const dennisColl = (await troveManager.Troves(dennis))[1]; - - // --- Check value of 0.5% of A, B, and C's collateral is <$10, and value of 0.5% of D's collateral is > $10 --- - const _0pt5percent_aliceColl = aliceColl.div(web3.utils.toBN("200")); - const _0pt5percent_bobColl = bobColl.div(web3.utils.toBN("200")); - const _0pt5percent_carolColl = carolColl.div(web3.utils.toBN("200")); - const _0pt5percent_dennisColl = dennisColl.div(web3.utils.toBN("200")); - - /* Expect total gas compensation = - 0.5% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedGasComp = _0pt5percent_aliceColl - .add(_0pt5percent_bobColl) - .add(_0pt5percent_carolColl) - .add(_0pt5percent_dennisColl) - .toString(); - - /* Expect liquidated coll = - 0.95% of [A_coll + B_coll + C_coll + D_coll] - */ - const expectedLiquidatedColl = aliceColl - .sub(_0pt5percent_aliceColl) - .add(bobColl.sub(_0pt5percent_bobColl)) - .add(carolColl.sub(_0pt5percent_carolColl)) - .add(dennisColl.sub(_0pt5percent_dennisColl)); - - // Expect liquidatedDebt = 51 + 190 + 1025 + 13510 = 14646 Bold - const expectedLiquidatedDebt = A_totalDebt.add(B_totalDebt) - .add(C_totalDebt) - .add(D_totalDebt); - - // Liquidate troves A-D - const liquidationTxData = await troveManager.liquidateTroves(4, { - from: liquidator, - gasPrice: GAS_PRICE, - }); - - // Get data from the liquidation event logs - const [loggedDebt, loggedColl, loggedGasComp] = - th.getEmittedLiquidationValues(liquidationTxData); - - assert.isAtMost(th.getDifference(expectedLiquidatedDebt, loggedDebt), 1000); - assert.isAtMost(th.getDifference(expectedLiquidatedColl, loggedColl), 1000); - assert.isAtMost(th.getDifference(expectedGasComp, loggedGasComp), 1000); - }); - // --- Trove ordering by ICR tests --- it("Trove ordering: same collateral, decreasing debt. Price successively increases. Troves should maintain ordering by ICR", async () => { diff --git a/contracts/test/TroveManagerTest.js b/contracts/test/TroveManagerTest.js index 9e25888b..b20f98e3 100644 --- a/contracts/test/TroveManagerTest.js +++ b/contracts/test/TroveManagerTest.js @@ -1237,851 +1237,6 @@ contract("TroveManager", async (accounts) => { assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); }); - // --- liquidateTroves() --- - // TODO: likely remove liquidateTroves() function and all tests for it, since it no longer works due to the - // new list ordering by interest rates - it.skip("liquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { - // A, B, C, D, E open troves - await openTrove({ ICR: toBN(dec(333, 16)), extraParams: { from: D } }); - await openTrove({ ICR: toBN(dec(333, 16)), extraParams: { from: E } }); - await openTrove({ ICR: toBN(dec(120, 16)), extraParams: { from: A } }); - await openTrove({ ICR: toBN(dec(133, 16)), extraParams: { from: B } }); - await openTrove({ ICR: toBN(dec(3, 18)), extraParams: { from: C } }); - - // Price drops - await priceFeed.setPrice(dec(175, 18)); - let price = await priceFeed.getPrice(); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // A gets liquidated, creates pending rewards for all - const liqTxA = await troveManager.liquidate(A); - assert.isTrue(liqTxA.receipt.status); - assert.isFalse(await sortedTroves.contains(A)); - - // A adds 10 Bold to the SP, but less than C's debt - await stabilityPool.provideToSP(dec(10, 18), { from: A }); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - price = await priceFeed.getPrice(); - // Confirm system is now in Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Confirm C has ICR > TCR - const TCR = await troveManager.getTCR(price); - const ICR_C = await troveManager.getCurrentICR(C, price); - - assert.isTrue(ICR_C.gt(TCR)); - - // Attempt to liquidate B and C, which skips C in the liquidation since it is immune - const liqTxBC = await troveManager.liquidateTroves(2); - assert.isTrue(liqTxBC.receipt.status); - assert.isFalse(await sortedTroves.contains(B)); - assert.isTrue(await sortedTroves.contains(C)); - assert.isTrue(await sortedTroves.contains(D)); - assert.isTrue(await sortedTroves.contains(E)); - - // // All remaining troves D and E repay a little debt, applying their pending rewards - assert.isTrue((await sortedTroves.getSize()).eq(toBN("3"))); - await borrowerOperations.repayBold(dec(1, 18), D, D, { from: D }); - await borrowerOperations.repayBold(dec(1, 18), E, E, { from: E }); - - // Check C is the only trove that has pending rewards - assert.isTrue(await troveManager.hasPendingRewards(C)); - assert.isFalse(await troveManager.hasPendingRewards(D)); - assert.isFalse(await troveManager.hasPendingRewards(E)); - - // Check C's pending coll and debt rewards are <= the coll and debt in the DefaultPool - const pendingETH_C = await troveManager.getPendingETHReward(C); - const pendingBoldDebt_C = await troveManager.getPendingBoldDebtReward(C); - const defaultPoolETH = await defaultPool.getETH(); - const defaultPoolBoldDebt = await defaultPool.getBoldDebt(); - assert.isTrue(pendingETH_C.lte(defaultPoolETH)); - assert.isTrue(pendingBoldDebt_C.lte(defaultPoolBoldDebt)); - //Check only difference is dust - assert.isAtMost(th.getDifference(pendingETH_C, defaultPoolETH), 1000); - assert.isAtMost( - th.getDifference(pendingBoldDebt_C, defaultPoolBoldDebt), - 1000 - ); - - // Confirm system is still in Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // D and E fill the Stability Pool, enough to completely absorb C's debt of 70 - await stabilityPool.provideToSP(dec(50, 18), { from: D }); - await stabilityPool.provideToSP(dec(50, 18), { from: E }); - - await priceFeed.setPrice(dec(50, 18)); - - // Try to liquidate C again. Check it succeeds and closes C's trove - const liqTx2 = await troveManager.liquidateTroves(2); - assert.isTrue(liqTx2.receipt.status); - assert.isFalse(await sortedTroves.contains(C)); - assert.isFalse(await sortedTroves.contains(D)); - assert.isTrue(await sortedTroves.contains(E)); - assert.isTrue((await sortedTroves.getSize()).eq(toBN("1"))); - }); - - it.skip("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { - // --- SETUP --- - await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); - - // create 5 Troves with varying ICRs - await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(190, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(195, 16)), extraParams: { from: erin } }); - await openTrove({ ICR: toBN(dec(120, 16)), extraParams: { from: flyn } }); - - // G,H, I open high-ICR troves - await openTrove({ ICR: toBN(dec(100, 18)), extraParams: { from: graham } }); - await openTrove({ ICR: toBN(dec(90, 18)), extraParams: { from: harriet } }); - await openTrove({ ICR: toBN(dec(80, 18)), extraParams: { from: ida } }); - - // Whale puts some tokens in Stability Pool - await stabilityPool.provideToSP(dec(300, 18), { - from: whale, - }); - - // --- TEST --- - - // Price drops to 1ETH:100Bold, reducing Bob and Carol's ICR below MCR - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Confirm troves A-E are ICR < 110% - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).lte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).lte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(erin, price)).lte(mv._MCR)); - assert.isTrue((await troveManager.getCurrentICR(flyn, price)).lte(mv._MCR)); - - // Confirm troves G, H, I are ICR > 110% - assert.isTrue( - (await troveManager.getCurrentICR(graham, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(harriet, price)).gte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(ida, price)).gte(mv._MCR)); - - // Confirm Whale is ICR > 110% - assert.isTrue( - (await troveManager.getCurrentICR(whale, price)).gte(mv._MCR) - ); - - // Liquidate 5 troves - await troveManager.liquidateTroves(5); - - // Confirm troves A-E have been removed from the system - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(flyn)); - - // Check all troves A-E are now closed by liquidation - assert.equal((await troveManager.Troves(alice))[3].toString(), "3"); - assert.equal((await troveManager.Troves(bob))[3].toString(), "3"); - assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); - assert.equal((await troveManager.Troves(erin))[3].toString(), "3"); - assert.equal((await troveManager.Troves(flyn))[3].toString(), "3"); - - // Check sorted list has been reduced to length 4 - assert.equal((await sortedTroves.getSize()).toString(), "4"); - }); - - it.skip("liquidateTroves(): liquidates up to the requested number of undercollateralized troves", async () => { - // --- SETUP --- - await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); - - // Alice, Bob, Carol, Dennis, Erin open troves with consecutively decreasing collateral ratio - await openTrove({ ICR: toBN(dec(202, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(204, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(206, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: erin } }); - - // --- TEST --- - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - await troveManager.liquidateTroves(3); - - const TroveOwnersArrayLength = await troveManager.getTroveOwnersCount(); - assert.equal(TroveOwnersArrayLength, "3"); - - // Check Alice, Bob, Carol troves have been closed - const aliceTroveStatus = ( - await troveManager.getTroveStatus(alice) - ).toString(); - const bobTroveStatus = (await troveManager.getTroveStatus(bob)).toString(); - const carolTroveStatus = ( - await troveManager.getTroveStatus(carol) - ).toString(); - - assert.equal(aliceTroveStatus, "3"); - assert.equal(bobTroveStatus, "3"); - assert.equal(carolTroveStatus, "3"); - - // Check Alice, Bob, and Carol's trove are no longer in the sorted list - const alice_isInSortedList = await sortedTroves.contains(alice); - const bob_isInSortedList = await sortedTroves.contains(bob); - const carol_isInSortedList = await sortedTroves.contains(carol); - - assert.isFalse(alice_isInSortedList); - assert.isFalse(bob_isInSortedList); - assert.isFalse(carol_isInSortedList); - - // Check Dennis, Erin still have active troves - const dennisTroveStatus = ( - await troveManager.getTroveStatus(dennis) - ).toString(); - const erinTroveStatus = ( - await troveManager.getTroveStatus(erin) - ).toString(); - - assert.equal(dennisTroveStatus, "1"); - assert.equal(erinTroveStatus, "1"); - - // Check Dennis, Erin still in sorted list - const dennis_isInSortedList = await sortedTroves.contains(dennis); - const erin_isInSortedList = await sortedTroves.contains(erin); - - assert.isTrue(dennis_isInSortedList); - assert.isTrue(erin_isInSortedList); - }); - - it.skip("liquidateTroves(): does nothing if all troves have ICR > 110%", async () => { - await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: whale } }); - await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: carol } }); - - // Price drops, but all troves remain active at 111% ICR - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_Before = (await th.getTCR(contracts)).toString(); - const listSize_Before = (await sortedTroves.getSize()).toString(); - - assert.isTrue( - (await troveManager.getCurrentICR(whale, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).gte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).gte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).gte(mv._MCR) - ); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Attempt liqudation sequence - await assertRevert( - troveManager.liquidateTroves(10), - "TroveManager: nothing to liquidate" - ); - - // Check all troves remain active - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_After = (await th.getTCR(contracts)).toString(); - const listSize_After = (await sortedTroves.getSize()).toString(); - - assert.equal(TCR_Before, TCR_After); - assert.equal(listSize_Before, listSize_After); - }); - - it.skip("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { - await openTrove({ ICR: toBN(dec(400, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(221, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); - await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: defaulter_1 }, - }); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - const alice_ICR_Before = await troveManager.getCurrentICR(alice, price); - const bob_ICR_Before = await troveManager.getCurrentICR(bob, price); - const carol_ICR_Before = await troveManager.getCurrentICR(carol, price); - - /* Before liquidation: - Alice ICR: = (2 * 100 / 100) = 200% - Bob ICR: (1 * 100 / 90.5) = 110.5% - Carol ICR: (1 * 100 / 100 ) = 100% - - Therefore Alice and Bob above the MCR, Carol is below */ - assert.isTrue(alice_ICR_Before.gte(mv._MCR)); - assert.isTrue(bob_ICR_Before.gte(mv._MCR)); - assert.isTrue(carol_ICR_Before.lte(mv._MCR)); - - // Liquidate defaulter. 30 Bold and 0.3 ETH is distributed uniformly between A, B and C. Each receive 10 Bold, 0.1 ETH - await troveManager.liquidate(defaulter_1); - - const alice_ICR_After = await troveManager.getCurrentICR(alice, price); - const bob_ICR_After = await troveManager.getCurrentICR(bob, price); - const carol_ICR_After = await troveManager.getCurrentICR(carol, price); - - /* After liquidation: - - Alice ICR: (1.0995 * 100 / 60) = 183.25% - Bob ICR:(1.0995 * 100 / 100.5) = 109.40% - Carol ICR: (1.0995 * 100 / 110 ) 99.95% - - Check Alice is above MCR, Bob below, Carol below. */ - assert.isTrue(alice_ICR_After.gte(mv._MCR)); - assert.isTrue(bob_ICR_After.lte(mv._MCR)); - assert.isTrue(carol_ICR_After.lte(mv._MCR)); - - /* Though Bob's true ICR (including pending rewards) is below the MCR, check that Bob's raw coll and debt has not changed */ - const bob_Coll = (await troveManager.Troves(bob))[1]; - const bob_Debt = (await troveManager.Troves(bob))[0]; - - const bob_rawICR = bob_Coll.mul(toBN(dec(100, 18))).div(bob_Debt); - assert.isTrue(bob_rawICR.gte(mv._MCR)); - - // Whale enters system, pulling it into Normal Mode - await openTrove({ - ICR: toBN(dec(10, 18)), - extraBoldAmount: dec(1, 24), - extraParams: { from: whale }, - }); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - //liquidate A, B, C - await troveManager.liquidateTroves(10); - - // Check A stays active, B and C get liquidated - assert.isTrue(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - - // check trove statuses - A active (1), B and C closed by liquidation (3) - assert.equal((await troveManager.Troves(alice))[3].toString(), "1"); - assert.equal((await troveManager.Troves(bob))[3].toString(), "3"); - assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); - }); - - it.skip("liquidateTroves(): reverts if n = 0", async () => { - await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(206, 16)), extraParams: { from: carol } }); - - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - const TCR_Before = (await th.getTCR(contracts)).toString(); - - // Confirm A, B, C ICRs are below 110% - const alice_ICR = await troveManager.getCurrentICR(alice, price); - const bob_ICR = await troveManager.getCurrentICR(bob, price); - const carol_ICR = await troveManager.getCurrentICR(carol, price); - assert.isTrue(alice_ICR.lte(mv._MCR)); - assert.isTrue(bob_ICR.lte(mv._MCR)); - assert.isTrue(carol_ICR.lte(mv._MCR)); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Liquidation with n = 0 - await assertRevert( - troveManager.liquidateTroves(0), - "TroveManager: nothing to liquidate" - ); - - // Check all troves are still in the system - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_After = (await th.getTCR(contracts)).toString(); - - // Check TCR has not changed after liquidation - assert.equal(TCR_Before, TCR_After); - }); - - it.skip("liquidateTroves(): liquidates troves with ICR < MCR", async () => { - await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); - - // A, B, C open troves that will remain active when price drops to 100 - await openTrove({ ICR: toBN(dec(220, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(230, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(240, 16)), extraParams: { from: carol } }); - - // D, E, F open troves that will fall below MCR when price drops to 100 - await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(216, 16)), extraParams: { from: erin } }); - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: flyn } }); - - // Check list size is 7 - assert.equal((await sortedTroves.getSize()).toString(), "7"); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - const alice_ICR = await troveManager.getCurrentICR(alice, price); - const bob_ICR = await troveManager.getCurrentICR(bob, price); - const carol_ICR = await troveManager.getCurrentICR(carol, price); - const dennis_ICR = await troveManager.getCurrentICR(dennis, price); - const erin_ICR = await troveManager.getCurrentICR(erin, price); - const flyn_ICR = await troveManager.getCurrentICR(flyn, price); - - // Check A, B, C have ICR above MCR - assert.isTrue(alice_ICR.gte(mv._MCR)); - assert.isTrue(bob_ICR.gte(mv._MCR)); - assert.isTrue(carol_ICR.gte(mv._MCR)); - - // Check D, E, F have ICR below MCR - assert.isTrue(dennis_ICR.lte(mv._MCR)); - assert.isTrue(erin_ICR.lte(mv._MCR)); - assert.isTrue(flyn_ICR.lte(mv._MCR)); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - //Liquidate sequence - await troveManager.liquidateTroves(10); - - // check list size reduced to 4 - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Check Whale and A, B, C remain in the system - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - // Check D, E, F have been removed - assert.isFalse(await sortedTroves.contains(dennis)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(flyn)); - }); - - it.skip("liquidateTroves(): does not affect the liquidated user's token balances", async () => { - await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); - - // D, E, F open troves that will fall below MCR when price drops to 100 - await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(216, 16)), extraParams: { from: erin } }); - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: flyn } }); - - const D_balanceBefore = await boldToken.balanceOf(dennis); - const E_balanceBefore = await boldToken.balanceOf(erin); - const F_balanceBefore = await boldToken.balanceOf(flyn); - - // Check list size is 4 - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - //Liquidate sequence - await troveManager.liquidateTroves(10); - - // check list size reduced to 1 - assert.equal((await sortedTroves.getSize()).toString(), "1"); - - // Check Whale remains in the system - assert.isTrue(await sortedTroves.contains(whale)); - - // Check D, E, F have been removed - assert.isFalse(await sortedTroves.contains(dennis)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(flyn)); - - // Check token balances of users whose troves were liquidated, have not changed - assert.equal( - (await boldToken.balanceOf(dennis)).toString(), - D_balanceBefore - ); - assert.equal((await boldToken.balanceOf(erin)).toString(), E_balanceBefore); - assert.equal((await boldToken.balanceOf(flyn)).toString(), F_balanceBefore); - }); - - it.skip("liquidateTroves(): A liquidation sequence containing Pool offsets increases the TCR", async () => { - // Whale provides 500 Bold to SP - await openTrove({ - ICR: toBN(dec(100, 18)), - extraBoldAmount: toBN(dec(500, 18)), - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(dec(500, 18), { - from: whale, - }); - - await openTrove({ ICR: toBN(dec(4, 18)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(28, 18)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(8, 18)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(80, 18)), extraParams: { from: dennis } }); - - await openTrove({ - ICR: toBN(dec(199, 16)), - extraParams: { from: defaulter_1 }, - }); - await openTrove({ - ICR: toBN(dec(156, 16)), - extraParams: { from: defaulter_2 }, - }); - await openTrove({ - ICR: toBN(dec(183, 16)), - extraParams: { from: defaulter_3 }, - }); - await openTrove({ - ICR: toBN(dec(166, 16)), - extraParams: { from: defaulter_4 }, - }); - - assert.isTrue(await sortedTroves.contains(defaulter_1)); - assert.isTrue(await sortedTroves.contains(defaulter_2)); - assert.isTrue(await sortedTroves.contains(defaulter_3)); - assert.isTrue(await sortedTroves.contains(defaulter_4)); - - assert.equal((await sortedTroves.getSize()).toString(), "9"); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - - const TCR_Before = await th.getTCR(contracts); - - // Check pool has 500 Bold - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - dec(500, 18) - ); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Liquidate troves - await troveManager.liquidateTroves(10); - - // Check pool has been emptied by the liquidations - assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); - - // Check all defaulters have been liquidated - assert.isFalse(await sortedTroves.contains(defaulter_1)); - assert.isFalse(await sortedTroves.contains(defaulter_2)); - assert.isFalse(await sortedTroves.contains(defaulter_3)); - assert.isFalse(await sortedTroves.contains(defaulter_4)); - - // check system sized reduced to 5 troves - assert.equal((await sortedTroves.getSize()).toString(), "5"); - - // Check that the liquidation sequence has improved the TCR - const TCR_After = await th.getTCR(contracts); - assert.isTrue(TCR_After.gte(TCR_Before)); - }); - - it.skip("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { - const { collateral: W_coll, totalDebt: W_debt } = await openTrove({ - ICR: toBN(dec(100, 18)), - extraParams: { from: whale }, - }); - const { collateral: A_coll, totalDebt: A_debt } = await openTrove({ - ICR: toBN(dec(4, 18)), - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_debt } = await openTrove({ - ICR: toBN(dec(28, 18)), - extraParams: { from: bob }, - }); - const { collateral: C_coll, totalDebt: C_debt } = await openTrove({ - ICR: toBN(dec(8, 18)), - extraParams: { from: carol }, - }); - const { collateral: D_coll, totalDebt: D_debt } = await openTrove({ - ICR: toBN(dec(80, 18)), - extraParams: { from: dennis }, - }); - - const { collateral: d1_coll, totalDebt: d1_debt } = await openTrove({ - ICR: toBN(dec(199, 16)), - extraParams: { from: defaulter_1 }, - }); - const { collateral: d2_coll, totalDebt: d2_debt } = await openTrove({ - ICR: toBN(dec(156, 16)), - extraParams: { from: defaulter_2 }, - }); - const { collateral: d3_coll, totalDebt: d3_debt } = await openTrove({ - ICR: toBN(dec(183, 16)), - extraParams: { from: defaulter_3 }, - }); - const { collateral: d4_coll, totalDebt: d4_debt } = await openTrove({ - ICR: toBN(dec(166, 16)), - extraParams: { from: defaulter_4 }, - }); - - const totalCollNonDefaulters = W_coll.add(A_coll) - .add(B_coll) - .add(C_coll) - .add(D_coll); - const totalCollDefaulters = d1_coll.add(d2_coll).add(d3_coll).add(d4_coll); - const totalColl = totalCollNonDefaulters.add(totalCollDefaulters); - const totalDebt = W_debt.add(A_debt) - .add(B_debt) - .add(C_debt) - .add(D_debt) - .add(d1_debt) - .add(d2_debt) - .add(d3_debt) - .add(d4_debt); - - assert.isTrue(await sortedTroves.contains(defaulter_1)); - assert.isTrue(await sortedTroves.contains(defaulter_2)); - assert.isTrue(await sortedTroves.contains(defaulter_3)); - assert.isTrue(await sortedTroves.contains(defaulter_4)); - - assert.equal((await sortedTroves.getSize()).toString(), "9"); - - // Price drops - const price = toBN(dec(100, 18)); - await priceFeed.setPrice(price); - - const TCR_Before = await th.getTCR(contracts); - assert.isAtMost( - th.getDifference(TCR_Before, totalColl.mul(price).div(totalDebt)), - 1000 - ); - - // Check pool is empty before liquidation - assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Liquidate - await troveManager.liquidateTroves(10); - - // Check all defaulters have been liquidated - assert.isFalse(await sortedTroves.contains(defaulter_1)); - assert.isFalse(await sortedTroves.contains(defaulter_2)); - assert.isFalse(await sortedTroves.contains(defaulter_3)); - assert.isFalse(await sortedTroves.contains(defaulter_4)); - - // check system sized reduced to 5 troves - assert.equal((await sortedTroves.getSize()).toString(), "5"); - - // Check that the liquidation sequence has reduced the TCR - const TCR_After = await th.getTCR(contracts); - // ((100+1+7+2+20)+(1+2+3+4)*0.995)*100/(2050+50+50+50+50+101+257+328+480) - assert.isAtMost( - th.getDifference( - TCR_After, - totalCollNonDefaulters - .add(th.applyLiquidationFee(totalCollDefaulters)) - .mul(price) - .div(totalDebt) - ), - 1000 - ); - assert.isTrue(TCR_Before.gte(TCR_After)); - assert.isTrue(TCR_After.gte(TCR_Before.mul(toBN(995)).div(toBN(1000)))); - }); - - it.skip("liquidateTroves(): Liquidating troves with SP deposits correctly impacts their SP deposit and ETH gain", async () => { - // Whale provides 400 Bold to the SP - const whaleDeposit = toBN(dec(40000, 18)); - await openTrove({ - ICR: toBN(dec(100, 18)), - extraBoldAmount: whaleDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(whaleDeposit, { - from: whale, - }); - - const A_deposit = toBN(dec(10000, 18)); - const B_deposit = toBN(dec(30000, 18)); - const { collateral: A_coll, totalDebt: A_debt } = await openTrove({ - ICR: toBN(dec(2, 18)), - extraBoldAmount: A_deposit, - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_debt } = await openTrove({ - ICR: toBN(dec(2, 18)), - extraBoldAmount: B_deposit, - extraParams: { from: bob }, - }); - const { collateral: C_coll, totalDebt: C_debt } = await openTrove({ - ICR: toBN(dec(2, 18)), - extraParams: { from: carol }, - }); - - const liquidatedColl = A_coll.add(B_coll).add(C_coll); - const liquidatedDebt = A_debt.add(B_debt).add(C_debt); - - // A, B provide 100, 300 to the SP - await stabilityPool.provideToSP(A_deposit, { from: alice }); - await stabilityPool.provideToSP(B_deposit, { from: bob }); - - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - - // Check 800 Bold in Pool - const totalDeposits = whaleDeposit.add(A_deposit).add(B_deposit); - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - totalDeposits - ); - - // Confirm system is not in Recovery Mode - assert.isFalse(await th.checkRecoveryMode(contracts)); - - // Liquidate - await troveManager.liquidateTroves(10); - - // Check all defaulters have been liquidated - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - - // check system sized reduced to 1 troves - assert.equal((await sortedTroves.getSize()).toString(), "1"); - - /* Prior to liquidation, SP deposits were: - Whale: 400 Bold - Alice: 100 Bold - Bob: 300 Bold - Carol: 0 Bold - - Total Bold in Pool: 800 Bold - - Then, liquidation hits A,B,C: - - Total liquidated debt = 150 + 350 + 150 = 650 Bold - Total liquidated ETH = 1.1 + 3.1 + 1.1 = 5.3 ETH - - whale bold loss: 650 * (400/800) = 325 bold - alice bold loss: 650 *(100/800) = 81.25 bold - bob bold loss: 650 * (300/800) = 243.75 bold - - whale remaining deposit: (400 - 325) = 75 bold - alice remaining deposit: (100 - 81.25) = 18.75 bold - bob remaining deposit: (300 - 243.75) = 56.25 bold - - whale eth gain: 5*0.995 * (400/800) = 2.4875 eth - alice eth gain: 5*0.995 *(100/800) = 0.621875 eth - bob eth gain: 5*0.995 * (300/800) = 1.865625 eth - - Total remaining deposits: 150 Bold - Total ETH gain: 4.975 ETH */ - - // Check remaining Bold Deposits and ETH gain, for whale and depositors whose troves were liquidated - const whale_Deposit_After = await stabilityPool.getCompoundedBoldDeposit( - whale - ); - const alice_Deposit_After = await stabilityPool.getCompoundedBoldDeposit( - alice - ); - const bob_Deposit_After = await stabilityPool.getCompoundedBoldDeposit(bob); - - const whale_ETHGain = await stabilityPool.getDepositorETHGain(whale); - const alice_ETHGain = await stabilityPool.getDepositorETHGain(alice); - const bob_ETHGain = await stabilityPool.getDepositorETHGain(bob); - - assert.isAtMost( - th.getDifference( - whale_Deposit_After, - whaleDeposit.sub(liquidatedDebt.mul(whaleDeposit).div(totalDeposits)) - ), - 100000 - ); - assert.isAtMost( - th.getDifference( - alice_Deposit_After, - A_deposit.sub(liquidatedDebt.mul(A_deposit).div(totalDeposits)) - ), - 100000 - ); - assert.isAtMost( - th.getDifference( - bob_Deposit_After, - B_deposit.sub(liquidatedDebt.mul(B_deposit).div(totalDeposits)) - ), - 100000 - ); - - assert.isAtMost( - th.getDifference( - whale_ETHGain, - th - .applyLiquidationFee(liquidatedColl) - .mul(whaleDeposit) - .div(totalDeposits) - ), - 100000 - ); - assert.isAtMost( - th.getDifference( - alice_ETHGain, - th.applyLiquidationFee(liquidatedColl).mul(A_deposit).div(totalDeposits) - ), - 100000 - ); - assert.isAtMost( - th.getDifference( - bob_ETHGain, - th.applyLiquidationFee(liquidatedColl).mul(B_deposit).div(totalDeposits) - ), - 100000 - ); - - // Check total remaining deposits and ETH gain in Stability Pool - const total_BoldinSP = ( - await stabilityPool.getTotalBoldDeposits() - ).toString(); - const total_ETHinSP = (await stabilityPool.getETH()).toString(); - - assert.isAtMost( - th.getDifference(total_BoldinSP, totalDeposits.sub(liquidatedDebt)), - 1000 - ); - assert.isAtMost( - th.getDifference(total_ETHinSP, th.applyLiquidationFee(liquidatedColl)), - 1000 - ); - }); - // --- batchLiquidateTroves() --- // TODO: revisit the relevance of this test since it relies on liquidateTroves(), which now no longer works due to ordering by interest rate. // Can we achieve / test the same thing using another liquidation function? diff --git a/contracts/test/TroveManager_RecoveryModeTest.js b/contracts/test/TroveManager_RecoveryModeTest.js index a174d4b1..22e9cfad 100644 --- a/contracts/test/TroveManager_RecoveryModeTest.js +++ b/contracts/test/TroveManager_RecoveryModeTest.js @@ -2425,1951 +2425,6 @@ contract("TroveManager - in Recovery Mode", async (accounts) => { ); }); - // --- liquidateTroves --- - - // TODO: delete these tests when we delete liquidateTroves(), since we no will no longer liquidate sequentially - - it.skip("liquidateTroves(): With all ICRs > 110%, Liquidates Troves until system leaves recovery mode", async () => { - // make 8 Troves accordingly - // --- SETUP --- - - // Everyone withdraws some Bold from their Trove, resulting in different ICRs - await openTrove({ ICR: toBN(dec(350, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(286, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(273, 16)), extraParams: { from: dennis } }); - const { totalDebt: E_totalDebt } = await openTrove({ - ICR: toBN(dec(261, 16)), - extraParams: { from: erin }, - }); - const { totalDebt: F_totalDebt } = await openTrove({ - ICR: toBN(dec(250, 16)), - extraParams: { from: freddy }, - }); - const { totalDebt: G_totalDebt } = await openTrove({ - ICR: toBN(dec(235, 16)), - extraParams: { from: greta }, - }); - const { totalDebt: H_totalDebt } = await openTrove({ - ICR: toBN(dec(222, 16)), - extraBoldAmount: dec(5000, 18), - extraParams: { from: harry }, - }); - const liquidationAmount = E_totalDebt.add(F_totalDebt) - .add(G_totalDebt) - .add(H_totalDebt); - await openTrove({ - ICR: toBN(dec(400, 16)), - extraBoldAmount: liquidationAmount, - extraParams: { from: alice }, - }); - - // Alice deposits Bold to Stability Pool - await stabilityPool.provideToSP(liquidationAmount, { - from: alice, - }); - - // price drops - // price drops to 1ETH:90Bold, reducing TCR below 150% - await priceFeed.setPrice("90000000000000000000"); - const price = await priceFeed.getPrice(); - - const recoveryMode_Before = await th.checkRecoveryMode(contracts); - assert.isTrue(recoveryMode_Before); - - // check TCR < 150% - const _150percent = web3.utils.toBN("1500000000000000000"); - const TCR_Before = await th.getTCR(contracts); - assert.isTrue(TCR_Before.lt(_150percent)); - - /* - After the price drop and prior to any liquidations, ICR should be: - - Trove ICR - Alice 161% - Bob 158% - Carol 129% - Dennis 123% - Elisa 117% - Freddy 113% - Greta 106% - Harry 100% - - */ - const alice_ICR = await troveManager.getCurrentICR(alice, price); - const bob_ICR = await troveManager.getCurrentICR(bob, price); - const carol_ICR = await troveManager.getCurrentICR(carol, price); - const dennis_ICR = await troveManager.getCurrentICR(dennis, price); - const erin_ICR = await troveManager.getCurrentICR(erin, price); - const freddy_ICR = await troveManager.getCurrentICR(freddy, price); - const greta_ICR = await troveManager.getCurrentICR(greta, price); - const harry_ICR = await troveManager.getCurrentICR(harry, price); - const TCR = await th.getTCR(contracts); - - // Alice and Bob should have ICR > TCR - assert.isTrue(alice_ICR.gt(TCR)); - assert.isTrue(bob_ICR.gt(TCR)); - // All other Troves should have ICR < TCR - assert.isTrue(carol_ICR.lt(TCR)); - assert.isTrue(dennis_ICR.lt(TCR)); - assert.isTrue(erin_ICR.lt(TCR)); - assert.isTrue(freddy_ICR.lt(TCR)); - assert.isTrue(greta_ICR.lt(TCR)); - assert.isTrue(harry_ICR.lt(TCR)); - - /* Liquidations should occur from the lowest ICR Trove upwards, i.e. - 1) Harry, 2) Greta, 3) Freddy, etc. - - Trove ICR - Alice 161% - Bob 158% - Carol 129% - Dennis 123% - ---- CUTOFF ---- - Elisa 117% - Freddy 113% - Greta 106% - Harry 100% - - If all Troves below the cutoff are liquidated, the TCR of the system rises above the CCR, to 152%. (see calculations in Google Sheet) - - Thus, after liquidateTroves(), expect all Troves to be liquidated up to the cut-off. - - Only Alice, Bob, Carol and Dennis should remain active - all others should be closed. */ - - // call liquidate Troves - await troveManager.liquidateTroves(10); - - // check system is no longer in Recovery Mode - const recoveryMode_After = await th.checkRecoveryMode(contracts); - assert.isFalse(recoveryMode_After); - - // After liquidation, TCR should rise to above 150%. - const TCR_After = await th.getTCR(contracts); - assert.isTrue(TCR_After.gt(_150percent)); - - // get all Troves - const alice_Trove = await troveManager.Troves(alice); - const bob_Trove = await troveManager.Troves(bob); - const carol_Trove = await troveManager.Troves(carol); - const dennis_Trove = await troveManager.Troves(dennis); - const erin_Trove = await troveManager.Troves(erin); - const freddy_Trove = await troveManager.Troves(freddy); - const greta_Trove = await troveManager.Troves(greta); - const harry_Trove = await troveManager.Troves(harry); - - // check that Alice, Bob, Carol, & Dennis' Troves remain active - assert.equal(alice_Trove[3], 1); - assert.equal(bob_Trove[3], 1); - assert.equal(carol_Trove[3], 1); - assert.equal(dennis_Trove[3], 1); - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - assert.isTrue(await sortedTroves.contains(dennis)); - - // check all other Troves are liquidated - assert.equal(erin_Trove[3], 3); - assert.equal(freddy_Trove[3], 3); - assert.equal(greta_Trove[3], 3); - assert.equal(harry_Trove[3], 3); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(freddy)); - assert.isFalse(await sortedTroves.contains(greta)); - assert.isFalse(await sortedTroves.contains(harry)); - }); - - it.skip("liquidateTroves(): Liquidates Troves until 1) system has left recovery mode AND 2) it reaches a Trove with ICR >= 110%", async () => { - // make 6 Troves accordingly - // --- SETUP --- - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(240, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(240, 16)), - extraParams: { from: carol }, - }); - const { totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(230, 16)), - extraParams: { from: dennis }, - }); - const { totalDebt: E_totalDebt } = await openTrove({ - ICR: toBN(dec(240, 16)), - extraParams: { from: erin }, - }); - const { totalDebt: F_totalDebt } = await openTrove({ - ICR: toBN(dec(240, 16)), - extraParams: { from: freddy }, - }); - - const liquidationAmount = B_totalDebt.add(C_totalDebt) - .add(D_totalDebt) - .add(E_totalDebt) - .add(F_totalDebt); - await openTrove({ - ICR: toBN(dec(400, 16)), - extraBoldAmount: liquidationAmount, - extraParams: { from: alice }, - }); - - // Alice deposits Bold to Stability Pool - await stabilityPool.provideToSP(liquidationAmount, { - from: alice, - }); - - // price drops to 1ETH:85Bold, reducing TCR below 150% - await priceFeed.setPrice("85000000000000000000"); - const price = await priceFeed.getPrice(); - - // check Recovery Mode kicks in - - const recoveryMode_Before = await th.checkRecoveryMode(contracts); - assert.isTrue(recoveryMode_Before); - - // check TCR < 150% - const _150percent = web3.utils.toBN("1500000000000000000"); - const TCR_Before = await th.getTCR(contracts); - assert.isTrue(TCR_Before.lt(_150percent)); - - /* - After the price drop and prior to any liquidations, ICR should be: - - Trove ICR - Alice 182% - Bob 102% - Carol 102% - Dennis 102% - Elisa 102% - Freddy 102% - */ - alice_ICR = await troveManager.getCurrentICR(alice, price); - bob_ICR = await troveManager.getCurrentICR(bob, price); - carol_ICR = await troveManager.getCurrentICR(carol, price); - dennis_ICR = await troveManager.getCurrentICR(dennis, price); - erin_ICR = await troveManager.getCurrentICR(erin, price); - freddy_ICR = await troveManager.getCurrentICR(freddy, price); - - // Alice should have ICR > 150% - assert.isTrue(alice_ICR.gt(_150percent)); - // All other Troves should have ICR < 150% - assert.isTrue(carol_ICR.lt(_150percent)); - assert.isTrue(dennis_ICR.lt(_150percent)); - assert.isTrue(erin_ICR.lt(_150percent)); - assert.isTrue(freddy_ICR.lt(_150percent)); - - /* Liquidations should occur from the lowest ICR Trove upwards, i.e. - 1) Freddy, 2) Elisa, 3) Dennis. - - After liquidating Freddy and Elisa, the the TCR of the system rises above the CCR, to 154%. - (see calculations in Google Sheet) - - Liquidations continue until all Troves with ICR < MCR have been closed. - Only Alice should remain active - all others should be closed. */ - - // call liquidate Troves - await troveManager.liquidateTroves(6); - - // check system is no longer in Recovery Mode - const recoveryMode_After = await th.checkRecoveryMode(contracts); - assert.isFalse(recoveryMode_After); - - // After liquidation, TCR should rise to above 150%. - const TCR_After = await th.getTCR(contracts); - assert.isTrue(TCR_After.gt(_150percent)); - - // get all Troves - const alice_Trove = await troveManager.Troves(alice); - const bob_Trove = await troveManager.Troves(bob); - const carol_Trove = await troveManager.Troves(carol); - const dennis_Trove = await troveManager.Troves(dennis); - const erin_Trove = await troveManager.Troves(erin); - const freddy_Trove = await troveManager.Troves(freddy); - - // check that Alice's Trove remains active - assert.equal(alice_Trove[3], 1); - assert.isTrue(await sortedTroves.contains(alice)); - - // check all other Troves are liquidated - assert.equal(bob_Trove[3], 3); - assert.equal(carol_Trove[3], 3); - assert.equal(dennis_Trove[3], 3); - assert.equal(erin_Trove[3], 3); - assert.equal(freddy_Trove[3], 3); - - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - assert.isFalse(await sortedTroves.contains(dennis)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(freddy)); - }); - - it.skip("liquidateTroves(): liquidates only up to the requested number of undercollateralized troves", async () => { - await openTrove({ - ICR: toBN(dec(300, 16)), - extraParams: { from: whale, value: dec(300, "ether") }, - }); - - // --- SETUP --- - // Alice, Bob, Carol, Dennis, Erin open troves with consecutively increasing collateral ratio - await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(212, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(214, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(216, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: erin } }); - - await priceFeed.setPrice(dec(100, 18)); - - const TCR = await th.getTCR(contracts); - - assert.isTrue(TCR.lte(web3.utils.toBN(dec(150, 18)))); - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // --- TEST --- - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - - await troveManager.liquidateTroves(3); - - // Check system still in Recovery Mode after liquidation tx - assert.isTrue(await th.checkRecoveryMode(contracts)); - - const TroveOwnersArrayLength = await troveManager.getTroveOwnersCount(); - assert.equal(TroveOwnersArrayLength, "3"); - - // Check Alice, Bob, Carol troves have been closed - const aliceTroveStatus = ( - await troveManager.getTroveStatus(alice) - ).toString(); - const bobTroveStatus = (await troveManager.getTroveStatus(bob)).toString(); - const carolTroveStatus = ( - await troveManager.getTroveStatus(carol) - ).toString(); - - assert.equal(aliceTroveStatus, "3"); - assert.equal(bobTroveStatus, "3"); - assert.equal(carolTroveStatus, "3"); - - // Check Alice, Bob, and Carol's trove are no longer in the sorted list - const alice_isInSortedList = await sortedTroves.contains(alice); - const bob_isInSortedList = await sortedTroves.contains(bob); - const carol_isInSortedList = await sortedTroves.contains(carol); - - assert.isFalse(alice_isInSortedList); - assert.isFalse(bob_isInSortedList); - assert.isFalse(carol_isInSortedList); - - // Check Dennis, Erin still have active troves - const dennisTroveStatus = ( - await troveManager.getTroveStatus(dennis) - ).toString(); - const erinTroveStatus = ( - await troveManager.getTroveStatus(erin) - ).toString(); - - assert.equal(dennisTroveStatus, "1"); - assert.equal(erinTroveStatus, "1"); - - // Check Dennis, Erin still in sorted list - const dennis_isInSortedList = await sortedTroves.contains(dennis); - const erin_isInSortedList = await sortedTroves.contains(erin); - - assert.isTrue(dennis_isInSortedList); - assert.isTrue(erin_isInSortedList); - }); - - it.skip("liquidateTroves(): does nothing if n = 0", async () => { - await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(100, 18), - extraParams: { from: alice }, - }); - await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(200, 18), - extraParams: { from: bob }, - }); - await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(300, 18), - extraParams: { from: carol }, - }); - - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - const TCR_Before = (await th.getTCR(contracts)).toString(); - - // Confirm A, B, C ICRs are below 110% - - const alice_ICR = await troveManager.getCurrentICR(alice, price); - const bob_ICR = await troveManager.getCurrentICR(bob, price); - const carol_ICR = await troveManager.getCurrentICR(carol, price); - assert.isTrue(alice_ICR.lte(mv._MCR)); - assert.isTrue(bob_ICR.lte(mv._MCR)); - assert.isTrue(carol_ICR.lte(mv._MCR)); - - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Liquidation with n = 0 - await assertRevert( - troveManager.liquidateTroves(0), - "TroveManager: nothing to liquidate" - ); - - // Check all troves are still in the system - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_After = (await th.getTCR(contracts)).toString(); - - // Check TCR has not changed after liquidation - assert.equal(TCR_Before, TCR_After); - }); - - it.skip("liquidateTroves(): closes every Trove with ICR < MCR, when n > number of undercollateralized troves", async () => { - // --- SETUP --- - await openTrove({ - ICR: toBN(dec(300, 16)), - extraParams: { from: whale, value: dec(300, "ether") }, - }); - - // create 5 Troves with varying ICRs - await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(133, 16)), extraParams: { from: bob } }); - await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(300, 18), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(182, 16)), extraParams: { from: erin } }); - await openTrove({ ICR: toBN(dec(111, 16)), extraParams: { from: freddy } }); - - // Whale puts some tokens in Stability Pool - await stabilityPool.provideToSP(dec(300, 18), { - from: whale, - }); - - // --- TEST --- - - // Price drops to 1ETH:100Bold, reducing Bob and Carol's ICR below MCR - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Confirm troves A-E are ICR < 110% - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).lte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).lte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).lte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(erin, price)).lte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(freddy, price)).lte(mv._MCR) - ); - - // Confirm Whale is ICR > 110% - assert.isTrue( - (await troveManager.getCurrentICR(whale, price)).gte(mv._MCR) - ); - - // Liquidate 5 troves - await troveManager.liquidateTroves(5); - - // Confirm troves A-E have been removed from the system - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(freddy)); - - // Check all troves are now liquidated - assert.equal((await troveManager.Troves(alice))[3].toString(), "3"); - assert.equal((await troveManager.Troves(bob))[3].toString(), "3"); - assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); - assert.equal((await troveManager.Troves(erin))[3].toString(), "3"); - assert.equal((await troveManager.Troves(freddy))[3].toString(), "3"); - }); - - it.skip("liquidateTroves(): a liquidation sequence containing Pool offsets increases the TCR", async () => { - // Whale provides 500 Bold to SP - await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(500, 18), - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(dec(500, 18), { - from: whale, - }); - - await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(320, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(340, 16)), extraParams: { from: dennis } }); - - await openTrove({ - ICR: toBN(dec(198, 16)), - extraBoldAmount: dec(101, 18), - extraParams: { from: defaulter_1 }, - }); - await openTrove({ - ICR: toBN(dec(184, 16)), - extraBoldAmount: dec(217, 18), - extraParams: { from: defaulter_2 }, - }); - await openTrove({ - ICR: toBN(dec(183, 16)), - extraBoldAmount: dec(328, 18), - extraParams: { from: defaulter_3 }, - }); - await openTrove({ - ICR: toBN(dec(186, 16)), - extraBoldAmount: dec(431, 18), - extraParams: { from: defaulter_4 }, - }); - - assert.isTrue(await sortedTroves.contains(defaulter_1)); - assert.isTrue(await sortedTroves.contains(defaulter_2)); - assert.isTrue(await sortedTroves.contains(defaulter_3)); - assert.isTrue(await sortedTroves.contains(defaulter_4)); - - // Price drops - await priceFeed.setPrice(dec(110, 18)); - const price = await priceFeed.getPrice(); - - assert.isTrue( - await th.ICRbetween100and110(defaulter_1, troveManager, price) - ); - assert.isTrue( - await th.ICRbetween100and110(defaulter_2, troveManager, price) - ); - assert.isTrue( - await th.ICRbetween100and110(defaulter_3, troveManager, price) - ); - assert.isTrue( - await th.ICRbetween100and110(defaulter_4, troveManager, price) - ); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - const TCR_Before = await th.getTCR(contracts); - - // Check Stability Pool has 500 Bold - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - dec(500, 18) - ); - - await troveManager.liquidateTroves(8); - - // assert.isFalse((await sortedTroves.contains(defaulter_1))) - // assert.isFalse((await sortedTroves.contains(defaulter_2))) - // assert.isFalse((await sortedTroves.contains(defaulter_3))) - assert.isFalse(await sortedTroves.contains(defaulter_4)); - - // Check Stability Pool has been emptied by the liquidations - assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); - - // Check that the liquidation sequence has improved the TCR - const TCR_After = await th.getTCR(contracts); - assert.isTrue(TCR_After.gte(TCR_Before)); - }); - - it.skip("liquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { - const { collateral: W_coll, totalDebt: W_totalDebt } = await openTrove({ - ICR: toBN(dec(250, 16)), - extraBoldAmount: dec(500, 18), - extraParams: { from: whale }, - }); - - const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(300, 16)), - extraParams: { from: alice }, - }); - const { collateral: C_coll, totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(400, 16)), - extraParams: { from: carol }, - }); - const { collateral: D_coll, totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(600, 16)), - extraParams: { from: dennis }, - }); - - const { collateral: d1_coll, totalDebt: d1_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraBoldAmount: dec(101, 18), - extraParams: { from: defaulter_1 }, - }); - const { collateral: d2_coll, totalDebt: d2_totalDebt } = await openTrove({ - ICR: toBN(dec(184, 16)), - extraBoldAmount: dec(217, 18), - extraParams: { from: defaulter_2 }, - }); - const { collateral: d3_coll, totalDebt: d3_totalDebt } = await openTrove({ - ICR: toBN(dec(183, 16)), - extraBoldAmount: dec(328, 18), - extraParams: { from: defaulter_3 }, - }); - const { collateral: d4_coll, totalDebt: d4_totalDebt } = await openTrove({ - ICR: toBN(dec(166, 16)), - extraBoldAmount: dec(431, 18), - extraParams: { from: defaulter_4 }, - }); - - assert.isTrue(await sortedTroves.contains(defaulter_1)); - assert.isTrue(await sortedTroves.contains(defaulter_2)); - assert.isTrue(await sortedTroves.contains(defaulter_3)); - assert.isTrue(await sortedTroves.contains(defaulter_4)); - - // Price drops - const price = toBN(dec(100, 18)); - await priceFeed.setPrice(price); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - const TCR_Before = await th.getTCR(contracts); - // (5+1+2+3+1+2+3+4)*100/(410+50+50+50+101+257+328+480) - const totalCollBefore = W_coll.add(A_coll) - .add(C_coll) - .add(D_coll) - .add(d1_coll) - .add(d2_coll) - .add(d3_coll) - .add(d4_coll); - const totalDebtBefore = W_totalDebt.add(A_totalDebt) - .add(C_totalDebt) - .add(D_totalDebt) - .add(d1_totalDebt) - .add(d2_totalDebt) - .add(d3_totalDebt) - .add(d4_totalDebt); - assert.isAtMost( - th.getDifference( - TCR_Before, - totalCollBefore.mul(price).div(totalDebtBefore) - ), - 1000 - ); - - // Check pool is empty before liquidation - assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); - - // Liquidate - await troveManager.liquidateTroves(8); - - // Check all defaulters have been liquidated - assert.isFalse(await sortedTroves.contains(defaulter_1)); - assert.isFalse(await sortedTroves.contains(defaulter_2)); - assert.isFalse(await sortedTroves.contains(defaulter_3)); - assert.isFalse(await sortedTroves.contains(defaulter_4)); - - // Check that the liquidation sequence has reduced the TCR - const TCR_After = await th.getTCR(contracts); - // ((5+1+2+3)+(1+2+3+4)*0.995)*100/(410+50+50+50+101+257+328+480) - const totalCollAfter = W_coll.add(A_coll) - .add(C_coll) - .add(D_coll) - .add( - th.applyLiquidationFee(d1_coll.add(d2_coll).add(d3_coll).add(d4_coll)) - ); - const totalDebtAfter = W_totalDebt.add(A_totalDebt) - .add(C_totalDebt) - .add(D_totalDebt) - .add(d1_totalDebt) - .add(d2_totalDebt) - .add(d3_totalDebt) - .add(d4_totalDebt); - assert.isAtMost( - th.getDifference( - TCR_After, - totalCollAfter.mul(price).div(totalDebtAfter) - ), - 1000 - ); - assert.isTrue(TCR_Before.gte(TCR_After)); - assert.isTrue( - TCR_After.gte(TCR_Before.mul(th.toBN(995)).div(th.toBN(1000))) - ); - }); - - it.skip("liquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { - await openTrove({ ICR: toBN(dec(400, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(220, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); - - // Defaulter opens with 60 Bold, 0.6 ETH - await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: defaulter_1 }, - }); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - const alice_ICR_Before = await troveManager.getCurrentICR(alice, price); - const bob_ICR_Before = await troveManager.getCurrentICR(bob, price); - const carol_ICR_Before = await troveManager.getCurrentICR(carol, price); - - /* Before liquidation: - Alice ICR: = (1 * 100 / 50) = 200% - Bob ICR: (1 * 100 / 90.5) = 110.5% - Carol ICR: (1 * 100 / 100 ) = 100% - - Therefore Alice and Bob above the MCR, Carol is below */ - assert.isTrue(alice_ICR_Before.gte(mv._MCR)); - assert.isTrue(bob_ICR_Before.gte(mv._MCR)); - assert.isTrue(carol_ICR_Before.lte(mv._MCR)); - - // Liquidate defaulter. 30 Bold and 0.3 ETH is distributed uniformly between A, B and C. Each receive 10 Bold, 0.1 ETH - await troveManager.liquidate(defaulter_1); - - const alice_ICR_After = await troveManager.getCurrentICR(alice, price); - const bob_ICR_After = await troveManager.getCurrentICR(bob, price); - const carol_ICR_After = await troveManager.getCurrentICR(carol, price); - - /* After liquidation: - - Alice ICR: (1.1 * 100 / 60) = 183.33% - Bob ICR:(1.1 * 100 / 100.5) = 109.45% - Carol ICR: (1.1 * 100 ) 100% - - Check Alice is above MCR, Bob below, Carol below. */ - assert.isTrue(alice_ICR_After.gte(mv._MCR)); - assert.isTrue(bob_ICR_After.lte(mv._MCR)); - assert.isTrue(carol_ICR_After.lte(mv._MCR)); - - /* Though Bob's true ICR (including pending rewards) is below the MCR, - check that Bob's raw coll and debt has not changed, and that his "raw" ICR is above the MCR */ - const bob_Coll = (await troveManager.Troves(bob))[1]; - const bob_Debt = (await troveManager.Troves(bob))[0]; - - const bob_rawICR = bob_Coll.mul(th.toBN(dec(100, 18))).div(bob_Debt); - assert.isTrue(bob_rawICR.gte(mv._MCR)); - - // Liquidate A, B, C - await troveManager.liquidateTroves(10); - - /* Since there is 0 Bold in the stability Pool, A, with ICR >110%, should stay active. - Check Alice stays active, Carol gets liquidated, and Bob gets liquidated - (because his pending rewards bring his ICR < MCR) */ - assert.isTrue(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - - // check trove statuses - A active (1), B and C liquidated (3) - assert.equal((await troveManager.Troves(alice))[3].toString(), "1"); - assert.equal((await troveManager.Troves(bob))[3].toString(), "3"); - assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); - }); - - it.skip("liquidateTroves(): does nothing if all troves have ICR > 110% and Stability Pool is empty", async () => { - await openTrove({ ICR: toBN(dec(222, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(285, 16)), extraParams: { from: carol } }); - - // Price drops, but all troves remain active - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_Before = (await th.getTCR(contracts)).toString(); - const listSize_Before = (await sortedTroves.getSize()).toString(); - - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).gte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).gte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).gte(mv._MCR) - ); - - // Confirm 0 Bold in Stability Pool - assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); - - // Attempt liqudation sequence - await assertRevert( - troveManager.liquidateTroves(10), - "TroveManager: nothing to liquidate" - ); - - // Check all troves remain active - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - - const TCR_After = (await th.getTCR(contracts)).toString(); - const listSize_After = (await sortedTroves.getSize()).toString(); - - assert.equal(TCR_Before, TCR_After); - assert.equal(listSize_Before, listSize_After); - }); - - it.skip("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves", async () => { - // Troves to be absorbed by SP - const { collateral: F_coll, totalDebt: F_totalDebt } = await openTrove({ - ICR: toBN(dec(222, 16)), - extraParams: { from: freddy }, - }); - const { collateral: G_coll, totalDebt: G_totalDebt } = await openTrove({ - ICR: toBN(dec(222, 16)), - extraParams: { from: greta }, - }); - - // Troves to be spared - await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: alice } }); - await openTrove({ ICR: toBN(dec(266, 16)), extraParams: { from: bob } }); - await openTrove({ ICR: toBN(dec(285, 16)), extraParams: { from: carol } }); - await openTrove({ ICR: toBN(dec(308, 16)), extraParams: { from: dennis } }); - - // Whale adds Bold to SP - const spDeposit = F_totalDebt.add(G_totalDebt); - await openTrove({ - ICR: toBN(dec(285, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops, but all troves remain active - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Confirm all troves have ICR > MCR - assert.isTrue( - (await troveManager.getCurrentICR(freddy, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(greta, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).gte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).gte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).gte(mv._MCR) - ); - - // Confirm Bold in Stability Pool - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - spDeposit.toString() - ); - - // Attempt liqudation sequence - const liquidationTx = await troveManager.liquidateTroves(10); - const [liquidatedDebt, liquidatedColl, gasComp] = - th.getEmittedLiquidationValues(liquidationTx); - - // Check F and G were liquidated - assert.isFalse(await sortedTroves.contains(freddy)); - assert.isFalse(await sortedTroves.contains(greta)); - - // Check whale and A-D remain active - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - assert.isTrue(await sortedTroves.contains(dennis)); - assert.isTrue(await sortedTroves.contains(whale)); - - // Liquidation event emits coll = (F_debt + G_debt)/price*1.1*0.995, and debt = (F_debt + G_debt) - th.assertIsApproximatelyEqual(liquidatedDebt, F_totalDebt.add(G_totalDebt)); - th.assertIsApproximatelyEqual( - liquidatedColl, - th.applyLiquidationFee( - F_totalDebt.add(G_totalDebt) - .mul(toBN(dec(11, 17))) - .div(price) - ) - ); - - // check collateral surplus - const freddy_remainingCollateral = F_coll.sub( - F_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - const greta_remainingCollateral = G_coll.sub( - G_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(freddy), - freddy_remainingCollateral - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(greta), - greta_remainingCollateral - ); - - // can claim collateral - const freddy_balanceBefore = th.toBN(await web3.eth.getBalance(freddy)); - const FREDDY_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: freddy, - gasPrice: GAS_PRICE, - }) - ); - const freddy_expectedBalance = freddy_balanceBefore.sub( - th.toBN(FREDDY_GAS * GAS_PRICE) - ); - const freddy_balanceAfter = th.toBN(await web3.eth.getBalance(freddy)); - th.assertIsApproximatelyEqual( - freddy_balanceAfter, - freddy_expectedBalance.add(th.toBN(freddy_remainingCollateral)) - ); - - const greta_balanceBefore = th.toBN(await web3.eth.getBalance(greta)); - const GRETA_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: greta, - gasPrice: GAS_PRICE, - }) - ); - const greta_expectedBalance = greta_balanceBefore.sub( - th.toBN(GRETA_GAS * GAS_PRICE) - ); - const greta_balanceAfter = th.toBN(await web3.eth.getBalance(greta)); - th.assertIsApproximatelyEqual( - greta_balanceAfter, - greta_expectedBalance.add(th.toBN(greta_remainingCollateral)) - ); - }); - - it.skip("liquidateTroves(): emits liquidation event with correct values when all troves have ICR > 110% and Stability Pool covers a subset of troves, including a partial", async () => { - // Troves to be absorbed by SP - const { collateral: F_coll, totalDebt: F_totalDebt } = await openTrove({ - ICR: toBN(dec(222, 16)), - extraParams: { from: freddy }, - }); - const { collateral: G_coll, totalDebt: G_totalDebt } = await openTrove({ - ICR: toBN(dec(222, 16)), - extraParams: { from: greta }, - }); - - // Troves to be spared - const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(250, 16)), - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(266, 16)), - extraParams: { from: bob }, - }); - const { collateral: C_coll, totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(285, 16)), - extraParams: { from: carol }, - }); - const { collateral: D_coll, totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(308, 16)), - extraParams: { from: dennis }, - }); - - // Whale adds Bold to SP - const spDeposit = F_totalDebt.add(G_totalDebt).add( - A_totalDebt.div(toBN(2)) - ); - const { collateral: W_coll, totalDebt: W_totalDebt } = await openTrove({ - ICR: toBN(dec(285, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops, but all troves remain active - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Confirm all troves have ICR > MCR - assert.isTrue( - (await troveManager.getCurrentICR(freddy, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(greta, price)).gte(mv._MCR) - ); - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).gte(mv._MCR) - ); - assert.isTrue((await troveManager.getCurrentICR(bob, price)).gte(mv._MCR)); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).gte(mv._MCR) - ); - - // Confirm Bold in Stability Pool - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - spDeposit.toString() - ); - - // Attempt liqudation sequence - const liquidationTx = await troveManager.liquidateTroves(10); - const [liquidatedDebt, liquidatedColl, gasComp] = - th.getEmittedLiquidationValues(liquidationTx); - - // Check F and G were liquidated - assert.isFalse(await sortedTroves.contains(freddy)); - assert.isFalse(await sortedTroves.contains(greta)); - - // Check whale and A-D remain active - assert.isTrue(await sortedTroves.contains(alice)); - assert.isTrue(await sortedTroves.contains(bob)); - assert.isTrue(await sortedTroves.contains(carol)); - assert.isTrue(await sortedTroves.contains(dennis)); - assert.isTrue(await sortedTroves.contains(whale)); - - // Check A's collateral and debt remain the same - const entireColl_A = (await troveManager.Troves(alice))[1].add( - await troveManager.getPendingETHReward(alice) - ); - const entireDebt_A = (await troveManager.Troves(alice))[0].add( - await troveManager.getPendingBoldDebtReward(alice) - ); - - assert.equal(entireColl_A.toString(), A_coll); - assert.equal(entireDebt_A.toString(), A_totalDebt); - - /* Liquidation event emits: - coll = (F_debt + G_debt)/price*1.1*0.995 - debt = (F_debt + G_debt) */ - th.assertIsApproximatelyEqual(liquidatedDebt, F_totalDebt.add(G_totalDebt)); - th.assertIsApproximatelyEqual( - liquidatedColl, - th.applyLiquidationFee( - F_totalDebt.add(G_totalDebt) - .mul(toBN(dec(11, 17))) - .div(price) - ) - ); - - // check collateral surplus - const freddy_remainingCollateral = F_coll.sub( - F_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - const greta_remainingCollateral = G_coll.sub( - G_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(freddy), - freddy_remainingCollateral - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(greta), - greta_remainingCollateral - ); - - // can claim collateral - const freddy_balanceBefore = th.toBN(await web3.eth.getBalance(freddy)); - const FREDDY_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: freddy, - gasPrice: GAS_PRICE, - }) - ); - const freddy_expectedBalance = freddy_balanceBefore.sub( - th.toBN(FREDDY_GAS * GAS_PRICE) - ); - const freddy_balanceAfter = th.toBN(await web3.eth.getBalance(freddy)); - th.assertIsApproximatelyEqual( - freddy_balanceAfter, - freddy_expectedBalance.add(th.toBN(freddy_remainingCollateral)) - ); - - const greta_balanceBefore = th.toBN(await web3.eth.getBalance(greta)); - const GRETA_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: greta, - gasPrice: GAS_PRICE, - }) - ); - const greta_expectedBalance = greta_balanceBefore.sub( - th.toBN(GRETA_GAS * GAS_PRICE) - ); - const greta_balanceAfter = th.toBN(await web3.eth.getBalance(greta)); - th.assertIsApproximatelyEqual( - greta_balanceAfter, - greta_expectedBalance.add(th.toBN(greta_remainingCollateral)) - ); - }); - - it.skip("liquidateTroves(): does not affect the liquidated user's token balances", async () => { - await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: whale } }); - - // D, E, F open troves that will fall below MCR when price drops to 100 - const { boldAmount: boldAmountD } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: dennis }, - }); - const { boldAmount: boldAmountE } = await openTrove({ - ICR: toBN(dec(133, 16)), - extraParams: { from: erin }, - }); - const { boldAmount: boldAmountF } = await openTrove({ - ICR: toBN(dec(111, 16)), - extraParams: { from: freddy }, - }); - - // Check list size is 4 - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Check token balances before - assert.equal((await boldToken.balanceOf(dennis)).toString(), boldAmountD); - assert.equal((await boldToken.balanceOf(erin)).toString(), boldAmountE); - assert.equal((await boldToken.balanceOf(freddy)).toString(), boldAmountF); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - //Liquidate sequence - await troveManager.liquidateTroves(10); - - // Check Whale remains in the system - assert.isTrue(await sortedTroves.contains(whale)); - - // Check D, E, F have been removed - assert.isFalse(await sortedTroves.contains(dennis)); - assert.isFalse(await sortedTroves.contains(erin)); - assert.isFalse(await sortedTroves.contains(freddy)); - - // Check token balances of users whose troves were liquidated, have not changed - assert.equal((await boldToken.balanceOf(dennis)).toString(), boldAmountD); - assert.equal((await boldToken.balanceOf(erin)).toString(), boldAmountE); - assert.equal((await boldToken.balanceOf(freddy)).toString(), boldAmountF); - }); - - it.skip("liquidateTroves(): Liquidating troves at 100 < ICR < 110 with SP deposits correctly impacts their SP deposit and ETH gain", async () => { - // Whale provides Bold to the SP - const { boldAmount: W_boldAmount } = await openTrove({ - ICR: toBN(dec(300, 16)), - extraBoldAmount: dec(4000, 18), - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(W_boldAmount, { - from: whale, - }); - - const { - boldAmount: A_boldAmount, - totalDebt: A_totalDebt, - collateral: A_coll, - } = await openTrove({ - ICR: toBN(dec(191, 16)), - extraBoldAmount: dec(40, 18), - extraParams: { from: alice }, - }); - const { - boldAmount: B_boldAmount, - totalDebt: B_totalDebt, - collateral: B_coll, - } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: dec(240, 18), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt, collateral: C_coll } = await openTrove({ - ICR: toBN(dec(209, 16)), - extraParams: { from: carol }, - }); - - // A, B provide to the SP - await stabilityPool.provideToSP(A_boldAmount, { - from: alice, - }); - await stabilityPool.provideToSP(B_boldAmount, {from: bob }); - - const totalDeposit = W_boldAmount.add(A_boldAmount).add(B_boldAmount); - - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Price drops - await priceFeed.setPrice(dec(105, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check Bold in Pool - assert.equal( - (await stabilityPool.getTotalBoldDeposits()).toString(), - totalDeposit - ); - - // *** Check A, B, C ICRs 100 { - // Whale provides 400 Bold to the SP - await openTrove({ - ICR: toBN(dec(300, 16)), - extraBoldAmount: dec(400, 18), - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(dec(400, 18), { - from: whale, - }); - - await openTrove({ - ICR: toBN(dec(182, 16)), - extraBoldAmount: dec(170, 18), - extraParams: { from: alice }, - }); - await openTrove({ - ICR: toBN(dec(180, 16)), - extraBoldAmount: dec(300, 18), - extraParams: { from: bob }, - }); - await openTrove({ ICR: toBN(dec(170, 16)), extraParams: { from: carol } }); - - // A, B provide 100, 300 to the SP - await stabilityPool.provideToSP(dec(100, 18), { - from: alice, - }); - await stabilityPool.provideToSP(dec(300, 18), {from: bob }); - - assert.equal((await sortedTroves.getSize()).toString(), "4"); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - - // Confirm Recovery Mode - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check Bold and ETH in Pool before - const BoldinSP_Before = ( - await stabilityPool.getTotalBoldDeposits() - ).toString(); - const ETHinSP_Before = (await stabilityPool.getETH()).toString(); - assert.equal(BoldinSP_Before, dec(800, 18)); - assert.equal(ETHinSP_Before, "0"); - - // *** Check A, B, C ICRs < 100 - assert.isTrue( - (await troveManager.getCurrentICR(alice, price)).lte(mv._ICR100) - ); - assert.isTrue( - (await troveManager.getCurrentICR(bob, price)).lte(mv._ICR100) - ); - assert.isTrue( - (await troveManager.getCurrentICR(carol, price)).lte(mv._ICR100) - ); - - // Liquidate - await troveManager.liquidateTroves(10); - - // Check all defaulters have been liquidated - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(carol)); - - // check system sized reduced to 1 troves - assert.equal((await sortedTroves.getSize()).toString(), "1"); - - // Check Bold and ETH in Pool after - const BoldinSP_After = ( - await stabilityPool.getTotalBoldDeposits() - ).toString(); - const ETHinSP_After = (await stabilityPool.getETH()).toString(); - assert.equal(BoldinSP_Before, BoldinSP_After); - assert.equal(ETHinSP_Before, ETHinSP_After); - - // Check remaining Bold Deposits and ETH gain, for whale and depositors whose troves were liquidated - const whale_Deposit_After = ( - await stabilityPool.getCompoundedBoldDeposit(whale) - ).toString(); - const alice_Deposit_After = ( - await stabilityPool.getCompoundedBoldDeposit(alice) - ).toString(); - const bob_Deposit_After = ( - await stabilityPool.getCompoundedBoldDeposit(bob) - ).toString(); - - const whale_ETHGain_After = ( - await stabilityPool.getDepositorETHGain(whale) - ).toString(); - const alice_ETHGain_After = ( - await stabilityPool.getDepositorETHGain(alice) - ).toString(); - const bob_ETHGain_After = ( - await stabilityPool.getDepositorETHGain(bob) - ).toString(); - - assert.equal(whale_Deposit_After, dec(400, 18)); - assert.equal(alice_Deposit_After, dec(100, 18)); - assert.equal(bob_Deposit_After, dec(300, 18)); - - assert.equal(whale_ETHGain_After, "0"); - assert.equal(alice_ETHGain_After, "0"); - assert.equal(bob_ETHGain_After, "0"); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains active", async () => { - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(196, 16)), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(206, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add( - C_totalDebt.div(toBN(2)) - ); - await openTrove({ - ICR: toBN(dec(300, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D, E troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 253 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 50 Bold in the Pool to absorb exactly half of Carol's debt (100) */ - await troveManager.liquidateTroves(10); - - // Check A and B closed - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - - // Check C remains active - assert.isTrue(await sortedTroves.contains(carol)); - assert.equal((await troveManager.Troves(carol))[3].toString(), "1"); // check Status is active - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: non liquidated trove remains in TroveOwners Array", async () => { - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(210, 16)), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(211, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(212, 16)), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(219, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(221, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add( - C_totalDebt.div(toBN(2)) - ); - await openTrove({ - ICR: toBN(dec(220, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C. - With 253 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 50 Bold in the Pool to absorb exactly half of Carol's debt (100) */ - await troveManager.liquidateTroves(10); - - // Check C is in Trove owners array - const arrayLength = (await troveManager.getTroveOwnersCount()).toNumber(); - let addressFound = false; - let addressIdx = 0; - - for (let i = 0; i < arrayLength; i++) { - const address = (await troveManager.TroveOwners(i)).toString(); - if (address == carol) { - addressFound = true; - addressIdx = i; - } - } - - assert.isTrue(addressFound); - - // Check TroveOwners idx on trove struct == idx of address found in TroveOwners array - const idxOnStruct = (await troveManager.Troves(carol))[4].toString(); - assert.equal(addressIdx.toString(), idxOnStruct); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, emptied pool", async () => { - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(196, 16)), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(206, 16)), - extraParams: { from: dennis }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: D_totalDebt, - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add(D_totalDebt); - await openTrove({ - ICR: toBN(dec(220, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D, E troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - const ICR_D = await troveManager.getCurrentICR(dennis, price); - const ICR_E = await troveManager.getCurrentICR(erin, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - assert.isTrue(ICR_D.gt(mv._MCR) && ICR_D.lt(TCR)); - assert.isTrue(ICR_E.gt(mv._MCR) && ICR_E.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 300 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 97 Bold in the Pool that won’t be enough to absorb Carol, - but it will be enough to liquidate Dennis. Afterwards the pool will be empty, - so Erin won’t liquidated. */ - const tx = await troveManager.liquidateTroves(10); - console.log("gasUsed: ", tx.receipt.gasUsed); - - // Check A, B and D are closed - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - console.log(await sortedTroves.contains(carol)); - assert.isFalse(await sortedTroves.contains(dennis)); - - // Check whale, C and E stay active - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(carol)); - assert.isTrue(await sortedTroves.contains(erin)); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: still can liquidate further troves after the non-liquidated, non emptied pool", async () => { - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(196, 16)), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: D_totalDebt } = await openTrove({ - ICR: toBN(dec(206, 16)), - extraParams: { from: dennis }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraBoldAmount: D_totalDebt, - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add(D_totalDebt); - await openTrove({ - ICR: toBN(dec(220, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C, D, E troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - const ICR_D = await troveManager.getCurrentICR(dennis, price); - const ICR_E = await troveManager.getCurrentICR(erin, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - assert.isTrue(ICR_D.gt(mv._MCR) && ICR_D.lt(TCR)); - assert.isTrue(ICR_E.gt(mv._MCR) && ICR_E.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 301 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 97 Bold in the Pool that won’t be enough to absorb Carol, - but it will be enough to liquidate Dennis. Afterwards the pool will be empty, - so Erin won’t liquidated. - Note that, compared to the previous test, this one will make 1 more loop iteration, - so it will consume more gas. */ - const tx = await troveManager.liquidateTroves(10); - console.log("gasUsed: ", tx.receipt.gasUsed); - - // Check A, B and D are closed - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - assert.isFalse(await sortedTroves.contains(dennis)); - - // Check whale, C and E stay active - assert.isTrue(await sortedTroves.contains(whale)); - assert.isTrue(await sortedTroves.contains(carol)); - assert.isTrue(await sortedTroves.contains(erin)); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: total liquidated coll and debt is correct", async () => { - const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(196, 16)), - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(206, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add( - C_totalDebt.div(toBN(2)) - ); - await openTrove({ - ICR: toBN(dec(220, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - - const entireSystemCollBefore = await troveManager.getEntireSystemColl(); - const entireSystemDebtBefore = await troveManager.getEntireSystemDebt(); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 253 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 50 Bold in the Pool that won’t be enough to absorb any other trove */ - const tx = await troveManager.liquidateTroves(10); - - // Expect system debt reduced by 203 Bold and system coll 2.3 ETH - const entireSystemCollAfter = await troveManager.getEntireSystemColl(); - const entireSystemDebtAfter = await troveManager.getEntireSystemDebt(); - - const changeInEntireSystemColl = entireSystemCollBefore.sub( - entireSystemCollAfter - ); - const changeInEntireSystemDebt = entireSystemDebtBefore.sub( - entireSystemDebtAfter - ); - - assert.equal(changeInEntireSystemColl.toString(), A_coll.add(B_coll)); - th.assertIsApproximatelyEqual( - changeInEntireSystemDebt.toString(), - A_totalDebt.add(B_totalDebt) - ); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: emits correct liquidation event values", async () => { - const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(210, 16)), - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(211, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(212, 16)), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(219, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(221, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add( - C_totalDebt.div(toBN(2)) - ); - await openTrove({ - ICR: toBN(dec(240, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C = await troveManager.getCurrentICR(carol, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C.gt(mv._MCR) && ICR_C.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 253 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 50 Bold in the Pool which won’t be enough for any other liquidation */ - const liquidationTx = await troveManager.liquidateTroves(10); - - const [liquidatedDebt, liquidatedColl, collGasComp, boldGasComp] = - th.getEmittedLiquidationValues(liquidationTx); - - th.assertIsApproximatelyEqual(liquidatedDebt, A_totalDebt.add(B_totalDebt)); - const equivalentColl = A_totalDebt.add(B_totalDebt) - .mul(toBN(dec(11, 17))) - .div(price); - th.assertIsApproximatelyEqual( - liquidatedColl, - th.applyLiquidationFee(equivalentColl) - ); - th.assertIsApproximatelyEqual( - collGasComp, - equivalentColl.sub(th.applyLiquidationFee(equivalentColl)) - ); // 0.5% of 283/120*1.1 - assert.equal(boldGasComp.toString(), dec(400, 18)); - - // check collateral surplus - const alice_remainingCollateral = A_coll.sub( - A_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - const bob_remainingCollateral = B_coll.sub( - B_totalDebt.mul(th.toBN(dec(11, 17))).div(price) - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(alice), - alice_remainingCollateral - ); - th.assertIsApproximatelyEqual( - await collSurplusPool.getCollateral(bob), - bob_remainingCollateral - ); - - // can claim collateral - const alice_balanceBefore = th.toBN(await web3.eth.getBalance(alice)); - const ALICE_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: alice, - gasPrice: GAS_PRICE, - }) - ); - const alice_balanceAfter = th.toBN(await web3.eth.getBalance(alice)); - th.assertIsApproximatelyEqual( - alice_balanceAfter, - alice_balanceBefore.add( - th.toBN(alice_remainingCollateral).sub(th.toBN(ALICE_GAS * GAS_PRICE)) - ) - ); - - const bob_balanceBefore = th.toBN(await web3.eth.getBalance(bob)); - const BOB_GAS = th.gasUsed( - await borrowerOperations.claimCollateral({ - from: bob, - gasPrice: GAS_PRICE, - }) - ); - const bob_balanceAfter = th.toBN(await web3.eth.getBalance(bob)); - th.assertIsApproximatelyEqual( - bob_balanceAfter, - bob_balanceBefore.add( - th.toBN(bob_remainingCollateral).sub(th.toBN(BOB_GAS * GAS_PRICE)) - ) - ); - }); - - it.skip("liquidateTroves() with a non fullfilled liquidation: ICR of non liquidated trove does not change", async () => { - const { totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(196, 16)), - extraParams: { from: alice }, - }); - const { totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(198, 16)), - extraParams: { from: bob }, - }); - const { totalDebt: C_totalDebt } = await openTrove({ - ICR: toBN(dec(200, 16)), - extraParams: { from: carol }, - }); - await openTrove({ ICR: toBN(dec(206, 16)), extraParams: { from: dennis } }); - await openTrove({ ICR: toBN(dec(208, 16)), extraParams: { from: erin } }); - - // Whale provides Bold to the SP - const spDeposit = A_totalDebt.add(B_totalDebt).add( - C_totalDebt.div(toBN(2)) - ); - await openTrove({ - ICR: toBN(dec(220, 16)), - extraBoldAmount: spDeposit, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(spDeposit, {from: whale }); - - // Price drops - await priceFeed.setPrice(dec(120, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check A, B, C troves are in range 110% < ICR < TCR - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - const ICR_C_Before = await troveManager.getCurrentICR(carol, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - assert.isTrue(ICR_C_Before.gt(mv._MCR) && ICR_C_Before.lt(TCR)); - - /* Liquidate troves. Troves are ordered by ICR, from low to high: A, B, C, D, E. - With 253 in the SP, Alice (102 debt) and Bob (101 debt) should be entirely liquidated. - That leaves 50 Bold in the Pool to absorb exactly half of Carol's debt (100) */ - await troveManager.liquidateTroves(10); - - const ICR_C_After = await troveManager.getCurrentICR(carol, price); - assert.equal(ICR_C_Before.toString(), ICR_C_After); - }); - - // TODO: LiquidateTroves tests that involve troves with ICR > TCR - // --- batchLiquidateTroves() --- it("batchLiquidateTroves(): Liquidates all troves with ICR < 110%, transitioning Normal -> Recovery Mode", async () => { diff --git a/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js b/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js index e1af318d..c6e4232c 100644 --- a/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js +++ b/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js @@ -265,77 +265,5 @@ contract( assert.equal((await troveManager.Troves(carol))[3], "1"); }); }); - - context("Sequential liquidations", () => { - const setup = async () => { - const { collateral: A_coll, totalDebt: A_totalDebt } = await openTrove({ - ICR: toBN(dec(299, 16)), - extraParams: { from: alice }, - }); - const { collateral: B_coll, totalDebt: B_totalDebt } = await openTrove({ - ICR: toBN(dec(298, 16)), - extraParams: { from: bob }, - }); - - const totalLiquidatedDebt = A_totalDebt.add(B_totalDebt); - - await openTrove({ - ICR: toBN(dec(300, 16)), - extraBoldAmount: totalLiquidatedDebt, - extraParams: { from: whale }, - }); - await stabilityPool.provideToSP(totalLiquidatedDebt, { - from: whale, - }); - - // Price drops - await priceFeed.setPrice(dec(100, 18)); - const price = await priceFeed.getPrice(); - const TCR = await th.getTCR(contracts); - - // Check Recovery Mode is active - assert.isTrue(await th.checkRecoveryMode(contracts)); - - // Check troves A, B are in range 110% < ICR < TCR, C is below 100% - const ICR_A = await troveManager.getCurrentICR(alice, price); - const ICR_B = await troveManager.getCurrentICR(bob, price); - - assert.isTrue(ICR_A.gt(mv._MCR) && ICR_A.lt(TCR)); - assert.isTrue(ICR_B.gt(mv._MCR) && ICR_B.lt(TCR)); - - return { - A_coll, - A_totalDebt, - B_coll, - B_totalDebt, - totalLiquidatedDebt, - price, - }; - }; - - it("First trove only doesn’t get out of Recovery Mode", async () => { - await setup(); - const tx = await troveManager.liquidateTroves(1); - - const TCR = await th.getTCR(contracts); - assert.isTrue(await th.checkRecoveryMode(contracts)); - }); - - it("Two troves over MCR are liquidated", async () => { - await setup(); - const tx = await troveManager.liquidateTroves(10); - - const liquidationEvents = th.getAllEventsByName(tx, "TroveLiquidated"); - assert.equal(liquidationEvents.length, 2, "Not enough liquidations"); - - // Confirm all troves removed - assert.isFalse(await sortedTroves.contains(alice)); - assert.isFalse(await sortedTroves.contains(bob)); - - // Confirm troves have status 'closed by liquidation' (Status enum element idx 3) - assert.equal((await troveManager.Troves(alice))[3], "3"); - assert.equal((await troveManager.Troves(bob))[3], "3"); - }); - }); } ); From 35397ec711a30bba808cc0fe00ab9ee32608a927 Mon Sep 17 00:00:00 2001 From: RickGriff Date: Wed, 14 Feb 2024 18:24:08 +0700 Subject: [PATCH 6/9] Minor comment and test fixes --- contracts/src/BorrowerOperations.sol | 1 + contracts/src/test/interestRateBasic.t.sol | 11 +++++------ contracts/test/TroveManagerTest.js | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/src/BorrowerOperations.sol b/contracts/src/BorrowerOperations.sol index ed03b14c..3b00657a 100644 --- a/contracts/src/BorrowerOperations.sol +++ b/contracts/src/BorrowerOperations.sol @@ -232,6 +232,7 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe } function adjustTroveInterestRate(uint _newAnnualInterestRate, address _upperHint, address _lowerHint) external { + // TODO: Delegation functionality _requireValidAnnualInterestRate(_newAnnualInterestRate); ITroveManager troveManagerCached = troveManager; _requireTroveisActive(troveManagerCached, msg.sender); diff --git a/contracts/src/test/interestRateBasic.t.sol b/contracts/src/test/interestRateBasic.t.sol index 26f9f38b..38c48e70 100644 --- a/contracts/src/test/interestRateBasic.t.sol +++ b/contracts/src/test/interestRateBasic.t.sol @@ -111,7 +111,6 @@ contract InterestRateBasic is DevTestSetup { assertEq(troveManager.getTroveAnnualInterestRate(C), 1e18); } - // TODO: test adjusting interest rates correctly orders sorted list function testAdjustTroveInterestRateInsertsToCorrectPositionInSortedList() public { priceFeed.setPrice(2000e18); openTroveNoHints100pctMaxFee(A, 2 ether, 2000e18, 1e17); @@ -120,7 +119,7 @@ contract InterestRateBasic is DevTestSetup { openTroveNoHints100pctMaxFee(D, 2 ether, 2000e18, 4e17); openTroveNoHints100pctMaxFee(E, 2 ether, 2000e18, 5e17); - // Check initial sorted list order - expect [A:1%, B:2%, C:3%, D:4%, E:5%] + // Check initial sorted list order - expect [A:10%, B:02%, C:30%, D:40%, E:50%] // A assertEq(sortedTroves.getNext(A), ZERO_ADDRESS); // tail assertEq(sortedTroves.getPrev(A), B); @@ -137,17 +136,17 @@ contract InterestRateBasic is DevTestSetup { assertEq(sortedTroves.getNext(E), D); assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); // head - // C sets rate to 0%, moves to tail - expect [C:0%, A:1%, B:2%, D:4%, E:5%] + // C sets rate to 0%, moves to tail - expect [C:0%, A:10%, B:20%, D:40%, E:50%] changeInterestRateNoHints(C, 0); assertEq(sortedTroves.getNext(C), ZERO_ADDRESS); assertEq(sortedTroves.getPrev(C), A); - // D sets rate to 7%, moves to head - expect [C:0%, A:1%, B:2%, E:5%, D:7%] + // D sets rate to 7%, moves to head - expect [C:0%, A:10%, B:20%, E:50%, D:70%] changeInterestRateNoHints(D, 7e17); assertEq(sortedTroves.getNext(D), E); assertEq(sortedTroves.getPrev(D), ZERO_ADDRESS); - // A sets rate to 6%, moves up 2 positions - expect [C:0%, B:2%, E:5%, A:6%, D:7%] + // A sets rate to 6%, moves up 2 positions - expect [C:0%, B:20%, E:50%, A:60%, D:70%] changeInterestRateNoHints(A, 6e17); assertEq(sortedTroves.getNext(A), E); assertEq(sortedTroves.getPrev(A), D); @@ -192,7 +191,7 @@ contract InterestRateBasic is DevTestSetup { // Adjust E's coll + debt adjustTrove100pctMaxFee(E, 10 ether, 5000e18, true, true); - // Check C's neighbors unchanged + // Check E's neighbors unchanged assertEq(sortedTroves.getNext(E), D); assertEq(sortedTroves.getPrev(E), ZERO_ADDRESS); // head } diff --git a/contracts/test/TroveManagerTest.js b/contracts/test/TroveManagerTest.js index b20f98e3..57a13027 100644 --- a/contracts/test/TroveManagerTest.js +++ b/contracts/test/TroveManagerTest.js @@ -1241,7 +1241,7 @@ contract("TroveManager", async (accounts) => { // TODO: revisit the relevance of this test since it relies on liquidateTroves(), which now no longer works due to ordering by interest rate. // Can we achieve / test the same thing using another liquidation function? - it.skip("batchLiquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { + it("batchLiquidateTroves(): liquidates a Trove that a) was skipped in a previous liquidation and b) has pending rewards", async () => { // A, B, C, D, E open troves await openTrove({ ICR: toBN(dec(300, 16)), extraParams: { from: C } }); await openTrove({ ICR: toBN(dec(364, 16)), extraParams: { from: D } }); @@ -1277,7 +1277,7 @@ contract("TroveManager", async (accounts) => { assert.isTrue(ICR_C.gt(TCR)); // Attempt to liquidate B and C, which skips C in the liquidation since it is immune - const liqTxBC = await troveManager.liquidateTroves(2); + const liqTxBC = await troveManager.batchLiquidateTroves([B,C]); assert.isTrue(liqTxBC.receipt.status); assert.isFalse(await sortedTroves.contains(B)); assert.isTrue(await sortedTroves.contains(C)); @@ -1286,8 +1286,8 @@ contract("TroveManager", async (accounts) => { // // All remaining troves D and E repay a little debt, applying their pending rewards assert.isTrue((await sortedTroves.getSize()).eq(toBN("3"))); - await borrowerOperations.repayBold(dec(1, 18), D, D, { from: D }); - await borrowerOperations.repayBold(dec(1, 18), E, E, { from: E }); + await borrowerOperations.repayBold(dec(1, 18), { from: D }); + await borrowerOperations.repayBold(dec(1, 18), { from: E }); // Check C is the only trove that has pending rewards assert.isTrue(await troveManager.hasPendingRewards(C)); From 7be23a899e73be52b17250e07c4be44eda787d6e Mon Sep 17 00:00:00 2001 From: RickGriff Date: Wed, 14 Feb 2024 18:31:19 +0700 Subject: [PATCH 7/9] Test helper tweaks --- contracts/utils/testHelpers.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/utils/testHelpers.js b/contracts/utils/testHelpers.js index 920198b7..25be0576 100644 --- a/contracts/utils/testHelpers.js +++ b/contracts/utils/testHelpers.js @@ -336,9 +336,7 @@ class TestHelper { * So, it adds the gas compensation and the borrowing fee */ static async getOpenTroveTotalDebt(contracts, boldAmount) { - const fee = this.toBN(0); - const compositeDebt = await this.getCompositeDebt(contracts, boldAmount); - return compositeDebt.add(fee); + return(await this.getCompositeDebt(contracts, boldAmount)); } /* @@ -354,11 +352,13 @@ class TestHelper { } // Subtracts the borrowing fee + // TODO: remove this, since we won't use the old borrow fee scheme static async getNetBorrowingAmount(contracts, debtWithFee) { return this.toBN(debtWithFee); } // Adds the borrowing fee + // TODO: remove this, since we won't use the old borrow fee scheme static async getAmountWithBorrowingFee(contracts, boldAmount) { return boldAmount; } From 60b2c214b7c3cd5ad536365237b3d2dc7eb0433e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Fingen?= Date: Mon, 19 Feb 2024 18:28:47 +0000 Subject: [PATCH 8/9] test: Translate liquidateTroves into batchLiquidateTroves --- contracts/test/TroveManagerTest.js | 526 +++++++++++++++++++++++++++++ 1 file changed, 526 insertions(+) diff --git a/contracts/test/TroveManagerTest.js b/contracts/test/TroveManagerTest.js index 57a13027..4050838f 100644 --- a/contracts/test/TroveManagerTest.js +++ b/contracts/test/TroveManagerTest.js @@ -1238,6 +1238,532 @@ contract("TroveManager", async (accounts) => { }); // --- batchLiquidateTroves() --- + + it("batchLiquidateTroves(): liquidates based on entire/collateral debt (including pending rewards), not raw collateral/debt", async () => { + await openTrove({ ICR: toBN(dec(400, 16)), extraParams: { from: alice } }); + await openTrove({ ICR: toBN(dec(221, 16)), extraParams: { from: bob } }); + await openTrove({ ICR: toBN(dec(200, 16)), extraParams: { from: carol } }); + await openTrove({ + ICR: toBN(dec(200, 16)), + extraParams: { from: defaulter_1 }, + }); + + // Price drops + await priceFeed.setPrice(dec(100, 18)); + const price = await priceFeed.getPrice(); + + const alice_ICR_Before = await troveManager.getCurrentICR(alice, price); + const bob_ICR_Before = await troveManager.getCurrentICR(bob, price); + const carol_ICR_Before = await troveManager.getCurrentICR(carol, price); + + /* Before liquidation: + Alice ICR: = (2 * 100 / 100) = 200% + Bob ICR: (1 * 100 / 90.5) = 110.5% + Carol ICR: (1 * 100 / 100 ) = 100% + + Therefore Alice and Bob above the MCR, Carol is below */ + assert.isTrue(alice_ICR_Before.gte(mv._MCR)); + assert.isTrue(bob_ICR_Before.gte(mv._MCR)); + assert.isTrue(carol_ICR_Before.lte(mv._MCR)); + + // Liquidate defaulter. 30 Bold and 0.3 ETH is distributed uniformly between A, B and C. Each receive 10 Bold, 0.1 ETH + await troveManager.liquidate(defaulter_1); + + const alice_ICR_After = await troveManager.getCurrentICR(alice, price); + const bob_ICR_After = await troveManager.getCurrentICR(bob, price); + const carol_ICR_After = await troveManager.getCurrentICR(carol, price); + + /* After liquidation: + + Alice ICR: (1.0995 * 100 / 60) = 183.25% + Bob ICR:(1.0995 * 100 / 100.5) = 109.40% + Carol ICR: (1.0995 * 100 / 110 ) 99.95% + + Check Alice is above MCR, Bob below, Carol below. */ + assert.isTrue(alice_ICR_After.gte(mv._MCR)); + assert.isTrue(bob_ICR_After.lte(mv._MCR)); + assert.isTrue(carol_ICR_After.lte(mv._MCR)); + + /* Though Bob's true ICR (including pending rewards) is below the MCR, check that Bob's raw coll and debt has not changed */ + const bob_Coll = (await troveManager.Troves(bob))[1]; + const bob_Debt = (await troveManager.Troves(bob))[0]; + + const bob_rawICR = bob_Coll.mul(toBN(dec(100, 18))).div(bob_Debt); + assert.isTrue(bob_rawICR.gte(mv._MCR)); + + // Whale enters system, pulling it into Normal Mode + await openTrove({ + ICR: toBN(dec(10, 18)), + extraBoldAmount: dec(1, 24), + extraParams: { from: whale }, + }); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + //liquidate A, B, C + await troveManager.batchLiquidateTroves([alice, bob, carol]); + + // Check A stays active, B and C get liquidated + assert.isTrue(await sortedTroves.contains(alice)); + assert.isFalse(await sortedTroves.contains(bob)); + assert.isFalse(await sortedTroves.contains(carol)); + + // check trove statuses - A active (1), B and C closed by liquidation (3) + assert.equal((await troveManager.Troves(alice))[3].toString(), "1"); + assert.equal((await troveManager.Troves(bob))[3].toString(), "3"); + assert.equal((await troveManager.Troves(carol))[3].toString(), "3"); + }); + + it("batchLiquidateTroves(): liquidates troves with ICR < MCR", async () => { + await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); + + // A, B, C open troves that will remain active when price drops to 100 + await openTrove({ ICR: toBN(dec(220, 16)), extraParams: { from: alice } }); + await openTrove({ ICR: toBN(dec(230, 16)), extraParams: { from: bob } }); + await openTrove({ ICR: toBN(dec(240, 16)), extraParams: { from: carol } }); + + // D, E, F open troves that will fall below MCR when price drops to 100 + await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: dennis } }); + await openTrove({ ICR: toBN(dec(216, 16)), extraParams: { from: erin } }); + await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: flyn } }); + + // Check list size is 7 + assert.equal((await sortedTroves.getSize()).toString(), "7"); + + // Price drops + await priceFeed.setPrice(dec(100, 18)); + const price = await priceFeed.getPrice(); + + const alice_ICR = await troveManager.getCurrentICR(alice, price); + const bob_ICR = await troveManager.getCurrentICR(bob, price); + const carol_ICR = await troveManager.getCurrentICR(carol, price); + const dennis_ICR = await troveManager.getCurrentICR(dennis, price); + const erin_ICR = await troveManager.getCurrentICR(erin, price); + const flyn_ICR = await troveManager.getCurrentICR(flyn, price); + + // Check A, B, C have ICR above MCR + assert.isTrue(alice_ICR.gte(mv._MCR)); + assert.isTrue(bob_ICR.gte(mv._MCR)); + assert.isTrue(carol_ICR.gte(mv._MCR)); + + // Check D, E, F have ICR below MCR + assert.isTrue(dennis_ICR.lte(mv._MCR)); + assert.isTrue(erin_ICR.lte(mv._MCR)); + assert.isTrue(flyn_ICR.lte(mv._MCR)); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + //Liquidate sequence + await troveManager.batchLiquidateTroves([alice, bob, carol, dennis, erin, flyn, whale]); + + // check list size reduced to 4 + assert.equal((await sortedTroves.getSize()).toString(), "4"); + + // Check Whale and A, B, C remain in the system + assert.isTrue(await sortedTroves.contains(whale)); + assert.isTrue(await sortedTroves.contains(alice)); + assert.isTrue(await sortedTroves.contains(bob)); + assert.isTrue(await sortedTroves.contains(carol)); + + // Check D, E, F have been removed + assert.isFalse(await sortedTroves.contains(dennis)); + assert.isFalse(await sortedTroves.contains(erin)); + assert.isFalse(await sortedTroves.contains(flyn)); + }); + + it("batchLiquidateTroves(): does not affect the liquidated user's token balances", async () => { + await openTrove({ ICR: toBN(dec(20, 18)), extraParams: { from: whale } }); + + // D, E, F open troves that will fall below MCR when price drops to 100 + await openTrove({ ICR: toBN(dec(218, 16)), extraParams: { from: dennis } }); + await openTrove({ ICR: toBN(dec(216, 16)), extraParams: { from: erin } }); + await openTrove({ ICR: toBN(dec(210, 16)), extraParams: { from: flyn } }); + + const D_balanceBefore = await boldToken.balanceOf(dennis); + const E_balanceBefore = await boldToken.balanceOf(erin); + const F_balanceBefore = await boldToken.balanceOf(flyn); + + // Check list size is 4 + assert.equal((await sortedTroves.getSize()).toString(), "4"); + + // Price drops + await priceFeed.setPrice(dec(100, 18)); + const price = await priceFeed.getPrice(); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + //Liquidate sequence + await troveManager.batchLiquidateTroves([dennis, erin, flyn, whale]); + + // check list size reduced to 1 + assert.equal((await sortedTroves.getSize()).toString(), "1"); + + // Check Whale remains in the system + assert.isTrue(await sortedTroves.contains(whale)); + + // Check D, E, F have been removed + assert.isFalse(await sortedTroves.contains(dennis)); + assert.isFalse(await sortedTroves.contains(erin)); + assert.isFalse(await sortedTroves.contains(flyn)); + + // Check token balances of users whose troves were liquidated, have not changed + assert.equal( + (await boldToken.balanceOf(dennis)).toString(), + D_balanceBefore + ); + assert.equal((await boldToken.balanceOf(erin)).toString(), E_balanceBefore); + assert.equal((await boldToken.balanceOf(flyn)).toString(), F_balanceBefore); + }); + + it("batchLiquidateTroves(): A liquidation sequence containing Pool offsets increases the TCR", async () => { + // Whale provides 500 Bold to SP + await openTrove({ + ICR: toBN(dec(100, 18)), + extraBoldAmount: toBN(dec(500, 18)), + extraParams: { from: whale }, + }); + await stabilityPool.provideToSP(dec(500, 18), { + from: whale, + }); + + await openTrove({ ICR: toBN(dec(4, 18)), extraParams: { from: alice } }); + await openTrove({ ICR: toBN(dec(28, 18)), extraParams: { from: bob } }); + await openTrove({ ICR: toBN(dec(8, 18)), extraParams: { from: carol } }); + await openTrove({ ICR: toBN(dec(80, 18)), extraParams: { from: dennis } }); + + await openTrove({ + ICR: toBN(dec(199, 16)), + extraParams: { from: defaulter_1 }, + }); + await openTrove({ + ICR: toBN(dec(156, 16)), + extraParams: { from: defaulter_2 }, + }); + await openTrove({ + ICR: toBN(dec(183, 16)), + extraParams: { from: defaulter_3 }, + }); + await openTrove({ + ICR: toBN(dec(166, 16)), + extraParams: { from: defaulter_4 }, + }); + + assert.isTrue(await sortedTroves.contains(defaulter_1)); + assert.isTrue(await sortedTroves.contains(defaulter_2)); + assert.isTrue(await sortedTroves.contains(defaulter_3)); + assert.isTrue(await sortedTroves.contains(defaulter_4)); + + assert.equal((await sortedTroves.getSize()).toString(), "9"); + + // Price drops + await priceFeed.setPrice(dec(100, 18)); + + const TCR_Before = await th.getTCR(contracts); + + // Check pool has 500 Bold + assert.equal( + (await stabilityPool.getTotalBoldDeposits()).toString(), + dec(500, 18) + ); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + // Liquidate troves + await troveManager.batchLiquidateTroves([alice, bob, carol, dennis, defaulter_1, defaulter_2, defaulter_3, defaulter_4, whale]); + + // Check pool has been emptied by the liquidations + assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); + + // Check all defaulters have been liquidated + assert.isFalse(await sortedTroves.contains(defaulter_1)); + assert.isFalse(await sortedTroves.contains(defaulter_2)); + assert.isFalse(await sortedTroves.contains(defaulter_3)); + assert.isFalse(await sortedTroves.contains(defaulter_4)); + + // check system sized reduced to 5 troves + assert.equal((await sortedTroves.getSize()).toString(), "5"); + + // Check that the liquidation sequence has improved the TCR + const TCR_After = await th.getTCR(contracts); + assert.isTrue(TCR_After.gte(TCR_Before)); + }); + + it("batchLiquidateTroves(): A liquidation sequence of pure redistributions decreases the TCR, due to gas compensation, but up to 0.5%", async () => { + const { collateral: W_coll, totalDebt: W_debt } = await openTrove({ + ICR: toBN(dec(100, 18)), + extraParams: { from: whale }, + }); + const { collateral: A_coll, totalDebt: A_debt } = await openTrove({ + ICR: toBN(dec(4, 18)), + extraParams: { from: alice }, + }); + const { collateral: B_coll, totalDebt: B_debt } = await openTrove({ + ICR: toBN(dec(28, 18)), + extraParams: { from: bob }, + }); + const { collateral: C_coll, totalDebt: C_debt } = await openTrove({ + ICR: toBN(dec(8, 18)), + extraParams: { from: carol }, + }); + const { collateral: D_coll, totalDebt: D_debt } = await openTrove({ + ICR: toBN(dec(80, 18)), + extraParams: { from: dennis }, + }); + + const { collateral: d1_coll, totalDebt: d1_debt } = await openTrove({ + ICR: toBN(dec(199, 16)), + extraParams: { from: defaulter_1 }, + }); + const { collateral: d2_coll, totalDebt: d2_debt } = await openTrove({ + ICR: toBN(dec(156, 16)), + extraParams: { from: defaulter_2 }, + }); + const { collateral: d3_coll, totalDebt: d3_debt } = await openTrove({ + ICR: toBN(dec(183, 16)), + extraParams: { from: defaulter_3 }, + }); + const { collateral: d4_coll, totalDebt: d4_debt } = await openTrove({ + ICR: toBN(dec(166, 16)), + extraParams: { from: defaulter_4 }, + }); + + const totalCollNonDefaulters = W_coll.add(A_coll) + .add(B_coll) + .add(C_coll) + .add(D_coll); + const totalCollDefaulters = d1_coll.add(d2_coll).add(d3_coll).add(d4_coll); + const totalColl = totalCollNonDefaulters.add(totalCollDefaulters); + const totalDebt = W_debt.add(A_debt) + .add(B_debt) + .add(C_debt) + .add(D_debt) + .add(d1_debt) + .add(d2_debt) + .add(d3_debt) + .add(d4_debt); + + assert.isTrue(await sortedTroves.contains(defaulter_1)); + assert.isTrue(await sortedTroves.contains(defaulter_2)); + assert.isTrue(await sortedTroves.contains(defaulter_3)); + assert.isTrue(await sortedTroves.contains(defaulter_4)); + + assert.equal((await sortedTroves.getSize()).toString(), "9"); + + // Price drops + const price = toBN(dec(100, 18)); + await priceFeed.setPrice(price); + + const TCR_Before = await th.getTCR(contracts); + assert.isAtMost( + th.getDifference(TCR_Before, totalColl.mul(price).div(totalDebt)), + 1000 + ); + + // Check pool is empty before liquidation + assert.equal((await stabilityPool.getTotalBoldDeposits()).toString(), "0"); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + // Liquidate + await troveManager.batchLiquidateTroves([alice, bob, carol, dennis, defaulter_1, defaulter_2, defaulter_3, defaulter_4, whale]); + + // Check all defaulters have been liquidated + assert.isFalse(await sortedTroves.contains(defaulter_1)); + assert.isFalse(await sortedTroves.contains(defaulter_2)); + assert.isFalse(await sortedTroves.contains(defaulter_3)); + assert.isFalse(await sortedTroves.contains(defaulter_4)); + + // check system sized reduced to 5 troves + assert.equal((await sortedTroves.getSize()).toString(), "5"); + + // Check that the liquidation sequence has reduced the TCR + const TCR_After = await th.getTCR(contracts); + // ((100+1+7+2+20)+(1+2+3+4)*0.995)*100/(2050+50+50+50+50+101+257+328+480) + assert.isAtMost( + th.getDifference( + TCR_After, + totalCollNonDefaulters + .add(th.applyLiquidationFee(totalCollDefaulters)) + .mul(price) + .div(totalDebt) + ), + 1000 + ); + assert.isTrue(TCR_Before.gte(TCR_After)); + assert.isTrue(TCR_After.gte(TCR_Before.mul(toBN(995)).div(toBN(1000)))); + }); + + it("batchLiquidateTroves(): Liquidating troves with SP deposits correctly impacts their SP deposit and ETH gain", async () => { + // Whale provides 400 Bold to the SP + const whaleDeposit = toBN(dec(40000, 18)); + await openTrove({ + ICR: toBN(dec(100, 18)), + extraBoldAmount: whaleDeposit, + extraParams: { from: whale }, + }); + await stabilityPool.provideToSP(whaleDeposit, { + from: whale, + }); + + const A_deposit = toBN(dec(10000, 18)); + const B_deposit = toBN(dec(30000, 18)); + const { collateral: A_coll, totalDebt: A_debt } = await openTrove({ + ICR: toBN(dec(2, 18)), + extraBoldAmount: A_deposit, + extraParams: { from: alice }, + }); + const { collateral: B_coll, totalDebt: B_debt } = await openTrove({ + ICR: toBN(dec(2, 18)), + extraBoldAmount: B_deposit, + extraParams: { from: bob }, + }); + const { collateral: C_coll, totalDebt: C_debt } = await openTrove({ + ICR: toBN(dec(2, 18)), + extraParams: { from: carol }, + }); + + const liquidatedColl = A_coll.add(B_coll).add(C_coll); + const liquidatedDebt = A_debt.add(B_debt).add(C_debt); + + // A, B provide 100, 300 to the SP + await stabilityPool.provideToSP(A_deposit, { from: alice }); + await stabilityPool.provideToSP(B_deposit, { from: bob }); + + assert.equal((await sortedTroves.getSize()).toString(), "4"); + + // Price drops + await priceFeed.setPrice(dec(100, 18)); + + // Check 800 Bold in Pool + const totalDeposits = whaleDeposit.add(A_deposit).add(B_deposit); + assert.equal( + (await stabilityPool.getTotalBoldDeposits()).toString(), + totalDeposits + ); + + // Confirm system is not in Recovery Mode + assert.isFalse(await th.checkRecoveryMode(contracts)); + + // Liquidate + await troveManager.batchLiquidateTroves([alice, bob, carol, whale]); + + // Check all defaulters have been liquidated + assert.isFalse(await sortedTroves.contains(alice)); + assert.isFalse(await sortedTroves.contains(bob)); + assert.isFalse(await sortedTroves.contains(carol)); + + // check system sized reduced to 1 troves + assert.equal((await sortedTroves.getSize()).toString(), "1"); + + /* Prior to liquidation, SP deposits were: + Whale: 400 Bold + Alice: 100 Bold + Bob: 300 Bold + Carol: 0 Bold + + Total Bold in Pool: 800 Bold + + Then, liquidation hits A,B,C: + + Total liquidated debt = 150 + 350 + 150 = 650 Bold + Total liquidated ETH = 1.1 + 3.1 + 1.1 = 5.3 ETH + + whale bold loss: 650 * (400/800) = 325 bold + alice bold loss: 650 *(100/800) = 81.25 bold + bob bold loss: 650 * (300/800) = 243.75 bold + + whale remaining deposit: (400 - 325) = 75 bold + alice remaining deposit: (100 - 81.25) = 18.75 bold + bob remaining deposit: (300 - 243.75) = 56.25 bold + + whale eth gain: 5*0.995 * (400/800) = 2.4875 eth + alice eth gain: 5*0.995 *(100/800) = 0.621875 eth + bob eth gain: 5*0.995 * (300/800) = 1.865625 eth + + Total remaining deposits: 150 Bold + Total ETH gain: 4.975 ETH */ + + // Check remaining Bold Deposits and ETH gain, for whale and depositors whose troves were liquidated + const whale_Deposit_After = await stabilityPool.getCompoundedBoldDeposit( + whale + ); + const alice_Deposit_After = await stabilityPool.getCompoundedBoldDeposit( + alice + ); + const bob_Deposit_After = await stabilityPool.getCompoundedBoldDeposit(bob); + + const whale_ETHGain = await stabilityPool.getDepositorETHGain(whale); + const alice_ETHGain = await stabilityPool.getDepositorETHGain(alice); + const bob_ETHGain = await stabilityPool.getDepositorETHGain(bob); + + assert.isAtMost( + th.getDifference( + whale_Deposit_After, + whaleDeposit.sub(liquidatedDebt.mul(whaleDeposit).div(totalDeposits)) + ), + 100000 + ); + assert.isAtMost( + th.getDifference( + alice_Deposit_After, + A_deposit.sub(liquidatedDebt.mul(A_deposit).div(totalDeposits)) + ), + 100000 + ); + assert.isAtMost( + th.getDifference( + bob_Deposit_After, + B_deposit.sub(liquidatedDebt.mul(B_deposit).div(totalDeposits)) + ), + 100000 + ); + + assert.isAtMost( + th.getDifference( + whale_ETHGain, + th + .applyLiquidationFee(liquidatedColl) + .mul(whaleDeposit) + .div(totalDeposits) + ), + 100000 + ); + assert.isAtMost( + th.getDifference( + alice_ETHGain, + th.applyLiquidationFee(liquidatedColl).mul(A_deposit).div(totalDeposits) + ), + 100000 + ); + assert.isAtMost( + th.getDifference( + bob_ETHGain, + th.applyLiquidationFee(liquidatedColl).mul(B_deposit).div(totalDeposits) + ), + 100000 + ); + + // Check total remaining deposits and ETH gain in Stability Pool + const total_BoldinSP = ( + await stabilityPool.getTotalBoldDeposits() + ).toString(); + const total_ETHinSP = (await stabilityPool.getETH()).toString(); + + assert.isAtMost( + th.getDifference(total_BoldinSP, totalDeposits.sub(liquidatedDebt)), + 1000 + ); + assert.isAtMost( + th.getDifference(total_ETHinSP, th.applyLiquidationFee(liquidatedColl)), + 1000 + ); + }); + // TODO: revisit the relevance of this test since it relies on liquidateTroves(), which now no longer works due to ordering by interest rate. // Can we achieve / test the same thing using another liquidation function? From 03d3b7430b45aa7bac2308e834aa16f6ee1e12f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Fingen?= Date: Mon, 19 Feb 2024 18:34:23 +0000 Subject: [PATCH 9/9] contracts: Remove warnings --- contracts/src/Interfaces/ITroveManager.sol | 2 +- contracts/src/PriceFeed.sol | 2 +- contracts/src/TroveManager.sol | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index 9a346e91..7469e5d9 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -97,7 +97,7 @@ interface ITroveManager is ILiquityBase { function decreaseTroveDebt(address _borrower, uint _collDecrease) external returns (uint); - function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external returns (uint256); + function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external; function getTCR(uint _price) external view returns (uint); diff --git a/contracts/src/PriceFeed.sol b/contracts/src/PriceFeed.sol index 468a5155..26a92c59 100644 --- a/contracts/src/PriceFeed.sol +++ b/contracts/src/PriceFeed.sol @@ -122,7 +122,7 @@ contract PriceFeed is Ownable, CheckContract, BaseMath, IPriceFeed { * it uses the last good price seen by Liquity. * */ - function fetchPrice() external override returns (uint) { + function fetchPrice() external override returns (uint _lastGoodPrice) { // Get current and previous price data from Chainlink, and current price data from Tellor ChainlinkResponse memory chainlinkResponse = _getCurrentChainlinkResponse(); ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(chainlinkResponse.roundId, chainlinkResponse.decimals); diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 758ffebf..62c3481f 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -1311,7 +1311,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { // return _calcRedemptionRate(_calcDecayedBaseRate()); } - function _calcRedemptionRate(uint _baseRate) internal pure returns (uint) { + function _calcRedemptionRate(uint /* _baseRate */) internal pure returns (uint) { return 0; // return LiquityMath._min( // REDEMPTION_FEE_FLOOR + _baseRate, @@ -1327,7 +1327,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { return _calcRedemptionFee(getRedemptionRateWithDecay(), _ETHDrawn); } - function _calcRedemptionFee(uint _redemptionRate, uint _ETHDrawn) internal pure returns (uint) { + function _calcRedemptionFee(uint /* _redemptionRate */, uint /* _ETHDrawn */) internal pure returns (uint) { return 0; // uint redemptionFee = _redemptionRate * _ETHDrawn / DECIMAL_PRECISION; // require(redemptionFee < _ETHDrawn, "TroveManager: Fee would eat up all returned collateral"); @@ -1457,7 +1457,7 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { return newDebt; } - function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external returns (uint256) { + function changeAnnualInterestRate(address _borrower, uint256 _newAnnualInterestRate) external { _requireCallerIsBorrowerOperations(); Troves[_borrower].annualInterestRate = _newAnnualInterestRate; }