编译器
0.6.12+commit.27d51765
文件 1 的 15: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 的 15: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 的 15: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 的 15: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
}
}
文件 5 的 15: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);
}
文件 6 的 15: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);
}
文件 7 的 15: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);
}
文件 8 的 15: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;
}
文件 9 的 15: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);
}
文件 10 的 15:IXToken.sol
pragma solidity 0.6.12;
import {IERC20} from './IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
interface IXToken is IERC20, IScaledBalanceToken {
event Mint(address indexed from, uint256 value, uint256 index);
function mint(
address user,
uint256 amount,
uint256 index
) external returns (bool);
event Burn(address indexed from, address indexed target, uint256 value, uint256 index);
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
function burn(
address user,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external;
function mintToTreasury(uint256 amount, uint256 index) external;
function transferOnLiquidation(
address from,
address to,
uint256 value
) external;
function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);
}
文件 11 的 15: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 {}
}
文件 12 的 15: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');
}
}
}
文件 13 的 15: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;
}
}
文件 14 的 15: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;
}
}
文件 15 的 15:XToken.sol
pragma solidity 0.6.12;
import {IERC20} from "./IERC20.sol";
import {SafeERC20} from "./SafeERC20.sol";
import {IMarginPool} from "./IMarginPool.sol";
import {IXToken} from "./IXToken.sol";
import {WadRayMath} from "./WadRayMath.sol";
import {Errors} from "./Errors.sol";
import {IncentivizedERC20} from "./IncentivizedERC20.sol";
import {SafeMath} from "./SafeMath.sol";
import {
IMarginPoolAddressesProvider
} from "./IMarginPoolAddressesProvider.sol";
import {Address} from "./Address.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 XToken is
IncentivizedERC20,
IXToken,
ReentrancyGuard
{
using WadRayMath for uint256;
using SafeERC20 for IERC20;
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;
bytes public constant EIP712_REVISION = bytes("1");
bytes32 internal constant EIP712_DOMAIN =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 public constant PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
uint256 public constant UINT_MAX_VALUE = uint256(-1);
address public immutable UNDERLYING_ASSET_ADDRESS;
address public immutable RESERVE_TREASURY_ADDRESS;
IMarginPool public immutable POOL;
IMarginPoolAddressesProvider public addressesProvider;
mapping(address => uint256) public _nonces;
bytes32 public DOMAIN_SEPARATOR;
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"
);
_;
}
modifier onlyMarginPool {
require(
_msgSender() == address(POOL),
Errors.CT_CALLER_MUST_BE_MARGIN_POOL
);
_;
}
constructor(
address _addressesProvider,
address underlyingAssetAddress,
string memory tokenName,
string memory tokenSymbol,
uint8 decimals
) public IncentivizedERC20(tokenName, tokenSymbol, decimals) {
addressesProvider = IMarginPoolAddressesProvider(_addressesProvider);
POOL = IMarginPool(addressesProvider.getMarginPool());
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
RESERVE_TREASURY_ADDRESS = addressesProvider.getTreasuryAddress();
rewardsToken = IERC20(IMarginPoolAddressesProvider(_addressesProvider).getLeverToken());
}
function burn(
address user,
address receiverOfUnderlying,
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);
if (receiverOfUnderlying != address(this)) {
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(
receiverOfUnderlying,
amount
);
}
emit Transfer(user, address(0), amount);
emit Burn(user, receiverOfUnderlying, amount, index);
}
function mint(
address user,
uint256 amount,
uint256 index
) external override onlyMarginPool updateReward(user) returns (bool) {
uint256 previousBalance = super.balanceOf(user);
uint256 amountScaled = amount.rayDiv(index);
require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT);
_mint(user, amountScaled);
emit Transfer(address(0), user, amount);
emit Mint(user, amount, index);
return previousBalance == 0;
}
function mintToTreasury(uint256 amount, uint256 index)
external
override
onlyMarginPool
updateReward(RESERVE_TREASURY_ADDRESS)
{
if (amount == 0) {
return;
}
_mint(RESERVE_TREASURY_ADDRESS, amount.rayDiv(index));
emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount);
emit Mint(RESERVE_TREASURY_ADDRESS, amount, index);
}
function transferOnLiquidation(
address from,
address to,
uint256 value
) external override onlyMarginPool updateReward(from) updateReward(to) {
_transfer(from, to, value, false);
emit Transfer(from, to, value);
}
function balanceOf(address user)
public
view
override(IncentivizedERC20, IERC20)
returns (uint256)
{
return
super.balanceOf(user).rayMul(
POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)
);
}
function scaledBalanceOf(address user)
external
view
override
returns (uint256)
{
return super.balanceOf(user);
}
function getScaledUserBalanceAndSupply(address user)
external
view
override
returns (uint256, uint256)
{
return (super.balanceOf(user), super.totalSupply());
}
function totalSupply()
public
view
override(IncentivizedERC20, IERC20)
returns (uint256)
{
uint256 currentSupplyScaled = super.totalSupply();
if (currentSupplyScaled == 0) {
return 0;
}
return
currentSupplyScaled.rayMul(
POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS)
);
}
function scaledTotalSupply()
public
view
virtual
override
returns (uint256)
{
return super.totalSupply();
}
function transferUnderlyingTo(address target, uint256 amount)
external
override
onlyMarginPool
returns (uint256)
{
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount);
return amount;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
require(owner != address(0), "INVALID_OWNER");
require(block.timestamp <= deadline, "INVALID_EXPIRATION");
uint256 currentValidNonce = _nonces[owner];
bytes32 digest =
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
value,
currentValidNonce,
deadline
)
)
)
);
require(owner == ecrecover(digest, v, r, s), "INVALID_SIGNATURE");
_nonces[owner] = currentValidNonce.add(1);
_approve(owner, spender, value);
}
function _transfer(
address from,
address to,
uint256 amount,
bool validate
) internal updateReward(from) updateReward(to) {
uint256 index =
POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index);
uint256 toBalanceBefore = super.balanceOf(to).rayMul(index);
super._transfer(from, to, amount.rayDiv(index));
if (validate) {
POOL.finalizeTransfer(
UNDERLYING_ASSET_ADDRESS,
from,
to,
amount,
fromBalanceBefore,
toBalanceBefore
);
}
emit BalanceTransfer(from, to, amount, index);
}
function _transfer(
address from,
address to,
uint256 amount
) internal override {
_transfer(from, to, amount, true);
}
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);
}
{
"compilationTarget": {
"XToken.sol": "XToken"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_addressesProvider","type":"address"},{"internalType":"address","name":"underlyingAssetAddress","type":"address"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"BalanceTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","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":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":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_REVISION","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL","outputs":[{"internalType":"contract IMarginPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVE_TREASURY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UINT_MAX_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_ASSET_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"receiverOfUnderlying","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":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mintToTreasury","outputs":[],"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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferOnLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferUnderlyingTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]