编译器
0.6.12+commit.27d51765
文件 1 的 17:Address.sol
pragma solidity 0.6.12;
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 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');
}
}
文件 2 的 17:Context.sol
pragma solidity 0.6.12;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 17:DataTypes.sol
pragma solidity 0.6.12;
library DataTypes {
struct ReserveData {
ReserveConfigurationMap configuration;
uint128 liquidityIndex;
uint128 variableBorrowIndex;
uint128 currentLiquidityRate;
uint128 currentVariableBorrowRate;
uint40 lastUpdateTimestamp;
address xTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint8 id;
}
struct ReserveConfigurationMap {
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
}
文件 4 的 17:DebtTokenBase.sol
pragma solidity 0.6.12;
import {IMarginPool} from './IMarginPool.sol';
import {ICreditDelegationToken} from './ICreditDelegationToken.sol';
import {IncentivizedERC20} from './IncentivizedERC20.sol';
import {Errors} from './Errors.sol';
abstract contract DebtTokenBase is
IncentivizedERC20,
ICreditDelegationToken
{
address public immutable UNDERLYING_ASSET_ADDRESS;
IMarginPool public immutable POOL;
mapping(address => mapping(address => uint256)) internal _borrowAllowances;
modifier onlyMarginPool {
require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_MARGIN_POOL);
_;
}
constructor(
address pool,
address underlyingAssetAddress,
string memory name,
string memory symbol,
uint8 decimals
) public IncentivizedERC20(name, symbol, decimals) {
POOL = IMarginPool(pool);
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
}
function approveDelegation(address delegatee, uint256 amount) external override {
_borrowAllowances[_msgSender()][delegatee] = amount;
emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount);
}
function borrowAllowance(address fromUser, address toUser)
external
view
override
returns (uint256)
{
return _borrowAllowances[fromUser][toUser];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
recipient;
amount;
revert('TRANSFER_NOT_SUPPORTED');
}
function allowance(address owner, address spender)
public
view
virtual
override
returns (uint256)
{
owner;
spender;
revert('ALLOWANCE_NOT_SUPPORTED');
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
spender;
amount;
revert('APPROVAL_NOT_SUPPORTED');
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
sender;
recipient;
amount;
revert('TRANSFER_NOT_SUPPORTED');
}
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
override
returns (bool)
{
spender;
addedValue;
revert('ALLOWANCE_NOT_SUPPORTED');
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
override
returns (bool)
{
spender;
subtractedValue;
revert('ALLOWANCE_NOT_SUPPORTED');
}
function _decreaseBorrowAllowance(
address delegator,
address delegatee,
uint256 amount
) internal {
uint256 newAllowance =
_borrowAllowances[delegator][delegatee].sub(amount, Errors.BORROW_ALLOWANCE_NOT_ENOUGH);
_borrowAllowances[delegator][delegatee] = newAllowance;
emit BorrowAllowanceDelegated(delegator, delegatee, UNDERLYING_ASSET_ADDRESS, newAllowance);
}
}
文件 5 的 17:Errors.sol
pragma solidity 0.6.12;
library Errors {
string public constant CALLER_NOT_POOL_ADMIN = '33';
string public constant BORROW_ALLOWANCE_NOT_ENOUGH = '59';
string public constant VL_INVALID_AMOUNT = '1';
string public constant VL_NO_ACTIVE_RESERVE = '2';
string public constant VL_RESERVE_FROZEN = '3';
string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4';
string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5';
string public constant VL_TRANSFER_NOT_ALLOWED = '6';
string public constant VL_BORROWING_NOT_ENABLED = '7';
string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = '8';
string public constant VL_COLLATERAL_BALANCE_IS_0 = '9';
string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10';
string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11';
string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13';
string public constant VL_NO_DEBT_OF_SELECTED_TYPE = '15';
string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16';
string public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = '18';
string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = '19';
string public constant VL_DEPOSIT_ALREADY_IN_USE = '20';
string public constant MP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '22';
string public constant MP_LIQUIDATION_CALL_FAILED = '23';
string public constant MP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = '24';
string public constant MP_REQUESTED_AMOUNT_TOO_SMALL = '25';
string public constant MP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26';
string public constant MP_CALLER_NOT_MARGIN_POOL_CONFIGURATOR = '27';
string public constant MP_INCONSISTENT_FLASHLOAN_PARAMS = '28';
string public constant CT_CALLER_MUST_BE_MARGIN_POOL = '29';
string public constant CT_CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30';
string public constant CT_TRANSFER_AMOUNT_NOT_GT_0 = '31';
string public constant RL_RESERVE_ALREADY_INITIALIZED = '32';
string public constant MPC_RESERVE_LIQUIDITY_NOT_0 = '34';
string public constant MPC_INVALID_XTOKEN_POOL_ADDRESS = '35';
string public constant MPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '37';
string public constant MPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '39';
string public constant MPC_INVALID_ADDRESSES_PROVIDER_ID = '40';
string public constant MPC_INVALID_CONFIGURATION = '75';
string public constant MPC_CALLER_NOT_EMERGENCY_ADMIN = '76';
string public constant MPAPR_PROVIDER_NOT_REGISTERED = '41';
string public constant MPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42';
string public constant MPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43';
string public constant MPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '44';
string public constant MPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = '45';
string public constant MPCM_NO_ERRORS = '46';
string public constant MP_INVALID_FLASHLOAN_MODE = '47';
string public constant MATH_MULTIPLICATION_OVERFLOW = '48';
string public constant MATH_ADDITION_OVERFLOW = '49';
string public constant MATH_DIVISION_BY_ZERO = '50';
string public constant RL_LIQUIDITY_INDEX_OVERFLOW = '51';
string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = '52';
string public constant RL_LIQUIDITY_RATE_OVERFLOW = '53';
string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = '54';
string public constant CT_INVALID_MINT_AMOUNT = '56';
string public constant MP_FAILED_REPAY_WITH_COLLATERAL = '57';
string public constant CT_INVALID_BURN_AMOUNT = '58';
string public constant MP_FAILED_COLLATERAL_SWAP = '60';
string public constant MP_INVALID_EQUAL_ASSETS_TO_SWAP = '61';
string public constant MP_REENTRANCY_NOT_ALLOWED = '62';
string public constant MP_CALLER_MUST_BE_AN_XTOKEN = '63';
string public constant MP_IS_PAUSED = '64';
string public constant MP_NO_MORE_RESERVES_ALLOWED = '65';
string public constant MP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66';
string public constant RC_INVALID_LTV = '67';
string public constant RC_INVALID_LIQ_THRESHOLD = '68';
string public constant RC_INVALID_LIQ_BONUS = '69';
string public constant RC_INVALID_DECIMALS = '70';
string public constant RC_INVALID_RESERVE_FACTOR = '71';
string public constant MPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72';
string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = '73';
string public constant MP_INCONSISTENT_PARAMS_LENGTH = '74';
string public constant UL_INVALID_INDEX = '77';
string public constant MP_NOT_CONTRACT = '78';
string public constant SDT_BURN_EXCEEDS_BALANCE = '80';
enum CollateralManagerErrors {
NO_ERROR,
NO_COLLATERAL_AVAILABLE,
COLLATERAL_CANNOT_BE_LIQUIDATED,
CURRRENCY_NOT_BORROWED,
HEALTH_FACTOR_ABOVE_THRESHOLD,
NOT_ENOUGH_LIQUIDITY,
NO_ACTIVE_RESERVE,
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
INVALID_EQUAL_ASSETS_TO_SWAP,
FROZEN_RESERVE
}
}
文件 6 的 17:ICreditDelegationToken.sol
pragma solidity 0.6.12;
interface ICreditDelegationToken {
event BorrowAllowanceDelegated(
address indexed fromUser,
address indexed toUser,
address asset,
uint256 amount
);
function approveDelegation(address delegatee, uint256 amount) external;
function borrowAllowance(address fromUser, address toUser) external view returns (uint256);
}
文件 7 的 17:IERC20.sol
pragma solidity 0.6.12;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 8 的 17:IERC20Detailed.sol
pragma solidity 0.6.12;
import {IERC20} from './IERC20.sol';
interface IERC20Detailed is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 17:IMarginPool.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IMarginPoolAddressesProvider} from './IMarginPoolAddressesProvider.sol';
import {DataTypes} from './DataTypes.sol';
interface IMarginPool {
event Deposit(
address indexed reserve,
address indexed user,
address indexed onBehalfOf,
uint256 amount
);
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
event Borrow(
address indexed reserve,
address indexed user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRate
);
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
event Swap(
address indexed user,
address indexed srcReserve,
address indexed dstReserve,
uint256 srcAmount,
uint256 dstAmount
);
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
event Paused();
event Unpaused();
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator
);
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
function deposit(
address asset,
uint256 amount,
address onBehalfOf
) external;
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
function borrow(
address asset,
uint256 amount,
address onBehalfOf
) external;
function repay(
address asset,
uint256 amount,
address onBehalfOf
) external returns (uint256);
function swapTokensForTokens(
uint256 amountIn,
uint256 amountOut,
address[] calldata path,
bool isExactIn,
bool isUni
) external;
function swapTokensForClosePosition(
uint256 amountIn,
uint256 amountOut,
address[] calldata path,
bool isExactIn,
bool isUni
) external;
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover
) external;
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function initReserve(
address reserve,
address xTokenAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
function getConfiguration(address asset)
external
view
returns (DataTypes.ReserveConfigurationMap memory);
function getUserConfiguration(address user)
external
view
returns (DataTypes.UserConfigurationMap memory);
function getReserveNormalizedIncome(address asset) external view returns (uint256);
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromAfter,
uint256 balanceToBefore
) external;
function getReservesList() external view returns (address[] memory);
function getAddressesProvider() external view returns (IMarginPoolAddressesProvider);
function setPause(bool val) external;
function paused() external view returns (bool);
}
文件 10 的 17:IMarginPoolAddressesProvider.sol
pragma solidity 0.6.12;
interface IMarginPoolAddressesProvider {
event MarginPoolUpdated(address indexed newAddress);
event ConfigurationAdminUpdated(address indexed newAddress);
event EmergencyAdminUpdated(address indexed newAddress);
event MarginPoolConfiguratorUpdated(address indexed newAddress);
event MarginPoolCollateralManagerUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
event LeverTokenUpdated(address indexed newAddress);
event TreasuryAddressUpdated(address indexed newAddress);
event RewardsDistributionUpdated(address indexed newAddress);
event OrderBookUpdated(address indexed newAddress);
event SwapMinerUpdated(address indexed newAddress);
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(bytes32 id, address impl) external;
function getAddress(bytes32 id) external view returns (address);
function getMarginPool() external view returns (address);
function setMarginPoolImpl(address pool, address UniswapRouter,address SushiswapRouter, address weth) external;
function getMarginPoolConfigurator() external view returns (address);
function setMarginPoolConfiguratorImpl(address configurator) external;
function getPoolAdmin() external view returns (address);
function setPoolAdmin(address admin) external;
function getEmergencyAdmin() external view returns (address);
function setEmergencyAdmin(address admin) external;
function getPriceOracle() external view returns (address);
function setPriceOracle(address priceOracle) external;
function getLeverToken() external view returns (address);
function setLeverToken(address lever) external;
function getTreasuryAddress() external view returns (address);
function setTreasuryAddress(address treasuryAddress) external;
function getRewardsDistribution() external view returns (address);
function setRewardsDistribution(address rewardsDistribution) external;
function getOrderBook() external view returns (address);
function setOrderBookImpl(address addressProvider, address UniswapRouter, address weth) external;
function getSwapMiner() external view returns (address);
function setSwapMinerImpl(address _swapMiner, address UniswapRouter, address _uniswapLevPairToken, address LeverUsdOracle) external;
}
文件 11 的 17:IScaledBalanceToken.sol
pragma solidity 0.6.12;
interface IScaledBalanceToken {
function scaledBalanceOf(address user) external view returns (uint256);
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
function scaledTotalSupply() external view returns (uint256);
}
文件 12 的 17:IVariableDebtToken.sol
pragma solidity 0.6.12;
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
interface IVariableDebtToken is IScaledBalanceToken {
event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index);
function mint(
address user,
address onBehalfOf,
uint256 amount,
uint256 index
) external returns (bool);
event Burn(address indexed user, uint256 amount, uint256 index);
function burn(
address user,
uint256 amount,
uint256 index
) external;
}
文件 13 的 17:IncentivizedERC20.sol
pragma solidity 0.6.12;
import {Context} from './Context.sol';
import {IERC20} from './IERC20.sol';
import {IERC20Detailed} from './IERC20Detailed.sol';
import {SafeMath} from './SafeMath.sol';
contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
using SafeMath for uint256;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 internal _totalSupply;
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 override returns (string memory) {
return _name;
}
function symbol() public view override returns (string memory) {
return _symbol;
}
function decimals() public view override returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
emit Transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender)
public
view
virtual
override
returns (uint256)
{
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()].sub(amount, 'ERC20: transfer amount exceeds allowance')
);
emit Transfer(sender, recipient, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
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 virtual {
require(sender != address(0), 'ERC20: transfer from the zero address');
require(recipient != address(0), 'ERC20: transfer to the zero address');
_beforeTokenTransfer(sender, recipient, amount);
uint256 oldSenderBalance = _balances[sender];
_balances[sender] = oldSenderBalance.sub(amount, 'ERC20: transfer amount exceeds balance');
_balances[recipient] = _balances[recipient].add(amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), 'ERC20: mint to the zero address');
_beforeTokenTransfer(address(0), account, amount);
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply.add(amount);
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.add(amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), 'ERC20: burn from the zero address');
_beforeTokenTransfer(account, address(0), amount);
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply.sub(amount);
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance');
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
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 _setName(string memory newName) internal {
_name = newName;
}
function _setSymbol(string memory newSymbol) internal {
_symbol = newSymbol;
}
function _setDecimals(uint8 newDecimals) internal {
_decimals = newDecimals;
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 14 的 17:SafeERC20.sol
pragma solidity 0.6.12;
import {IERC20} from './IERC20.sol';
import {SafeMath} from './SafeMath.sol';
import {Address} from './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 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');
}
}
}
文件 15 的 17:SafeMath.sol
pragma solidity 0.6.12;
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;
}
}
文件 16 的 17:VariableDebtToken.sol
pragma solidity 0.6.12;
import {IVariableDebtToken} from "./IVariableDebtToken.sol";
import {WadRayMath} from "./WadRayMath.sol";
import {Errors} from "./Errors.sol";
import {DebtTokenBase} from "./DebtTokenBase.sol";
import {SafeMath} from "./SafeMath.sol";
import {
IMarginPoolAddressesProvider
} from "./IMarginPoolAddressesProvider.sol";
import {IERC20} from "./IERC20.sol";
import {SafeERC20} from "./SafeERC20.sol";
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);
}
}
contract ReentrancyGuard {
uint256 private _guardCounter;
constructor() internal {
_guardCounter = 1;
}
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(
localCounter == _guardCounter,
"ReentrancyGuard: reentrant call"
);
}
}
contract VariableDebtToken is DebtTokenBase, IVariableDebtToken, ReentrancyGuard {
using WadRayMath for uint256;
using SafeERC20 for IERC20;
uint256 public constant DEBT_TOKEN_REVISION = 0x1;
IERC20 public rewardsToken;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public rewardsDuration = 30 days;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
IMarginPoolAddressesProvider public addressesProvider;
constructor(
address _addressesProvider,
address underlyingAsset,
string memory name,
string memory symbol,
uint8 decimals
)
public
DebtTokenBase(
IMarginPoolAddressesProvider(_addressesProvider).getMarginPool(),
underlyingAsset,
name,
symbol,
decimals
)
{
addressesProvider = IMarginPoolAddressesProvider(_addressesProvider);
rewardsToken = IERC20(IMarginPoolAddressesProvider(_addressesProvider).getLeverToken());
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
modifier onlyRewardsDistribution() {
require(
msg.sender == addressesProvider.getRewardsDistribution(),
"Caller is not RewardsDistribution contract"
);
_;
}
function balanceOf(address user)
public
view
virtual
override
returns (uint256)
{
uint256 scaledBalance = super.balanceOf(user);
if (scaledBalance == 0) {
return 0;
}
return
scaledBalance.rayMul(
POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)
);
}
function mint(
address user,
address onBehalfOf,
uint256 amount,
uint256 index
) external override onlyMarginPool updateReward(onBehalfOf) returns (bool) {
if (user != onBehalfOf) {
_decreaseBorrowAllowance(onBehalfOf, user, amount);
}
uint256 previousBalance = super.balanceOf(onBehalfOf);
uint256 amountScaled = amount.rayDiv(index);
require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT);
_mint(onBehalfOf, amountScaled);
emit Transfer(address(0), onBehalfOf, amount);
emit Mint(user, onBehalfOf, amount, index);
return previousBalance == 0;
}
function burn(
address user,
uint256 amount,
uint256 index
) external override onlyMarginPool updateReward(user) {
uint256 amountScaled = amount.rayDiv(index);
require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT);
_burn(user, amountScaled);
emit Transfer(user, address(0), amount);
emit Burn(user, amount, index);
}
function scaledBalanceOf(address user)
public
view
virtual
override
returns (uint256)
{
return super.balanceOf(user);
}
function totalSupply() public view virtual override returns (uint256) {
return
super.totalSupply().rayMul(
POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS)
);
}
function scaledTotalSupply()
public
view
virtual
override
returns (uint256)
{
return super.totalSupply();
}
function getScaledUserBalanceAndSupply(address user)
external
view
override
returns (uint256, uint256)
{
return (super.balanceOf(user), super.totalSupply());
}
function _transfer(
address from,
address to,
uint256 amount
) internal override updateReward(from) updateReward(to) {
super._transfer(from, to, amount);
}
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 getRewardForDuration() external view returns (uint256) {
return rewardRate.mul(rewardsDuration);
}
function getReward() public nonReentrant updateReward(msg.sender) {
uint256 reward = rewards[msg.sender];
require(reward > 0);
rewards[msg.sender] = 0;
rewardsToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
function notifyRewardAmount(uint256 reward, uint256 _rewardsDuration)
external
onlyRewardsDistribution
updateReward(address(0))
{
uint256 balance = rewardsToken.balanceOf(address(this));
if (block.timestamp >= periodFinish) {
rewardsDuration = _rewardsDuration;
rewardRate = reward.div(rewardsDuration);
require(
rewardRate <= balance.div(rewardsDuration),
"Provided reward too high"
);
periodFinish = block.timestamp.add(rewardsDuration);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(remaining);
require(
rewardRate <= balance.div(remaining),
"Provided reward too high"
);
}
lastUpdateTime = block.timestamp;
emit RewardAdded(reward, _rewardsDuration);
}
event RewardAdded(uint256 reward, uint256 _rewardsDuration);
event RewardPaid(address indexed user, uint256 reward);
}
文件 17 的 17:WadRayMath.sol
pragma solidity 0.6.12;
import {Errors} from './Errors.sol';
library WadRayMath {
uint256 internal constant WAD = 1e18;
uint256 internal constant halfWAD = WAD / 2;
uint256 internal constant RAY = 1e27;
uint256 internal constant halfRAY = RAY / 2;
uint256 internal constant WAD_RAY_RATIO = 1e9;
function ray() internal pure returns (uint256) {
return RAY;
}
function wad() internal pure returns (uint256) {
return WAD;
}
function halfRay() internal pure returns (uint256) {
return halfRAY;
}
function halfWad() internal pure returns (uint256) {
return halfWAD;
}
function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
require(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW);
return (a * b + halfWAD) / WAD;
}
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, Errors.MATH_DIVISION_BY_ZERO);
uint256 halfB = b / 2;
require(a <= (type(uint256).max - halfB) / WAD, Errors.MATH_MULTIPLICATION_OVERFLOW);
return (a * WAD + halfB) / b;
}
function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0 || b == 0) {
return 0;
}
require(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW);
return (a * b + halfRAY) / RAY;
}
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, Errors.MATH_DIVISION_BY_ZERO);
uint256 halfB = b / 2;
require(a <= (type(uint256).max - halfB) / RAY, Errors.MATH_MULTIPLICATION_OVERFLOW);
return (a * RAY + halfB) / b;
}
function rayToWad(uint256 a) internal pure returns (uint256) {
uint256 halfRatio = WAD_RAY_RATIO / 2;
uint256 result = halfRatio + a;
require(result >= halfRatio, Errors.MATH_ADDITION_OVERFLOW);
return result / WAD_RAY_RATIO;
}
function wadToRay(uint256 a) internal pure returns (uint256) {
uint256 result = a * WAD_RAY_RATIO;
require(result / WAD_RAY_RATIO == a, Errors.MATH_MULTIPLICATION_OVERFLOW);
return result;
}
}
{
"compilationTarget": {
"VariableDebtToken.sol": "VariableDebtToken"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_addressesProvider","type":"address"},{"internalType":"address","name":"underlyingAsset","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromUser","type":"address"},{"indexed":true,"internalType":"address","name":"toUser","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BorrowAllowanceDelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"onBehalfOf","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rewardsDuration","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEBT_TOKEN_REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL","outputs":[{"internalType":"contract IMarginPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_ASSET_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressesProvider","outputs":[{"internalType":"contract IMarginPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromUser","type":"address"},{"internalType":"address","name":"toUser","type":"address"}],"name":"borrowAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getScaledUserBalanceAndSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"onBehalfOf","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"scaledBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scaledTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]