diff --git a/contracts/src/BorrowerOperations.sol b/contracts/src/BorrowerOperations.sol index b7f5639e..68e43fbc 100644 --- a/contracts/src/BorrowerOperations.sol +++ b/contracts/src/BorrowerOperations.sol @@ -122,7 +122,6 @@ contract BorrowerOperations is LiquityBase, Ownable, CheckContract, IBorrowerOpe checkContract(_priceFeedAddress); checkContract(_sortedTrovesAddress); checkContract(_boldTokenAddress); - checkContract(_lqtyStakingAddress); troveManager = ITroveManager(_troveManagerAddress); activePool = IActivePool(_activePoolAddress); diff --git a/contracts/src/GasPool.sol b/contracts/src/GasPool.sol index feb6967b..40ed1af1 100644 --- a/contracts/src/GasPool.sol +++ b/contracts/src/GasPool.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT - pragma solidity 0.8.18; - /** * The purpose of this contract is to hold Bold tokens for gas compensation: * https://github.com/liquity/dev#gas-compensation diff --git a/contracts/src/Interfaces/IActivePool.sol b/contracts/src/Interfaces/IActivePool.sol index 1ea9d48f..24116cb8 100644 --- a/contracts/src/Interfaces/IActivePool.sol +++ b/contracts/src/Interfaces/IActivePool.sol @@ -6,5 +6,15 @@ import "./IPool.sol"; interface IActivePool is IPool { + function stabilityPoolAddress() external view returns (address); + function defaultPoolAddress() external view returns (address); + function borrowerOperationsAddress() external view returns (address); + function troveManagerAddress() external view returns (address); function sendETH(address _account, uint _amount) external; + function setAddresses( + address _borrowerOperationsAddress, + address _troveManagerAddress, + address _stabilityPoolAddress, + address _defaultPoolAddress + ) external; } diff --git a/contracts/src/Interfaces/IBorrowerOperations.sol b/contracts/src/Interfaces/IBorrowerOperations.sol index eb3e03be..5db241c6 100644 --- a/contracts/src/Interfaces/IBorrowerOperations.sol +++ b/contracts/src/Interfaces/IBorrowerOperations.sol @@ -2,8 +2,16 @@ pragma solidity 0.8.18; +import "./ILiquityBase.sol"; +import "./ITroveManager.sol"; +import "./IPriceFeed.sol"; +import "./ISortedTroves.sol"; + // Common interface for the Trove Manager. -interface IBorrowerOperations { +interface IBorrowerOperations is ILiquityBase { + function troveManager() external view returns (ITroveManager); + function sortedTroves() external view returns (ISortedTroves); + function setAddresses( address _troveManagerAddress, address _activePoolAddress, diff --git a/contracts/src/Interfaces/IDefaultPool.sol b/contracts/src/Interfaces/IDefaultPool.sol index 9b6f8d6b..a819b167 100644 --- a/contracts/src/Interfaces/IDefaultPool.sol +++ b/contracts/src/Interfaces/IDefaultPool.sol @@ -6,6 +6,9 @@ import "./IPool.sol"; interface IDefaultPool is IPool { + function troveManagerAddress() external view returns (address); + function activePoolAddress() external view returns (address); // --- Functions --- function sendETHToActivePool(uint _amount) external; + function setAddresses(address _troveManagerAddress, address _activePoolAddress) external; } diff --git a/contracts/src/Interfaces/ILiquityBase.sol b/contracts/src/Interfaces/ILiquityBase.sol index c6c7016d..46dc1005 100644 --- a/contracts/src/Interfaces/ILiquityBase.sol +++ b/contracts/src/Interfaces/ILiquityBase.sol @@ -2,9 +2,12 @@ pragma solidity 0.8.18; +import "./IActivePool.sol"; +import "./IDefaultPool.sol"; import "./IPriceFeed.sol"; - interface ILiquityBase { + function activePool() external view returns (IActivePool); + function defaultPool() external view returns (IDefaultPool); function priceFeed() external view returns (IPriceFeed); } diff --git a/contracts/src/Interfaces/ISortedTroves.sol b/contracts/src/Interfaces/ISortedTroves.sol index fefc1187..9cfaf1d3 100644 --- a/contracts/src/Interfaces/ISortedTroves.sol +++ b/contracts/src/Interfaces/ISortedTroves.sol @@ -2,8 +2,13 @@ pragma solidity 0.8.18; +import "./ITroveManager.sol"; + // Common interface for the SortedTroves Doubly Linked List. interface ISortedTroves { + function borrowerOperationsAddress() external view returns (address); + function troveManager() external view returns (ITroveManager); + function setParams(uint256 _size, address _TroveManagerAddress, address _borrowerOperationsAddress) external; function insert(address _id, uint256 _ICR, address _prevId, address _nextId) external; diff --git a/contracts/src/Interfaces/IStabilityPool.sol b/contracts/src/Interfaces/IStabilityPool.sol index d97c5c76..2f5dc63d 100644 --- a/contracts/src/Interfaces/IStabilityPool.sol +++ b/contracts/src/Interfaces/IStabilityPool.sol @@ -2,6 +2,12 @@ pragma solidity 0.8.18; +import "./IActivePool.sol"; +import "./ILiquityBase.sol"; +import "./IBorrowerOperations.sol"; +import "./IBoldToken.sol"; +import "./ITroveManager.sol"; + /* * The Stability Pool holds Bold tokens deposited by Stability Pool depositors. * @@ -33,7 +39,11 @@ pragma solidity 0.8.18; * Please see the system Readme for an overview: * https://github.com/liquity/dev/blob/main/README.md#lqty-issuance-to-stability-providers */ -interface IStabilityPool { +interface IStabilityPool is ILiquityBase { + function borrowerOperations() external view returns (IBorrowerOperations); + function boldToken() external view returns (IBoldToken); + function troveManager() external view returns (ITroveManager); + /* * Called only once on init, to set addresses of other Liquity contracts * Callable only by owner, renounces ownership at the end diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index b9a4e78c..f5ed1f3c 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.18; import "./ILiquityBase.sol"; import "./IStabilityPool.sol"; import "./IBoldToken.sol"; +import "./ISortedTroves.sol"; import "./ILQTYToken.sol"; import "./ILQTYStaking.sol"; @@ -29,6 +30,8 @@ interface ITroveManager is ILiquityBase { function boldToken() external view returns (IBoldToken); function lqtyToken() external view returns (ILQTYToken); function lqtyStaking() external view returns (ILQTYStaking); + function sortedTroves() external view returns(ISortedTroves); + function borrowerOperationsAddress() external view returns (address); function getTroveOwnersCount() external view returns (uint); diff --git a/contracts/src/OldTestContracts/ActivePoolTester.sol b/contracts/src/OldTestContracts/ActivePoolTester.sol new file mode 100644 index 00000000..75cee9b5 --- /dev/null +++ b/contracts/src/OldTestContracts/ActivePoolTester.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../ActivePool.sol"; + +contract ActivePoolTester is ActivePool { + + function unprotectedIncreaseBoldDebt(uint _amount) external { + boldDebt = boldDebt + _amount; + } + + function unprotectedPayable() external payable { + ETH = ETH + msg.value; + } +} diff --git a/contracts/src/OldTestContracts/BoldTokenCaller.sol b/contracts/src/OldTestContracts/BoldTokenCaller.sol new file mode 100644 index 00000000..613b41a3 --- /dev/null +++ b/contracts/src/OldTestContracts/BoldTokenCaller.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../Interfaces/IBoldToken.sol"; + +contract BoldTokenCaller { + IBoldToken Bold; + + function setBold(IBoldToken _bold) external { + Bold = _bold; + } + + function boldMint(address _account, uint _amount) external { + Bold.mint(_account, _amount); + } + + function boldBurn(address _account, uint _amount) external { + Bold.burn(_account, _amount); + } + + function boldSendToPool(address _sender, address _poolAddress, uint256 _amount) external { + Bold.sendToPool(_sender, _poolAddress, _amount); + } + + function boldReturnFromPool(address _poolAddress, address _receiver, uint256 _amount ) external { + Bold.returnFromPool(_poolAddress, _receiver, _amount); + } +} diff --git a/contracts/src/OldTestContracts/BoldTokenTester.sol b/contracts/src/OldTestContracts/BoldTokenTester.sol new file mode 100644 index 00000000..446299e6 --- /dev/null +++ b/contracts/src/OldTestContracts/BoldTokenTester.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../BoldToken.sol"; + +contract BoldTokenTester is BoldToken { + + bytes32 private immutable _PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + + constructor( + address _troveManagerAddress, + address _stabilityPoolAddress, + address _borrowerOperationsAddress + ) public BoldToken(_troveManagerAddress, + _stabilityPoolAddress, + _borrowerOperationsAddress) {} + + function unprotectedMint(address _account, uint256 _amount) external { + // No check on caller here + + _mint(_account, _amount); + } + + function unprotectedBurn(address _account, uint _amount) external { + // No check on caller here + + _burn(_account, _amount); + } + + function unprotectedSendToPool(address _sender, address _poolAddress, uint256 _amount) external { + // No check on caller here + + _transfer(_sender, _poolAddress, _amount); + } + + function unprotectedReturnFromPool(address _poolAddress, address _receiver, uint256 _amount ) external { + // No check on caller here + + _transfer(_poolAddress, _receiver, _amount); + } + + function callInternalApprove(address owner, address spender, uint256 amount) external returns (bool) { + _approve(owner, spender, amount); + } + + function getChainId() external view returns (uint256 chainID) { + //return _chainID(); // it’s private + assembly { + chainID := chainid() + } + } + + function getDigest(address owner, address spender, uint amount, uint nonce, uint deadline) external view returns (bytes32) { + return keccak256(abi.encodePacked( + uint16(0x1901), + domainSeparator(), + keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, amount, nonce, deadline)) + ) + ); + } + + function recoverAddress(bytes32 digest, uint8 v, bytes32 r, bytes32 s) external pure returns (address) { + return ecrecover(digest, v, r, s); + } +} diff --git a/contracts/src/OldTestContracts/BorrowerOperationsTester.sol b/contracts/src/OldTestContracts/BorrowerOperationsTester.sol new file mode 100644 index 00000000..142cbdad --- /dev/null +++ b/contracts/src/OldTestContracts/BorrowerOperationsTester.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../BorrowerOperations.sol"; + +/* Tester contract inherits from BorrowerOperations, and provides external functions +for testing the parent's internal functions. */ +contract BorrowerOperationsTester is BorrowerOperations { + + function getNewICRFromTroveChange + ( + uint _coll, + uint _debt, + uint _collChange, + bool isCollIncrease, + uint _debtChange, + bool isDebtIncrease, + uint _price + ) + external + pure + returns (uint) + { + return _getNewICRFromTroveChange(_coll, _debt, _collChange, isCollIncrease, _debtChange, isDebtIncrease, _price); + } + + function getNewTCRFromTroveChange + ( + uint _collChange, + bool isCollIncrease, + uint _debtChange, + bool isDebtIncrease, + uint _price + ) + external + view + returns (uint) + { + return _getNewTCRFromTroveChange(_collChange, isCollIncrease, _debtChange, isDebtIncrease, _price); + } + + function getUSDValue(uint _coll, uint _price) external pure returns (uint) { + return _getUSDValue(_coll, _price); + } + + function callInternalAdjustLoan + ( + address _borrower, + uint _collWithdrawal, + uint _debtChange, + bool _isDebtIncrease, + address _upperHint, + address _lowerHint) + external + { + _adjustTrove(_borrower, _collWithdrawal, _debtChange, _isDebtIncrease, _upperHint, _lowerHint, 0); + } + + + // Payable fallback function + receive() external payable { } +} diff --git a/contracts/src/OldTestContracts/CDPManagerTester.sol b/contracts/src/OldTestContracts/CDPManagerTester.sol new file mode 100644 index 00000000..02eee294 --- /dev/null +++ b/contracts/src/OldTestContracts/CDPManagerTester.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../TroveManager.sol"; + +/* Tester contract inherits from TroveManager, and provides external functions +for testing the parent's internal functions. */ + +contract TroveManagerTester is TroveManager { + + function computeICR(uint _coll, uint _debt, uint _price) external pure returns (uint) { + return LiquityMath._computeCR(_coll, _debt, _price); + } + + function getCollGasCompensation(uint _coll) external pure returns (uint) { + return _getCollGasCompensation(_coll); + } + + function getBoldGasCompensation() external pure returns (uint) { + return BOLD_GAS_COMPENSATION; + } + + function getCompositeDebt(uint _debt) external pure returns (uint) { + return _getCompositeDebt(_debt); + } + + function unprotectedDecayBaseRateFromBorrowing() external returns (uint) { + baseRate = _calcDecayedBaseRate(); + assert(baseRate >= 0 && baseRate <= DECIMAL_PRECISION); + + _updateLastFeeOpTime(); + return baseRate; + } + + function minutesPassedSinceLastFeeOp() external view returns (uint) { + return _minutesPassedSinceLastFeeOp(); + } + + function setLastFeeOpTimeToNow() external { + lastFeeOperationTime = block.timestamp; + } + + function setBaseRate(uint _baseRate) external { + baseRate = _baseRate; + } + + function callGetRedemptionFee(uint _ETHDrawn) external view returns (uint) { + _getRedemptionFee(_ETHDrawn); + } + + function getActualDebtFromComposite(uint _debtVal) external pure returns (uint) { + return _getNetDebt(_debtVal); + } + + function callInternalRemoveTroveOwner(address _troveOwner) external { + uint troveOwnersArrayLength = TroveOwners.length; + _removeTroveOwner(_troveOwner, troveOwnersArrayLength); + } +} diff --git a/contracts/src/OldTestContracts/DefaultPoolTester.sol b/contracts/src/OldTestContracts/DefaultPoolTester.sol new file mode 100644 index 00000000..a81c3f47 --- /dev/null +++ b/contracts/src/OldTestContracts/DefaultPoolTester.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../DefaultPool.sol"; + +contract DefaultPoolTester is DefaultPool { + + function unprotectedIncreaseBoldDebt(uint _amount) external { + BoldDebt = BoldDebt + _amount; + } + + function unprotectedPayable() external payable { + ETH = ETH + msg.value; + } +} diff --git a/contracts/src/OldTestContracts/Destructible.sol b/contracts/src/OldTestContracts/Destructible.sol new file mode 100644 index 00000000..2146a9ff --- /dev/null +++ b/contracts/src/OldTestContracts/Destructible.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +contract Destructible { + + receive() external payable {} + + function destruct(address payable _receiver) external { + selfdestruct(_receiver); + } +} diff --git a/contracts/src/OldTestContracts/FunctionCaller.sol b/contracts/src/OldTestContracts/FunctionCaller.sol new file mode 100644 index 00000000..04929ae6 --- /dev/null +++ b/contracts/src/OldTestContracts/FunctionCaller.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import '../Interfaces/ITroveManager.sol'; +import '../Interfaces/ISortedTroves.sol'; +import '../Interfaces/IPriceFeed.sol'; +import '../Dependencies/LiquityMath.sol'; + +/* Wrapper contract - used for calculating gas of read-only and internal functions. +Not part of the Liquity application. */ +contract FunctionCaller { + + ITroveManager troveManager; + address public troveManagerAddress; + + ISortedTroves sortedTroves; + address public sortedTrovesAddress; + + IPriceFeed priceFeed; + address public priceFeedAddress; + + // --- Dependency setters --- + + function setTroveManagerAddress(address _troveManagerAddress) external { + troveManagerAddress = _troveManagerAddress; + troveManager = ITroveManager(_troveManagerAddress); + } + + function setSortedTrovesAddress(address _sortedTrovesAddress) external { + troveManagerAddress = _sortedTrovesAddress; + sortedTroves = ISortedTroves(_sortedTrovesAddress); + } + + function setPriceFeedAddress(address _priceFeedAddress) external { + priceFeedAddress = _priceFeedAddress; + priceFeed = IPriceFeed(_priceFeedAddress); + } + + // --- Non-view wrapper functions used for calculating gas --- + + function troveManager_getCurrentICR(address _address, uint _price) external returns (uint) { + return troveManager.getCurrentICR(_address, _price); + } + + function sortedTroves_findInsertPosition(uint _NICR, address _prevId, address _nextId) external returns (address, address) { + return sortedTroves.findInsertPosition(_NICR, _prevId, _nextId); + } +} diff --git a/contracts/src/OldTestContracts/LiquityMathTester.sol b/contracts/src/OldTestContracts/LiquityMathTester.sol new file mode 100644 index 00000000..627bf788 --- /dev/null +++ b/contracts/src/OldTestContracts/LiquityMathTester.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../Dependencies/LiquityMath.sol"; + +/* Tester contract for math functions in Math.sol library. */ + +contract LiquityMathTester { + + function callMax(uint _a, uint _b) external pure returns (uint) { + return LiquityMath._max(_a, _b); + } + + // Non-view wrapper for gas test + function callDecPowTx(uint _base, uint _n) external returns (uint) { + return LiquityMath._decPow(_base, _n); + } + + // External wrapper + function callDecPow(uint _base, uint _n) external pure returns (uint) { + return LiquityMath._decPow(_base, _n); + } +} diff --git a/contracts/src/OldTestContracts/MockTellor.sol b/contracts/src/OldTestContracts/MockTellor.sol new file mode 100644 index 00000000..be039b47 --- /dev/null +++ b/contracts/src/OldTestContracts/MockTellor.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + + +contract MockTellor { + + // --- Mock price data --- + + bool didRetrieve = true; // default to a positive retrieval + uint private price; + uint private updateTime; + + bool private revertRequest; + + // --- Setters for mock price data --- + + function setPrice(uint _price) external { + price = _price; + } + + function setDidRetrieve(bool _didRetrieve) external { + didRetrieve = _didRetrieve; + } + + function setUpdateTime(uint _updateTime) external { + updateTime = _updateTime; + } + + function setRevertRequest() external { + revertRequest = !revertRequest; + } + + // --- Mock data reporting functions --- + + function getTimestampbyRequestIDandIndex(uint, uint) external view returns (uint) { + return updateTime; + } + + function getNewValueCountbyRequestId(uint) external view returns (uint) { + if (revertRequest) {require (1 == 0, "Tellor request reverted");} + return 1; + } + + function retrieveData(uint256, uint256) external view returns (uint256) { + return price; + } + + + +} diff --git a/contracts/src/OldTestContracts/NonPayable.sol b/contracts/src/OldTestContracts/NonPayable.sol new file mode 100644 index 00000000..6539427c --- /dev/null +++ b/contracts/src/OldTestContracts/NonPayable.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +//import "../Dependencies/console.sol"; + + +contract NonPayable { + bool isPayable; + + function setPayable(bool _isPayable) external { + isPayable = _isPayable; + } + + function forward(address _dest, bytes calldata _data) external payable { + (bool success, bytes memory returnData) = _dest.call{ value: msg.value }(_data); + //console.logBytes(returnData); + require(success, string(returnData)); + } + + receive() external payable { + require(isPayable); + } +} diff --git a/contracts/src/OldTestContracts/PriceFeedTester.sol b/contracts/src/OldTestContracts/PriceFeedTester.sol new file mode 100644 index 00000000..aec017ef --- /dev/null +++ b/contracts/src/OldTestContracts/PriceFeedTester.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../PriceFeed.sol"; + +contract PriceFeedTester is PriceFeed { + + function setLastGoodPrice(uint _lastGoodPrice) external { + lastGoodPrice = _lastGoodPrice; + } + + function setStatus(Status _status) external { + status = _status; + } +} \ No newline at end of file diff --git a/contracts/src/OldTestContracts/PriceFeedTestnet.sol b/contracts/src/OldTestContracts/PriceFeedTestnet.sol new file mode 100644 index 00000000..2f220196 --- /dev/null +++ b/contracts/src/OldTestContracts/PriceFeedTestnet.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../Interfaces/IPriceFeed.sol"; + +/* +* PriceFeed placeholder for testnet and development. The price is simply set manually and saved in a state +* variable. The contract does not connect to a live Chainlink price feed. +*/ +contract PriceFeedTestnet is IPriceFeed { + event LastGoodPriceUpdated(uint _lastGoodPrice); + + uint256 private _price = 200 * 1e18; + + // --- Functions --- + + // View price getter for simplicity in tests + function getPrice() external view returns (uint256) { + return _price; + } + + function fetchPrice() external override returns (uint256) { + // Fire an event just like the mainnet version would. + // This lets the subgraph rely on events to get the latest price even when developing locally. + emit LastGoodPriceUpdated(_price); + return _price; + } + + // Manual external price setter. + function setPrice(uint256 price) external returns (bool) { + _price = price; + return true; + } +} diff --git a/contracts/src/OldTestContracts/SortedTrovesTester.sol b/contracts/src/OldTestContracts/SortedTrovesTester.sol new file mode 100644 index 00000000..3a373d16 --- /dev/null +++ b/contracts/src/OldTestContracts/SortedTrovesTester.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../Interfaces/ISortedTroves.sol"; + + +contract SortedTrovesTester { + ISortedTroves sortedTroves; + + function setSortedTroves(address _sortedTrovesAddress) external { + sortedTroves = ISortedTroves(_sortedTrovesAddress); + } + + function insert(address _id, uint256 _NICR, address _prevId, address _nextId) external { + sortedTroves.insert(_id, _NICR, _prevId, _nextId); + } + + function remove(address _id) external { + sortedTroves.remove(_id); + } + + function reInsert(address _id, uint256 _newNICR, address _prevId, address _nextId) external { + sortedTroves.reInsert(_id, _newNICR, _prevId, _nextId); + } + + function getNominalICR(address) external pure returns (uint) { + return 1; + } + + function getCurrentICR(address, uint) external pure returns (uint) { + return 1; + } +} diff --git a/contracts/src/OldTestContracts/StabilityPoolTester.sol b/contracts/src/OldTestContracts/StabilityPoolTester.sol new file mode 100644 index 00000000..57f503ce --- /dev/null +++ b/contracts/src/OldTestContracts/StabilityPoolTester.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "../StabilityPool.sol"; + +contract StabilityPoolTester is StabilityPool { + + function unprotectedPayable() external payable { + ETH = ETH + msg.value; + } + + function setCurrentScale(uint128 _currentScale) external { + currentScale = _currentScale; + } + + function setTotalDeposits(uint _totalBoldDeposits) external { + totalBoldDeposits = _totalBoldDeposits; + } +} diff --git a/contracts/src/StabilityPool.sol b/contracts/src/StabilityPool.sol index 5070951a..aa90762c 100644 --- a/contracts/src/StabilityPool.sol +++ b/contracts/src/StabilityPool.sol @@ -283,7 +283,6 @@ contract StabilityPool is LiquityBase, Ownable, CheckContract, IStabilityPool { checkContract(_boldTokenAddress); checkContract(_sortedTrovesAddress); checkContract(_priceFeedAddress); - checkContract(_communityIssuanceAddress); borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress); troveManager = ITroveManager(_troveManagerAddress); diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 3c7cbf24..c023d45b 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -257,8 +257,6 @@ contract TroveManager is LiquityBase, Ownable, CheckContract, ITroveManager { checkContract(_priceFeedAddress); checkContract(_boldTokenAddress); checkContract(_sortedTrovesAddress); - checkContract(_lqtyTokenAddress); - checkContract(_lqtyStakingAddress); borrowerOperationsAddress = _borrowerOperationsAddress; activePool = IActivePool(_activePoolAddress); diff --git a/contracts/src/test/TestContracts/Accounts.sol b/contracts/src/test/TestContracts/Accounts.sol new file mode 100644 index 00000000..a63ccb3f --- /dev/null +++ b/contracts/src/test/TestContracts/Accounts.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.18; + +contract Accounts { + // Private keys for first 10 Hardhat test accounts + uint256[10] public accountsPks = [ + 0x60ddFE7f579aB6867cbE7A2Dc03853dC141d7A4aB6DBEFc0Dae2d2B1Bd4e487F, + 0xeaa445c85f7b438dEd6e831d06a4eD0CEBDc2f8527f84Fcda6EBB5fCfAd4C0e9, + 0x8b693607Bd68C4dEB7bcF976a473Cf998BDE9fBeDF08e1D8ADadAcDff4e5D1b6, + 0x519B6e4f493e532a1BEbfeB2a06eA25AAD691A17875cCB38607D4A4C28DFADC2, + 0x09CFF53c181C96B42255ccbCEB2CeE7012A532EcbcEaaBab4d55a47E1874FbFC, + 0x054ce61b1eA12d9Edb667ceFB001FADB07FE0C37b5A74542BB0DaBF5DDeEe5f0, + 0x42F55f0dFFE4e9e2C2BdfdE2FF98f3d1ea6d3F21A8bB0dA644f1c0e0Acd84FA0, + 0x8F3aFFEC01e78ea6925De62d68A5F3f2cFda7D0C1E7ED9b20d31eb88b9Ed6A58, + 0xBeBeF90A7E9A8e018F0F0baBb868Bc432C5e7F1EfaAe7e5B465d74afDD87c7cf, + 0xaD55BABd2FdceD7aa85eB1FEf47C455DBB7a57a46a16aC9ACFFBE66d7Caf83Ee + ]; + + function getAccountsCount() external view returns (uint) { + return accountsPks.length; + } +} \ No newline at end of file diff --git a/contracts/src/test/TestContracts/BaseTest.sol b/contracts/src/test/TestContracts/BaseTest.sol new file mode 100644 index 00000000..8973d834 --- /dev/null +++ b/contracts/src/test/TestContracts/BaseTest.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.18; + +import "./Accounts.sol"; +import "../../Interfaces/IActivePool.sol"; +import "../../Interfaces/IBoldToken.sol"; +import "../../Interfaces/IBorrowerOperations.sol"; +import "../../Interfaces/ICollSurplusPool.sol"; +import "../../Interfaces/IDefaultPool.sol"; +import "../../Interfaces/IPriceFeed.sol"; +import "../../Interfaces/ISortedTroves.sol"; +import "../../Interfaces/IStabilityPool.sol"; +import "../../Interfaces/ITroveManager.sol"; + +import "../../GasPool.sol"; + +import "forge-std/Test.sol"; +import "forge-std/console2.sol"; + +contract BaseTest is Test { + Accounts accounts; + + address[] accountsList; + address public A; + address public B; + address public C; + address public D; + address public E; + address public F; + + uint256 public constant MAX_UINT256 = type(uint256).max; + uint256 public constant SECONDS_IN_1_YEAR = 31536000; // 60*60*24*365 + address public constant ZERO_ADDRESS = address(0); + + // Core contracts + IActivePool activePool; + IBorrowerOperations borrowerOperations; + ICollSurplusPool collSurplusPool; + IDefaultPool defaultPool; + IPriceFeed priceFeed; + ISortedTroves sortedTroves; + IStabilityPool stabilityPool; + ITroveManager troveManager; + IBoldToken boldToken; + + GasPool gasPool; + + function createAccounts() public { + address[10] memory tempAccounts; + for (uint256 i = 0; i < accounts.getAccountsCount(); i++) { + tempAccounts[i] = vm.addr(uint256(accounts.accountsPks(i))); + } + + accountsList = tempAccounts; + } + + function logContractAddresses() public { + console.log("ActivePool addr: ", address(activePool)); + console.log("BorrowerOps addr: ", address(borrowerOperations)); + console.log("CollSurplusPool addr: ", address(collSurplusPool)); + console.log("DefaultPool addr: ", address(defaultPool)); + console.log("GasPool addr: ", address(gasPool)); + console.log("PriceFeed addr: ", address(priceFeed)); + console.log("SortedTroves addr: ", address(sortedTroves)); + console.log("StabilityPool addr: ", address(stabilityPool)); + console.log("TroveManager addr: ", address(troveManager)); + console.log("BoldToken addr: ", address(boldToken)); + } +} \ No newline at end of file diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol new file mode 100644 index 00000000..f44f6ed9 --- /dev/null +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -0,0 +1,127 @@ + +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.18; + +import "../../ActivePool.sol"; +import "../../BoldToken.sol"; +import "../../BorrowerOperations.sol"; +import "../../CollSurplusPool.sol"; +import "../../DefaultPool.sol"; +import "../../GasPool.sol"; +import "../../HintHelpers.sol"; +import "../../MultiTroveGetter.sol"; +import "../../OldTestContracts/PriceFeedTestnet.sol"; +import "../../SortedTroves.sol"; +import "../../StabilityPool.sol"; +import "../../TroveManager.sol"; + +import "./BaseTest.sol"; + +contract DevTestSetup is BaseTest { + function setUp() public virtual { + // Start tests at a non-zero timestamp + vm.warp(block.timestamp + 600); + + accounts = new Accounts(); + createAccounts(); + + (A, B, C, D, E, F) = + (accountsList[0], accountsList[1], accountsList[2], accountsList[3], accountsList[4], accountsList[5]); + + // Give some StETH to test accounts + uint256 initialETHAmount = 2000e18; + deal(A, initialETHAmount); + deal(B, initialETHAmount); + deal(C, initialETHAmount); + deal(D, initialETHAmount); + deal(E, initialETHAmount); + deal(F, initialETHAmount); + + // Check accounts are funded + assertEq(A.balance, initialETHAmount); + assertEq(B.balance, initialETHAmount); + assertEq(C.balance, initialETHAmount); + assertEq(D.balance, initialETHAmount); + assertEq(E.balance, initialETHAmount); + assertEq(F.balance, initialETHAmount); + + // TODO: optimize deployment order & constructor args & connector functions + + // Deploy all contracts + activePool = new ActivePool(); + borrowerOperations = new BorrowerOperations(); + collSurplusPool = new CollSurplusPool(); + defaultPool = new DefaultPool(); + gasPool = new GasPool(); + priceFeed = new PriceFeedTestnet(); + sortedTroves = new SortedTroves(); + stabilityPool = new StabilityPool(); + troveManager = new TroveManager(); + boldToken = new BoldToken(address(troveManager), address(stabilityPool), address(borrowerOperations)); + + // Connect contracts + sortedTroves.setParams( + MAX_UINT256, + address(troveManager), + address(borrowerOperations) + ); + + // set contracts in the Trove Manager + troveManager.setAddresses( + address(borrowerOperations), + address(activePool), + address(defaultPool), + address(stabilityPool), + address(gasPool), + address(collSurplusPool), + address(priceFeed), + address(boldToken), + address(sortedTroves), + ZERO_ADDRESS, // No LQTY token + ZERO_ADDRESS // No LQTY staking + ); + + // set contracts in BorrowerOperations + borrowerOperations.setAddresses( + address(troveManager), + address(activePool), + address(defaultPool), + address(stabilityPool), + address(gasPool), + address(collSurplusPool), + address(priceFeed), + address(sortedTroves), + address(boldToken), + ZERO_ADDRESS // No LQTY staking + ); + + // set contracts in the Pools + stabilityPool.setAddresses( + address(borrowerOperations), + address(troveManager), + address(activePool), + address(boldToken), + address(sortedTroves), + address(priceFeed), + ZERO_ADDRESS // No Community Issuance + ); + + activePool.setAddresses( + address(borrowerOperations), + address(troveManager), + address(stabilityPool), + address(defaultPool) + ); + + defaultPool.setAddresses( + address(troveManager), + address(activePool) + ); + + collSurplusPool.setAddresses( + address(borrowerOperations), + address(troveManager), + address(activePool) + ); + } +} \ No newline at end of file diff --git a/contracts/src/test/deployment.t.sol b/contracts/src/test/deployment.t.sol new file mode 100644 index 00000000..d8992215 --- /dev/null +++ b/contracts/src/test/deployment.t.sol @@ -0,0 +1,177 @@ + +pragma solidity 0.8.18; + +import "./TestContracts/DevTestSetup.sol"; + +contract Deployment is DevTestSetup { + + function testContractsDeployed() public { + assertNotEq(address(activePool), address(0)); + assertNotEq(address(boldToken), address(0)); + assertNotEq(address(borrowerOperations), address(0)); + assertNotEq(address(collSurplusPool), address(0)); + assertNotEq(address(gasPool), address(0)); + assertNotEq(address(priceFeed), address(0)); + assertNotEq(address(sortedTroves), address(0)); + assertNotEq(address(stabilityPool), address(0)); + assertNotEq(address(troveManager), address(0)); + logContractAddresses(); + } + + function testTroveManagerHasCorrectPriceFeedAddress() public { + address priceFeedAddress = address(priceFeed); + address recordedPriceFeedAddress = address(troveManager.priceFeed()); + assertEq(priceFeedAddress, recordedPriceFeedAddress); + } + + function testTroveManagerHasCorrectBoldTokenAddress() public { + address boldTokenAddress = address(boldToken); + address recordedBoldTokenAddress = address(troveManager.boldToken()); + assertEq(boldTokenAddress, recordedBoldTokenAddress); + } + + function testTroveManagerHasCorrectSortedTrovesAddress() public { + address sortedTrovesAddress = address(sortedTroves); + address recordedSortedTrovesAddress = address(troveManager.sortedTroves()); + assertEq(sortedTrovesAddress, recordedSortedTrovesAddress); + } + + function testTroveManagerHasCorrectBorrowerOpsAddress() public { + address borrowerOperationsAddress = address(borrowerOperations); + address recordedBorrowerOperationsAddress = troveManager.borrowerOperationsAddress(); + assertEq(borrowerOperationsAddress, recordedBorrowerOperationsAddress); + } + + // ActivePool in TroveM + function testTroveManagerHasCorrectActivePoolAddress() public { + address activePoolAddress = address(activePool); + address recordedActivePoolAddress = address(troveManager.activePool()); + assertEq(activePoolAddress, recordedActivePoolAddress); + } + + // DefaultPool in TroveM + function testTroveManagerHasCorrectDefaultPoolAddress() public { + address defaultPoolAddress = address(defaultPool); + address recordedDefaultPoolAddress = address(troveManager.defaultPool()); + assertEq(defaultPoolAddress, recordedDefaultPoolAddress); + } + + // StabilityPool in TroveM + function testTroveManagerHasCorrectSPAddress() public { + address stabilityPoolAddress = address(stabilityPool); + address recordedStabilityPoolAddress = address(troveManager.stabilityPool()); + assertEq(stabilityPoolAddress, recordedStabilityPoolAddress); + } + + // Active Pool + + function testActivePoolHasCorrectStabilityPoolAddress() public { + address stabilityPoolAddress = address(stabilityPool); + address recordedStabilityPoolAddress = activePool.stabilityPoolAddress(); + assertEq(stabilityPoolAddress, recordedStabilityPoolAddress); + } + + function testActivePoolHasCorrectDefaultPoolAddress() public { + address defaultPoolAddress = address(defaultPool); + address recordedDefaultPoolAddress = activePool.defaultPoolAddress(); + assertEq(defaultPoolAddress, recordedDefaultPoolAddress); + } + + function testActivePoolHasCorrectBorrowerOpsAddress() public { + address borrowerOperationsAddress = address(borrowerOperations); + address recordedBorrowerOperationsAddress = activePool.borrowerOperationsAddress(); + assertEq(borrowerOperationsAddress, recordedBorrowerOperationsAddress); + } + + function testActivePoolHasCorrectTroveManagerAddress() public { + address troveManagerAddress = address(troveManager); + address recordedTroveManagerAddress = activePool.troveManagerAddress(); + assertEq(troveManagerAddress, recordedTroveManagerAddress); + } + + // Stability Pool + + function testStabilityPoolHasCorrectActivePoolAddress() public { + address activePoolAddress = address(activePool); + address recordedActivePoolAddress = address(stabilityPool.activePool()); + assertEq(activePoolAddress, recordedActivePoolAddress); + } + + function testStabilityPoolHasCorrectCorrectBorrowerOpsAddress() public { + address borrowerOperationsAddress = address(borrowerOperations); + address recordedBorrowerOperationsAddress = address(stabilityPool.borrowerOperations()); + assertEq(borrowerOperationsAddress, recordedBorrowerOperationsAddress); + } + + function testStabilityPoolHasCorrectCorrectBoldTokenAddress() public { + address boldTokenAddress = address(boldToken); + address recordedBoldTokenAddress = address(stabilityPool.boldToken()); + assertEq(boldTokenAddress, recordedBoldTokenAddress); + } + + function testStabilityPoolHasCorrectTroveManagerAddress() public { + address troveManagerAddress = address(troveManager); + address recordedTroveManagerAddress = address(stabilityPool.troveManager()); + assertEq(troveManagerAddress, recordedTroveManagerAddress); + } + + // Default Pool + + function testDefaultPoolHasCorrectTroveManagerAddress() public { + address troveManagerAddress = address(troveManager); + address recordedTroveManagerAddress = defaultPool.troveManagerAddress(); + assertEq(troveManagerAddress, recordedTroveManagerAddress); + } + + function testDefaultPoolHasCorrectActivePoolAddress() public { + address activePoolAddress = address(activePool); + address recordedActivePoolAddress = defaultPool.activePoolAddress(); + assertEq(activePoolAddress, recordedActivePoolAddress); + } + + // Sorted Troves + + function testSortedTrovesHasCorrectBorrowerOperationsAddress() public { + address borrowerOperationsAddress = address(borrowerOperations); + address recordedBorrowerOperationsAddress = sortedTroves.borrowerOperationsAddress(); + assertEq(borrowerOperationsAddress, recordedBorrowerOperationsAddress); + } + + function testSortedTrovesHasCorrectTroveManagerAddress() public { + address troveManagerAddress = address(troveManager); + address recordedTroveManagerAddress = address(sortedTroves.troveManager()); + assertEq(troveManagerAddress, recordedTroveManagerAddress); + } + + //--- BorrowerOperations --- + + function testBorrowerOperationsHasCorrectTroveManagerAddress() public { + address troveManagerAddress = address(troveManager); + address recordedTroveManagerAddress = address(borrowerOperations.troveManager()); + assertEq(troveManagerAddress, recordedTroveManagerAddress); + } + + function testBorrowerOperationsHasCorrectPriceFeedAddress() public { + address priceFeedAddress = address(priceFeed); + address recordedPriceFeedAddress = address(borrowerOperations.priceFeed()); + assertEq(priceFeedAddress, recordedPriceFeedAddress); + } + + function testBorrowerOperationsHasCorrectSortedTrovesAddress() public { + address sortedTrovesAddress = address(sortedTroves); + address recordedSortedTrovesAddress = address(borrowerOperations.sortedTroves()); + assertEq(sortedTrovesAddress, recordedSortedTrovesAddress); + } + + function testBorrowerOperationsHasCorrectActivePoolAddress() public { + address activePoolAddress = address(activePool); + address recordedActivePoolAddress = address(borrowerOperations.activePool()); + assertEq(activePoolAddress, recordedActivePoolAddress); + } + + function testBorrowerOperationsHasCorrectDefaultPoolAddress() public { + address defaultPoolAddress = address(defaultPool); + address recordedDefaultPoolAddress = address(borrowerOperations.defaultPool()); + assertEq(defaultPoolAddress, recordedDefaultPoolAddress); + } +} \ No newline at end of file