-
Notifications
You must be signed in to change notification settings - Fork 0
Add a vault to store ActivePool assets #6
base: add/upgradeability
Are you sure you want to change the base?
Changes from all commits
d57def2
046ece2
73702bf
a21b226
e95e7cc
70cfd82
3139013
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,9 @@ contract ActivePool is Initializable, IActivePool { | |
| // Last time at which the aggregate batch fees and weighted sum were updated | ||
| uint256 public lastAggBatchManagementFeesUpdateTime; | ||
|
|
||
| // vault for collateral funds | ||
| address public vault; | ||
|
|
||
| // --- Events --- | ||
|
|
||
| event CollTokenAddressChanged(address _newCollTokenAddress); | ||
|
|
@@ -73,6 +76,7 @@ contract ActivePool is Initializable, IActivePool { | |
| event StabilityPoolAddressChanged(address _newStabilityPoolAddress); | ||
| event ActivePoolBoldDebtUpdated(uint256 _recordedDebtSum); | ||
| event ActivePoolCollBalanceUpdated(uint256 _collBalance); | ||
| event CollateralVaultChanged(address _newCollateralVault); | ||
|
|
||
| function initialize(IAddressesRegistry _addressesRegistry) external initializer { | ||
| collToken = _addressesRegistry.collToken(); | ||
|
|
@@ -83,12 +87,14 @@ contract ActivePool is Initializable, IActivePool { | |
| interestRouter = _addressesRegistry.interestRouter(); | ||
| boldToken = _addressesRegistry.boldToken(); | ||
| parameters = _addressesRegistry.parameters(); | ||
| vault = address(_addressesRegistry.collateralVault()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe, let's not add collateralVault's address to addressesRegistry as collateralVault feels like a dynamic address or more likely to be changed frequently compared to core contracts. The collateralVault should be get-able directly from ActivePool's interface via a getter method |
||
|
|
||
| emit CollTokenAddressChanged(address(collToken)); | ||
| emit BorrowerOperationsAddressChanged(borrowerOperationsAddress); | ||
| emit TroveManagerAddressChanged(troveManagerAddress); | ||
| emit StabilityPoolAddressChanged(address(stabilityPool)); | ||
| emit DefaultPoolAddressChanged(defaultPoolAddress); | ||
| emit CollateralVaultChanged(address(vault)); | ||
|
|
||
| // Allow funds movements between Liquity contracts | ||
| collToken.approve(defaultPoolAddress, type(uint256).max); | ||
|
|
@@ -168,7 +174,9 @@ contract ActivePool is Initializable, IActivePool { | |
|
|
||
| _accountForSendColl(_amount); | ||
|
|
||
| collToken.safeTransfer(_account, _amount); | ||
| uint256 b = collToken.balanceOf(address(vault)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't understand the purpose of uint256 a and uint256 b |
||
| uint256 a = collToken.allowance(address(vault), address(this)); | ||
| collToken.safeTransferFrom(address(vault), _account, _amount); | ||
| } | ||
|
|
||
| function sendCollToDefaultPool(uint256 _amount) external override { | ||
|
|
@@ -191,7 +199,7 @@ contract ActivePool is Initializable, IActivePool { | |
| _accountForReceivedColl(_amount); | ||
|
|
||
| // Pull Coll tokens from sender | ||
| collToken.safeTransferFrom(msg.sender, address(this), _amount); | ||
| collToken.safeTransferFrom(msg.sender, address(vault), _amount); | ||
| } | ||
|
|
||
| function accountForReceivedColl(uint256 _amount) public { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1318,7 +1318,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio | |
|
|
||
| function _pullCollAndSendToActivePool(IActivePool _activePool, uint256 _amount) internal { | ||
| // Send Coll tokens from sender to active pool | ||
| collToken.safeTransferFrom(msg.sender, address(_activePool), _amount); | ||
| collToken.safeTransferFrom(msg.sender, address(_activePool.vault()), _amount); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, _activePool.vault() should be the correct way of fetching the collateralVault. Should be removed from addressesRegistry. |
||
| // Make sure Active Pool accountancy is right | ||
| _activePool.accountForReceivedColl(_amount); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
|
|
||
| pragma solidity 0.8.24; | ||
|
|
||
| import "openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol"; | ||
| import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/utils/SafeERC20Upgradeable.sol"; | ||
|
|
||
| import "./Interfaces/IAddressesRegistry.sol"; | ||
| import "./Interfaces/ICollateralVault.sol"; | ||
|
|
||
| contract CollateralVault is Ownable2StepUpgradeable, ICollateralVault { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kinda recommend standard EIP4626 vault or async vault instead of custom one to avoid integration issues if we create strategies later on for yield |
||
| using SafeERC20Upgradeable for IERC20Upgradeable; | ||
|
|
||
| IERC20Upgradeable collToken; | ||
| // debt is negative when owner has returned more than withdrawed before | ||
| int256 public ownerDebt; | ||
|
|
||
| function initialize( | ||
| address _owner, | ||
| IAddressesRegistry _addressesRegistry | ||
| ) external initializer { | ||
| __Ownable2Step_init(); | ||
| _transferOwnership(_owner); | ||
|
|
||
| collToken = _addressesRegistry.collToken(); | ||
|
|
||
| // Allow funds movements between Liquity contracts | ||
| address activePool = address(_addressesRegistry.activePool()); | ||
| collToken.approve(activePool, type(uint256).max); | ||
| address borrowerOps = address(_addressesRegistry.borrowerOperations()); | ||
| collToken.approve(borrowerOps, type(uint256).max); | ||
| address defaultPool = address(_addressesRegistry.defaultPool()); | ||
| collToken.approve(defaultPool, type(uint256).max); | ||
| } | ||
|
|
||
| // only owner can withdraw | ||
| function withdraw(uint256 amount) external onlyOwner { | ||
| _requireBalanceIsEnough(amount); | ||
| ownerDebt += int256(amount); | ||
| collToken.approve(owner(), amount); | ||
| collToken.safeTransfer(owner(), amount); | ||
| } | ||
|
|
||
| // anyone can top up | ||
| function topUp(uint256 amount) external { | ||
| ownerDebt -= int256(amount); | ||
| collToken.safeTransferFrom(msg.sender, address(this), amount); | ||
| } | ||
|
|
||
| function _requireBalanceIsEnough(uint256 amount) internal view { | ||
| require(amount <= collToken.balanceOf(address(this)), "CollateralVault: Too big withdraw"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,11 +24,13 @@ contract DefaultPool is Initializable, IDefaultPool { | |
| IERC20Upgradeable public collToken; | ||
| address public troveManagerAddress; | ||
| address public activePoolAddress; | ||
| address public activePoolVaultAddress; | ||
| uint256 internal collBalance; // deposited Coll tracker | ||
| uint256 internal BoldDebt; // debt | ||
|
|
||
| event CollTokenAddressChanged(address _newCollTokenAddress); | ||
| event ActivePoolAddressChanged(address _newActivePoolAddress); | ||
| event ActivePoolVaultAddressChanged(address _newActivePoolAddress); | ||
| event TroveManagerAddressChanged(address _newTroveManagerAddress); | ||
| event DefaultPoolBoldDebtUpdated(uint256 _boldDebt); | ||
| event DefaultPoolCollBalanceUpdated(uint256 _collBalance); | ||
|
|
@@ -37,10 +39,12 @@ contract DefaultPool is Initializable, IDefaultPool { | |
| collToken = _addressesRegistry.collToken(); | ||
| troveManagerAddress = address(_addressesRegistry.troveManager()); | ||
| activePoolAddress = address(_addressesRegistry.activePool()); | ||
| activePoolVaultAddress = address(_addressesRegistry.collateralVault()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Caching activePoolVaultAddress in multiple contracts requires multiple setters. I recommend fetching the address directly from activePool to avoid this redundancy. Also, the naming for the external vault is inconsistent across contracts |
||
|
|
||
| emit CollTokenAddressChanged(address(collToken)); | ||
| emit TroveManagerAddressChanged(troveManagerAddress); | ||
| emit ActivePoolAddressChanged(activePoolAddress); | ||
| emit ActivePoolVaultAddressChanged(activePoolVaultAddress); | ||
|
|
||
| // Allow funds movements between Liquity contracts | ||
| collToken.approve(activePoolAddress, type(uint256).max); | ||
|
|
@@ -79,8 +83,8 @@ contract DefaultPool is Initializable, IDefaultPool { | |
| uint256 newCollBalance = collBalance + _amount; | ||
| collBalance = newCollBalance; | ||
|
|
||
| // Pull Coll tokens from ActivePool | ||
| collToken.safeTransferFrom(msg.sender, address(this), _amount); | ||
| // Pull Coll tokens from ActivePool vault | ||
| collToken.safeTransferFrom(activePoolVaultAddress, address(this), _amount); | ||
|
|
||
| emit DefaultPoolCollBalanceUpdated(newCollBalance); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8.0; | ||
|
|
||
| interface ICollateralVault { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no setter method for vault to have this event emitted.