编译器
0.5.17+commit.d19bba13
文件 1 的 64:ATokenMock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../libs/DecMath.sol";
contract ATokenMock is ERC20, ERC20Detailed {
using SafeMath for uint256;
using DecMath for uint256;
uint256 internal constant YEAR = 31556952;
ERC20 public dai;
uint256 public liquidityRate;
uint256 public normalizedIncome;
address[] public users;
mapping(address => bool) public isUser;
constructor(address _dai)
public
ERC20Detailed("aDAI", "aDAI", 18)
{
dai = ERC20(_dai);
liquidityRate = 10 ** 26;
normalizedIncome = 10 ** 27;
}
function mint(address _user, uint256 _amount) external {
_mint(_user, _amount);
if (!isUser[_user]) {
users.push(_user);
isUser[_user] = true;
}
}
function burn(address _user, uint256 _amount) external {
_burn(_user, _amount);
}
function mintInterest(uint256 _seconds) external {
uint256 interest;
address user;
for (uint256 i = 0; i < users.length; i++) {
user = users[i];
interest = balanceOf(user).mul(_seconds).mul(liquidityRate).div(YEAR.mul(10**27));
_mint(user, interest);
}
normalizedIncome = normalizedIncome.mul(_seconds).mul(liquidityRate).div(YEAR.mul(10**27)).add(normalizedIncome);
}
function setLiquidityRate(uint256 _liquidityRate) external {
liquidityRate = _liquidityRate;
}
}
文件 2 的 64:AaveMarket.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../IMoneyMarket.sol";
import "./imports/ILendingPool.sol";
import "./imports/ILendingPoolAddressesProvider.sol";
contract AaveMarket is IMoneyMarket, Ownable {
using SafeMath for uint256;
using SafeERC20 for ERC20;
using Address for address;
uint16 internal constant REFERRALCODE = 20;
ILendingPoolAddressesProvider public provider;
ERC20 public stablecoin;
ERC20 public aToken;
constructor(
address _provider,
address _aToken,
address _stablecoin
) public {
require(
_provider != address(0) &&
_aToken != address(0) &&
_stablecoin != address(0),
"AaveMarket: An input address is 0"
);
require(
_provider.isContract() &&
_aToken.isContract() &&
_stablecoin.isContract(),
"AaveMarket: An input address is not a contract"
);
provider = ILendingPoolAddressesProvider(_provider);
stablecoin = ERC20(_stablecoin);
aToken = ERC20(_aToken);
}
function deposit(uint256 amount) external onlyOwner {
require(amount > 0, "AaveMarket: amount is 0");
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
stablecoin.safeTransferFrom(msg.sender, address(this), amount);
stablecoin.safeIncreaseAllowance(address(lendingPool), amount);
lendingPool.deposit(
address(stablecoin),
amount,
address(this),
REFERRALCODE
);
}
function withdraw(uint256 amountInUnderlying)
external
onlyOwner
returns (uint256 actualAmountWithdrawn)
{
require(amountInUnderlying > 0, "AaveMarket: amountInUnderlying is 0");
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
lendingPool.withdraw(
address(stablecoin),
amountInUnderlying,
msg.sender
);
return amountInUnderlying;
}
function claimRewards() external {}
function totalValue() external returns (uint256) {
return aToken.balanceOf(address(this));
}
function incomeIndex() external returns (uint256) {
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
return lendingPool.getReserveNormalizedIncome(address(stablecoin));
}
function setRewards(address newValue) external {}
}
文件 3 的 64:Address.sol
pragma solidity ^0.5.5;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
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");
}
}
文件 4 的 64:CERC20Mock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
contract CERC20Mock is ERC20, ERC20Detailed {
address public dai;
uint256 internal _supplyRate;
uint256 internal _exchangeRate;
constructor(address _dai) public ERC20Detailed("cDAI", "cDAI", 8) {
dai = _dai;
uint256 daiDecimals = ERC20Detailed(_dai).decimals();
_exchangeRate = 2 * (10**(daiDecimals + 8));
_supplyRate = 45290900000;
}
function mint(uint256 amount) external returns (uint256) {
require(
ERC20(dai).transferFrom(msg.sender, address(this), amount),
"Error during transferFrom"
);
_mint(msg.sender, (amount * 10**18) / _exchangeRate);
return 0;
}
function redeemUnderlying(uint256 amount) external returns (uint256) {
_burn(msg.sender, (amount * 10**18) / _exchangeRate);
require(
ERC20(dai).transfer(msg.sender, amount),
"Error during transfer"
);
return 0;
}
function exchangeRateStored() external view returns (uint256) {
return _exchangeRate;
}
function exchangeRateCurrent() external view returns (uint256) {
return _exchangeRate;
}
function _setExchangeRateStored(uint256 _rate) external returns (uint256) {
_exchangeRate = _rate;
}
function supplyRatePerBlock() external view returns (uint256) {
return _supplyRate;
}
function _setSupplyRatePerBlock(uint256 _rate) external {
_supplyRate = _rate;
}
}
文件 5 的 64:CompoundERC20Market.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../IMoneyMarket.sol";
import "../../libs/DecMath.sol";
import "./imports/ICERC20.sol";
import "./imports/IComptroller.sol";
contract CompoundERC20Market is IMoneyMarket, Ownable {
using DecMath for uint256;
using SafeERC20 for ERC20;
using Address for address;
uint256 internal constant ERRCODE_OK = 0;
ICERC20 public cToken;
IComptroller public comptroller;
address public rewards;
ERC20 public stablecoin;
constructor(
address _cToken,
address _comptroller,
address _rewards,
address _stablecoin
) public {
require(
_cToken != address(0) &&
_comptroller != address(0) &&
_rewards != address(0) &&
_stablecoin != address(0),
"CompoundERC20Market: An input address is 0"
);
require(
_cToken.isContract() &&
_comptroller.isContract() &&
_rewards.isContract() &&
_stablecoin.isContract(),
"CompoundERC20Market: An input address is not a contract"
);
cToken = ICERC20(_cToken);
comptroller = IComptroller(_comptroller);
rewards = _rewards;
stablecoin = ERC20(_stablecoin);
}
function deposit(uint256 amount) external onlyOwner {
require(amount > 0, "CompoundERC20Market: amount is 0");
stablecoin.safeTransferFrom(msg.sender, address(this), amount);
stablecoin.safeIncreaseAllowance(address(cToken), amount);
require(
cToken.mint(amount) == ERRCODE_OK,
"CompoundERC20Market: Failed to mint cTokens"
);
}
function withdraw(uint256 amountInUnderlying)
external
onlyOwner
returns (uint256 actualAmountWithdrawn)
{
require(
amountInUnderlying > 0,
"CompoundERC20Market: amountInUnderlying is 0"
);
require(
cToken.redeemUnderlying(amountInUnderlying) == ERRCODE_OK,
"CompoundERC20Market: Failed to redeem"
);
stablecoin.safeTransfer(msg.sender, amountInUnderlying);
return amountInUnderlying;
}
function claimRewards() external {
comptroller.claimComp(address(this));
ERC20 comp = ERC20(comptroller.getCompAddress());
comp.safeTransfer(rewards, comp.balanceOf(address(this)));
}
function totalValue() external returns (uint256) {
uint256 cTokenBalance = cToken.balanceOf(address(this));
uint256 cTokenPrice = cToken.exchangeRateCurrent();
return cTokenBalance.decmul(cTokenPrice);
}
function incomeIndex() external returns (uint256) {
return cToken.exchangeRateCurrent();
}
function setRewards(address newValue) external onlyOwner {
require(newValue.isContract(), "CompoundERC20Market: not contract");
rewards = newValue;
emit ESetParamAddress(msg.sender, "rewards", newValue);
}
}
文件 6 的 64:ComptrollerMock.sol
pragma solidity 0.5.17;
import "./ERC20Mock.sol";
contract ComptrollerMock {
uint256 public constant CLAIM_AMOUNT = 10**18;
ERC20Mock public comp;
constructor (address _comp) public {
comp = ERC20Mock(_comp);
}
function claimComp(address holder) external {
comp.mint(holder, CLAIM_AMOUNT);
}
function getCompAddress() external view returns (address) {
return address(comp);
}
}
文件 7 的 64:Context.sol
pragma solidity ^0.5.0;
contract Context {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
文件 8 的 64:Counters.sol
pragma solidity ^0.5.0;
import "../math/SafeMath.sol";
library Counters {
using SafeMath for uint256;
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
文件 9 的 64:Curve.sol
pragma solidity ^0.5.17;
interface ICurveFi {
function remove_liquidity_imbalance(
uint256[2] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity_imbalance(
uint256[3] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity_imbalance(
uint256[4] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity_imbalance(
uint256[5] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity(uint256 _amount, uint256[2] calldata amounts)
external;
function remove_liquidity(uint256 _amount, uint256[3] calldata amounts)
external;
function remove_liquidity(uint256 _amount, uint256[4] calldata amounts)
external;
function remove_liquidity(uint256 _amount, uint256[5] calldata amounts)
external;
}
interface Zap {
function remove_liquidity_one_coin(
uint256,
int128,
uint256
) external;
}
文件 10 的 64:CurveLPWithdrawer.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/access/roles/SignerRole.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../imports/Curve.sol";
import "../../IRewards.sol";
contract CurveLPWithdrawer is SignerRole {
function curveWithdraw2(
address lpTokenAddress,
address curvePoolAddress,
uint256[2] calldata minAmounts
) external onlySigner {
IERC20 lpToken = IERC20(lpTokenAddress);
uint256 lpTokenBalance = lpToken.balanceOf(address(this));
ICurveFi curvePool = ICurveFi(curvePoolAddress);
curvePool.remove_liquidity(lpTokenBalance, minAmounts);
}
function curveWithdraw3(
address lpTokenAddress,
address curvePoolAddress,
uint256[3] calldata minAmounts
) external onlySigner {
IERC20 lpToken = IERC20(lpTokenAddress);
uint256 lpTokenBalance = lpToken.balanceOf(address(this));
ICurveFi curvePool = ICurveFi(curvePoolAddress);
curvePool.remove_liquidity(lpTokenBalance, minAmounts);
}
function curveWithdraw4(
address lpTokenAddress,
address curvePoolAddress,
uint256[4] calldata minAmounts
) external onlySigner {
IERC20 lpToken = IERC20(lpTokenAddress);
uint256 lpTokenBalance = lpToken.balanceOf(address(this));
ICurveFi curvePool = ICurveFi(curvePoolAddress);
curvePool.remove_liquidity(lpTokenBalance, minAmounts);
}
function curveWithdraw5(
address lpTokenAddress,
address curvePoolAddress,
uint256[5] calldata minAmounts
) external onlySigner {
IERC20 lpToken = IERC20(lpTokenAddress);
uint256 lpTokenBalance = lpToken.balanceOf(address(this));
ICurveFi curvePool = ICurveFi(curvePoolAddress);
curvePool.remove_liquidity(lpTokenBalance, minAmounts);
}
function curveWithdrawOneCoin(
address lpTokenAddress,
address curvePoolAddress,
int128 coinIndex,
uint256 minAmount
) external onlySigner {
IERC20 lpToken = IERC20(lpTokenAddress);
uint256 lpTokenBalance = lpToken.balanceOf(address(this));
Zap curvePool = Zap(curvePoolAddress);
curvePool.remove_liquidity_one_coin(
lpTokenBalance,
coinIndex,
minAmount
);
}
}
文件 11 的 64:DInterest.sol
pragma solidity 0.5.17;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "./libs/DecMath.sol";
import "./moneymarkets/IMoneyMarket.sol";
import "./models/fee/IFeeModel.sol";
import "./models/interest/IInterestModel.sol";
import "./NFT.sol";
import "./rewards/MPHMinter.sol";
import "./models/interest-oracle/IInterestOracle.sol";
contract DInterest is ReentrancyGuard, Ownable {
using SafeMath for uint256;
using DecMath for uint256;
using SafeERC20 for ERC20;
using Address for address;
uint256 internal constant PRECISION = 10**18;
uint256 internal constant ONE = 10**18;
struct Deposit {
uint256 amount;
uint256 maturationTimestamp;
uint256 interestOwed;
uint256 initialMoneyMarketIncomeIndex;
bool active;
bool finalSurplusIsNegative;
uint256 finalSurplusAmount;
uint256 mintMPHAmount;
uint256 depositTimestamp;
}
Deposit[] internal deposits;
uint256 public latestFundedDepositID;
uint256 public unfundedUserDepositAmount;
struct Funding {
uint256 fromDepositID;
uint256 toDepositID;
uint256 recordedFundedDepositAmount;
uint256 recordedMoneyMarketIncomeIndex;
uint256 creationTimestamp;
}
Funding[] internal fundingList;
uint256 public MinDepositPeriod;
uint256 public MaxDepositPeriod;
uint256 public MinDepositAmount;
uint256 public MaxDepositAmount;
uint256 public totalDeposit;
uint256 public totalInterestOwed;
IMoneyMarket public moneyMarket;
ERC20 public stablecoin;
IFeeModel public feeModel;
IInterestModel public interestModel;
IInterestOracle public interestOracle;
NFT public depositNFT;
NFT public fundingNFT;
MPHMinter public mphMinter;
event EDeposit(
address indexed sender,
uint256 indexed depositID,
uint256 amount,
uint256 maturationTimestamp,
uint256 interestAmount,
uint256 mintMPHAmount
);
event EWithdraw(
address indexed sender,
uint256 indexed depositID,
uint256 indexed fundingID,
bool early,
uint256 takeBackMPHAmount
);
event EFund(
address indexed sender,
uint256 indexed fundingID,
uint256 deficitAmount
);
event ESetParamAddress(
address indexed sender,
string indexed paramName,
address newValue
);
event ESetParamUint(
address indexed sender,
string indexed paramName,
uint256 newValue
);
struct DepositLimit {
uint256 MinDepositPeriod;
uint256 MaxDepositPeriod;
uint256 MinDepositAmount;
uint256 MaxDepositAmount;
}
constructor(
DepositLimit memory _depositLimit,
address _moneyMarket,
address _stablecoin,
address _feeModel,
address _interestModel,
address _interestOracle,
address _depositNFT,
address _fundingNFT,
address _mphMinter
) public {
require(
_moneyMarket.isContract() &&
_stablecoin.isContract() &&
_feeModel.isContract() &&
_interestModel.isContract() &&
_interestOracle.isContract() &&
_depositNFT.isContract() &&
_fundingNFT.isContract() &&
_mphMinter.isContract(),
"DInterest: An input address is not a contract"
);
moneyMarket = IMoneyMarket(_moneyMarket);
stablecoin = ERC20(_stablecoin);
feeModel = IFeeModel(_feeModel);
interestModel = IInterestModel(_interestModel);
interestOracle = IInterestOracle(_interestOracle);
depositNFT = NFT(_depositNFT);
fundingNFT = NFT(_fundingNFT);
mphMinter = MPHMinter(_mphMinter);
require(
moneyMarket.stablecoin() == _stablecoin,
"DInterest: moneyMarket.stablecoin() != _stablecoin"
);
require(
interestOracle.moneyMarket() == _moneyMarket,
"DInterest: interestOracle.moneyMarket() != _moneyMarket"
);
require(
_depositLimit.MaxDepositPeriod > 0 &&
_depositLimit.MaxDepositAmount > 0,
"DInterest: An input uint256 is 0"
);
require(
_depositLimit.MinDepositPeriod <= _depositLimit.MaxDepositPeriod,
"DInterest: Invalid DepositPeriod range"
);
require(
_depositLimit.MinDepositAmount <= _depositLimit.MaxDepositAmount,
"DInterest: Invalid DepositAmount range"
);
MinDepositPeriod = _depositLimit.MinDepositPeriod;
MaxDepositPeriod = _depositLimit.MaxDepositPeriod;
MinDepositAmount = _depositLimit.MinDepositAmount;
MaxDepositAmount = _depositLimit.MaxDepositAmount;
totalDeposit = 0;
}
function deposit(uint256 amount, uint256 maturationTimestamp)
external
nonReentrant
{
_deposit(amount, maturationTimestamp);
}
function withdraw(uint256 depositID, uint256 fundingID)
external
nonReentrant
{
_withdraw(depositID, fundingID, false);
}
function earlyWithdraw(uint256 depositID, uint256 fundingID)
external
nonReentrant
{
_withdraw(depositID, fundingID, true);
}
function multiDeposit(
uint256[] calldata amountList,
uint256[] calldata maturationTimestampList
) external nonReentrant {
require(
amountList.length == maturationTimestampList.length,
"DInterest: List lengths unequal"
);
for (uint256 i = 0; i < amountList.length; i = i.add(1)) {
_deposit(amountList[i], maturationTimestampList[i]);
}
}
function multiWithdraw(
uint256[] calldata depositIDList,
uint256[] calldata fundingIDList
) external nonReentrant {
require(
depositIDList.length == fundingIDList.length,
"DInterest: List lengths unequal"
);
for (uint256 i = 0; i < depositIDList.length; i = i.add(1)) {
_withdraw(depositIDList[i], fundingIDList[i], false);
}
}
function multiEarlyWithdraw(
uint256[] calldata depositIDList,
uint256[] calldata fundingIDList
) external nonReentrant {
require(
depositIDList.length == fundingIDList.length,
"DInterest: List lengths unequal"
);
for (uint256 i = 0; i < depositIDList.length; i = i.add(1)) {
_withdraw(depositIDList[i], fundingIDList[i], true);
}
}
function fundAll() external nonReentrant {
(bool isNegative, uint256 deficit) = surplus();
require(isNegative, "DInterest: No deficit available");
require(
!depositIsFunded(deposits.length),
"DInterest: All deposits funded"
);
uint256 incomeIndex = moneyMarket.incomeIndex();
require(incomeIndex > 0, "DInterest: incomeIndex == 0");
fundingList.push(
Funding({
fromDepositID: latestFundedDepositID,
toDepositID: deposits.length,
recordedFundedDepositAmount: unfundedUserDepositAmount,
recordedMoneyMarketIncomeIndex: incomeIndex,
creationTimestamp: now
})
);
latestFundedDepositID = deposits.length;
unfundedUserDepositAmount = 0;
_fund(deficit);
}
function fundMultiple(uint256 toDepositID) external nonReentrant {
require(
toDepositID > latestFundedDepositID,
"DInterest: Deposits already funded"
);
require(
toDepositID <= deposits.length,
"DInterest: Invalid toDepositID"
);
(bool isNegative, uint256 surplus) = surplus();
require(isNegative, "DInterest: No deficit available");
uint256 totalDeficit = 0;
uint256 totalSurplus = 0;
uint256 totalDepositToFund = 0;
for (
uint256 id = latestFundedDepositID.add(1);
id <= toDepositID;
id = id.add(1)
) {
Deposit storage depositEntry = _getDeposit(id);
if (depositEntry.active) {
(isNegative, surplus) = surplusOfDeposit(id);
} else {
(isNegative, surplus) = (
depositEntry.finalSurplusIsNegative,
depositEntry.finalSurplusAmount
);
}
if (isNegative) {
totalDeficit = totalDeficit.add(surplus);
} else {
totalSurplus = totalSurplus.add(surplus);
}
if (depositEntry.active) {
totalDepositToFund = totalDepositToFund.add(
depositEntry.amount
);
}
}
if (totalSurplus >= totalDeficit) {
revert("DInterest: Selected deposits in surplus");
} else {
totalDeficit = totalDeficit.sub(totalSurplus);
}
uint256 incomeIndex = moneyMarket.incomeIndex();
require(incomeIndex > 0, "DInterest: incomeIndex == 0");
fundingList.push(
Funding({
fromDepositID: latestFundedDepositID,
toDepositID: toDepositID,
recordedFundedDepositAmount: totalDepositToFund,
recordedMoneyMarketIncomeIndex: incomeIndex,
creationTimestamp: now
})
);
latestFundedDepositID = toDepositID;
unfundedUserDepositAmount = unfundedUserDepositAmount.sub(
totalDepositToFund
);
_fund(totalDeficit);
}
function calculateInterestAmount(
uint256 depositAmount,
uint256 depositPeriodInSeconds
) public returns (uint256 interestAmount) {
(, uint256 moneyMarketInterestRatePerSecond) = interestOracle
.updateAndQuery();
(bool surplusIsNegative, uint256 surplusAmount) = surplus();
return
interestModel.calculateInterestAmount(
depositAmount,
depositPeriodInSeconds,
moneyMarketInterestRatePerSecond,
surplusIsNegative,
surplusAmount
);
}
function surplus() public returns (bool isNegative, uint256 surplusAmount) {
uint256 totalValue = moneyMarket.totalValue();
uint256 totalOwed = totalDeposit.add(totalInterestOwed);
if (totalValue >= totalOwed) {
isNegative = false;
surplusAmount = totalValue.sub(totalOwed);
} else {
isNegative = true;
surplusAmount = totalOwed.sub(totalValue);
}
}
function surplusOfDeposit(uint256 depositID)
public
returns (bool isNegative, uint256 surplusAmount)
{
Deposit storage depositEntry = _getDeposit(depositID);
uint256 currentMoneyMarketIncomeIndex = moneyMarket.incomeIndex();
uint256 currentDepositValue = depositEntry
.amount
.mul(currentMoneyMarketIncomeIndex)
.div(depositEntry.initialMoneyMarketIncomeIndex);
uint256 owed = depositEntry.amount.add(depositEntry.interestOwed);
if (currentDepositValue >= owed) {
isNegative = false;
surplusAmount = currentDepositValue.sub(owed);
} else {
isNegative = true;
surplusAmount = owed.sub(currentDepositValue);
}
}
function depositIsFunded(uint256 id) public view returns (bool) {
return (id <= latestFundedDepositID);
}
function depositsLength() external view returns (uint256) {
return deposits.length;
}
function fundingListLength() external view returns (uint256) {
return fundingList.length;
}
function getDeposit(uint256 depositID)
external
view
returns (Deposit memory)
{
return deposits[depositID.sub(1)];
}
function getFunding(uint256 fundingID)
external
view
returns (Funding memory)
{
return fundingList[fundingID.sub(1)];
}
function moneyMarketIncomeIndex() external returns (uint256) {
return moneyMarket.incomeIndex();
}
function setFeeModel(address newValue) external onlyOwner {
require(newValue.isContract(), "DInterest: not contract");
feeModel = IFeeModel(newValue);
emit ESetParamAddress(msg.sender, "feeModel", newValue);
}
function setInterestModel(address newValue) external onlyOwner {
require(newValue.isContract(), "DInterest: not contract");
interestModel = IInterestModel(newValue);
emit ESetParamAddress(msg.sender, "interestModel", newValue);
}
function setInterestOracle(address newValue) external onlyOwner {
require(newValue.isContract(), "DInterest: not contract");
interestOracle = IInterestOracle(newValue);
emit ESetParamAddress(msg.sender, "interestOracle", newValue);
}
function setRewards(address newValue) external onlyOwner {
require(newValue.isContract(), "DInterest: not contract");
moneyMarket.setRewards(newValue);
emit ESetParamAddress(msg.sender, "moneyMarket.rewards", newValue);
}
function setMPHMinter(address newValue) external onlyOwner {
require(newValue.isContract(), "DInterest: not contract");
mphMinter = MPHMinter(newValue);
emit ESetParamAddress(msg.sender, "mphMinter", newValue);
}
function setMinDepositPeriod(uint256 newValue) external onlyOwner {
require(newValue <= MaxDepositPeriod, "DInterest: invalid value");
MinDepositPeriod = newValue;
emit ESetParamUint(msg.sender, "MinDepositPeriod", newValue);
}
function setMaxDepositPeriod(uint256 newValue) external onlyOwner {
require(
newValue >= MinDepositPeriod && newValue > 0,
"DInterest: invalid value"
);
MaxDepositPeriod = newValue;
emit ESetParamUint(msg.sender, "MaxDepositPeriod", newValue);
}
function setMinDepositAmount(uint256 newValue) external onlyOwner {
require(newValue <= MaxDepositAmount, "DInterest: invalid value");
MinDepositAmount = newValue;
emit ESetParamUint(msg.sender, "MinDepositAmount", newValue);
}
function setMaxDepositAmount(uint256 newValue) external onlyOwner {
require(
newValue >= MinDepositAmount && newValue > 0,
"DInterest: invalid value"
);
MaxDepositAmount = newValue;
emit ESetParamUint(msg.sender, "MaxDepositAmount", newValue);
}
function setDepositNFTTokenURI(uint256 tokenId, string calldata newURI)
external
onlyOwner
{
depositNFT.setTokenURI(tokenId, newURI);
}
function setDepositNFTBaseURI(string calldata newURI) external onlyOwner {
depositNFT.setBaseURI(newURI);
}
function setDepositNFTContractURI(string calldata newURI)
external
onlyOwner
{
depositNFT.setContractURI(newURI);
}
function setFundingNFTTokenURI(uint256 tokenId, string calldata newURI)
external
onlyOwner
{
fundingNFT.setTokenURI(tokenId, newURI);
}
function setFundingNFTBaseURI(string calldata newURI) external onlyOwner {
fundingNFT.setBaseURI(newURI);
}
function setFundingNFTContractURI(string calldata newURI)
external
onlyOwner
{
fundingNFT.setContractURI(newURI);
}
function _getDeposit(uint256 depositID)
internal
view
returns (Deposit storage)
{
return deposits[depositID.sub(1)];
}
function _getFunding(uint256 fundingID)
internal
view
returns (Funding storage)
{
return fundingList[fundingID.sub(1)];
}
function _deposit(uint256 amount, uint256 maturationTimestamp) internal {
require(amount > 0, "DInterest: Deposit amount is 0");
require(
amount >= MinDepositAmount && amount <= MaxDepositAmount,
"DInterest: Deposit amount out of range"
);
uint256 depositPeriod = maturationTimestamp.sub(now);
require(
depositPeriod >= MinDepositPeriod &&
depositPeriod <= MaxDepositPeriod,
"DInterest: Deposit period out of range"
);
totalDeposit = totalDeposit.add(amount);
uint256 id = deposits.length.add(1);
unfundedUserDepositAmount = unfundedUserDepositAmount.add(amount);
uint256 interestAmount = calculateInterestAmount(amount, depositPeriod);
require(interestAmount > 0, "DInterest: interestAmount == 0");
totalInterestOwed = totalInterestOwed.add(interestAmount);
uint256 mintMPHAmount = mphMinter.mintDepositorReward(
msg.sender,
amount,
depositPeriod,
interestAmount
);
deposits.push(
Deposit({
amount: amount,
maturationTimestamp: maturationTimestamp,
interestOwed: interestAmount,
initialMoneyMarketIncomeIndex: moneyMarket.incomeIndex(),
active: true,
finalSurplusIsNegative: false,
finalSurplusAmount: 0,
mintMPHAmount: mintMPHAmount,
depositTimestamp: now
})
);
stablecoin.safeTransferFrom(msg.sender, address(this), amount);
stablecoin.safeIncreaseAllowance(address(moneyMarket), amount);
moneyMarket.deposit(amount);
depositNFT.mint(msg.sender, id);
emit EDeposit(
msg.sender,
id,
amount,
maturationTimestamp,
interestAmount,
mintMPHAmount
);
}
function _withdraw(
uint256 depositID,
uint256 fundingID,
bool early
) internal {
Deposit storage depositEntry = _getDeposit(depositID);
require(depositEntry.active, "DInterest: Deposit not active");
depositEntry.active = false;
if (early) {
require(
now < depositEntry.maturationTimestamp,
"DInterest: Deposit mature, use withdraw() instead"
);
require(
now > depositEntry.depositTimestamp,
"DInterest: Deposited in same block"
);
} else {
require(
now >= depositEntry.maturationTimestamp,
"DInterest: Deposit not mature"
);
}
require(
depositNFT.ownerOf(depositID) == msg.sender,
"DInterest: Sender doesn't own depositNFT"
);
uint256 takeBackMPHAmount = mphMinter.takeBackDepositorReward(
msg.sender,
depositEntry.mintMPHAmount,
early
);
totalDeposit = totalDeposit.sub(depositEntry.amount);
totalInterestOwed = totalInterestOwed.sub(depositEntry.interestOwed);
uint256 feeAmount;
uint256 withdrawAmount;
if (early) {
withdrawAmount = depositEntry.amount;
} else {
feeAmount = feeModel.getFee(depositEntry.interestOwed);
withdrawAmount = depositEntry.amount.add(depositEntry.interestOwed);
}
withdrawAmount = moneyMarket.withdraw(withdrawAmount);
(
bool depositSurplusIsNegative,
uint256 depositSurplus
) = surplusOfDeposit(depositID);
if (depositIsFunded(depositID)) {
_payInterestToFunder(
fundingID,
depositID,
depositEntry.amount,
depositEntry.maturationTimestamp,
depositSurplusIsNegative,
depositSurplus,
early
);
} else {
unfundedUserDepositAmount = unfundedUserDepositAmount.sub(
depositEntry.amount
);
depositEntry.finalSurplusIsNegative = depositSurplusIsNegative;
depositEntry.finalSurplusAmount = depositSurplus;
}
stablecoin.safeTransfer(msg.sender, withdrawAmount.sub(feeAmount));
stablecoin.safeTransfer(feeModel.beneficiary(), feeAmount);
emit EWithdraw(
msg.sender,
depositID,
fundingID,
early,
takeBackMPHAmount
);
}
function _payInterestToFunder(
uint256 fundingID,
uint256 depositID,
uint256 depositAmount,
uint256 depositMaturationTimestamp,
bool depositSurplusIsNegative,
uint256 depositSurplus,
bool early
) internal {
Funding storage f = _getFunding(fundingID);
require(
depositID > f.fromDepositID && depositID <= f.toDepositID,
"DInterest: Deposit not funded by fundingID"
);
uint256 currentMoneyMarketIncomeIndex = moneyMarket.incomeIndex();
require(
currentMoneyMarketIncomeIndex > 0,
"DInterest: currentMoneyMarketIncomeIndex == 0"
);
uint256 interestAmount = f
.recordedFundedDepositAmount
.mul(currentMoneyMarketIncomeIndex)
.div(f.recordedMoneyMarketIncomeIndex)
.sub(f.recordedFundedDepositAmount);
f.recordedFundedDepositAmount = f.recordedFundedDepositAmount.sub(
depositAmount
);
f.recordedMoneyMarketIncomeIndex = currentMoneyMarketIncomeIndex;
address funder = fundingNFT.ownerOf(fundingID);
uint256 transferToFunderAmount = (early && depositSurplusIsNegative)
? interestAmount.add(depositSurplus)
: interestAmount;
if (transferToFunderAmount > 0) {
transferToFunderAmount = moneyMarket.withdraw(
transferToFunderAmount
);
stablecoin.safeTransfer(funder, transferToFunderAmount);
}
mphMinter.mintFunderReward(
funder,
depositAmount,
f.creationTimestamp,
depositMaturationTimestamp,
interestAmount,
early
);
}
function _fund(uint256 totalDeficit) internal {
stablecoin.safeTransferFrom(msg.sender, address(this), totalDeficit);
stablecoin.safeIncreaseAllowance(address(moneyMarket), totalDeficit);
moneyMarket.deposit(totalDeficit);
fundingNFT.mint(msg.sender, fundingList.length);
uint256 fundingID = fundingList.length;
emit EFund(msg.sender, fundingID, totalDeficit);
}
}
文件 12 的 64:DecMath.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
library DecMath {
using SafeMath for uint256;
uint256 internal constant PRECISION = 10**18;
function decmul(uint256 a, uint256 b) internal pure returns (uint256) {
return a.mul(b).div(PRECISION);
}
function decdiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a.mul(PRECISION).div(b);
}
}
文件 13 的 64:Dumper.sol
pragma solidity 0.5.17;
import "./OneSplitDumper.sol";
import "./withdrawers/CurveLPWithdrawer.sol";
import "./withdrawers/YearnWithdrawer.sol";
contract Dumper is OneSplitDumper, CurveLPWithdrawer, YearnWithdrawer {
constructor(
address _oneSplit,
address _rewards,
address _rewardToken
) public OneSplitDumper(_oneSplit, _rewards, _rewardToken) {}
}
文件 14 的 64:EMAOracle.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../../moneymarkets/IMoneyMarket.sol";
import "../../libs/DecMath.sol";
import "./IInterestOracle.sol";
contract EMAOracle is IInterestOracle {
using SafeMath for uint256;
using DecMath for uint256;
uint256 internal constant PRECISION = 10**18;
uint256 public UPDATE_INTERVAL;
uint256 public UPDATE_MULTIPLIER;
uint256 public ONE_MINUS_UPDATE_MULTIPLIER;
uint256 public emaStored;
uint256 public lastIncomeIndex;
uint256 public lastUpdateTimestamp;
IMoneyMarket public moneyMarket;
constructor(
uint256 _emaInitial,
uint256 _updateInterval,
uint256 _smoothingFactor,
uint256 _averageWindowInIntervals,
address _moneyMarket
) public {
emaStored = _emaInitial;
UPDATE_INTERVAL = _updateInterval;
lastUpdateTimestamp = now;
uint256 updateMultiplier = _smoothingFactor.div(_averageWindowInIntervals.add(1));
UPDATE_MULTIPLIER = updateMultiplier;
ONE_MINUS_UPDATE_MULTIPLIER = PRECISION.sub(updateMultiplier);
moneyMarket = IMoneyMarket(_moneyMarket);
lastIncomeIndex = moneyMarket.incomeIndex();
}
function updateAndQuery() public returns (bool updated, uint256 value) {
uint256 timeElapsed = now - lastUpdateTimestamp;
if (timeElapsed < UPDATE_INTERVAL) {
return (false, emaStored);
}
uint256 _lastIncomeIndex = lastIncomeIndex;
uint256 _emaStored = emaStored;
uint256 newIncomeIndex = moneyMarket.incomeIndex();
uint256 incomingValue = newIncomeIndex.sub(_lastIncomeIndex).decdiv(_lastIncomeIndex).div(timeElapsed);
updated = true;
value = incomingValue.mul(UPDATE_MULTIPLIER).add(_emaStored.mul(ONE_MINUS_UPDATE_MULTIPLIER)).div(PRECISION);
emaStored = value;
lastIncomeIndex = newIncomeIndex;
lastUpdateTimestamp = now;
}
function query() public view returns (uint256 value) {
return emaStored;
}
}
文件 15 的 64:ERC165.sol
pragma solidity ^0.5.0;
import "./IERC165.sol";
contract ERC165 is IERC165 {
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
_registerInterface(_INTERFACE_ID_ERC165);
}
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
return _supportedInterfaces[interfaceId];
}
function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
文件 16 的 64:ERC20.sol
pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
}
文件 17 的 64:ERC20Burnable.sol
pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC20.sol";
contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public {
_burnFrom(account, amount);
}
}
文件 18 的 64:ERC20Detailed.sol
pragma solidity ^0.5.0;
import "./IERC20.sol";
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
}
文件 19 的 64:ERC20Mock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
contract ERC20Mock is ERC20, ERC20Detailed("", "", 6) {
function mint(address to, uint256 amount) public {
_mint(to, amount);
}
}
文件 20 的 64:ERC721.sol
pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../drafts/Counters.sol";
import "../../introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
mapping (uint256 => address) private _tokenOwner;
mapping (uint256 => address) private _tokenApprovals;
mapping (address => Counters.Counter) private _ownedTokensCount;
mapping (address => mapping (address => bool)) private _operatorApprovals;
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
constructor () public {
_registerInterface(_INTERFACE_ID_ERC721);
}
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _ownedTokensCount[owner].current();
}
function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address to, bool approved) public {
require(to != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][to] = approved;
emit ApprovalForAll(_msgSender(), to, approved);
}
function isApprovedForAll(address owner, address operator) public view returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(address from, address to, uint256 tokenId) public {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransferFrom(from, to, tokenId, _data);
}
function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal {
_transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view returns (bool) {
address owner = _tokenOwner[tokenId];
return owner != address(0);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _mint(address to, uint256 tokenId) internal {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_tokenOwner[tokenId] = to;
_ownedTokensCount[to].increment();
emit Transfer(address(0), to, tokenId);
}
function _burn(address owner, uint256 tokenId) internal {
require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
_clearApproval(tokenId);
_ownedTokensCount[owner].decrement();
_tokenOwner[tokenId] = address(0);
emit Transfer(owner, address(0), tokenId);
}
function _burn(uint256 tokenId) internal {
_burn(ownerOf(tokenId), tokenId);
}
function _transferFrom(address from, address to, uint256 tokenId) internal {
require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_clearApproval(tokenId);
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
_tokenOwner[tokenId] = to;
emit Transfer(from, to, tokenId);
}
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
internal returns (bool)
{
if (!to.isContract()) {
return true;
}
(bool success, bytes memory returndata) = to.call(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
));
if (!success) {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert("ERC721: transfer to non ERC721Receiver implementer");
}
} else {
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
}
function _clearApproval(uint256 tokenId) private {
if (_tokenApprovals[tokenId] != address(0)) {
_tokenApprovals[tokenId] = address(0);
}
}
}
文件 21 的 64:ERC721Metadata.sol
pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC721.sol";
import "./IERC721Metadata.sol";
import "../../introspection/ERC165.sol";
contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
string private _name;
string private _symbol;
string private _baseURI;
mapping(uint256 => string) private _tokenURIs;
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
}
function name() external view returns (string memory) {
return _name;
}
function symbol() external view returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
if (bytes(_tokenURI).length == 0) {
return "";
} else {
return string(abi.encodePacked(_baseURI, _tokenURI));
}
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _setBaseURI(string memory baseURI) internal {
_baseURI = baseURI;
}
function baseURI() external view returns (string memory) {
return _baseURI;
}
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
文件 22 的 64:HarvestMarket.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../IMoneyMarket.sol";
import "../../libs/DecMath.sol";
import "./imports/HarvestVault.sol";
import "./imports/HarvestStaking.sol";
contract HarvestMarket is IMoneyMarket, Ownable {
using SafeMath for uint256;
using DecMath for uint256;
using SafeERC20 for ERC20;
using Address for address;
HarvestVault public vault;
address public rewards;
HarvestStaking public stakingPool;
ERC20 public stablecoin;
constructor(
address _vault,
address _rewards,
address _stakingPool,
address _stablecoin
) public {
require(
_vault != address(0) &&
_rewards != address(0) &&
_stakingPool != address(0) &&
_stablecoin != address(0),
"HarvestMarket: An input address is 0"
);
require(
_vault.isContract() &&
_rewards.isContract() &&
_stakingPool.isContract() &&
_stablecoin.isContract(),
"HarvestMarket: An input address is not a contract"
);
vault = HarvestVault(_vault);
rewards = _rewards;
stakingPool = HarvestStaking(_stakingPool);
stablecoin = ERC20(_stablecoin);
}
function deposit(uint256 amount) external onlyOwner {
require(amount > 0, "HarvestMarket: amount is 0");
stablecoin.safeTransferFrom(msg.sender, address(this), amount);
stablecoin.safeIncreaseAllowance(address(vault), amount);
vault.deposit(amount);
uint256 vaultShareBalance = vault.balanceOf(address(this));
vault.approve(address(stakingPool), vaultShareBalance);
stakingPool.stake(vaultShareBalance);
}
function withdraw(uint256 amountInUnderlying)
external
onlyOwner
returns (uint256 actualAmountWithdrawn)
{
require(
amountInUnderlying > 0,
"HarvestMarket: amountInUnderlying is 0"
);
uint256 sharePrice = vault.getPricePerFullShare();
uint256 amountInShares = amountInUnderlying.decdiv(sharePrice);
stakingPool.withdraw(amountInShares);
vault.withdraw(amountInShares);
actualAmountWithdrawn = stablecoin.balanceOf(address(this));
stablecoin.safeTransfer(msg.sender, actualAmountWithdrawn);
}
function claimRewards() external {
stakingPool.getReward();
ERC20 rewardToken = ERC20(stakingPool.rewardToken());
rewardToken.safeTransfer(rewards, rewardToken.balanceOf(address(this)));
}
function totalValue() external returns (uint256) {
uint256 sharePrice = vault.getPricePerFullShare();
uint256 shareBalance = vault.balanceOf(address(this)).add(stakingPool.balanceOf(address(this)));
return shareBalance.decmul(sharePrice);
}
function incomeIndex() external returns (uint256) {
return vault.getPricePerFullShare();
}
function setRewards(address newValue) external onlyOwner {
require(newValue.isContract(), "HarvestMarket: not contract");
rewards = newValue;
emit ESetParamAddress(msg.sender, "rewards", newValue);
}
}
文件 23 的 64:HarvestStaking.sol
pragma solidity 0.5.17;
interface HarvestStaking {
function stake(uint256 amount) external;
function withdraw(uint256 amount) external;
function getReward() external;
function rewardToken() external returns (address);
function balanceOf(address account) external view returns (uint256);
}
文件 24 的 64:HarvestStakingMock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract IRewardDistributionRecipient is Ownable {
mapping(address => bool) public isRewardDistribution;
function notifyRewardAmount(uint256 reward) external;
modifier onlyRewardDistribution() {
require(
isRewardDistribution[_msgSender()],
"Caller is not reward distribution"
);
_;
}
function setRewardDistribution(
address _rewardDistribution,
bool _isRewardDistribution
) external onlyOwner {
isRewardDistribution[_rewardDistribution] = _isRewardDistribution;
}
}
contract LPTokenWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public stakeToken;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
constructor(address _stakeToken) public {
stakeToken = IERC20(_stakeToken);
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
stakeToken.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
stakeToken.safeTransfer(msg.sender, amount);
}
}
contract HarvestStakingMock is LPTokenWrapper, IRewardDistributionRecipient {
IERC20 public rewardToken;
uint256 public constant DURATION = 7 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
modifier checkStart {
require(block.timestamp >= starttime, "Rewards: not start");
_;
}
constructor(
address _stakeToken,
address _rewardToken,
uint256 _starttime
) public LPTokenWrapper(_stakeToken) {
rewardToken = IERC20(_rewardToken);
starttime = _starttime;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount) public updateReward(msg.sender) checkStart {
require(amount > 0, "Rewards: cannot stake 0");
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
updateReward(msg.sender)
checkStart
{
require(amount > 0, "Rewards: cannot withdraw 0");
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
onlyRewardDistribution
updateReward(address(0))
{
require(reward > 0, "Rewards: reward == 0");
require(
reward < uint256(-1) / 10**18,
"Rewards: rewards too large, would lock"
);
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 25 的 64:HarvestVault.sol
pragma solidity 0.5.17;
interface HarvestVault {
function deposit(uint256) external;
function withdraw(uint256) external;
function getPricePerFullShare() external view returns (uint256);
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
);
}
文件 26 的 64:ICERC20.sol
pragma solidity 0.5.17;
interface ICERC20 {
function transfer(address dst, uint256 amount) external returns (bool);
function transferFrom(address src, address dst, uint256 amount)
external
returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function balanceOfUnderlying(address owner) external returns (uint256);
function getAccountSnapshot(address account)
external
view
returns (uint256, uint256, uint256, uint256);
function borrowRatePerBlock() external view returns (uint256);
function supplyRatePerBlock() external view returns (uint256);
function totalBorrowsCurrent() external returns (uint256);
function borrowBalanceCurrent(address account) external returns (uint256);
function borrowBalanceStored(address account)
external
view
returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function exchangeRateStored() external view returns (uint256);
function getCash() external view returns (uint256);
function accrueInterest() external returns (uint256);
function seize(address liquidator, address borrower, uint256 seizeTokens)
external
returns (uint256);
function mint(uint256 mintAmount) external returns (uint256);
function redeem(uint256 redeemTokens) external returns (uint256);
function redeemUnderlying(uint256 redeemAmount) external returns (uint256);
function borrow(uint256 borrowAmount) external returns (uint256);
function repayBorrow(uint256 repayAmount) external returns (uint256);
function repayBorrowBehalf(address borrower, uint256 repayAmount)
external
returns (uint256);
function liquidateBorrow(
address borrower,
uint256 repayAmount,
address cTokenCollateral
) external returns (uint256);
}
文件 27 的 64:IComptroller.sol
pragma solidity 0.5.17;
interface IComptroller {
function claimComp(address holder) external;
function getCompAddress() external view returns (address);
}
文件 28 的 64:IERC165.sol
pragma solidity ^0.5.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 29 的 64:IERC20.sol
pragma solidity ^0.5.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);
}
文件 30 的 64:IERC721.sol
pragma solidity ^0.5.0;
import "../../introspection/IERC165.sol";
contract 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) public view returns (uint256 balance);
function ownerOf(uint256 tokenId) public view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) public;
function transferFrom(address from, address to, uint256 tokenId) public;
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address operator);
function setApprovalForAll(address operator, bool _approved) public;
function isApprovedForAll(address owner, address operator) public view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}
文件 31 的 64:IERC721Metadata.sol
pragma solidity ^0.5.0;
import "./IERC721.sol";
contract IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 32 的 64:IERC721Receiver.sol
pragma solidity ^0.5.0;
contract IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}
文件 33 的 64:IFeeModel.sol
pragma solidity 0.5.17;
interface IFeeModel {
function beneficiary() external view returns (address payable);
function getFee(uint256 _txAmount)
external
pure
returns (uint256 _feeAmount);
}
文件 34 的 64:IInterestModel.sol
pragma solidity 0.5.17;
interface IInterestModel {
function calculateInterestAmount(
uint256 depositAmount,
uint256 depositPeriodInSeconds,
uint256 moneyMarketInterestRatePerSecond,
bool surplusIsNegative,
uint256 surplusAmount
) external view returns (uint256 interestAmount);
}
文件 35 的 64:IInterestOracle.sol
pragma solidity 0.5.17;
interface IInterestOracle {
function updateAndQuery() external returns (bool updated, uint256 value);
function query() external view returns (uint256 value);
function moneyMarket() external view returns (address);
}
文件 36 的 64:ILendingPool.sol
pragma solidity 0.5.17;
interface ILendingPool {
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
function getReserveNormalizedIncome(address asset)
external
view
returns (uint256);
}
文件 37 的 64:ILendingPoolAddressesProvider.sol
pragma solidity 0.5.17;
interface ILendingPoolAddressesProvider {
function getLendingPool() external view returns (address);
}
文件 38 的 64:IMPHIssuanceModel.sol
pragma solidity 0.5.17;
interface IMPHIssuanceModel {
function computeDepositorReward(
address pool,
uint256 depositAmount,
uint256 depositPeriodInSeconds,
uint256 interestAmount
)
external
view
returns (
uint256 depositorReward,
uint256 devReward,
uint256 govReward
);
function computeTakeBackDepositorRewardAmount(
address pool,
uint256 mintMPHAmount,
bool early
)
external
view
returns (
uint256 takeBackAmount,
uint256 devReward,
uint256 govReward
);
function computeFunderReward(
address pool,
uint256 depositAmount,
uint256 fundingCreationTimestamp,
uint256 maturationTimestamp,
uint256 interestPayoutAmount,
bool early
)
external
view
returns (
uint256 funderReward,
uint256 devReward,
uint256 govReward
);
function poolDepositorRewardVestPeriod(address pool)
external
view
returns (uint256 vestPeriodInSeconds);
function poolFunderRewardVestPeriod(address pool)
external
view
returns (uint256 vestPeriodInSeconds);
}
文件 39 的 64:IMoneyMarket.sol
pragma solidity 0.5.17;
interface IMoneyMarket {
function deposit(uint256 amount) external;
function withdraw(uint256 amountInUnderlying)
external
returns (uint256 actualAmountWithdrawn);
function claimRewards() external;
function totalValue() external returns (uint256);
function incomeIndex() external returns (uint256);
function stablecoin() external view returns (address);
function setRewards(address newValue) external;
event ESetParamAddress(
address indexed sender,
string indexed paramName,
address newValue
);
}
文件 40 的 64:IRewards.sol
pragma solidity 0.5.17;
interface IRewards {
function notifyRewardAmount(uint256 reward) external;
}
文件 41 的 64:LendingPoolAddressesProviderMock.sol
pragma solidity 0.5.17;
contract LendingPoolAddressesProviderMock {
address internal pool;
address internal core;
function getLendingPool() external view returns (address) {
return pool;
}
function setLendingPoolImpl(address _pool) external {
pool = _pool;
}
}
文件 42 的 64:LendingPoolMock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./ATokenMock.sol";
contract LendingPoolMock {
mapping(address => address) internal reserveAToken;
function setReserveAToken(address _reserve, address _aTokenAddress)
external
{
reserveAToken[_reserve] = _aTokenAddress;
}
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16
) external {
ERC20 token = ERC20(asset);
token.transferFrom(msg.sender, address(this), amount);
address aTokenAddress = reserveAToken[asset];
ATokenMock aToken = ATokenMock(aTokenAddress);
aToken.mint(onBehalfOf, amount);
}
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256) {
address aTokenAddress = reserveAToken[asset];
ATokenMock aToken = ATokenMock(aTokenAddress);
aToken.burn(msg.sender, amount);
ERC20 token = ERC20(asset);
token.transfer(to, amount);
}
function getReserveNormalizedIncome(address asset)
external
view
returns (uint256)
{
address aTokenAddress = reserveAToken[asset];
ATokenMock aToken = ATokenMock(aTokenAddress);
return aToken.normalizedIncome();
}
}
文件 43 的 64:LinearInterestModel.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../../libs/DecMath.sol";
contract LinearInterestModel {
using SafeMath for uint256;
using DecMath for uint256;
uint256 public constant PRECISION = 10**18;
uint256 public IRMultiplier;
constructor(uint256 _IRMultiplier) public {
IRMultiplier = _IRMultiplier;
}
function calculateInterestAmount(
uint256 depositAmount,
uint256 depositPeriodInSeconds,
uint256 moneyMarketInterestRatePerSecond,
bool,
uint256
) external view returns (uint256 interestAmount) {
interestAmount = depositAmount
.mul(PRECISION)
.decmul(moneyMarketInterestRatePerSecond)
.decmul(IRMultiplier)
.mul(depositPeriodInSeconds)
.div(PRECISION);
}
}
文件 44 的 64:MPHIssuanceModel01.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../../libs/DecMath.sol";
import "./IMPHIssuanceModel.sol";
contract MPHIssuanceModel01 is Ownable, IMPHIssuanceModel {
using Address for address;
using DecMath for uint256;
using SafeMath for uint256;
uint256 internal constant PRECISION = 10**18;
mapping(address => uint256) public poolDepositorRewardMintMultiplier;
mapping(address => uint256) public poolDepositorRewardTakeBackMultiplier;
mapping(address => uint256) public poolFunderRewardMultiplier;
mapping(address => uint256) public poolDepositorRewardVestPeriod;
mapping(address => uint256) public poolFunderRewardVestPeriod;
uint256 public devRewardMultiplier;
event ESetParamAddress(
address indexed sender,
string indexed paramName,
address newValue
);
event ESetParamUint(
address indexed sender,
string indexed paramName,
address indexed pool,
uint256 newValue
);
constructor(uint256 _devRewardMultiplier) public {
devRewardMultiplier = _devRewardMultiplier;
}
function computeDepositorReward(
address pool,
uint256 depositAmount,
uint256 depositPeriodInSeconds,
uint256 interestAmount
)
external
view
returns (
uint256 depositorReward,
uint256 devReward,
uint256 govReward
)
{
uint256 mintAmount = depositAmount.mul(depositPeriodInSeconds).decmul(
poolDepositorRewardMintMultiplier[pool]
);
depositorReward = mintAmount;
devReward = mintAmount.decmul(devRewardMultiplier);
govReward = 0;
}
function computeTakeBackDepositorRewardAmount(
address pool,
uint256 mintMPHAmount,
bool early
)
external
view
returns (
uint256 takeBackAmount,
uint256 devReward,
uint256 govReward
)
{
takeBackAmount = early
? mintMPHAmount
: mintMPHAmount.decmul(poolDepositorRewardTakeBackMultiplier[pool]);
devReward = 0;
govReward = early ? 0 : takeBackAmount;
}
function computeFunderReward(
address pool,
uint256 depositAmount,
uint256 fundingCreationTimestamp,
uint256 maturationTimestamp,
uint256 interestPayoutAmount,
bool early
)
external
view
returns (
uint256 funderReward,
uint256 devReward,
uint256 govReward
)
{
if (early) {
return (0, 0, 0);
}
funderReward = maturationTimestamp > fundingCreationTimestamp
? depositAmount
.mul(maturationTimestamp.sub(fundingCreationTimestamp))
.decmul(poolFunderRewardMultiplier[pool])
: 0;
devReward = funderReward.decmul(devRewardMultiplier);
govReward = 0;
}
function setPoolDepositorRewardMintMultiplier(
address pool,
uint256 newMultiplier
) external onlyOwner {
require(pool.isContract(), "MPHIssuanceModel: pool not contract");
poolDepositorRewardMintMultiplier[pool] = newMultiplier;
emit ESetParamUint(
msg.sender,
"poolDepositorRewardMintMultiplier",
pool,
newMultiplier
);
}
function setPoolDepositorRewardTakeBackMultiplier(
address pool,
uint256 newMultiplier
) external onlyOwner {
require(pool.isContract(), "MPHIssuanceModel: pool not contract");
require(
newMultiplier <= PRECISION,
"MPHIssuanceModel: invalid multiplier"
);
poolDepositorRewardTakeBackMultiplier[pool] = newMultiplier;
emit ESetParamUint(
msg.sender,
"poolDepositorRewardTakeBackMultiplier",
pool,
newMultiplier
);
}
function setPoolFunderRewardMultiplier(address pool, uint256 newMultiplier)
external
onlyOwner
{
require(pool.isContract(), "MPHIssuanceModel: pool not contract");
poolFunderRewardMultiplier[pool] = newMultiplier;
emit ESetParamUint(
msg.sender,
"poolFunderRewardMultiplier",
pool,
newMultiplier
);
}
function setPoolDepositorRewardVestPeriod(
address pool,
uint256 newVestPeriodInSeconds
) external onlyOwner {
require(pool.isContract(), "MPHIssuanceModel: pool not contract");
poolDepositorRewardVestPeriod[pool] = newVestPeriodInSeconds;
emit ESetParamUint(
msg.sender,
"poolDepositorRewardVestPeriod",
pool,
newVestPeriodInSeconds
);
}
function setPoolFunderRewardVestPeriod(
address pool,
uint256 newVestPeriodInSeconds
) external onlyOwner {
require(pool.isContract(), "MPHIssuanceModel: pool not contract");
poolFunderRewardVestPeriod[pool] = newVestPeriodInSeconds;
emit ESetParamUint(
msg.sender,
"poolFunderRewardVestPeriod",
pool,
newVestPeriodInSeconds
);
}
function setDevRewardMultiplier(uint256 newMultiplier) external onlyOwner {
require(
newMultiplier <= PRECISION,
"MPHIssuanceModel: invalid multiplier"
);
devRewardMultiplier = newMultiplier;
emit ESetParamUint(
msg.sender,
"devRewardMultiplier",
address(0),
newMultiplier
);
}
}
文件 45 的 64:MPHMinter.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./MPHToken.sol";
import "../models/issuance/IMPHIssuanceModel.sol";
import "./Vesting.sol";
contract MPHMinter is Ownable {
using Address for address;
using SafeMath for uint256;
mapping(address => bool) public poolWhitelist;
modifier onlyWhitelistedPool {
require(poolWhitelist[msg.sender], "MPHMinter: sender not whitelisted");
_;
}
event ESetParamAddress(
address indexed sender,
string indexed paramName,
address newValue
);
event WhitelistPool(
address indexed sender,
address pool,
bool isWhitelisted
);
event MintDepositorReward(
address indexed sender,
address indexed to,
uint256 depositorReward
);
event TakeBackDepositorReward(
address indexed sender,
address indexed from,
uint256 takeBackAmount
);
event MintFunderReward(
address indexed sender,
address indexed to,
uint256 funderReward
);
MPHToken public mph;
address public govTreasury;
address public devWallet;
IMPHIssuanceModel public issuanceModel;
Vesting public vesting;
constructor(
address _mph,
address _govTreasury,
address _devWallet,
address _issuanceModel,
address _vesting
) public {
mph = MPHToken(_mph);
govTreasury = _govTreasury;
devWallet = _devWallet;
issuanceModel = IMPHIssuanceModel(_issuanceModel);
vesting = Vesting(_vesting);
}
function mintDepositorReward(
address to,
uint256 depositAmount,
uint256 depositPeriodInSeconds,
uint256 interestAmount
) external onlyWhitelistedPool returns (uint256) {
(
uint256 depositorReward,
uint256 devReward,
uint256 govReward
) = issuanceModel.computeDepositorReward(
msg.sender,
depositAmount,
depositPeriodInSeconds,
interestAmount
);
if (depositorReward == 0 && devReward == 0 && govReward == 0) {
return 0;
}
mph.ownerMint(address(this), depositorReward);
uint256 vestPeriodInSeconds = issuanceModel
.poolDepositorRewardVestPeriod(msg.sender);
if (vestPeriodInSeconds == 0) {
mph.transfer(to, depositorReward);
} else {
mph.increaseAllowance(address(vesting), depositorReward);
vesting.vest(to, depositorReward, vestPeriodInSeconds);
}
mph.ownerMint(devWallet, devReward);
mph.ownerMint(govTreasury, govReward);
emit MintDepositorReward(msg.sender, to, depositorReward);
return depositorReward;
}
function takeBackDepositorReward(
address from,
uint256 mintMPHAmount,
bool early
) external onlyWhitelistedPool returns (uint256) {
(
uint256 takeBackAmount,
uint256 devReward,
uint256 govReward
) = issuanceModel.computeTakeBackDepositorRewardAmount(
msg.sender,
mintMPHAmount,
early
);
if (takeBackAmount == 0 && devReward == 0 && govReward == 0) {
return 0;
}
require(
takeBackAmount >= devReward.add(govReward),
"MPHMinter: takeBackAmount < devReward + govReward"
);
mph.transferFrom(from, address(this), takeBackAmount);
mph.transfer(devWallet, devReward);
mph.transfer(govTreasury, govReward);
mph.burn(takeBackAmount.sub(devReward).sub(govReward));
emit TakeBackDepositorReward(msg.sender, from, takeBackAmount);
return takeBackAmount;
}
function mintFunderReward(
address to,
uint256 depositAmount,
uint256 fundingCreationTimestamp,
uint256 maturationTimestamp,
uint256 interestPayoutAmount,
bool early
) external onlyWhitelistedPool returns (uint256) {
(
uint256 funderReward,
uint256 devReward,
uint256 govReward
) = issuanceModel.computeFunderReward(
msg.sender,
depositAmount,
fundingCreationTimestamp,
maturationTimestamp,
interestPayoutAmount,
early
);
if (funderReward == 0 && devReward == 0 && govReward == 0) {
return 0;
}
mph.ownerMint(address(this), funderReward);
uint256 vestPeriodInSeconds = issuanceModel.poolFunderRewardVestPeriod(
msg.sender
);
if (vestPeriodInSeconds == 0) {
mph.transfer(to, funderReward);
} else {
mph.increaseAllowance(address(vesting), funderReward);
vesting.vest(to, funderReward, vestPeriodInSeconds);
}
mph.ownerMint(devWallet, devReward);
mph.ownerMint(govTreasury, govReward);
emit MintFunderReward(msg.sender, to, funderReward);
return funderReward;
}
function setGovTreasury(address newValue) external onlyOwner {
require(newValue != address(0), "MPHMinter: 0 address");
govTreasury = newValue;
emit ESetParamAddress(msg.sender, "govTreasury", newValue);
}
function setDevWallet(address newValue) external onlyOwner {
require(newValue != address(0), "MPHMinter: 0 address");
devWallet = newValue;
emit ESetParamAddress(msg.sender, "devWallet", newValue);
}
function setMPHTokenOwner(address newValue) external onlyOwner {
require(newValue != address(0), "MPHMinter: 0 address");
mph.transferOwnership(newValue);
emit ESetParamAddress(msg.sender, "mphTokenOwner", newValue);
}
function setMPHTokenOwnerToZero() external onlyOwner {
mph.renounceOwnership();
emit ESetParamAddress(msg.sender, "mphTokenOwner", address(0));
}
function setIssuanceModel(address newValue) external onlyOwner {
require(newValue.isContract(), "MPHMinter: not contract");
issuanceModel = IMPHIssuanceModel(newValue);
emit ESetParamAddress(msg.sender, "issuanceModel", newValue);
}
function setVesting(address newValue) external onlyOwner {
require(newValue.isContract(), "MPHMinter: not contract");
vesting = Vesting(newValue);
emit ESetParamAddress(msg.sender, "vesting", newValue);
}
function setPoolWhitelist(address pool, bool isWhitelisted)
external
onlyOwner
{
require(pool.isContract(), "MPHMinter: pool not contract");
poolWhitelist[pool] = isWhitelisted;
emit WhitelistPool(msg.sender, pool, isWhitelisted);
}
}
文件 46 的 64:MPHToken.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
contract MPHToken is ERC20, ERC20Burnable, Ownable {
string public constant name = "88mph.app";
string public constant symbol = "MPH";
uint8 public constant decimals = 18;
bool public initialized;
function init() public {
require(!initialized, "MPHToken: initialized");
initialized = true;
_transferOwnership(msg.sender);
}
function ownerMint(address account, uint256 amount)
public
onlyOwner
returns (bool)
{
_mint(account, amount);
return true;
}
}
文件 47 的 64:Math.sol
pragma solidity ^0.5.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 48 的 64:NFT.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC721/ERC721Metadata.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
contract NFT is ERC721Metadata, Ownable {
string internal _contractURI;
constructor(string memory name, string memory symbol)
public
ERC721Metadata(name, symbol)
{}
function contractURI() external view returns (string memory) {
return _contractURI;
}
function mint(address to, uint256 tokenId) external onlyOwner {
_safeMint(to, tokenId);
}
function burn(uint256 tokenId) external onlyOwner {
_burn(tokenId);
}
function setContractURI(string calldata newURI) external onlyOwner {
_contractURI = newURI;
}
function setTokenURI(uint256 tokenId, string calldata newURI)
external
onlyOwner
{
_setTokenURI(tokenId, newURI);
}
function setBaseURI(string calldata newURI) external onlyOwner {
_setBaseURI(newURI);
}
}
文件 49 的 64:OneSplitAudit.sol
pragma solidity 0.5.17;
interface OneSplitAudit {
function swap(
address fromToken,
address destToken,
uint256 amount,
uint256 minReturn,
uint256[] calldata distribution,
uint256 flags
) external payable;
function getExpectedReturn(
address fromToken,
address destToken,
uint256 amount,
uint256 parts,
uint256 flags
)
external
view
returns (uint256 returnAmount, uint256[] memory distribution);
}
文件 50 的 64:OneSplitDumper.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/access/roles/SignerRole.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./imports/OneSplitAudit.sol";
import "../IRewards.sol";
contract OneSplitDumper is SignerRole {
using SafeERC20 for IERC20;
OneSplitAudit public oneSplit;
IRewards public rewards;
IERC20 public rewardToken;
constructor(
address _oneSplit,
address _rewards,
address _rewardToken
) public {
oneSplit = OneSplitAudit(_oneSplit);
rewards = IRewards(_rewards);
rewardToken = IERC20(_rewardToken);
}
function getDumpParams(address tokenAddress, uint256 parts)
external
view
returns (uint256 returnAmount, uint256[] memory distribution)
{
IERC20 token = IERC20(tokenAddress);
uint256 tokenBalance = token.balanceOf(address(this));
(returnAmount, distribution) = oneSplit.getExpectedReturn(
tokenAddress,
address(rewardToken),
tokenBalance,
parts,
0
);
}
function dump(
address tokenAddress,
uint256 returnAmount,
uint256[] calldata distribution
) external onlySigner {
IERC20 token = IERC20(tokenAddress);
uint256 tokenBalance = token.balanceOf(address(this));
token.safeIncreaseAllowance(address(oneSplit), tokenBalance);
uint256 rewardTokenBalanceBefore = rewardToken.balanceOf(address(this));
oneSplit.swap(
tokenAddress,
address(rewardToken),
tokenBalance,
returnAmount,
distribution,
0
);
uint256 rewardTokenBalanceAfter = rewardToken.balanceOf(address(this));
require(
rewardTokenBalanceAfter > rewardTokenBalanceBefore,
"OneSplitDumper: receivedRewardTokenAmount == 0"
);
}
function notify() external onlySigner {
uint256 balance = rewardToken.balanceOf(address(this));
rewardToken.safeTransfer(address(rewards), balance);
rewards.notifyRewardAmount(balance);
}
}
文件 51 的 64:Ownable.sol
pragma solidity ^0.5.0;
import "../GSN/Context.sol";
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 52 的 64:PercentageFeeModel.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "./IFeeModel.sol";
contract PercentageFeeModel is IFeeModel, Ownable {
using SafeMath for uint256;
address payable public beneficiary;
event SetBeneficiary(address newBeneficiary);
constructor(address payable _beneficiary) public {
beneficiary = _beneficiary;
}
function getFee(uint256 _txAmount)
external
pure
returns (uint256 _feeAmount)
{
_feeAmount = _txAmount.div(10);
}
function setBeneficiary(address payable newValue) external onlyOwner {
require(newValue != address(0), "PercentageFeeModel: 0 address");
beneficiary = newValue;
emit SetBeneficiary(newValue);
}
}
文件 53 的 64:ReentrancyGuard.sol
pragma solidity ^0.5.0;
contract ReentrancyGuard {
bool private _notEntered;
constructor () internal {
_notEntered = true;
}
modifier nonReentrant() {
require(_notEntered, "ReentrancyGuard: reentrant call");
_notEntered = false;
_;
_notEntered = true;
}
}
文件 54 的 64:Rewards.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract IRewardDistributionRecipient is Ownable {
mapping(address => bool) public isRewardDistribution;
function notifyRewardAmount(uint256 reward) external;
modifier onlyRewardDistribution() {
require(
isRewardDistribution[_msgSender()],
"Caller is not reward distribution"
);
_;
}
function setRewardDistribution(
address _rewardDistribution,
bool _isRewardDistribution
) external onlyOwner {
isRewardDistribution[_rewardDistribution] = _isRewardDistribution;
}
}
contract LPTokenWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public stakeToken;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
constructor(address _stakeToken) public {
stakeToken = IERC20(_stakeToken);
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function stake(uint256 amount) public {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
stakeToken.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) public {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
stakeToken.safeTransfer(msg.sender, amount);
}
}
contract Rewards is LPTokenWrapper, IRewardDistributionRecipient {
IERC20 public rewardToken;
uint256 public constant DURATION = 7 days;
uint256 public starttime;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
modifier checkStart {
require(block.timestamp >= starttime, "Rewards: not start");
_;
}
constructor(
address _stakeToken,
address _rewardToken,
uint256 _starttime
) public LPTokenWrapper(_stakeToken) {
rewardToken = IERC20(_rewardToken);
starttime = _starttime;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 amount) public updateReward(msg.sender) checkStart {
require(amount > 0, "Rewards: cannot stake 0");
super.stake(amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
updateReward(msg.sender)
checkStart
{
require(amount > 0, "Rewards: cannot withdraw 0");
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}
function getReward() public updateReward(msg.sender) checkStart {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function notifyRewardAmount(uint256 reward)
external
onlyRewardDistribution
updateReward(address(0))
{
require(reward > 0, "Rewards: reward == 0");
require(
reward < uint256(-1) / 10**18,
"Rewards: rewards too large, would lock"
);
if (block.timestamp > starttime) {
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
} else {
rewardRate = reward.div(DURATION);
lastUpdateTime = starttime;
periodFinish = starttime.add(DURATION);
emit RewardAdded(reward);
}
}
}
文件 55 的 64:Roles.sol
pragma solidity ^0.5.0;
library Roles {
struct Role {
mapping (address => bool) bearer;
}
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
文件 56 的 64:SafeERC20.sol
pragma solidity ^0.5.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
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).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 57 的 64:SafeMath.sol
pragma solidity ^0.5.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 58 的 64:SignerRole.sol
pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol";
contract SignerRole is Context {
using Roles for Roles.Role;
event SignerAdded(address indexed account);
event SignerRemoved(address indexed account);
Roles.Role private _signers;
constructor () internal {
_addSigner(_msgSender());
}
modifier onlySigner() {
require(isSigner(_msgSender()), "SignerRole: caller does not have the Signer role");
_;
}
function isSigner(address account) public view returns (bool) {
return _signers.has(account);
}
function addSigner(address account) public onlySigner {
_addSigner(account);
}
function renounceSigner() public {
_removeSigner(_msgSender());
}
function _addSigner(address account) internal {
_signers.add(account);
emit SignerAdded(account);
}
function _removeSigner(address account) internal {
_signers.remove(account);
emit SignerRemoved(account);
}
}
文件 59 的 64:Vault.sol
pragma solidity 0.5.17;
interface Vault {
function deposit(uint256) external;
function withdraw(uint256) external;
function getPricePerFullShare() external view returns (uint256);
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
);
}
文件 60 的 64:VaultMock.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../libs/DecMath.sol";
contract VaultMock is ERC20, ERC20Detailed {
using SafeMath for uint256;
using DecMath for uint256;
ERC20 public underlying;
constructor(address _underlying) public ERC20Detailed("yUSD", "yUSD", 18) {
underlying = ERC20(_underlying);
}
function deposit(uint256 tokenAmount) public {
uint256 sharePrice = getPricePerFullShare();
_mint(msg.sender, tokenAmount.decdiv(sharePrice));
underlying.transferFrom(msg.sender, address(this), tokenAmount);
}
function withdraw(uint256 sharesAmount) public {
uint256 sharePrice = getPricePerFullShare();
uint256 underlyingAmount = sharesAmount.decmul(sharePrice);
_burn(msg.sender, sharesAmount);
underlying.transfer(msg.sender, underlyingAmount);
}
function getPricePerFullShare() public view returns (uint256) {
uint256 _totalSupply = totalSupply();
if (_totalSupply == 0) {
return 10**18;
}
return underlying.balanceOf(address(this)).decdiv(_totalSupply);
}
}
文件 61 的 64:Vesting.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
contract Vesting {
using SafeERC20 for IERC20;
using SafeMath for uint256;
struct Vest {
uint256 amount;
uint256 vestPeriodInSeconds;
uint256 creationTimestamp;
uint256 withdrawnAmount;
}
mapping(address => Vest[]) public accountVestList;
IERC20 public token;
constructor(address _token) public {
token = IERC20(_token);
}
function vest(
address to,
uint256 amount,
uint256 vestPeriodInSeconds
) external returns (uint256 vestIdx) {
require(vestPeriodInSeconds > 0, "Vesting: vestPeriodInSeconds == 0");
token.safeTransferFrom(msg.sender, address(this), amount);
vestIdx = accountVestList[to].length;
accountVestList[to].push(
Vest({
amount: amount,
vestPeriodInSeconds: vestPeriodInSeconds,
creationTimestamp: now,
withdrawnAmount: 0
})
);
}
function withdrawVested(address account, uint256 vestIdx)
external
returns (uint256 withdrawnAmount)
{
withdrawnAmount = _getVestWithdrawableAmount(account, vestIdx);
if (withdrawnAmount == 0) {
return 0;
}
uint256 recordedWithdrawnAmount = accountVestList[account][vestIdx]
.withdrawnAmount;
accountVestList[account][vestIdx]
.withdrawnAmount = recordedWithdrawnAmount.add(withdrawnAmount);
token.safeTransfer(account, withdrawnAmount);
}
function getVestWithdrawableAmount(address account, uint256 vestIdx)
external
view
returns (uint256)
{
return _getVestWithdrawableAmount(account, vestIdx);
}
function _getVestWithdrawableAmount(address account, uint256 vestIdx)
internal
view
returns (uint256)
{
Vest storage vest = accountVestList[account][vestIdx];
uint256 vestFullAmount = vest.amount;
uint256 vestCreationTimestamp = vest.creationTimestamp;
uint256 vestPeriodInSeconds = vest.vestPeriodInSeconds;
uint256 vestedAmount;
if (now >= vestCreationTimestamp.add(vestPeriodInSeconds)) {
vestedAmount = vestFullAmount;
} else {
vestedAmount = vestFullAmount
.mul(now.sub(vestCreationTimestamp))
.div(vestPeriodInSeconds);
}
return vestedAmount.sub(vest.withdrawnAmount);
}
}
文件 62 的 64:YVaultMarket.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../IMoneyMarket.sol";
import "../../libs/DecMath.sol";
import "./imports/Vault.sol";
contract YVaultMarket is IMoneyMarket, Ownable {
using SafeMath for uint256;
using DecMath for uint256;
using SafeERC20 for ERC20;
using Address for address;
Vault public vault;
ERC20 public stablecoin;
constructor(address _vault, address _stablecoin) public {
require(
_vault != address(0) && _stablecoin != address(0),
"YVaultMarket: An input address is 0"
);
require(
_vault.isContract() && _stablecoin.isContract(),
"YVaultMarket: An input address is not a contract"
);
vault = Vault(_vault);
stablecoin = ERC20(_stablecoin);
}
function deposit(uint256 amount) external onlyOwner {
require(amount > 0, "YVaultMarket: amount is 0");
stablecoin.safeTransferFrom(msg.sender, address(this), amount);
stablecoin.safeIncreaseAllowance(address(vault), amount);
vault.deposit(amount);
}
function withdraw(uint256 amountInUnderlying)
external
onlyOwner
returns (uint256 actualAmountWithdrawn)
{
require(
amountInUnderlying > 0,
"YVaultMarket: amountInUnderlying is 0"
);
uint256 sharePrice = vault.getPricePerFullShare();
uint256 amountInShares = amountInUnderlying.decdiv(sharePrice);
vault.withdraw(amountInShares);
actualAmountWithdrawn = stablecoin.balanceOf(address(this));
stablecoin.safeTransfer(msg.sender, actualAmountWithdrawn);
}
function claimRewards() external {}
function totalValue() external returns (uint256) {
uint256 sharePrice = vault.getPricePerFullShare();
uint256 shareBalance = vault.balanceOf(address(this));
return shareBalance.decmul(sharePrice);
}
function incomeIndex() external returns (uint256) {
return vault.getPricePerFullShare();
}
function setRewards(address newValue) external {}
}
文件 63 的 64:YearnWithdrawer.sol
pragma solidity 0.5.17;
import "@openzeppelin/contracts/access/roles/SignerRole.sol";
import "../imports/yERC20.sol";
contract YearnWithdrawer is SignerRole {
function yearnWithdraw(address yTokenAddress) external onlySigner {
yERC20 yToken = yERC20(yTokenAddress);
uint256 balance = yToken.balanceOf(address(this));
yToken.withdraw(balance);
}
}
文件 64 的 64:yERC20.sol
pragma solidity 0.5.17;
interface yERC20 {
function balanceOf(address owner) external view returns (uint256);
function deposit(uint256 _amount) external;
function withdraw(uint256 _amount) external;
function getPricePerFullShare() external view returns (uint256);
}
{
"compilationTarget": {
"contracts/DInterest.sol": "DInterest"
},
"evmVersion": "istanbul",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"uint256","name":"MinDepositPeriod","type":"uint256"},{"internalType":"uint256","name":"MaxDepositPeriod","type":"uint256"},{"internalType":"uint256","name":"MinDepositAmount","type":"uint256"},{"internalType":"uint256","name":"MaxDepositAmount","type":"uint256"}],"internalType":"struct DInterest.DepositLimit","name":"_depositLimit","type":"tuple"},{"internalType":"address","name":"_moneyMarket","type":"address"},{"internalType":"address","name":"_stablecoin","type":"address"},{"internalType":"address","name":"_feeModel","type":"address"},{"internalType":"address","name":"_interestModel","type":"address"},{"internalType":"address","name":"_interestOracle","type":"address"},{"internalType":"address","name":"_depositNFT","type":"address"},{"internalType":"address","name":"_fundingNFT","type":"address"},{"internalType":"address","name":"_mphMinter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maturationTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintMPHAmount","type":"uint256"}],"name":"EDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"fundingID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deficitAmount","type":"uint256"}],"name":"EFund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"string","name":"paramName","type":"string"},{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"ESetParamAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"string","name":"paramName","type":"string"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"ESetParamUint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"fundingID","type":"uint256"},{"indexed":false,"internalType":"bool","name":"early","type":"bool"},{"indexed":false,"internalType":"uint256","name":"takeBackMPHAmount","type":"uint256"}],"name":"EWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"constant":true,"inputs":[],"name":"MaxDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MaxDepositPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MinDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MinDepositPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"depositPeriodInSeconds","type":"uint256"}],"name":"calculateInterestAmount","outputs":[{"internalType":"uint256","name":"interestAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maturationTimestamp","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"depositIsFunded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"depositNFT","outputs":[{"internalType":"contract NFT","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"depositsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"depositID","type":"uint256"},{"internalType":"uint256","name":"fundingID","type":"uint256"}],"name":"earlyWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeModel","outputs":[{"internalType":"contract IFeeModel","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"fundAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toDepositID","type":"uint256"}],"name":"fundMultiple","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fundingListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fundingNFT","outputs":[{"internalType":"contract NFT","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"depositID","type":"uint256"}],"name":"getDeposit","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maturationTimestamp","type":"uint256"},{"internalType":"uint256","name":"interestOwed","type":"uint256"},{"internalType":"uint256","name":"initialMoneyMarketIncomeIndex","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"finalSurplusIsNegative","type":"bool"},{"internalType":"uint256","name":"finalSurplusAmount","type":"uint256"},{"internalType":"uint256","name":"mintMPHAmount","type":"uint256"},{"internalType":"uint256","name":"depositTimestamp","type":"uint256"}],"internalType":"struct DInterest.Deposit","name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"fundingID","type":"uint256"}],"name":"getFunding","outputs":[{"components":[{"internalType":"uint256","name":"fromDepositID","type":"uint256"},{"internalType":"uint256","name":"toDepositID","type":"uint256"},{"internalType":"uint256","name":"recordedFundedDepositAmount","type":"uint256"},{"internalType":"uint256","name":"recordedMoneyMarketIncomeIndex","type":"uint256"},{"internalType":"uint256","name":"creationTimestamp","type":"uint256"}],"internalType":"struct DInterest.Funding","name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"interestModel","outputs":[{"internalType":"contract IInterestModel","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"interestOracle","outputs":[{"internalType":"contract IInterestOracle","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"latestFundedDepositID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"moneyMarket","outputs":[{"internalType":"contract IMoneyMarket","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"moneyMarketIncomeIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"mphMinter","outputs":[{"internalType":"contract MPHMinter","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"amountList","type":"uint256[]"},{"internalType":"uint256[]","name":"maturationTimestampList","type":"uint256[]"}],"name":"multiDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"depositIDList","type":"uint256[]"},{"internalType":"uint256[]","name":"fundingIDList","type":"uint256[]"}],"name":"multiEarlyWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"depositIDList","type":"uint256[]"},{"internalType":"uint256[]","name":"fundingIDList","type":"uint256[]"}],"name":"multiWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setDepositNFTBaseURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setDepositNFTContractURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"}],"name":"setDepositNFTTokenURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setFeeModel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setFundingNFTBaseURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setFundingNFTContractURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"newURI","type":"string"}],"name":"setFundingNFTTokenURI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setInterestModel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setInterestOracle","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setMPHMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDepositAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDepositPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stablecoin","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"surplus","outputs":[{"internalType":"bool","name":"isNegative","type":"bool"},{"internalType":"uint256","name":"surplusAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"depositID","type":"uint256"}],"name":"surplusOfDeposit","outputs":[{"internalType":"bool","name":"isNegative","type":"bool"},{"internalType":"uint256","name":"surplusAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalInterestOwed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"unfundedUserDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"depositID","type":"uint256"},{"internalType":"uint256","name":"fundingID","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]