Skip to content

Commit

Permalink
feat: improve cToken <> underlying conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
MathisGD committed Jul 25, 2021
1 parent 0e672e0 commit b5a8915
Showing 1 changed file with 50 additions and 63 deletions.
113 changes: 50 additions & 63 deletions contracts/CompoundModuleETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,25 @@ contract CompoundModuleETH is ReentrancyGuard {
function lend(uint256 _amount) external {
require(_amount > 0, "Amount cannot be 0");
lenders.add(msg.sender); // Return false when lender is already there. O(1)
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
// If some borrowers are on Compound, we must move them to Morpho.
if (borrowersOnComp.length() > 0) {
// Find borrowers and move them to Morpho.
uint256 remainingToSupplyToComp = (_moveBorrowersFromCompToMorpho(
_amount
) * 1e18) / cDaiExchangeRate;
uint256 remainingToSupplyToComp = _moveBorrowersFromCompToMorpho(
_amount / oneCDaiInDai
);
// Repay Compound.
cDaiToken.repayBorrow(_amount - remainingToSupplyToComp); // Revert on error.
// Update lender balance.
lendingBalanceOf[msg.sender].onMorpho +=
_amount -
remainingToSupplyToComp; // In underlying.
lendingBalanceOf[msg.sender].onComp +=
(remainingToSupplyToComp * cDaiExchangeRate) /
1e18; // In cToken.
lendingBalanceOf[msg.sender].onComp += (remainingToSupplyToComp /
oneCDaiInDai); // In cToken.
if (remainingToSupplyToComp > 0)
_supplyDaiToComp(remainingToSupplyToComp);
} else {
lendingBalanceOf[msg.sender].onComp +=
(_amount * 1e18) /
cDaiExchangeRate; // In cToken.
lendingBalanceOf[msg.sender].onComp += _amount / oneCDaiInDai; // In cToken.
_supplyDaiToComp(_amount);
}
}
Expand All @@ -105,19 +102,19 @@ contract CompoundModuleETH is ReentrancyGuard {
cDaiToken.transferFrom(msg.sender, address(this), _amount);
// If some borrowers are on Compound, we must move them to Morpho.
if (borrowersOnComp.length() > 0) {
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 amounInDai = (_amount * cDaiExchangeRate) / 1e18;
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
uint256 amounInDai = _amount * oneCDaiInDai;
// Find borrowers and move them to Morpho.
uint256 remainingToSupplyToComp = (_moveBorrowersFromCompToMorpho(
amounInDai
) * 1e18) / cDaiExchangeRate;
uint256 remainingToSupplyToComp = _moveBorrowersFromCompToMorpho(
amounInDai / oneCDaiInDai
);
_redeemDaiFromComp(remainingToSupplyToComp, false);
// Repay Compound.
cDaiToken.repayBorrow(amounInDai - remainingToSupplyToComp); // Revert on error.
// Update lender balance.
lendingBalanceOf[msg.sender].onMorpho +=
((_amount - remainingToSupplyToComp) * cDaiExchangeRate) /
1e18;
(_amount - remainingToSupplyToComp) *
oneCDaiInDai;
lendingBalanceOf[msg.sender].onComp += remainingToSupplyToComp;
} else {
lendingBalanceOf[msg.sender].onComp += _amount; // In cToken.
Expand All @@ -141,23 +138,23 @@ contract CompoundModuleETH is ReentrancyGuard {
"Oracle failed."
);
uint256 numerator = _amount * daiPriceMantissa * collateralFactor;
uint256 denominator = ethPriceMantissa *
cEthToken.exchangeRateCurrent();
uint256 denominator = (ethPriceMantissa *
cEthToken.exchangeRateCurrent()) / 1e18;
uint256 collateralRequiredInCEth = numerator / denominator;
// Check if borrower has enough collateral.
require(
collateralRequiredInCEth <= collateralBalanceOf[msg.sender],
"Not enough collateral."
);
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 amountInCDai = (_amount * 1e18) / cDaiExchangeRate;
uint256 remainingToBorrowOnComp = (_moveLendersFromCompToMorpho(
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
uint256 amountInCDai = _amount / oneCDaiInDai;
uint256 remainingToBorrowOnComp = _moveLendersFromCompToMorpho(
amountInCDai,
msg.sender
) * cDaiExchangeRate) / 1e18; // In underlying.
) * oneCDaiInDai; // In underlying.
borrowingBalanceOf[msg.sender].onMorpho +=
((amountInCDai - remainingToBorrowOnComp) / cDaiExchangeRate) *
1e18; // In underlying.
(amountInCDai - remainingToBorrowOnComp) *
oneCDaiInDai; // In underlying.
// If not enough cTokens on Morpho, we must borrow it on Compound.
if (remainingToBorrowOnComp > 0) {
cDaiToken.borrow(remainingToBorrowOnComp); // Revert on error.
Expand All @@ -182,9 +179,9 @@ contract CompoundModuleETH is ReentrancyGuard {
* @param _amount The amount in DAI to cash-out.
*/
function cashOut(uint256 _amount) external nonReentrant {
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 amountOnCompInDai = (lendingBalanceOf[msg.sender].onComp *
cDaiExchangeRate) / 1e18;
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
uint256 amountOnCompInDai = lendingBalanceOf[msg.sender].onComp *
oneCDaiInDai;
if (_amount <= amountOnCompInDai) {
lendingBalanceOf[msg.sender].onComp -=
(_amount * 1e18) /
Expand All @@ -195,8 +192,8 @@ contract CompoundModuleETH is ReentrancyGuard {
_redeemDaiFromComp(amountOnCompInDai, false);
uint256 remainingToCashOutInDai = _amount - amountOnCompInDai; // In underlying.
lendingBalanceOf[msg.sender].onMorpho -= remainingToCashOutInDai; // In underlying.
uint256 remainingToCashOutInCDai = (remainingToCashOutInDai *
1e18) / cDaiExchangeRate;
uint256 remainingToCashOutInCDai = remainingToCashOutInDai /
oneCDaiInDai;
uint256 cDaiContractBalance = cDaiToken.balanceOf(address(this));
if (remainingToCashOutInCDai <= cDaiContractBalance) {
_moveLendersFromCompToMorpho(
Expand All @@ -207,12 +204,9 @@ contract CompoundModuleETH is ReentrancyGuard {
_moveLendersFromCompToMorpho(cDaiContractBalance, msg.sender);
remainingToCashOutInCDai -= cDaiContractBalance;
remainingToCashOutInCDai -=
(_moveBorrowersFromMorphoToComp(remainingToCashOutInCDai) *
1e18) /
cDaiExchangeRate;
cDaiToken.borrow(
(remainingToCashOutInCDai * cDaiExchangeRate) / 1e18
); // Revert on error.
_moveBorrowersFromMorphoToComp(remainingToCashOutInCDai) /
oneCDaiInDai;
cDaiToken.borrow(remainingToCashOutInCDai * oneCDaiInDai); // Revert on error.
}
}
daiToken.safeTransfer(msg.sender, _amount);
Expand All @@ -232,13 +226,13 @@ contract CompoundModuleETH is ReentrancyGuard {
if (_amount <= lendingBalanceOf[msg.sender].onComp) {
lendingBalanceOf[msg.sender].onComp -= _amount;
} else {
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
uint256 remainingToUnstakeInCDai = _amount -
lendingBalanceOf[msg.sender].onComp;
lendingBalanceOf[msg.sender].onComp = 0;
lendingBalanceOf[msg.sender].onMorpho -=
(remainingToUnstakeInCDai * cDaiExchangeRate) /
1e18;
remainingToUnstakeInCDai *
oneCDaiInDai;
uint256 cDaiContractBalance = cDaiToken.balanceOf(address(this));
if (remainingToUnstakeInCDai <= cDaiContractBalance) {
_moveLendersFromCompToMorpho(
Expand All @@ -248,13 +242,10 @@ contract CompoundModuleETH is ReentrancyGuard {
} else {
_moveLendersFromCompToMorpho(cDaiContractBalance, msg.sender);
remainingToUnstakeInCDai -= cDaiContractBalance;
remainingToUnstakeInCDai -=
(_moveBorrowersFromMorphoToComp(remainingToUnstakeInCDai) *
1e18) /
cDaiExchangeRate;
cDaiToken.borrow(
(remainingToUnstakeInCDai * cDaiExchangeRate) / 1e18
); // Revert on error.
remainingToUnstakeInCDai -= (_moveBorrowersFromMorphoToComp(
remainingToUnstakeInCDai
) * oneCDaiInDai);
cDaiToken.borrow(remainingToUnstakeInCDai * oneCDaiInDai); // Revert on error.
}
}
cDaiToken.transfer(msg.sender, _amount);
Expand Down Expand Up @@ -283,8 +274,8 @@ contract CompoundModuleETH is ReentrancyGuard {
* @param _amount The amount in ETH to get back.
*/
function redeemCollateral(uint256 _amount) external nonReentrant {
uint256 cEthExchangeRate = cEthToken.exchangeRateCurrent();
uint256 amountInCEth = (_amount * 1e18) / cEthExchangeRate;
uint256 oneCEthInEth = cEthToken.exchangeRateCurrent() / 1e18;
uint256 amountInCEth = _amount / oneCEthInEth;
require(
amountInCEth <= collateralBalanceOf[msg.sender],
"Must redeem less than collateral."
Expand All @@ -296,8 +287,8 @@ contract CompoundModuleETH is ReentrancyGuard {
CETH_ADDRESS,
CDAI_ADDRESS
);
uint256 collateralRequiredInCEth = (collateralRequiredInEth * 1e18) /
cEthExchangeRate;
uint256 collateralRequiredInCEth = collateralRequiredInEth /
oneCEthInEth;
uint256 collateralAfterInCEth = collateralBalanceOf[msg.sender] -
amountInCEth;
require(
Expand All @@ -324,7 +315,8 @@ contract CompoundModuleETH is ReentrancyGuard {
uint256 collateralInEth,
uint256 collateralRequiredInEth
) = getAccountLiquidity(_borrower);
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 oneCDaiInDai = cDaiToken.exchangeRateCurrent() / 1e18;
uint256 oneCEthInEth = cDaiToken.exchangeRateCurrent() / 1e18;
require(
collateralInEth < collateralRequiredInEth,
"Borrower position cannot be liquidated."
Expand All @@ -346,14 +338,13 @@ contract CompoundModuleETH is ReentrancyGuard {
collateralInEth *
liquidationIncentive;
uint256 totalBorrowingBalance = borrowingBalanceOf[_borrower].onMorpho +
(borrowingBalanceOf[_borrower].onComp * cDaiExchangeRate) /
1e18;
borrowingBalanceOf[_borrower].onComp *
oneCDaiInDai;
uint256 denominator = totalBorrowingBalance *
ethPriceMantissa *
DENOMINATOR;
uint256 ethAmountToSeize = numerator / denominator;
uint256 cEthAmountToSeize = (ethAmountToSeize * 1e18) /
cEthToken.exchangeRateCurrent();
uint256 cEthAmountToSeize = ethAmountToSeize / oneCEthInEth;
require(
cEthAmountToSeize <= collateralBalanceOf[_borrower],
"Cannot get more than collateral balance of borrower."
Expand Down Expand Up @@ -537,7 +528,6 @@ contract CompoundModuleETH is ReentrancyGuard {
address _lenderToAvoid
) internal returns (uint256 remainingToMove) {
remainingToMove = _amount; // In cToken.
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 i;
while (remainingToMove > 0 && i < lenders.length()) {
address lender = lenders.at(i);
Expand All @@ -547,9 +537,8 @@ contract CompoundModuleETH is ReentrancyGuard {
if (onComp > 0) {
uint256 amountToMove = min(onComp, remainingToMove); // In cToken.
lendingBalanceOf[lender].onComp -= amountToMove; // In cToken.
lendingBalanceOf[lender].onMorpho +=
(amountToMove * cDaiExchangeRate) /
1e18; // In underlying.
lendingBalanceOf[lender].onMorpho += ((amountToMove *
cDaiToken.exchangeRateCurrent()) / 1e18); // In underlying.
remainingToMove -= amountToMove;
}
}
Expand All @@ -566,7 +555,6 @@ contract CompoundModuleETH is ReentrancyGuard {
address _lenderToAvoid
) internal {
uint256 remainingToMove = _amount; // In cToken.
uint256 cDaiExchangeRate = cDaiToken.exchangeRateCurrent();
uint256 i;
while (remainingToMove > 0 && i < lenders.length()) {
address lender = lenders.at(i);
Expand All @@ -576,9 +564,8 @@ contract CompoundModuleETH is ReentrancyGuard {
if (used > 0) {
uint256 amountToMove = min(used, remainingToMove); // In cToken.
lendingBalanceOf[lender].onComp += amountToMove; // In cToken.
lendingBalanceOf[lender].onMorpho -=
(amountToMove * cDaiExchangeRate) /
1e18; // In underlying.
lendingBalanceOf[lender].onMorpho -= ((amountToMove *
cDaiToken.exchangeRateCurrent()) / 1e18); // In underlying.
remainingToMove -= amountToMove; // In cToken.
}
}
Expand Down

0 comments on commit b5a8915

Please sign in to comment.