Skip to content

Commit

Permalink
chore: money market
Browse files Browse the repository at this point in the history
  • Loading branch information
LidoKing committed Feb 23, 2023
1 parent b1ab102 commit 1b58c2c
Show file tree
Hide file tree
Showing 52 changed files with 4,855 additions and 2 deletions.
182 changes: 182 additions & 0 deletions contracts/money-market/ExponentialNoError.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
contract ExponentialNoError {
uint256 constant expScale = 1e18;
uint256 constant doubleScale = 1e36;
uint256 constant halfExpScale = expScale / 2;
uint256 constant mantissaOne = expScale;

struct Exp {
uint256 mantissa;
}

struct Double {
uint256 mantissa;
}

/**
* @dev Truncates the given exp to a whole number value.
* For example, truncate(Exp{mantissa: 15 * expScale}) = 15
*/
function truncate(Exp memory _exp) internal pure returns (uint256) {
// Note: We are not using careful math here as we're performing a division that cannot fail
return _exp.mantissa / expScale;
}

/**
* @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.
*/
function mul_ScalarTruncate(Exp memory _a, uint256 _scalar) internal pure returns (uint256) {
Exp memory product = mul_(_a, _scalar);
return truncate(product);
}

/**
* @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.
*/
function mul_ScalarTruncateAddUInt(
Exp memory _a,
uint256 _scalar,
uint256 _addend
) internal pure returns (uint256) {
Exp memory product = mul_(_a, _scalar);
return add_(truncate(product), _addend);
}

/**
* @dev Multiply an Exp by a scalar, truncate, then minus an unsigned integer, returning an unsigned integer.
*/
function mul_ScalarTruncateSubUInt(Exp memory _a, uint256 _scalar, uint256 _minus) internal pure returns (uint256) {
Exp memory product = mul_(_a, _scalar);
return sub_(truncate(product), _minus);
}

/**
* @dev Checks if first Exp is less than second Exp.
*/
function lessThanExp(Exp memory _left, Exp memory _right) internal pure returns (bool) {
return _left.mantissa < _right.mantissa;
}

/**
* @dev Checks if left Exp <= right Exp.
*/
function lessThanOrEqualExp(Exp memory _left, Exp memory _right) internal pure returns (bool) {
return _left.mantissa <= _right.mantissa;
}

/**
* @dev Checks if left Exp > right Exp.
*/
function greaterThanExp(Exp memory _left, Exp memory _right) internal pure returns (bool) {
return _left.mantissa > _right.mantissa;
}

/**
* @dev returns true if Exp is exactly zero
*/
function isZeroExp(Exp memory _value) internal pure returns (bool) {
return _value.mantissa == 0;
}

function safe224(uint256 _n, string memory _errorMessage) internal pure returns (uint224) {
require(_n < 2 ** 224, _errorMessage);
return uint224(_n);
}

function safe32(uint256 _n, string memory _errorMessage) internal pure returns (uint32) {
require(_n < 2 ** 32, _errorMessage);
return uint32(_n);
}

function add_(Exp memory _a, Exp memory _b) internal pure returns (Exp memory) {
return Exp({ mantissa: add_(_a.mantissa, _b.mantissa) });
}

function add_(Double memory _a, Double memory _b) internal pure returns (Double memory) {
return Double({ mantissa: add_(_a.mantissa, _b.mantissa) });
}

function add_(uint256 _a, uint256 _b) internal pure returns (uint256) {
return _a + _b;
}

function sub_(Exp memory _a, Exp memory _b) internal pure returns (Exp memory) {
return Exp({ mantissa: sub_(_a.mantissa, _b.mantissa) });
}

function sub_(Double memory _a, Double memory _b) internal pure returns (Double memory) {
return Double({ mantissa: sub_(_a.mantissa, _b.mantissa) });
}

function sub_(uint256 _a, uint256 _b) internal pure returns (uint256) {
return _a - _b;
}

function mul_(Exp memory _a, Exp memory _b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(_a.mantissa, _b.mantissa) / expScale });
}

function mul_(Exp memory _a, uint256 _b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(_a.mantissa, _b) });
}

function mul_(uint256 _a, Exp memory _b) internal pure returns (uint256) {
return mul_(_a, _b.mantissa) / expScale;
}

function mul_(Double memory _a, Double memory _b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(_a.mantissa, _b.mantissa) / doubleScale });
}

function mul_(Double memory _a, uint256 _b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(_a.mantissa, _b) });
}

function mul_(uint256 _a, Double memory _b) internal pure returns (uint256) {
return mul_(_a, _b.mantissa) / doubleScale;
}

function mul_(uint256 _a, uint256 _b) internal pure returns (uint256) {
return _a * _b;
}

function div_(Exp memory _a, Exp memory _b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(mul_(_a.mantissa, expScale), _b.mantissa) });
}

function div_(Exp memory _a, uint256 _b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(_a.mantissa, _b) });
}

function div_(uint256 _a, Exp memory _b) internal pure returns (uint256) {
return div_(mul_(_a, expScale), _b.mantissa);
}

function div_(Double memory _a, Double memory _b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(_a.mantissa, doubleScale), _b.mantissa) });
}

function div_(Double memory _a, uint256 _b) internal pure returns (Double memory) {
return Double({ mantissa: div_(_a.mantissa, _b) });
}

function div_(uint256 _a, Double memory _b) internal pure returns (uint256) {
return div_(mul_(_a, doubleScale), _b.mantissa);
}

function div_(uint256 _a, uint256 _b) internal pure returns (uint256) {
return _a / _b;
}

function fraction(uint256 _a, uint256 _b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(_a, doubleScale), _b) });
}
}
79 changes: 79 additions & 0 deletions contracts/money-market/FErc20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./TokenBase.sol";
import "./TokenStorages.sol";
import "./interfaces/IFErc20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract FErc20 is TokenBase, FErc20Storage, IFErc20 {
function initialize(
address _underlying,
address _riskManager,
address _interestRateModel,
address _priceOracle,
address _checker,
string memory _name,
string memory _symbol
) public initializer {
__TokenBase_init(_riskManager, _interestRateModel, _priceOracle, _checker, _name, _symbol);

underlying = _underlying;
}

function supply(uint256 _supplyAmount) external {
// Params: supplier, supply amount
supplyInternal(msg.sender, _supplyAmount);
}

function redeem(uint256 _redeemTokens) external {
// Params: redeemer, tokens supplied for redemption, amount of underlying to receive
redeemInternal(msg.sender, _redeemTokens, 0);
}

function redeemUnderlying(uint256 _redeemAmount) external {
// Params: redeemer, tokens supplied for redemption, amount of underlying to receive
redeemInternal(msg.sender, 0, _redeemAmount);
}

function borrow(uint256 _borrowAmount) external {
// Params: borrower, borrow amount
borrowInternal(msg.sender, _borrowAmount);
}

function repayBorrow(uint256 _repayAmount) external {
// Params: payer, borrower, repay amount
repayBorrowInternal(msg.sender, msg.sender, _repayAmount);
}

function repayBorrowBehalf(address _borrower, uint256 _repayAmount) external {
// Params: payer, borrower, repay amount
repayBorrowInternal(msg.sender, _borrower, _repayAmount);
}

function liquidateBorrow(address _borrower, uint256 _repayAmount, address _fTokenCollateral) external {
// Params: liquidator, borrower, repay amount, collateral token to be seized
liquidateBorrowInternal(msg.sender, _borrower, _repayAmount, _fTokenCollateral);
}

/******************************* Safe Token *******************************/

function getUnderlying() public view override returns (address) {
return underlying;
}

function doTransferIn(address _from, uint256 _amount) internal override {
IERC20 underlyingToken = IERC20(underlying);
underlyingToken.transferFrom(_from, address(this), _amount);

totalCash += _amount;
}

function doTransferOut(address payable _to, uint256 _amount) internal override {
IERC20 underlyingToken = IERC20(underlying);
underlyingToken.transfer(_to, _amount);

totalCash -= _amount;
}
}
92 changes: 92 additions & 0 deletions contracts/money-market/FEther.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./TokenBase.sol";

contract FEther is TokenBase {
function initialize(
address _riskManager,
address _interestRateModel,
address _priceOracle,
address _checker
) public initializer {
__TokenBase_init(_riskManager, _interestRateModel, _priceOracle, _checker, "Furion Ether", "fETH");
}

/**
* @notice Sender supplies ETH into the market and receives fETH in exchange
* @dev Reverts upon any failure
*/
function supply() external payable {
// Params: supplier, supply amount
supplyInternal(msg.sender, msg.value);
}

/**
* @notice Sender redeems fETH in exchange for ETH.
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param _redeemTokens The number of fETH to redeem into underlying
*/
function redeem(uint256 _redeemTokens) external {
// Params: redeemer, tokens supplied for redemption, amount of underlying to receive
redeemInternal(msg.sender, _redeemTokens, 0);
}

/**
* @notice Sender redeems fETH in exchange for a specified amount of ETH.
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param _redeemAmount The amount of ETH to redeem
*/
function redeemUnderlying(uint256 _redeemAmount) external {
// Params: redeemer, tokens supplied for redemption, amount of underlying to receive
redeemInternal(msg.sender, 0, _redeemAmount);
}

/**
* @notice Sender borrows ETH from the protocol to their own address
* @param _borrowAmount The amount of ETH to borrow
*/
function borrow(uint256 _borrowAmount) external {
// Params: borrower, borrow amount
borrowInternal(msg.sender, _borrowAmount);
}

/**
* @notice Sender repays their own borrow
* @dev Reverts upon any failure
*/
function repayBorrow() external payable {
// Params: payer, borrower, repay amount
repayBorrowInternal(msg.sender, msg.sender, msg.value);
}

/**
* @notice Sender repays a borrow belonging to borrower
* @dev Reverts upon any failure
* @param _borrower the account with the debt being payed off
*/
function repayBorrowBehalf(address _borrower) external payable {
// Params: payer, borrower, repay amount
repayBorrowInternal(msg.sender, _borrower, msg.value);
}

function liquidateBorrow(address _borrower, address _fTokenCollateral) external payable {
liquidateBorrowInternal(msg.sender, _borrower, msg.value, _fTokenCollateral);
}

/******************************* Safe Token *******************************/

function doTransferIn(address _from, uint256 _amount) internal override {
require(msg.sender == _from, "FEther: Not owner of account");
require(msg.value == _amount, "FEther: Not enough ETH supplied");

totalCash += _amount;
}

function doTransferOut(address payable _to, uint256 _amount) internal override {
_to.transfer(_amount);

totalCash -= _amount;
}
}
Loading

0 comments on commit 1b58c2c

Please sign in to comment.