文件 1 的 23:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 23:AssetBond.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
import '../libraries/Math.sol';
import '../libraries/WadRayMath.sol';
import '../libraries/TimeConverter.sol';
library AssetBond {
using WadRayMath for uint256;
using AssetBond for DataStruct.AssetBondData;
uint256 constant NONCE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00;
uint256 constant COUNTRY_CODE =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC003FF;
uint256 constant COLLATERAL_SERVICE_PROVIDER_IDENTIFICATION_NUMBER =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000003FFFFF;
uint256 constant COLLATERAL_LATITUDE =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000FFFFFFFFFFFFFFFFFF;
uint256 constant COLLATERAL_LATITUDE_SIGNS =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant COLLATERAL_LONGITUDE =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0000001FFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant COLLATERAL_LONGITUDE_SIGNS =
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant COLLATERAL_DETAILS =
0xFFFFFFFFFFFFFFFFFFFFFC0000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant COLLATERAL_CATEGORY =
0xFFFFFFFFFFFFFFFFFFF003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant PRODUCT_NUMBER =
0xFFFFFFFFFFFFFFFFC00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 constant NONCE_START = 0;
uint256 constant COUNTRY_CODE_START = 10;
uint256 constant COLLATERAL_SERVICE_PROVIDER_IDENTIFICATION_NUMBER_START = 22;
uint256 constant COLLATERAL_LATITUDE_START = 72;
uint256 constant COLLATERAL_LATITUDE_SIGNS_START = 100;
uint256 constant COLLATERAL_LONGITUDE_START = 101;
uint256 constant COLLATERAL_LONGITUDE_SIGNS_START = 129;
uint256 constant COLLATERAL_DETAILS_START = 130;
uint256 constant COLLATERAL_CATEGORY_START = 170;
uint256 constant PRODUCT_NUMBER_START = 180;
function parseAssetBondId(uint256 tokenId)
public
pure
returns (DataStruct.AssetBondIdData memory)
{
DataStruct.AssetBondIdData memory vars;
vars.nonce = tokenId & ~NONCE;
vars.countryCode = (tokenId & ~COUNTRY_CODE) >> COUNTRY_CODE_START;
vars.collateralServiceProviderIdentificationNumber =
(tokenId & ~COLLATERAL_SERVICE_PROVIDER_IDENTIFICATION_NUMBER) >>
COLLATERAL_SERVICE_PROVIDER_IDENTIFICATION_NUMBER_START;
vars.collateralLatitude = (tokenId & ~COLLATERAL_LATITUDE) >> COLLATERAL_LATITUDE_START;
vars.collateralLatitudeSign =
(tokenId & ~COLLATERAL_LATITUDE_SIGNS) >>
COLLATERAL_LATITUDE_SIGNS_START;
vars.collateralLongitude = (tokenId & ~COLLATERAL_LONGITUDE) >> COLLATERAL_LONGITUDE_START;
vars.collateralLongitudeSign =
(tokenId & ~COLLATERAL_LONGITUDE_SIGNS) >>
COLLATERAL_LONGITUDE_SIGNS_START;
vars.collateralDetail = (tokenId & ~COLLATERAL_DETAILS) >> COLLATERAL_DETAILS_START;
vars.collateralCategory = (tokenId & ~COLLATERAL_CATEGORY) >> COLLATERAL_CATEGORY_START;
vars.productNumber = (tokenId & ~PRODUCT_NUMBER) >> PRODUCT_NUMBER_START;
return vars;
}
function getAssetBondDebtData(DataStruct.AssetBondData memory assetBondData)
public
view
returns (uint256, uint256)
{
if (assetBondData.state != DataStruct.AssetBondState.COLLATERALIZED) {
return (0, 0);
}
uint256 accruedDebtOnMoneyPool = Math
.calculateCompoundedInterest(
assetBondData.interestRate,
assetBondData.collateralizeTimestamp,
block.timestamp
).rayMul(assetBondData.principal);
uint256 feeOnCollateralServiceProvider = calculateFeeOnRepayment(
assetBondData,
block.timestamp
);
return (accruedDebtOnMoneyPool, feeOnCollateralServiceProvider);
}
struct CalculateFeeOnRepaymentLocalVars {
TimeConverter.DateTime paymentDateTimeStruct;
uint256 paymentDate;
uint256 firstTermRate;
uint256 secondTermRate;
uint256 secondTermOverdueRate;
uint256 thirdTermRate;
uint256 totalRate;
}
function calculateFeeOnRepayment(
DataStruct.AssetBondData memory assetBondData,
uint256 paymentTimestamp
) internal pure returns (uint256) {
CalculateFeeOnRepaymentLocalVars memory vars;
vars.firstTermRate = Math.calculateCompoundedInterest(
assetBondData.couponRate,
assetBondData.loanStartTimestamp,
assetBondData.collateralizeTimestamp
);
vars.paymentDateTimeStruct = TimeConverter.parseTimestamp(paymentTimestamp);
vars.paymentDate = TimeConverter.toTimestamp(
vars.paymentDateTimeStruct.year,
vars.paymentDateTimeStruct.month,
vars.paymentDateTimeStruct.day + 1
);
if (paymentTimestamp <= assetBondData.liquidationTimestamp) {
vars.secondTermRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate - assetBondData.interestRate,
assetBondData.collateralizeTimestamp,
paymentTimestamp
) -
WadRayMath.ray();
vars.thirdTermRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate,
paymentTimestamp,
vars.paymentDate
) -
WadRayMath.ray();
vars.totalRate = vars.firstTermRate + vars.secondTermRate + vars.thirdTermRate;
return assetBondData.principal.rayMul(vars.totalRate) - assetBondData.principal;
}
vars.secondTermRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate - assetBondData.interestRate,
assetBondData.collateralizeTimestamp,
assetBondData.maturityTimestamp
) -
WadRayMath.ray();
vars.secondTermOverdueRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate + assetBondData.delinquencyRate - assetBondData.interestRate,
assetBondData.maturityTimestamp,
paymentTimestamp
) -
WadRayMath.ray();
vars.thirdTermRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate + assetBondData.delinquencyRate,
paymentTimestamp,
vars.paymentDate
) -
WadRayMath.ray();
vars.totalRate =
vars.firstTermRate +
vars.secondTermRate +
vars.secondTermOverdueRate +
vars.thirdTermRate;
return assetBondData.principal.rayMul(vars.totalRate) - assetBondData.principal;
}
function getAssetBondLiquidationData(DataStruct.AssetBondData memory assetBondData)
internal
view
returns (uint256, uint256)
{
uint256 accruedDebtOnMoneyPool = Math
.calculateCompoundedInterest(
assetBondData.interestRate,
assetBondData.collateralizeTimestamp,
block.timestamp
).rayMul(assetBondData.principal);
uint256 feeOnCollateralServiceProvider = calculateDebtAmountToLiquidation(
assetBondData,
block.timestamp
);
return (accruedDebtOnMoneyPool, feeOnCollateralServiceProvider);
}
struct CalculateDebtAmountToLiquidationLocalVars {
TimeConverter.DateTime paymentDateTimeStruct;
uint256 paymentDate;
uint256 firstTermRate;
uint256 secondTermRate;
uint256 totalRate;
}
function calculateDebtAmountToLiquidation(
DataStruct.AssetBondData memory assetBondData,
uint256 paymentTimestamp
) internal pure returns (uint256) {
CalculateDebtAmountToLiquidationLocalVars memory vars;
vars.firstTermRate = Math.calculateCompoundedInterest(
assetBondData.couponRate,
assetBondData.loanStartTimestamp,
assetBondData.maturityTimestamp
);
vars.paymentDateTimeStruct = TimeConverter.parseTimestamp(paymentTimestamp);
vars.paymentDate = TimeConverter.toTimestamp(
vars.paymentDateTimeStruct.year,
vars.paymentDateTimeStruct.month,
vars.paymentDateTimeStruct.day + 1
);
vars.secondTermRate =
Math.calculateCompoundedInterest(
assetBondData.couponRate + assetBondData.delinquencyRate,
assetBondData.maturityTimestamp,
vars.paymentDate
) -
WadRayMath.ray();
vars.totalRate = vars.firstTermRate + vars.secondTermRate;
return assetBondData.principal.rayMul(vars.totalRate) - assetBondData.principal;
}
}
文件 3 的 23:DataStruct.sol
pragma solidity 0.8.3;
library DataStruct {
struct ReserveData {
uint256 moneyPoolFactor;
uint256 lTokenInterestIndex;
uint256 borrowAPY;
uint256 depositAPY;
uint256 lastUpdateTimestamp;
address lTokenAddress;
address dTokenAddress;
address interestModelAddress;
address tokenizerAddress;
uint8 id;
bool isPaused;
bool isActivated;
}
struct AssetBondData {
AssetBondState state;
address borrower;
address signer;
address collateralServiceProvider;
uint256 principal;
uint256 debtCeiling;
uint256 couponRate;
uint256 interestRate;
uint256 delinquencyRate;
uint256 loanStartTimestamp;
uint256 collateralizeTimestamp;
uint256 maturityTimestamp;
uint256 liquidationTimestamp;
string ipfsHash;
string signerOpinionHash;
}
struct AssetBondIdData {
uint256 nonce;
uint256 countryCode;
uint256 collateralServiceProviderIdentificationNumber;
uint256 collateralLatitude;
uint256 collateralLatitudeSign;
uint256 collateralLongitude;
uint256 collateralLongitudeSign;
uint256 collateralDetail;
uint256 collateralCategory;
uint256 productNumber;
}
enum AssetBondState {
EMPTY,
SETTLED,
CONFIRMED,
COLLATERALIZED,
DELINQUENT,
REDEEMED,
LIQUIDATED
}
}
文件 4 的 23:IConnector.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
interface IConnector {
event NewCouncilAdded(address indexed account);
event NewCollateralServiceProviderAdded(address indexed account);
event CouncilRevoked(address indexed account);
event CollateralServiceProviderRevoked(address indexed account);
function isCollateralServiceProvider(address account) external view returns (bool);
function isCouncil(address account) external view returns (bool);
function isMoneyPoolAdmin(address account) external view returns (bool);
}
文件 5 的 23:IDToken.sol
pragma solidity 0.8.3;
import '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';
interface IDToken is IERC20Metadata {
event Mint(
address indexed account,
address indexed receiver,
uint256 amount,
uint256 currentBalance,
uint256 balanceIncrease,
uint256 newRate,
uint256 avgStableRate,
uint256 newTotalSupply
);
event Burn(
address indexed account,
uint256 amount,
uint256 currentBalance,
uint256 balanceIncrease,
uint256 avgStableRate,
uint256 newTotalSupply
);
function mint(
address account,
address receiver,
uint256 amount,
uint256 rate
) external;
function burn(address account, uint256 amount) external;
function getTotalAverageRealAssetBorrowRate() external view returns (uint256);
function getUserAverageRealAssetBorrowRate(address account) external view returns (uint256);
function getUserLastUpdateTimestamp(address account) external view returns (uint256);
function getDTokenData()
external
view
returns (
uint256,
uint256,
uint256,
uint256
);
function getTotalSupplyLastUpdated() external view returns (uint256);
function getTotalSupplyAndAvgRate() external view returns (uint256, uint256);
function principalBalanceOf(address account) external view returns (uint256);
}
文件 6 的 23:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 23:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 8 的 23:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 23:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 10 的 23:IIncentivePool.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
interface IIncentivePool {
event ClaimIncentive(address indexed user, uint256 claimedIncentive, uint256 userIncentiveIndex);
event UpdateIncentivePool(address indexed user, uint256 accruedIncentive, uint256 incentiveIndex);
event IncentivePoolEnded();
event RewardPerSecondUpdated(uint256 newAmountPerSecond);
event IncentiveEndTimestampUpdated(uint256 newEndTimestamp);
function initializeIncentivePool(address lToken) external;
function setAmountPerSecond(uint256 newAmountPerSecond) external;
function setEndTimestamp(uint256 newEndTimestamp) external;
function updateIncentivePool(address user) external;
function beforeTokenTransfer(address from, address to) external;
function claimIncentive() external;
function withdrawResidue() external;
}
文件 11 的 23:IInterestRateModel.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
interface IInterestRateModel {
function calculateRates(
uint256 lTokenAssetBalance,
uint256 totalDTokenBalance,
uint256 depositAmount,
uint256 borrowAmount,
uint256 moneyPoolFactor
) external view returns (uint256, uint256);
}
文件 12 的 23:ILToken.sol
pragma solidity 0.8.3;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface ILToken is IERC20 {
event Mint(address indexed account, uint256 amount, uint256 index);
event Burn(
address indexed account,
address indexed underlyingAssetReceiver,
uint256 amount,
uint256 index
);
event BalanceTransfer(address indexed account, address indexed to, uint256 amount, uint256 index);
function mint(
address account,
uint256 amount,
uint256 index
) external;
function burn(
address account,
address receiver,
uint256 amount,
uint256 index
) external;
function getUnderlyingAsset() external view returns (address);
function implicitBalanceOf(address account) external view returns (uint256);
function implicitTotalSupply() external view returns (uint256);
function transferUnderlyingTo(address underlyingAssetReceiver, uint256 amount) external;
function updateIncentivePool(address newIncentivePool) external;
}
文件 13 的 23:IMoneyPool.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
interface IMoneyPool {
event NewReserve(
address indexed asset,
address lToken,
address dToken,
address interestModel,
address tokenizer,
address incentivePool,
uint256 moneyPoolFactor
);
event Deposit(address indexed asset, address indexed account, uint256 amount);
event Withdraw(
address indexed asset,
address indexed account,
address indexed to,
uint256 amount
);
event Borrow(
address indexed asset,
address indexed collateralServiceProvider,
address indexed borrower,
uint256 tokenId,
uint256 borrowAPY,
uint256 borrowAmount
);
event Repay(
address indexed asset,
address indexed borrower,
uint256 tokenId,
uint256 userDTokenBalance,
uint256 feeOnCollateralServiceProvider
);
event Liquidation(
address indexed asset,
address indexed borrower,
uint256 tokenId,
uint256 userDTokenBalance,
uint256 feeOnCollateralServiceProvider
);
function deposit(
address asset,
address account,
uint256 amount
) external;
function withdraw(
address asset,
address account,
uint256 amount
) external;
function borrow(address asset, uint256 tokenID) external;
function repay(address asset, uint256 tokenId) external;
function liquidate(address asset, uint256 tokenId) external;
function getLTokenInterestIndex(address asset) external view returns (uint256);
function getReserveData(address asset) external view returns (DataStruct.ReserveData memory);
function addNewReserve(
address asset,
address lToken,
address dToken,
address interestModel,
address tokenizer,
address incentivePool,
uint256 moneyPoolFactor_
) external;
}
文件 14 的 23:ITokenizer.sol
pragma solidity 0.8.3;
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
import '../libraries/DataStruct.sol';
interface ITokenizer is IERC721 {
event EmptyAssetBondMinted(address indexed account, uint256 tokenId);
event AssetBondSettled(
address indexed borrower,
address indexed signer,
uint256 tokenId,
uint256 principal,
uint256 couponRate,
uint256 delinquencyRate,
uint256 debtCeiling,
uint256 maturityTimestamp,
uint256 liquidationTimestamp,
uint256 loanStartTimestamp,
string ifpsHash
);
event AssetBondSigned(address indexed signer, uint256 tokenId, string signerOpinionHash);
event AssetBondCollateralized(
address indexed account,
uint256 tokenId,
uint256 borrowAmount,
uint256 interestRate
);
event AssetBondReleased(address indexed borrower, uint256 tokenId);
event AssetBondLiquidated(address indexed liquidator, uint256 tokenId);
function mintAssetBond(address account, uint256 id) external;
function collateralizeAssetBond(
address collateralServiceProvider,
uint256 tokenId,
uint256 borrowAmount,
uint256 borrowAPY
) external;
function releaseAssetBond(address account, uint256 tokenId) external;
function liquidateAssetBond(address account, uint256 tokenId) external;
function getAssetBondIdData(uint256 tokenId)
external
view
returns (DataStruct.AssetBondIdData memory);
function getAssetBondData(uint256 tokenId)
external
view
returns (DataStruct.AssetBondData memory);
function getAssetBondDebtData(uint256 tokenId) external view returns (uint256, uint256);
function getMinter(uint256 tokenId) external view returns (address);
}
文件 15 的 23:Index.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
import '../libraries/Math.sol';
library Index {
using WadRayMath for uint256;
using Index for DataStruct.ReserveData;
event LTokenIndexUpdated(address indexed asset, uint256 lTokenIndex, uint256 lastUpdateTimestamp);
function getLTokenInterestIndex(DataStruct.ReserveData storage reserve)
public
view
returns (uint256)
{
uint256 lastUpdateTimestamp = reserve.lastUpdateTimestamp;
if (lastUpdateTimestamp == block.timestamp) {
return reserve.lTokenInterestIndex;
}
uint256 newIndex = Math
.calculateLinearInterest(reserve.depositAPY, lastUpdateTimestamp, block.timestamp)
.rayMul(reserve.lTokenInterestIndex);
return newIndex;
}
function updateState(DataStruct.ReserveData storage reserve, address asset) internal {
if (reserve.depositAPY == 0) {
reserve.lastUpdateTimestamp = block.timestamp;
return;
}
reserve.lTokenInterestIndex = getLTokenInterestIndex(reserve);
reserve.lastUpdateTimestamp = block.timestamp;
emit LTokenIndexUpdated(asset, reserve.lTokenInterestIndex, reserve.lastUpdateTimestamp);
}
}
文件 16 的 23:Math.sol
pragma solidity 0.8.3;
import './WadRayMath.sol';
library Math {
using WadRayMath for uint256;
uint256 internal constant SECONDSPERYEAR = 365 days;
function calculateLinearInterest(
uint256 rate,
uint256 lastUpdateTimestamp,
uint256 currentTimestamp
) internal pure returns (uint256) {
uint256 timeDelta = currentTimestamp - uint256(lastUpdateTimestamp);
return ((rate * timeDelta) / SECONDSPERYEAR) + WadRayMath.ray();
}
function calculateCompoundedInterest(
uint256 rate,
uint256 lastUpdateTimestamp,
uint256 currentTimestamp
) internal pure returns (uint256) {
uint256 exp = currentTimestamp - lastUpdateTimestamp;
if (exp == 0) {
return WadRayMath.ray();
}
uint256 expMinusOne = exp - 1;
uint256 expMinusTwo = exp > 2 ? exp - 2 : 0;
uint256 ratePerSecond = rate / SECONDSPERYEAR;
uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond);
uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond);
uint256 secondTerm = (exp * expMinusOne * basePowerTwo) / 2;
uint256 thirdTerm = (exp * expMinusOne * expMinusTwo * basePowerThree) / 6;
return WadRayMath.ray() + (ratePerSecond * exp) + secondTerm + thirdTerm;
}
function calculateRateInIncreasingBalance(
uint256 averageRate,
uint256 totalBalance,
uint256 amountIn,
uint256 rate
) internal pure returns (uint256, uint256) {
uint256 weightedAverageRate = totalBalance.wadToRay().rayMul(averageRate);
uint256 weightedAmountRate = amountIn.wadToRay().rayMul(rate);
uint256 newTotalBalance = totalBalance + amountIn;
uint256 newAverageRate = (weightedAverageRate + weightedAmountRate).rayDiv(
newTotalBalance.wadToRay()
);
return (newTotalBalance, newAverageRate);
}
function calculateRateInDecreasingBalance(
uint256 averageRate,
uint256 totalBalance,
uint256 amountOut,
uint256 rate
) internal pure returns (uint256, uint256) {
if (totalBalance <= amountOut) {
return (0, 0);
}
uint256 weightedAverageRate = totalBalance.wadToRay().rayMul(averageRate);
uint256 weightedAmountRate = amountOut.wadToRay().rayMul(rate);
if (weightedAverageRate <= weightedAmountRate) {
return (0, 0);
}
uint256 newTotalBalance = totalBalance - amountOut;
uint256 newAverageRate = (weightedAverageRate - weightedAmountRate).rayDiv(
newTotalBalance.wadToRay()
);
return (newTotalBalance, newAverageRate);
}
}
文件 17 的 23:MoneyPool.sol
pragma solidity 0.8.3;
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import './libraries/DataStruct.sol';
import './logic/Index.sol';
import './logic/Rate.sol';
import './logic/Validation.sol';
import './logic/AssetBond.sol';
import './interfaces/ILToken.sol';
import './interfaces/IDToken.sol';
import './interfaces/IMoneyPool.sol';
import './interfaces/IIncentivePool.sol';
import './interfaces/ITokenizer.sol';
import './MoneyPoolStorage.sol';
contract MoneyPool is IMoneyPool, MoneyPoolStorage {
using SafeERC20 for IERC20;
using Index for DataStruct.ReserveData;
using Validation for DataStruct.ReserveData;
using Rate for DataStruct.ReserveData;
using AssetBond for DataStruct.AssetBondData;
constructor(uint256 maxReserveCount_, address connector) {
_connector = IConnector(connector);
_maxReserveCount = maxReserveCount_;
_reserveCount += 1;
}
function deposit(
address asset,
address account,
uint256 amount
) external override {
DataStruct.ReserveData storage reserve = _reserves[asset];
Validation.validateDeposit(reserve, amount);
reserve.updateState(asset);
reserve.updateRates(asset, amount, 0);
IERC20(asset).safeTransferFrom(msg.sender, reserve.lTokenAddress, amount);
ILToken(reserve.lTokenAddress).mint(account, amount, reserve.lTokenInterestIndex);
emit Deposit(asset, account, amount);
}
function withdraw(
address asset,
address account,
uint256 amount
) external override {
DataStruct.ReserveData storage reserve = _reserves[asset];
uint256 userLTokenBalance = ILToken(reserve.lTokenAddress).balanceOf(msg.sender);
uint256 amountToWithdraw = amount;
if (amount == type(uint256).max) {
amountToWithdraw = userLTokenBalance;
}
Validation.validateWithdraw(reserve, asset, amountToWithdraw, userLTokenBalance);
reserve.updateState(asset);
reserve.updateRates(asset, 0, amountToWithdraw);
ILToken(reserve.lTokenAddress).burn(
msg.sender,
account,
amountToWithdraw,
reserve.lTokenInterestIndex
);
emit Withdraw(asset, msg.sender, account, amountToWithdraw);
}
function borrow(address asset, uint256 tokenId) external override {
require(_connector.isCollateralServiceProvider(msg.sender), 'OnlyCollateralServiceProvider');
DataStruct.ReserveData storage reserve = _reserves[asset];
DataStruct.AssetBondData memory assetBond = ITokenizer(reserve.tokenizerAddress)
.getAssetBondData(tokenId);
uint256 borrowAmount = assetBond.principal;
address receiver = assetBond.borrower;
Validation.validateBorrow(reserve, assetBond, asset, borrowAmount);
reserve.updateState(asset);
ITokenizer(reserve.tokenizerAddress).collateralizeAssetBond(
msg.sender,
tokenId,
borrowAmount,
reserve.borrowAPY
);
IDToken(reserve.dTokenAddress).mint(msg.sender, receiver, borrowAmount, reserve.borrowAPY);
reserve.updateRates(asset, 0, borrowAmount);
ILToken(reserve.lTokenAddress).transferUnderlyingTo(receiver, borrowAmount);
emit Borrow(asset, msg.sender, receiver, tokenId, reserve.borrowAPY, borrowAmount);
}
function repay(address asset, uint256 tokenId) external override {
DataStruct.ReserveData storage reserve = _reserves[asset];
DataStruct.AssetBondData memory assetBond = ITokenizer(reserve.tokenizerAddress)
.getAssetBondData(tokenId);
Validation.validateRepay(reserve, assetBond);
(uint256 accruedDebtOnMoneyPool, uint256 feeOnCollateralServiceProvider) = assetBond
.getAssetBondDebtData();
uint256 totalRetrieveAmount = accruedDebtOnMoneyPool + feeOnCollateralServiceProvider;
reserve.updateState(asset);
IERC20(asset).safeTransferFrom(msg.sender, reserve.lTokenAddress, totalRetrieveAmount);
IDToken(reserve.dTokenAddress).burn(assetBond.borrower, accruedDebtOnMoneyPool);
reserve.updateRates(asset, totalRetrieveAmount, 0);
ITokenizer(reserve.tokenizerAddress).releaseAssetBond(assetBond.borrower, tokenId);
ILToken(reserve.lTokenAddress).mint(
assetBond.collateralServiceProvider,
feeOnCollateralServiceProvider,
reserve.lTokenInterestIndex
);
emit Repay(
asset,
assetBond.borrower,
tokenId,
accruedDebtOnMoneyPool,
feeOnCollateralServiceProvider
);
}
function liquidate(address asset, uint256 tokenId) external override {
require(_connector.isCollateralServiceProvider(msg.sender), 'OnlyCollateralServiceProvider');
DataStruct.ReserveData storage reserve = _reserves[asset];
DataStruct.AssetBondData memory assetBond = ITokenizer(reserve.tokenizerAddress)
.getAssetBondData(tokenId);
Validation.validateLiquidation(reserve, assetBond);
(uint256 accruedDebtOnMoneyPool, uint256 feeOnCollateralServiceProvider) = assetBond
.getAssetBondLiquidationData();
uint256 totalLiquidationAmount = accruedDebtOnMoneyPool + feeOnCollateralServiceProvider;
reserve.updateState(asset);
IDToken(reserve.dTokenAddress).burn(assetBond.borrower, accruedDebtOnMoneyPool);
reserve.updateRates(asset, totalLiquidationAmount, 0);
IERC20(asset).safeTransferFrom(msg.sender, reserve.lTokenAddress, totalLiquidationAmount);
ITokenizer(reserve.tokenizerAddress).liquidateAssetBond(msg.sender, tokenId);
ILToken(reserve.lTokenAddress).mint(
assetBond.collateralServiceProvider,
feeOnCollateralServiceProvider,
reserve.lTokenInterestIndex
);
emit Liquidation(
asset,
assetBond.borrower,
tokenId,
accruedDebtOnMoneyPool,
feeOnCollateralServiceProvider
);
}
function getLTokenInterestIndex(address asset) external view override returns (uint256) {
return _reserves[asset].getLTokenInterestIndex();
}
function getReserveData(address asset)
external
view
override
returns (DataStruct.ReserveData memory)
{
return _reserves[asset];
}
function addNewReserve(
address asset,
address lToken,
address dToken,
address interestModel,
address tokenizer,
address incentivePool,
uint256 moneyPoolFactor_
) external override onlyMoneyPoolAdmin {
DataStruct.ReserveData memory newReserveData = DataStruct.ReserveData({
moneyPoolFactor: moneyPoolFactor_,
lTokenInterestIndex: WadRayMath.ray(),
borrowAPY: 0,
depositAPY: 0,
lastUpdateTimestamp: block.timestamp,
lTokenAddress: lToken,
dTokenAddress: dToken,
interestModelAddress: interestModel,
tokenizerAddress: tokenizer,
id: 0,
isPaused: false,
isActivated: true
});
_reserves[asset] = newReserveData;
_addNewReserveToList(asset);
IIncentivePool(incentivePool).initializeIncentivePool(lToken);
emit NewReserve(
asset,
lToken,
dToken,
interestModel,
tokenizer,
incentivePool,
moneyPoolFactor_
);
}
function _addNewReserveToList(address asset) internal {
uint256 reserveCount = _reserveCount;
require(reserveCount < _maxReserveCount, 'MaxReserveCountExceeded');
require(_reserves[asset].id == 0, 'DigitalAssetAlreadyAdded');
_reserves[asset].id = uint8(reserveCount);
_reservesList[reserveCount] = asset;
_reserveCount = reserveCount + 1;
}
function deactivateMoneyPool(address asset) external onlyMoneyPoolAdmin {
_reserves[asset].isActivated = false;
}
function activateMoneyPool(address asset) external onlyMoneyPoolAdmin {
_reserves[asset].isActivated = true;
}
function pauseMoneyPool(address asset) external onlyMoneyPoolAdmin {
_reserves[asset].isPaused = true;
}
function unPauseMoneyPool(address asset) external onlyMoneyPoolAdmin {
_reserves[asset].isPaused = false;
}
function updateIncentivePool(address asset, address newIncentivePool)
external
onlyMoneyPoolAdmin
{
DataStruct.ReserveData storage reserve = _reserves[asset];
ILToken(reserve.lTokenAddress).updateIncentivePool(newIncentivePool);
}
modifier onlyMoneyPoolAdmin {
require(_connector.isMoneyPoolAdmin(msg.sender), 'OnlyMoneyPoolAdmin');
_;
}
}
文件 18 的 23:MoneyPoolStorage.sol
pragma solidity 0.8.3;
import './libraries/DataStruct.sol';
import './logic/Index.sol';
import './interfaces/IConnector.sol';
contract MoneyPoolStorage {
using Index for DataStruct.ReserveData;
mapping(address => DataStruct.ReserveData) internal _reserves;
mapping(uint256 => address) internal _reservesList;
uint256 internal _reserveCount;
uint256 internal _maxReserveCount;
IConnector internal _connector;
}
文件 19 的 23:Rate.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
import '../libraries/Math.sol';
import '../interfaces/ILToken.sol';
import '../interfaces/IDToken.sol';
import '../interfaces/ITokenizer.sol';
import '../interfaces/IInterestRateModel.sol';
library Rate {
using WadRayMath for uint256;
using Rate for DataStruct.ReserveData;
event RatesUpdated(
address indexed underlyingAssetAddress,
uint256 lTokenIndex,
uint256 borrowAPY,
uint256 depositAPY,
uint256 totalBorrow,
uint256 totalDeposit
);
struct UpdateRatesLocalVars {
uint256 totalDToken;
uint256 newBorrowAPY;
uint256 newDepositAPY;
uint256 averageBorrowAPY;
uint256 totalVariableDebt;
}
function updateRates(
DataStruct.ReserveData storage reserve,
address underlyingAssetAddress,
uint256 depositAmount,
uint256 borrowAmount
) public {
UpdateRatesLocalVars memory vars;
vars.totalDToken = IDToken(reserve.dTokenAddress).totalSupply();
vars.averageBorrowAPY = IDToken(reserve.dTokenAddress).getTotalAverageRealAssetBorrowRate();
uint256 lTokenAssetBalance = IERC20(underlyingAssetAddress).balanceOf(reserve.lTokenAddress);
(vars.newBorrowAPY, vars.newDepositAPY) = IInterestRateModel(reserve.interestModelAddress)
.calculateRates(
lTokenAssetBalance,
vars.totalDToken,
depositAmount,
borrowAmount,
reserve.moneyPoolFactor
);
reserve.borrowAPY = vars.newBorrowAPY;
reserve.depositAPY = vars.newDepositAPY;
emit RatesUpdated(
underlyingAssetAddress,
reserve.lTokenInterestIndex,
vars.newBorrowAPY,
vars.newDepositAPY,
vars.totalDToken,
lTokenAssetBalance + depositAmount - borrowAmount + vars.totalDToken
);
}
}
文件 20 的 23:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 21 的 23:TimeConverter.sol
pragma solidity 0.8.3;
library TimeConverter {
struct DateTime {
uint16 year;
uint8 month;
uint8 day;
uint8 hour;
uint8 minute;
uint8 second;
uint8 weekday;
}
uint256 constant DAY_IN_SECONDS = 86400;
uint256 constant YEAR_IN_SECONDS = 31536000;
uint256 constant LEAP_YEAR_IN_SECONDS = 31622400;
uint256 constant HOUR_IN_SECONDS = 3600;
uint256 constant MINUTE_IN_SECONDS = 60;
uint16 constant ORIGIN_YEAR = 1970;
function isLeapYear(uint16 year) internal pure returns (bool) {
if (year % 4 != 0) {
return false;
}
if (year % 100 != 0) {
return true;
}
if (year % 400 != 0) {
return false;
}
return true;
}
function leapYearsBefore(uint256 year) internal pure returns (uint256) {
year -= 1;
return year / 4 - year / 100 + year / 400;
}
function getDaysInMonth(uint8 month, uint16 year) internal pure returns (uint8) {
if (
month == 1 ||
month == 3 ||
month == 5 ||
month == 7 ||
month == 8 ||
month == 10 ||
month == 12
) {
return 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
}
function parseTimestamp(uint256 timestamp) public pure returns (DateTime memory dateTime) {
uint256 secondsAccountedFor = 0;
uint256 buf;
uint8 i;
dateTime.year = getYear(timestamp);
buf = leapYearsBefore(dateTime.year) - leapYearsBefore(ORIGIN_YEAR);
secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
secondsAccountedFor += YEAR_IN_SECONDS * (dateTime.year - ORIGIN_YEAR - buf);
uint256 secondsInMonth;
for (i = 1; i <= 12; i++) {
secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dateTime.year);
if (secondsInMonth + secondsAccountedFor > timestamp) {
dateTime.month = i;
break;
}
secondsAccountedFor += secondsInMonth;
}
for (i = 1; i <= getDaysInMonth(dateTime.month, dateTime.year); i++) {
if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) {
dateTime.day = i;
break;
}
secondsAccountedFor += DAY_IN_SECONDS;
}
dateTime.hour = getHour(timestamp);
dateTime.minute = getMinute(timestamp);
dateTime.second = getSecond(timestamp);
dateTime.weekday = getWeekday(timestamp);
}
function getYear(uint256 timestamp) internal pure returns (uint16) {
uint256 secondsAccountedFor = 0;
uint16 year;
uint256 numLeapYears;
year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);
numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);
secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;
secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);
while (secondsAccountedFor > timestamp) {
if (isLeapYear(uint16(year - 1))) {
secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;
} else {
secondsAccountedFor -= YEAR_IN_SECONDS;
}
year -= 1;
}
return year;
}
function getMonth(uint256 timestamp) internal pure returns (uint8) {
return parseTimestamp(timestamp).month;
}
function getDay(uint256 timestamp) internal pure returns (uint8) {
return parseTimestamp(timestamp).day;
}
function getHour(uint256 timestamp) internal pure returns (uint8) {
return uint8((timestamp / 60 / 60) % 24);
}
function getMinute(uint256 timestamp) internal pure returns (uint8) {
return uint8((timestamp / 60) % 60);
}
function getSecond(uint256 timestamp) internal pure returns (uint8) {
return uint8(timestamp % 60);
}
function getWeekday(uint256 timestamp) internal pure returns (uint8) {
return uint8((timestamp / DAY_IN_SECONDS + 4) % 7);
}
function toTimestamp(
uint16 year,
uint8 month,
uint8 day
) public pure returns (uint256 timestamp) {
return toTimestamp(year, month, day, 0, 0, 0);
}
function toTimestamp(
uint16 year,
uint8 month,
uint8 day,
uint8 hour
) public pure returns (uint256 timestamp) {
return toTimestamp(year, month, day, hour, 0, 0);
}
function toTimestamp(
uint16 year,
uint8 month,
uint8 day,
uint8 hour,
uint8 minute,
uint8 second
) public pure returns (uint256 timestamp) {
uint16 i;
for (i = ORIGIN_YEAR; i < year; i++) {
if (isLeapYear(i)) {
timestamp += LEAP_YEAR_IN_SECONDS;
} else {
timestamp += YEAR_IN_SECONDS;
}
}
uint8[12] memory monthDayCounts;
monthDayCounts[0] = 31;
if (isLeapYear(year)) {
monthDayCounts[1] = 29;
} else {
monthDayCounts[1] = 28;
}
monthDayCounts[2] = 31;
monthDayCounts[3] = 30;
monthDayCounts[4] = 31;
monthDayCounts[5] = 30;
monthDayCounts[6] = 31;
monthDayCounts[7] = 31;
monthDayCounts[8] = 30;
monthDayCounts[9] = 31;
monthDayCounts[10] = 30;
monthDayCounts[11] = 31;
for (i = 1; i < month; i++) {
timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1];
}
timestamp += DAY_IN_SECONDS * (day - 1);
timestamp += HOUR_IN_SECONDS * (hour);
timestamp += MINUTE_IN_SECONDS * (minute);
timestamp += second;
return timestamp;
}
}
文件 22 的 23:Validation.sol
pragma solidity 0.8.3;
import '../libraries/DataStruct.sol';
import '../libraries/Math.sol';
import '../interfaces/ILToken.sol';
library Validation {
using WadRayMath for uint256;
using Validation for DataStruct.ReserveData;
function validateDeposit(DataStruct.ReserveData storage reserve, uint256 amount) public view {
require(amount != 0, 'InvalidAmount');
require(!reserve.isPaused, 'ReservePaused');
require(reserve.isActivated, 'ReserveInactivated');
}
function validateWithdraw(
DataStruct.ReserveData storage reserve,
address asset,
uint256 amount,
uint256 userLTokenBalance
) public view {
require(amount != 0, 'InvalidAmount');
require(!reserve.isPaused, 'ReservePaused');
require(reserve.isActivated, 'ReserveInactivated');
require(amount <= userLTokenBalance, 'InsufficientBalance');
uint256 availableLiquidity = IERC20(asset).balanceOf(reserve.lTokenAddress);
require(availableLiquidity >= amount, 'NotEnoughLiquidity');
}
function validateBorrow(
DataStruct.ReserveData storage reserve,
DataStruct.AssetBondData memory assetBond,
address asset,
uint256 borrowAmount
) public view {
require(!reserve.isPaused, 'ReservePaused');
require(reserve.isActivated, 'ReserveInactivated');
require(assetBond.state == DataStruct.AssetBondState.CONFIRMED, 'OnlySignedTokenBorrowAllowed');
require(msg.sender == assetBond.collateralServiceProvider, 'OnlyOwnerBorrowAllowed');
uint256 availableLiquidity = IERC20(asset).balanceOf(reserve.lTokenAddress);
require(availableLiquidity >= borrowAmount, 'NotEnoughLiquidity');
require(block.timestamp >= assetBond.loanStartTimestamp, 'NotTimeForLoanStart');
require(assetBond.loanStartTimestamp + 18 hours >= block.timestamp, 'TimeOutForCollateralize');
}
function validateLTokenTrasfer() internal pure {}
function validateRepay(
DataStruct.ReserveData storage reserve,
DataStruct.AssetBondData memory assetBond
) public view {
require(reserve.isActivated, 'ReserveInactivated');
require(block.timestamp < assetBond.liquidationTimestamp, 'LoanExpired');
require(
(assetBond.state == DataStruct.AssetBondState.COLLATERALIZED ||
assetBond.state == DataStruct.AssetBondState.DELINQUENT),
'NotRepayableState'
);
}
function validateLiquidation(
DataStruct.ReserveData storage reserve,
DataStruct.AssetBondData memory assetBond
) public view {
require(reserve.isActivated, 'ReserveInactivated');
require(assetBond.state == DataStruct.AssetBondState.LIQUIDATED, 'NotLiquidatbleState');
}
function validateSignAssetBond(DataStruct.AssetBondData storage assetBond) public view {
require(assetBond.state == DataStruct.AssetBondState.SETTLED, 'OnlySettledTokenSignAllowed');
require(assetBond.signer == msg.sender, 'NotAllowedSigner');
}
function validateSettleAssetBond(DataStruct.AssetBondData memory assetBond) public view {
require(block.timestamp < assetBond.loanStartTimestamp, 'OnlySettledSigned');
require(assetBond.loanStartTimestamp != assetBond.maturityTimestamp, 'LoanDurationInvalid');
}
function validateTokenId(DataStruct.AssetBondIdData memory idData) internal pure {
require(idData.collateralLatitude < 9000000, 'InvaildLatitude');
require(idData.collateralLongitude < 18000000, 'InvaildLongitude');
}
}
文件 23 的 23:WadRayMath.sol
pragma solidity 0.8.3;
library WadRayMath {
uint256 internal constant WAD = 1e18;
uint256 internal constant halfWAD = WAD / 2;
uint256 internal constant RAY = 1e27;
uint256 internal constant halfRAY = RAY / 2;
uint256 internal constant WAD_RAY_RATIO = 1e9;
function ray() internal pure returns (uint256) {
return RAY;
}
function wad() internal pure returns (uint256) {
return WAD;
}
function halfRay() internal pure returns (uint256) {
return halfRAY;
}
function halfWad() internal pure returns (uint256) {
return halfWAD;
}
function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
return (a * b + halfWAD) / WAD;
}
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, 'Division by Zero');
uint256 halfB = b / 2;
return (a * WAD + halfB) / b;
}
function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
return (a * b + halfRAY) / RAY;
}
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, 'Division by Zero');
uint256 halfB = b / 2;
return (a * RAY + halfB) / b;
}
function rayToWad(uint256 a) internal pure returns (uint256) {
uint256 halfRatio = WAD_RAY_RATIO / 2;
uint256 result = halfRatio + a;
return result / WAD_RAY_RATIO;
}
function wadToRay(uint256 a) internal pure returns (uint256) {
uint256 result = a * WAD_RAY_RATIO;
return result;
}
}
{
"compilationTarget": {
"contracts/MoneyPool.sol": "MoneyPool"
},
"evmVersion": "istanbul",
"libraries": {
"contracts/libraries/TimeConverter.sol:TimeConverter": "0x01d07c9fd2e3fbc493e0a2de588ce1c1ead137e4",
"contracts/logic/AssetBond.sol:AssetBond": "0xa139841e0d43bab85ddd00469eed93a5a000ca9e",
"contracts/logic/Index.sol:Index": "0x9eb704b380e6cae794af479796866a264f87aa79",
"contracts/logic/Rate.sol:Rate": "0x625b4afcf08a5f4f85fc45e56387376ff4bed6bf",
"contracts/logic/Validation.sol:Validation": "0x08f7e687a90bba01e8613827fd0d67e41949f9cc"
},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1
},
"remappings": []
}
[{"inputs":[{"internalType":"uint256","name":"maxReserveCount_","type":"uint256"},{"internalType":"address","name":"connector","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"collateralServiceProvider","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowAPY","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"userDTokenBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeOnCollateralServiceProvider","type":"uint256"}],"name":"Liquidation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"lToken","type":"address"},{"indexed":false,"internalType":"address","name":"dToken","type":"address"},{"indexed":false,"internalType":"address","name":"interestModel","type":"address"},{"indexed":false,"internalType":"address","name":"tokenizer","type":"address"},{"indexed":false,"internalType":"address","name":"incentivePool","type":"address"},{"indexed":false,"internalType":"uint256","name":"moneyPoolFactor","type":"uint256"}],"name":"NewReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"userDTokenBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeOnCollateralServiceProvider","type":"uint256"}],"name":"Repay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"activateMoneyPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"lToken","type":"address"},{"internalType":"address","name":"dToken","type":"address"},{"internalType":"address","name":"interestModel","type":"address"},{"internalType":"address","name":"tokenizer","type":"address"},{"internalType":"address","name":"incentivePool","type":"address"},{"internalType":"uint256","name":"moneyPoolFactor_","type":"uint256"}],"name":"addNewReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"deactivateMoneyPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getLTokenInterestIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getReserveData","outputs":[{"components":[{"internalType":"uint256","name":"moneyPoolFactor","type":"uint256"},{"internalType":"uint256","name":"lTokenInterestIndex","type":"uint256"},{"internalType":"uint256","name":"borrowAPY","type":"uint256"},{"internalType":"uint256","name":"depositAPY","type":"uint256"},{"internalType":"uint256","name":"lastUpdateTimestamp","type":"uint256"},{"internalType":"address","name":"lTokenAddress","type":"address"},{"internalType":"address","name":"dTokenAddress","type":"address"},{"internalType":"address","name":"interestModelAddress","type":"address"},{"internalType":"address","name":"tokenizerAddress","type":"address"},{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"bool","name":"isPaused","type":"bool"},{"internalType":"bool","name":"isActivated","type":"bool"}],"internalType":"struct DataStruct.ReserveData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"pauseMoneyPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"unPauseMoneyPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"newIncentivePool","type":"address"}],"name":"updateIncentivePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]