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

OIP-168: USDS Migrator #18

Open
wants to merge 148 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
148 commits
Select commit Hold shift + click to select a range
a05f63a
Create EmissionManager.sol
chefomi Sep 18, 2024
b455632
Merge branch 'protocoloop' of https://github.com/OlympusDAO/bophades …
chefomi Sep 18, 2024
db08743
add backing module and integrate
chefomi Sep 20, 2024
3c684b1
add some comments
chefomi Sep 20, 2024
fdb730c
fix conditional
chefomi Sep 20, 2024
16d6454
account for inventory edge case
chefomi Sep 20, 2024
3dea8ed
remove redundancy
chefomi Sep 20, 2024
909e50c
typo
chefomi Sep 20, 2024
6937dfd
fix: update bond market decimals and config
Oighty Sep 20, 2024
ff3a170
chore: some cleanup
Oighty Sep 20, 2024
a601816
fix: emissions manager cleanup
Oighty Sep 28, 2024
d68c8dd
add shutdown() and restart() logic
chefomi Sep 28, 2024
df87b58
mutable restart timeframe + init assignments
chefomi Sep 28, 2024
400a318
fix: actually initialize vars
Oighty Sep 28, 2024
68736c1
variable cant be constant
chefomi Sep 28, 2024
891c075
Merge branch 'emissions-controller' of https://github.com/OlympusDAO/…
Oighty Sep 28, 2024
b8a65a3
merge
Oighty Sep 28, 2024
c168724
fix: restart timeframe not constant
Oighty Sep 28, 2024
0af991d
test: start test plan for emission manager
Oighty Oct 5, 2024
e06ee6a
have base rate taper changes
chefomi Oct 5, 2024
c622317
fix: handle no previous sale
Oighty Oct 7, 2024
f9391a1
test: start test setup
Oighty Oct 8, 2024
fbdad72
test: initial emission controller test setup
Oighty Oct 9, 2024
9fa1396
fix: beatcounter
Oighty Oct 9, 2024
619cc89
test: add'l emission manager tests
Oighty Oct 9, 2024
5eba1f3
test: minor branch updates
Oighty Oct 11, 2024
29a5c21
create variable and setter for vesting
chefomi Oct 14, 2024
ec84b13
feat: reserve migrator policy
Oighty Oct 15, 2024
c3bb796
feat: shutdown and rescue for reserve migrator + handle local tokens
Oighty Oct 17, 2024
fda6cc5
test: reserve migration tests
Oighty Oct 17, 2024
87ba3f0
test attempt + view funcs
chefomi Oct 23, 2024
4d1ac94
Merge branch 'emissions-controller' of https://github.com/OlympusDAO/…
Oighty Oct 23, 2024
15fe4cf
remove sales array
chefomi Oct 23, 2024
d96a23b
Merge branch 'emissions-controller' of https://github.com/OlympusDAO/…
Oighty Oct 23, 2024
deb45d0
fix: premium values are percents above backing
Oighty Oct 23, 2024
f22c4f2
feat: add backing update event
Oighty Oct 23, 2024
dfa01b3
test: fix tests and add modifiers to make branching easier
Oighty Oct 23, 2024
7e9a971
feat: emission manager callback to simplify accounting
Oighty Oct 23, 2024
64f02af
fix: move mint approval to execute function
Oighty Oct 23, 2024
2a0e92d
test: update existing tests for refactor
Oighty Oct 23, 2024
6905b31
test: add callback unit tests
Oighty Oct 23, 2024
49700e7
max approve teller for ohm
chefomi Oct 24, 2024
59ae165
Revert "max approve teller for ohm"
chefomi Oct 24, 2024
a48619c
fix: use correct calculation for backing percent change
Oighty Oct 24, 2024
2897434
test: more emissions tests
Oighty Oct 24, 2024
b29f35c
Merge branch 'emissions-controller' of https://github.com/OlympusDAO/…
Oighty Oct 24, 2024
9bbf5af
test: rate adjustment tests
Oighty Oct 24, 2024
845a94b
fix: use custom errors throughout and add validations
Oighty Oct 24, 2024
efc6b2d
test: update test TODOs
Oighty Oct 24, 2024
644db12
fix: consistent admin function names and comment cleanup
Oighty Oct 24, 2024
4d729fd
fix: remove deprecated 1 years reference
Oighty Oct 24, 2024
be76454
fix: compile error
Oighty Oct 24, 2024
fdd35d6
test: add shutdown tests
Oighty Oct 25, 2024
c9f4886
chore: comment cleanup
Oighty Oct 28, 2024
7bd2141
chore: rename dai/sDAI on YRF to more generic "reserves"
Oighty Oct 28, 2024
79e2dce
chore: more renaming and constructor cleanup
Oighty Oct 28, 2024
22d8d47
Merge branch 'develop' into reserve-migrator
Oighty Oct 28, 2024
446cd72
chore: change role for running to the Operator to "heart" to match ot…
Oighty Oct 28, 2024
c08eeb4
fix: test and ancillary compile issues
Oighty Oct 28, 2024
1d01d37
fix: change internal function to view
Oighty Oct 28, 2024
458315b
feat: update heart to call reserve migrator
Oighty Oct 28, 2024
b53763b
fix: lower floor on reserve and cushion factors to > 0 instead of > 1%
Oighty Oct 28, 2024
85085cd
feat: allow Operator to use old reserve balance in addition to new one
Oighty Oct 28, 2024
705a51d
script: USDS migration deploy config
Oighty Oct 28, 2024
8ac3589
script: add USDS migration batch script and update env.json
Oighty Oct 28, 2024
049ca0e
Cross-port ROLES documentation from PR #427, with modifications
0xJem Oct 29, 2024
b6d379d
Add missing daiUsdsMigrator address
0xJem Oct 29, 2024
420e78c
Update test TODOs
0xJem Oct 29, 2024
d9d05c5
Add missing address
0xJem Oct 29, 2024
8b7e13b
Add fuzz and constructor tests for changes to cushionFactor and reser…
0xJem Oct 29, 2024
91c51ad
Add VERSION() function to updated policies
0xJem Oct 29, 2024
1bc9d54
Remove obsolete error
0xJem Oct 29, 2024
3d8a785
wrappedReserve -> sReserve for consistency
0xJem Oct 29, 2024
f2ee591
Shenanigans to get under the maximum contract size. 1 byte margin!
0xJem Oct 29, 2024
a5904f9
Add proposal script (test will fail until deployment and address upda…
0xJem Oct 29, 2024
d7c0a3c
proposal: add reserve_migrator_admin role grant to OIP168 proposal
Oighty Oct 29, 2024
622bfed
fix: restart reverts if timeframe passed + tests
Oighty Oct 29, 2024
8250e8c
test: initialize function
Oighty Oct 29, 2024
8fd8a36
test: finish emission manager admin tests
Oighty Oct 29, 2024
09b97d9
test: view function tests
Oighty Oct 29, 2024
ae3306e
chore: tidy up test todos
Oighty Oct 29, 2024
43361e5
chore: rename wrappedReserve -> sReserve for consistency
Oighty Oct 31, 2024
60a0453
docs: natspec comment updates
Oighty Oct 31, 2024
6c27d04
Merge pull request #410 from OlympusDAO/emissions-controller
Oighty Oct 31, 2024
999d25d
Merge branch 'emissions-controller' into reserve-migrator
Oighty Oct 31, 2024
05f6271
chore: remove proposal sim tests from CI
Oighty Oct 31, 2024
3098556
feat: add emission manager to the heart and update tests
Oighty Oct 31, 2024
f6f28bc
Add events for admin functions
0xJem Nov 1, 2024
a95a419
Add tests, missing events
0xJem Nov 1, 2024
22d8c1d
chore: linting
0xJem Nov 1, 2024
66e83b7
Fix TODOs in OCG proposal
0xJem Nov 1, 2024
b9f614a
Cross-port script script improvements from PR #412
0xJem Nov 1, 2024
7ce5cb7
Compilation fixes for OIP-168 proposal
0xJem Nov 1, 2024
0d6a890
Update deployment scripts to include EmissionManager
0xJem Nov 1, 2024
43ecc56
Add EmissionManager to installation script
0xJem Nov 1, 2024
0fc95ed
Better formatting in OIP-168 proposal
0xJem Nov 1, 2024
75e2318
Update roles document
0xJem Nov 1, 2024
aefeec3
Add OCG proposal for EmissionManager
0xJem Nov 1, 2024
e112dc2
chore: linting
0xJem Nov 1, 2024
e367e79
chore: linting
0xJem Nov 1, 2024
1cfc82b
Make batch script executable
0xJem Nov 4, 2024
af1b0b4
Fix arguments in installation script
0xJem Nov 4, 2024
a2f6602
fix: getSupply in wrong scale
Oighty Nov 11, 2024
fb90f53
fix: remove unused import
Oighty Nov 11, 2024
a1e708c
fix: revert if new backing is zero
Oighty Nov 11, 2024
96f6a25
fix: change beatsLeft to daysLeft
Oighty Nov 11, 2024
3594366
fix: use safe transfer library in reserve migrator
Oighty Nov 11, 2024
6255ff1
fix: remove burn/transfer from shutdown, add rescue function
Oighty Nov 11, 2024
3ace544
fix: close bond market on shutdown
Oighty Nov 11, 2024
098eacd
Merge pull request #438 from OlympusDAO/rm-em-audit-fixes
Oighty Nov 12, 2024
892151a
feat: operator fails silently on beat if inactive
Oighty Nov 12, 2024
b44fe70
Merge pull request #435 from OlympusDAO/reserve-migrator-improvements
Oighty Nov 12, 2024
41ef99c
Merge remote-tracking branch 'origin/bophades/reserve-migrator' into …
0xJem Nov 12, 2024
4ae48fd
Correct name for fork test
0xJem Nov 12, 2024
b22a3f8
Cross-port remappings fixes from commit https://github.com/OlympusDAO…
0xJem Nov 12, 2024
752224c
Fixes failing tests due to change in behaviour with Operator.operate(…
0xJem Nov 12, 2024
549e509
Merge branch 'develop' into reserve-migrator
0xJem Nov 12, 2024
e3c065e
Update OIP-168 proposal description
0xJem Nov 13, 2024
ff42341
Adjust proposal number
0xJem Nov 13, 2024
56f54e5
Update OCG proposal
0xJem Nov 13, 2024
0499ee9
Remove proposal for Emissions Manager (shifted into another PR)
0xJem Nov 13, 2024
a9ce29b
Proposal: add resources section, link to PR
0xJem Nov 13, 2024
a768c0a
Merge branch 'reserve-migrator' into emissions-manager
0xJem Nov 13, 2024
3a7d6e1
Proposal: re-structure, add link to PR
0xJem Nov 13, 2024
54ec7b3
Set initial values based on forum proposal
0xJem Nov 13, 2024
3ffef53
Merge branch 'develop' into reserve-migrator
0xJem Nov 13, 2024
e2ad554
Merge branch 'reserve-migrator' into emissions-manager
0xJem Nov 13, 2024
140210a
Merge branch 'develop' into reserve-migrator
0xJem Nov 13, 2024
74f7cea
Shift OIP-168 proposal script to use ProposalScript
0xJem Nov 13, 2024
4f063fb
Merge branch 'reserve-migrator' into emissions-manager
0xJem Nov 13, 2024
07d8568
Shift EmissionManager proposal script to use ProposalScript
0xJem Nov 13, 2024
fa55fee
Merge pull request #21 from OlympusDAO/emissions-manager
Oighty Nov 18, 2024
ba6fe03
proposal: remove YRF initialization from OCG proposal due to time sen…
Oighty Nov 18, 2024
886db59
proposal: also grant dao ms emissions_admin role and fix validation
Oighty Nov 18, 2024
798cd28
proposal: move emission manager initialization to a MS transaction
Oighty Nov 18, 2024
93a8041
feat: look up receivables from CHREG in YRF
Oighty Nov 18, 2024
dce7e99
script: move policy initializations to MS script so heart can beat af…
Oighty Nov 18, 2024
08231a9
fix: compile
Oighty Nov 18, 2024
c7bc456
chore: linting
0xJem Nov 18, 2024
589f3a4
script: add emergency_shutdown to MS and don't beat heart in script
Oighty Nov 18, 2024
6ce3530
deploy: new contracts for usds migration
Oighty Nov 18, 2024
7135e14
script: cleanup
Oighty Nov 18, 2024
bba59a1
Merge branch 'reserve-migrator' of https://github.com/OlympusDAO/olym…
Oighty Nov 18, 2024
23e5ad6
Update deployment addresses. Mark OIP-168 proposal as submitted.
0xJem Nov 19, 2024
ae48f89
Update proposal description
0xJem Nov 19, 2024
936e521
Merge branch 'reserve-migrator' of https://github.com/OlympusDAO/olym…
Oighty Nov 19, 2024
e242564
proposal: emission manager final tweaks
Oighty Nov 19, 2024
9334e49
script: remove operator initialization from USDS migration script
Oighty Nov 26, 2024
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
9 changes: 6 additions & 3 deletions ROLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ This document describes the roles that are used in the Olympus protocol.
| custodian | TreasuryCustodian | Deposit/withdraw reserves and grant/revoke approvals |
| distributor_admin | Distributor | Set reward rate, bounty, and other parameters |
| emergency_restart | Emergency | Reactivates the TRSRY and/or MINTR modules |
| emergency_restart | EmissionManager | Reactivates the EmissionManager |
| emergency_shutdown | Clearinghouse | Allows shutting down the protocol in an emergency |
| emergency_shutdown | Emergency | Deactivates the TRSRY and/or MINTR modules |
| emergency_shutdown | EmissionManager | Deactivates the EmissionManager |
| emissions_admin | EmissionManager | Set configuration parameters |
| heart | EmissionManager | Calls the execute() function |
| heart | Operator | Call the operate() function |
| heart | ReserveMigrator | Allows migrating reserves from one reserve token to another |
| heart | YieldRepurchaseFacility | Creates a new YRF market |
Expand All @@ -25,6 +29,7 @@ This document describes the roles that are used in the Olympus protocol.
| operator_policy | Operator | Set spreads, threshold factor, and cushion factor |
| operator_reporter | Operator | Report bond purchases |
| poly_admin | pOLY | Allows migrating pOLY terms to another contract |
| reserve_migrator_admin | ReserveMigrator | Activate/deactivate the functionality |

## Role Allocations

Expand Down Expand Up @@ -62,9 +67,7 @@ This document describes the roles that are used in the Olympus protocol.
"bridge_admin",
"heart_admin",
"operator_policy",
"loop_daddy",
"contract_registry_admin",
"loan_consolidator_admin"
"loop_daddy"
],
"0xda9fEDBcAF319Ecf8AB11fe874Fb1AbFc2181766": [ // pOly MS
"poly_admin"
Expand Down
8 changes: 8 additions & 0 deletions deployments/.mainnet-1731957551.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"ReserveMigrator": "0x986b99579BEc7B990331474b66CcDB94Fa2419F5",
"YieldRepurchaseFacility": "0xcaA3d3E653A626e2656d2E799564fE952D39d855",
"EmissionManager": "0x50f441a3387625bDA8B8081cE3fd6C04CC48C0A2",
"Operator": "0x6417F206a0a6628Da136C0Faa39026d0134D2b52",
"Clearinghouse": "0x1e094fE00E13Fd06D64EeA4FB3cD912893606fE0",
"OlympusHeart": "0xf7602C0421c283A2fc113172EBDf64C30F21654D"
}
146 changes: 78 additions & 68 deletions src/policies/Clearinghouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
event Deactivate();
/// @notice Logs whenever the treasury is defunded.
event Defund(address token, uint256 amount);
/// @notice Logs the balance change (in DAI terms) whenever a rebalance occurs.
event Rebalance(bool defund, uint256 daiAmount);
/// @notice Logs the balance change (in reserve terms) whenever a rebalance occurs.
event Rebalance(bool defund, uint256 reserveAmount);

// --- RELEVANT CONTRACTS ----------------------------------------

ERC20 public immutable dai; // Debt token
ERC4626 public immutable sdai; // Idle DAI will be wrapped into sDAI
ERC20 public immutable reserve; // Debt token
ERC4626 public immutable sReserve; // Idle reserve will be wrapped into sReserve
ERC20 public immutable gohm; // Collateral token
ERC20 public immutable ohm; // Unwrapped gOHM
IStaking public immutable staking; // Necessary to unstake (and burn) OHM from defaults
Expand All @@ -62,7 +62,7 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
// --- PARAMETER BOUNDS ------------------------------------------

uint256 public constant INTEREST_RATE = 5e15; // 0.5% anually
uint256 public constant LOAN_TO_COLLATERAL = 289292e16; // 2,892.92 DAI/gOHM
uint256 public constant LOAN_TO_COLLATERAL = 289292e16; // 2,892.92 reserve/gOHM
uint256 public constant DURATION = 121 days; // Four months
uint256 public constant FUND_CADENCE = 7 days; // One week
uint256 public constant FUND_AMOUNT = 18_000_000e18; // 18 million
Expand All @@ -88,16 +88,16 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
address ohm_,
address gohm_,
address staking_,
address sdai_,
address sReserve_,
address coolerFactory_,
address kernel_
) Policy(Kernel(kernel_)) CoolerCallback(coolerFactory_) {
// Store the relevant contracts.
ohm = ERC20(ohm_);
gohm = ERC20(gohm_);
staking = IStaking(staking_);
sdai = ERC4626(sdai_);
dai = ERC20(sdai.asset());
sReserve = ERC4626(sReserve_);
reserve = ERC20(sReserve.asset());
}

/// @notice Default framework setup. Configure dependencies for olympus-v3 modules.
Expand Down Expand Up @@ -147,13 +147,21 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
requests[5] = Permissions(TRSRY_KEYCODE, TRSRY.withdrawReserves.selector);
}

/// @notice Returns the version of the policy.
///
/// @return major The major version of the policy.
/// @return minor The minor version of the policy.
function VERSION() external pure returns (uint8 major, uint8 minor) {
return (1, 2);
}

// --- OPERATION -------------------------------------------------

/// @notice Lend to a cooler.
/// @dev To simplify the UX and easily ensure that all holders get the same terms,
/// this function requests a new loan and clears it in the same transaction.
/// @param cooler_ to lend to.
/// @param amount_ of DAI to lend.
/// @param amount_ of reserve to lend.
/// @return the id of the granted loan.
function lendToCooler(Cooler cooler_, uint256 amount_) external returns (uint256) {
// Attempt a Clearinghouse <> Treasury rebalance.
Expand All @@ -163,7 +171,7 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
if (!factory.created(address(cooler_))) revert OnlyFromFactory();

// Validate cooler collateral and debt tokens.
if (cooler_.collateral() != gohm || cooler_.debt() != dai) revert BadEscrow();
if (cooler_.collateral() != gohm || cooler_.debt() != reserve) revert BadEscrow();

// Transfer in collateral owed
uint256 collateral = cooler_.collateralFor(amount_, LOAN_TO_COLLATERAL);
Expand All @@ -178,9 +186,9 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
gohm.approve(address(cooler_), collateral);
uint256 reqID = cooler_.requestLoan(amount_, INTEREST_RATE, LOAN_TO_COLLATERAL, DURATION);

// Clear the created loan request by providing enough DAI.
sdai.withdraw(amount_, address(this), address(this));
dai.approve(address(cooler_), amount_);
// Clear the created loan request by providing enough reserve.
sReserve.withdraw(amount_, address(this), address(this));
reserve.approve(address(cooler_), amount_);
uint256 loanID = cooler_.clearRequest(reqID, address(this), true);

return loanID;
Expand All @@ -202,11 +210,11 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
uint256 interestBase = interestForLoan(loan.principal, loan.request.duration);

// Transfer in extension interest from the caller.
dai.transferFrom(msg.sender, address(this), interestBase * times_);
reserve.transferFrom(msg.sender, address(this), interestBase * times_);
if (active) {
_sweepIntoDSR(interestBase * times_);
_sweepIntoSavingsVault(interestBase * times_);
} else {
_defund(dai, interestBase * times_);
_defund(reserve, interestBase * times_);
}

// Signal to cooler that loan should be extended.
Expand Down Expand Up @@ -266,12 +274,12 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
: 0;

// Update outstanding debt owed to the Treasury upon default.
uint256 outstandingDebt = TRSRY.reserveDebt(dai, address(this));
uint256 outstandingDebt = TRSRY.reserveDebt(reserve, address(this));

// debt owed to TRSRY = user debt - user interest
TRSRY.setDebt({
debtor_: address(this),
token_: dai,
token_: reserve,
amount_: (outstandingDebt > totalPrincipal) ? outstandingDebt - totalPrincipal : 0
});

Expand All @@ -285,13 +293,13 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {

/// @notice Overridden callback to decrement loan receivables.
/// @param *unused loadID_ of the load.
/// @param principalPaid_ in DAI.
/// @param interestPaid_ in DAI.
/// @param principalPaid_ in reserve.
/// @param interestPaid_ in reserve.
function _onRepay(uint256, uint256 principalPaid_, uint256 interestPaid_) internal override {
if (active) {
_sweepIntoDSR(principalPaid_ + interestPaid_);
_sweepIntoSavingsVault(principalPaid_ + interestPaid_);
} else {
_defund(dai, principalPaid_ + interestPaid_);
_defund(reserve, principalPaid_ + interestPaid_);
}

// Decrement loan receivables.
Expand Down Expand Up @@ -323,45 +331,45 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
if (fundTime > block.timestamp) return false;
fundTime += FUND_CADENCE;

// Sweep DAI into DSR if necessary.
uint256 idle = dai.balanceOf(address(this));
if (idle != 0) _sweepIntoDSR(idle);
// Sweep reserve into DSR if necessary.
uint256 idle = reserve.balanceOf(address(this));
if (idle != 0) _sweepIntoSavingsVault(idle);

uint256 daiBalance = sdai.maxWithdraw(address(this));
uint256 outstandingDebt = TRSRY.reserveDebt(dai, address(this));
uint256 reserveBalance = sReserve.maxWithdraw(address(this));
uint256 outstandingDebt = TRSRY.reserveDebt(reserve, address(this));
// Rebalance funds on hand with treasury's reserves.
if (daiBalance < maxFundAmount) {
// Since users loans are denominated in DAI, the clearinghouse
// debt is set in DAI terms. It must be adjusted when funding.
uint256 fundAmount = maxFundAmount - daiBalance;
if (reserveBalance < maxFundAmount) {
// Since users loans are denominated in reserve, the clearinghouse
// debt is set in reserve terms. It must be adjusted when funding.
uint256 fundAmount = maxFundAmount - reserveBalance;
TRSRY.setDebt({
debtor_: address(this),
token_: dai,
token_: reserve,
amount_: outstandingDebt + fundAmount
});

// Since TRSRY holds sDAI, a conversion must be done before
// Since TRSRY holds sReserve, a conversion must be done before
// funding the clearinghouse.
uint256 sdaiAmount = sdai.previewWithdraw(fundAmount);
TRSRY.increaseWithdrawApproval(address(this), sdai, sdaiAmount);
TRSRY.withdrawReserves(address(this), sdai, sdaiAmount);
uint256 sReserveAmount = sReserve.previewWithdraw(fundAmount);
TRSRY.increaseWithdrawApproval(address(this), sReserve, sReserveAmount);
TRSRY.withdrawReserves(address(this), sReserve, sReserveAmount);

// Log the event.
emit Rebalance(false, fundAmount);
} else if (daiBalance > maxFundAmount) {
// Since users loans are denominated in DAI, the clearinghouse
// debt is set in DAI terms. It must be adjusted when defunding.
uint256 defundAmount = daiBalance - maxFundAmount;
} else if (reserveBalance > maxFundAmount) {
// Since users loans are denominated in reserve, the clearinghouse
// debt is set in reserve terms. It must be adjusted when defunding.
uint256 defundAmount = reserveBalance - maxFundAmount;
TRSRY.setDebt({
debtor_: address(this),
token_: dai,
token_: reserve,
amount_: (outstandingDebt > defundAmount) ? outstandingDebt - defundAmount : 0
});

// Since TRSRY holds sDAI, a conversion must be done before
// sending sDAI back.
uint256 sdaiAmount = sdai.previewWithdraw(defundAmount);
sdai.transfer(address(TRSRY), sdaiAmount);
// Since TRSRY holds sReserve, a conversion must be done before
// sending sReserve back.
uint256 sReserveAmount = sReserve.previewWithdraw(defundAmount);
sReserve.transfer(address(TRSRY), sReserveAmount);

// Log the event.
emit Rebalance(true, defundAmount);
Expand All @@ -370,16 +378,16 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
return true;
}

/// @notice Sweep excess DAI into vault.
function sweepIntoDSR() public {
uint256 daiBalance = dai.balanceOf(address(this));
_sweepIntoDSR(daiBalance);
/// @notice Sweep excess reserve into savings vault.
function sweepIntoSavingsVault() public {
uint256 reserveBalance = reserve.balanceOf(address(this));
_sweepIntoSavingsVault(reserveBalance);
}

/// @notice Sweep excess DAI into vault.
function _sweepIntoDSR(uint256 amount_) internal {
dai.approve(address(sdai), amount_);
sdai.deposit(amount_, address(this));
/// @notice Sweep excess reserve into vault.
function _sweepIntoSavingsVault(uint256 amount_) internal {
reserve.approve(address(sReserve), amount_);
sReserve.deposit(amount_, address(this));
}

/// @notice Public function to burn gOHM.
Expand Down Expand Up @@ -408,13 +416,13 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
function emergencyShutdown() external onlyRole("emergency_shutdown") {
active = false;

// If necessary, defund sDAI.
uint256 sdaiBalance = sdai.balanceOf(address(this));
if (sdaiBalance != 0) _defund(sdai, sdaiBalance);
// If necessary, defund sReserve.
uint256 sReserveBalance = sReserve.balanceOf(address(this));
if (sReserveBalance != 0) _defund(sReserve, sReserveBalance);

// If necessary, defund DAI.
uint256 daiBalance = dai.balanceOf(address(this));
if (daiBalance != 0) _defund(dai, daiBalance);
// If necessary, defund reserve.
uint256 reserveBalance = reserve.balanceOf(address(this));
if (reserveBalance != 0) _defund(reserve, reserveBalance);

// Signal to CHREG that the contract has been deactivated.
CHREG.deactivateClearinghouse(address(this));
Expand All @@ -434,16 +442,18 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
/// @param token_ to transfer.
/// @param amount_ to transfer.
function _defund(ERC20 token_, uint256 amount_) internal {
if (token_ == sdai || token_ == dai) {
// Since users loans are denominated in DAI, the clearinghouse
// debt is set in DAI terms. It must be adjusted when defunding.
uint256 outstandingDebt = TRSRY.reserveDebt(dai, address(this));
uint256 daiAmount = (token_ == sdai) ? sdai.previewRedeem(amount_) : amount_;
if (token_ == sReserve || token_ == reserve) {
// Since users loans are denominated in reserve, the clearinghouse
// debt is set in reserve terms. It must be adjusted when defunding.
uint256 outstandingDebt = TRSRY.reserveDebt(reserve, address(this));
uint256 reserveAmount = (token_ == sReserve)
? sReserve.previewRedeem(amount_)
: amount_;

TRSRY.setDebt({
debtor_: address(this),
token_: dai,
amount_: (outstandingDebt > daiAmount) ? outstandingDebt - daiAmount : 0
token_: reserve,
amount_: (outstandingDebt > reserveAmount) ? outstandingDebt - reserveAmount : 0
});
}

Expand All @@ -469,14 +479,14 @@ contract Clearinghouse is Policy, RolesConsumer, CoolerCallback {
}

/// @notice view function to compute the interest for given principal amount.
/// @param principal_ amount of DAI being lent.
/// @param principal_ amount of reserve being lent.
/// @param duration_ elapsed time in seconds.
function interestForLoan(uint256 principal_, uint256 duration_) public pure returns (uint256) {
uint256 interestPercent = (INTEREST_RATE * duration_) / 365 days;
return (principal_ * interestPercent) / 1e18;
}

/// @notice Get total receivable DAI for the treasury.
/// @notice Get total receivable reserve for the treasury.
/// Includes both principal and interest.
function getTotalReceivables() external view returns (uint256) {
return principalReceivables + interestReceivables;
Expand Down
Loading
Loading