Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cooler v2 #46

Open
wants to merge 97 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
8837b70
sync with olympus-v3
frontier159 Dec 5, 2024
c857395
proxy FORK_TEST_RPC_URL
frontier159 Dec 5, 2024
6ff2bdd
fix CI
frontier159 Dec 5, 2024
01f63b6
feat: draft cooler v2
frontier159 Oct 25, 2024
da1fa26
feat: added some notes
frontier159 Oct 25, 2024
66280a4
feat: start adding tests
frontier159 Oct 28, 2024
6cc1997
feat: split out delegations into new module
frontier159 Nov 20, 2024
d2a17cf
feat: rework DLGTE, add clones for escrow
frontier159 Nov 21, 2024
e3d0260
feat: added borrow/repay tests
frontier159 Nov 22, 2024
21b9aac
fix: review feedback
frontier159 Nov 27, 2024
fc9f1a3
chore: lint
frontier159 Nov 27, 2024
62eaa04
add composite functions for UX
frontier159 Dec 5, 2024
b00743c
start composite tests
frontier159 Dec 5, 2024
2e6e071
update build post merge
frontier159 Dec 6, 2024
c6a4f4f
lint
frontier159 Dec 6, 2024
9c360a8
feat: add composite tests, fixes
frontier159 Dec 11, 2024
6e12620
fix: remove CHREG dep
frontier159 Dec 11, 2024
ca3f007
don't allow origination LTV to be reduced
frontier159 Dec 23, 2024
5c16fbf
bump forge-std version
frontier159 Jan 7, 2025
d05c91c
ltv oracle
frontier159 Jan 20, 2025
42ce7ee
update ltv oracle tests
frontier159 Jan 21, 2025
e0707de
update tests to have realistic OLTV
frontier159 Jan 22, 2025
e575265
initial implementation of adding 3rd party authorization
frontier159 Jan 22, 2025
d74d571
Merge pull request #443 from OlympusDAO/cooler-v2-ltv-oracle
frontier159 Jan 22, 2025
a2c3cd8
completed tests
frontier159 Jan 22, 2025
49a8ad2
Merge pull request #444 from OlympusDAO/cooler-v2-operator
frontier159 Jan 23, 2025
0162fdc
separated out the treasury borrow/repay into a new module
frontier159 Jan 23, 2025
8405277
roles update for trsry borrower, test to change debt token on the fly
frontier159 Jan 29, 2025
2842651
Merge pull request #445 from OlympusDAO/cooler-v2-trsry-borrower
frontier159 Jan 29, 2025
a5ce630
nit: rename wei to wad
frontier159 Jan 29, 2025
3364757
added liquidation incentive
frontier159 Jan 29, 2025
24c7730
liquidations tests
frontier159 Jan 29, 2025
34031b7
cooler liquidation tests
frontier159 Feb 3, 2025
5202871
completed tests for liquidations
frontier159 Feb 4, 2025
537ac6f
Merge pull request #446 from OlympusDAO/cooler-v2-incentives
frontier159 Feb 4, 2025
ef216fd
missing test update
frontier159 Feb 4, 2025
a6ab8ac
cleanup
frontier159 Feb 4, 2025
b91ab4b
First pass at function for enable/disable functionality
0xJem Feb 4, 2025
61ac6f7
Add documentation
0xJem Feb 4, 2025
6d57c21
Make implementation-specific functions optional
0xJem Feb 4, 2025
05649c0
update the interest rate to be in WAD
frontier159 Feb 4, 2025
46f3a45
Rename Enableable -> PolicyEnabler and change directories
0xJem Feb 5, 2025
e76051c
Add role constants
0xJem Feb 5, 2025
e173fb1
Allow emergency or admin access
0xJem Feb 5, 2025
6582415
Rename modifiers
0xJem Feb 6, 2025
3ec98ae
Add tests
0xJem Feb 6, 2025
7221437
chore: tidy comments
frontier159 Feb 10, 2025
ccc40dd
Merge remote-tracking branch 'origin/bophades/cooler-v2' into cooler-v2
0xJem Feb 10, 2025
2b85dcf
Amend install script to use forge-std 1.9.5
0xJem Feb 10, 2025
e3e452c
Fixes to Cooler/Clearinghouse tests due to MockStaking/MockGohm changes
0xJem Feb 10, 2025
5592522
Fix Quabi-dependent tests caused by changes to optimizer runs and com…
0xJem Feb 10, 2025
132f592
Restore old MockStaking, rename new MockStaking to MockStakingReal
0xJem Feb 10, 2025
6b7719a
Fixes failing EmissionManager test by reverting gOHM index change
0xJem Feb 10, 2025
35f3a4a
pOLY fuzz test fix
0xJem Feb 10, 2025
8a8b1ff
chore: linting
0xJem Feb 10, 2025
0adb257
Revert git submodule change
0xJem Feb 10, 2025
3505d63
Typo
0xJem Feb 10, 2025
95cddab
Document new role
0xJem Feb 10, 2025
b088e9f
ROLES
0xJem Feb 10, 2025
7b6b296
Merge branch 'policy-improvements' into cooler-v2-policy-enabler
0xJem Feb 10, 2025
434f547
Add PolicyEnabler to CoolerTreasuryBorrower, consolidate on "admin" r…
0xJem Feb 10, 2025
dfd99ea
Shift CoolerLtvOracle to use PolicyEnabler. Updates tests.
0xJem Feb 10, 2025
6b47e35
Update ROLES
0xJem Feb 10, 2025
ff6a665
Add isAdmin() and isEmergency() to PolicyEnabler
0xJem Feb 10, 2025
cedeb02
Add PolicyEnabler to MonoCooler
0xJem Feb 10, 2025
f3c93ef
borrow and liquidation actions fail if the policy is not enabled. Gat…
0xJem Feb 10, 2025
49f2559
Trying to reduce contract size
0xJem Feb 10, 2025
20593b1
Shift interfaces to use included IERC20 interface to remove external …
0xJem Feb 11, 2025
00090cc
Use ERC20 for internal variables, add public getters. Strangely reduc…
0xJem Feb 11, 2025
916d392
Fix compile error from previous commit
0xJem Feb 11, 2025
e397f09
Return IERC20 in ICoolerLtvOracle instead of address
0xJem Feb 11, 2025
c3333e4
Shift structs/errors/events from DLGTEv1 into interface
0xJem Feb 11, 2025
b359ff2
Relative imports in interfaces to avoid remappings hell
0xJem Feb 11, 2025
70bd83b
Merge branch 'cooler-v2' into cooler-v2-policy-enabler
0xJem Feb 11, 2025
708e365
Add remaining tests
0xJem Feb 11, 2025
3df1eda
Extract functions
0xJem Feb 11, 2025
45026b5
Reduce bytecode size of MonoCooler by tweaking optimiser
0xJem Feb 11, 2025
78476a5
Use SHA instead of version tag
0xJem Feb 11, 2025
4ebc3f1
Merge branch 'cooler-v2' into cooler-v2-policy-enabler
0xJem Feb 11, 2025
34bf6ea
Fix issues with code coverage
0xJem Feb 11, 2025
77cdc4b
Disable lcov comment for now
0xJem Feb 11, 2025
b730dd0
Merge branch 'cooler-v2' into cooler-v2-policy-enabler
0xJem Feb 11, 2025
ec1ca21
Extract admin/emergency checks into PolicyAdmin mix-in
0xJem Feb 11, 2025
ec596e1
Update MonoCooler to use PolicyAdmin
0xJem Feb 11, 2025
ff2d404
Add convenience modifiers for admin and emergency roles
0xJem Feb 11, 2025
60fc082
Shift cooler contracts to use PolicyAdmin modifiers
0xJem Feb 11, 2025
dcb25b0
More PolicyAdmin changes
0xJem Feb 11, 2025
da24bc8
Merge pull request #47 from OlympusDAO/cooler-v2-policy-enabler
0xJem Feb 11, 2025
9c066a8
update timestamp to uint40 to future proof
frontier159 Feb 13, 2025
7a599fd
ltv oracle: update timestamp to uint40 to future proof
frontier159 Feb 14, 2025
22b05ad
Merge branch 'develop' into cooler-v2
0xJem Feb 17, 2025
2412de7
Apply foundry 1.0 migration fixes
0xJem Feb 17, 2025
8b8c8ea
fix: UnauthorizedOnBehalfOf typo
frontier159 Feb 17, 2025
1d8adcf
fix: cap liquidation incentive to user collateral
frontier159 Feb 17, 2025
5aae2a7
fix: accountDelegationsList paging
frontier159 Feb 17, 2025
6b702f0
chore: lint
frontier159 Feb 17, 2025
a47670c
chore: pull DLGTE interface out
frontier159 Feb 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use ERC20 for internal variables, add public getters. Strangely reduc…
…es contract size.
  • Loading branch information
0xJem committed Feb 11, 2025
commit 00090ccc8f6fa8457a6398c7887ce494d95eb009
38 changes: 19 additions & 19 deletions src/policies/cooler/CoolerTreasuryBorrower.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ contract CoolerTreasuryBorrower is ICoolerTreasuryBorrower, Policy, RolesConsume
TRSRYv1 public TRSRY;

/// @notice sUSDS is used within TRSRY to generate yield on idle USDS
ERC4626 public immutable susds;
ERC4626 public immutable SUSDS;

/// @dev The SKY USDS token
ERC20 private immutable _usds;
ERC20 private immutable _USDS;

bytes32 public constant COOLER_ROLE = bytes32("treasuryborrower_cooler");
bytes32 public constant ADMIN_ROLE = bytes32("treasuryborrower_admin");

constructor(address kernel_, address susds_) Policy(Kernel(kernel_)) {
susds = ERC4626(susds_);
_usds = ERC20(susds.asset());
SUSDS = ERC4626(susds_);
_USDS = ERC20(SUSDS.asset());

// This particular implemenation can only handle an 18dp debtToken
// If (for example) USDC were to be used then logic should be added
// within borrow() and repay() to do the conversions.
if (_usds.decimals() != DECIMALS) revert InvalidParam();
if (_USDS.decimals() != DECIMALS) revert InvalidParam();
}

/// @inheritdoc Policy
Expand Down Expand Up @@ -84,54 +84,54 @@ contract CoolerTreasuryBorrower is ICoolerTreasuryBorrower, Policy, RolesConsume
if (amountInWad == 0) revert ExpectedNonZero();
if (recipient == address(0)) revert InvalidAddress();

uint256 outstandingDebt = TRSRY.reserveDebt(_usds, address(this));
uint256 outstandingDebt = TRSRY.reserveDebt(_USDS, address(this));
TRSRY.setDebt({
debtor_: address(this),
token_: _usds,
token_: _USDS,
amount_: outstandingDebt + amountInWad
});

// Since TRSRY holds sUSDS, a conversion must be done before funding.
// Withdraw that sUSDS amount locally and then redeem to USDS sending to the recipient
uint256 susdsAmount = susds.previewWithdraw(amountInWad);
TRSRY.increaseWithdrawApproval(address(this), susds, susdsAmount);
TRSRY.withdrawReserves(address(this), susds, susdsAmount);
susds.redeem(susdsAmount, recipient, address(this));
uint256 susdsAmount = SUSDS.previewWithdraw(amountInWad);
TRSRY.increaseWithdrawApproval(address(this), SUSDS, susdsAmount);
TRSRY.withdrawReserves(address(this), SUSDS, susdsAmount);
SUSDS.redeem(susdsAmount, recipient, address(this));
}

/// @inheritdoc ICoolerTreasuryBorrower
function repay() external override onlyRole(COOLER_ROLE) {
uint256 debtTokenAmount = _usds.balanceOf(address(this));
uint256 debtTokenAmount = _USDS.balanceOf(address(this));
if (debtTokenAmount == 0) revert ExpectedNonZero();

// This policy is allowed to overpay TRSRY, in which case it's debt is set to zero
// and any future repayments are just deposited. There are no 'credits' for overpaying
uint256 outstandingDebt = TRSRY.reserveDebt(_usds, address(this));
uint256 outstandingDebt = TRSRY.reserveDebt(_USDS, address(this));
TRSRY.setDebt({
debtor_: address(this),
token_: _usds,
token_: _USDS,
amount_: (outstandingDebt > debtTokenAmount) ? outstandingDebt - debtTokenAmount : 0
});

_usds.safeApprove(address(susds), debtTokenAmount);
susds.deposit(debtTokenAmount, address(TRSRY));
_USDS.safeApprove(address(SUSDS), debtTokenAmount);
SUSDS.deposit(debtTokenAmount, address(TRSRY));
}

/// @inheritdoc ICoolerTreasuryBorrower
function setDebt(uint256 debtTokenAmount) external override onlyRole(ADMIN_ROLE) {
TRSRY.setDebt({debtor_: address(this), token_: _usds, amount_: debtTokenAmount});
TRSRY.setDebt({debtor_: address(this), token_: _USDS, amount_: debtTokenAmount});
}

/// @inheritdoc ICoolerTreasuryBorrower
function debtToken() external view override returns (IERC20) {
return IERC20(address(_usds));
return IERC20(address(_USDS));
}

/// @inheritdoc ICoolerTreasuryBorrower
function convertToDebtTokenAmount(
uint256 amountInWad
) external view override returns (IERC20 dToken, uint256 dTokenAmount) {
dToken = IERC20(address(_usds));
dToken = IERC20(address(_USDS));
dTokenAmount = amountInWad;
}
}
78 changes: 47 additions & 31 deletions src/policies/cooler/MonoCooler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
// IMMUTABLES //
//============================================================================================//

/// @inheritdoc IMonoCooler
IERC20 public immutable override collateralToken;
/// @dev The collateral token, eg gOHM
ERC20 private immutable _COLLATERAL_TOKEN;

/// @inheritdoc IMonoCooler
IERC20 public immutable override ohm;
/// @dev The OHM token
ERC20 private immutable _OHM;

/// @inheritdoc IMonoCooler
IStaking public immutable override staking;
/// @dev The OHM staking contract
IStaking private immutable _STAKING;

/// @inheritdoc IMonoCooler
uint256 public immutable override minDebtRequired;
/// @dev The minimum debt a user needs to maintain
uint256 private immutable _MIN_DEBT_REQUIRED;

/// @inheritdoc IMonoCooler
bytes32 public immutable override DOMAIN_SEPARATOR;
Expand Down Expand Up @@ -126,7 +126,7 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
"Authorization(address account,address authorized,uint96 authorizationDeadline,uint256 nonce,uint256 signatureDeadline)"
);

/// @dev expected decimals for the `collateralToken` and `treasuryBorrower`
/// @dev expected decimals for the `_COLLATERAL_TOKEN` and `treasuryBorrower`
uint8 private constant _EXPECTED_DECIMALS = 18;

//============================================================================================//
Expand All @@ -142,14 +142,14 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
uint96 interestRateWad_,
uint256 minDebtRequired_
) Policy(Kernel(kernel_)) {
collateralToken = IERC20(gohm_);
_COLLATERAL_TOKEN = ERC20(gohm_);

// Only handle 18dp collateral
if (collateralToken.decimals() != _EXPECTED_DECIMALS) revert InvalidParam();
if (_COLLATERAL_TOKEN.decimals() != _EXPECTED_DECIMALS) revert InvalidParam();

ohm = IERC20(ohm_);
staking = IStaking(staking_);
minDebtRequired = minDebtRequired_;
_OHM = ERC20(ohm_);
_STAKING = IStaking(staking_);
_MIN_DEBT_REQUIRED = minDebtRequired_;

ltvOracle = ICoolerLtvOracle(ltvOracle_);
(uint96 newOLTV, uint96 newLLTV) = ltvOracle.currentLtvs();
Expand Down Expand Up @@ -186,18 +186,18 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
// If MINTR has changed, then update approval to burn OHM from the old
address oldAddress = address(MINTR);
if (address(newMINTR) != oldAddress) {
if (oldAddress != address(0)) ohm.approve(oldAddress, 0);
if (oldAddress != address(0)) _OHM.approve(oldAddress, 0);

ohm.approve(address(newMINTR), type(uint256).max);
_OHM.approve(address(newMINTR), type(uint256).max);
MINTR = newMINTR;
}

// If DLGTE has changed, then update approval to pull gOHM for delegation
oldAddress = address(DLGTE);
if (address(newDLGTE) != oldAddress) {
if (oldAddress != address(0)) collateralToken.approve(address(oldAddress), 0);
if (oldAddress != address(0)) _COLLATERAL_TOKEN.approve(address(oldAddress), 0);

collateralToken.approve(address(newDLGTE), type(uint256).max);
_COLLATERAL_TOKEN.approve(address(newDLGTE), type(uint256).max);
DLGTE = newDLGTE;
}
}
Expand Down Expand Up @@ -275,11 +275,7 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {

// Add collateral on behalf of another account
AccountState storage aState = allAccountState[onBehalfOf];
ERC20(address(collateralToken)).safeTransferFrom(
msg.sender,
address(this),
collateralAmount
);
_COLLATERAL_TOKEN.safeTransferFrom(msg.sender, address(this), collateralAmount);

aState.collateral += collateralAmount;
totalCollateral += collateralAmount;
Expand Down Expand Up @@ -363,7 +359,7 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {

// Finally transfer the collateral to the recipient
emit CollateralWithdrawn(msg.sender, onBehalfOf, recipient, collateralWithdrawn);
ERC20(address(collateralToken)).safeTransfer(recipient, collateralWithdrawn);
_COLLATERAL_TOKEN.safeTransfer(recipient, collateralWithdrawn);
}

//============================================================================================//
Expand Down Expand Up @@ -414,8 +410,8 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
_accountDebtCheckpoint = currentDebt + amountBorrowed;
}

if (_accountDebtCheckpoint < minDebtRequired)
revert MinDebtNotMet(minDebtRequired, _accountDebtCheckpoint);
if (_accountDebtCheckpoint < _MIN_DEBT_REQUIRED)
revert MinDebtNotMet(_MIN_DEBT_REQUIRED, _accountDebtCheckpoint);

// Update the state
aState.debtCheckpoint = _accountDebtCheckpoint;
Expand Down Expand Up @@ -462,8 +458,8 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {

// Ensure the minimum debt amounts are still maintained
aState.debtCheckpoint = _accountDebtCheckpoint = latestDebt - amountRepaid;
if (_accountDebtCheckpoint < minDebtRequired) {
revert MinDebtNotMet(minDebtRequired, _accountDebtCheckpoint);
if (_accountDebtCheckpoint < _MIN_DEBT_REQUIRED) {
revert MinDebtNotMet(_MIN_DEBT_REQUIRED, _accountDebtCheckpoint);
}
} else {
amountRepaid = latestDebt;
Expand Down Expand Up @@ -583,9 +579,9 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
if (totalCollateralClaimed > 0) {
// Unstake and burn gOHM holdings.
uint128 gOhmToBurn = totalCollateralClaimed - totalLiquidationIncentive;
ERC20(address(collateralToken)).safeApprove(address(staking), gOhmToBurn);
_COLLATERAL_TOKEN.safeApprove(address(_STAKING), gOhmToBurn);

MINTR.burnOhm(address(this), staking.unstake(address(this), gOhmToBurn, false, false));
MINTR.burnOhm(address(this), _STAKING.unstake(address(this), gOhmToBurn, false, false));

totalCollateral -= totalCollateralClaimed;
}
Expand All @@ -597,7 +593,7 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {

// The liquidator receives the total incentives across all accounts
if (totalLiquidationIncentive > 0) {
ERC20(address(collateralToken)).safeTransfer(msg.sender, totalLiquidationIncentive);
_COLLATERAL_TOKEN.safeTransfer(msg.sender, totalLiquidationIncentive);
}
}

Expand Down Expand Up @@ -675,11 +671,31 @@ contract MonoCooler is IMonoCooler, Policy, RolesConsumer {
// VIEW FUNCTIONS //
//============================================================================================//

/// @inheritdoc IMonoCooler
function collateralToken() external view override returns (IERC20) {
return IERC20(address(_COLLATERAL_TOKEN));
}

/// @inheritdoc IMonoCooler
function ohm() external view override returns (IERC20) {
return IERC20(address(_OHM));
}

/// @inheritdoc IMonoCooler
function debtToken() external view override returns (IERC20) {
return treasuryBorrower.debtToken();
}

/// @inheritdoc IMonoCooler
function staking() external view override returns (IStaking) {
return _STAKING;
}

/// @inheritdoc IMonoCooler
function minDebtRequired() external view override returns (uint256) {
return _MIN_DEBT_REQUIRED;
}

/// @inheritdoc IMonoCooler
function loanToValues()
external
Expand Down