编译器
0.5.16+commit.9c3226ce
文件 1 的 10:CarefulMath.sol
pragma solidity ^0.5.16;
contract CarefulMath {
enum MathError {
NO_ERROR,
DIVISION_BY_ZERO,
INTEGER_OVERFLOW,
INTEGER_UNDERFLOW
}
function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {
if (a == 0) {
return (MathError.NO_ERROR, 0);
}
uint c = a * b;
if (c / a != b) {
return (MathError.INTEGER_OVERFLOW, 0);
} else {
return (MathError.NO_ERROR, c);
}
}
function divUInt(uint a, uint b) internal pure returns (MathError, uint) {
if (b == 0) {
return (MathError.DIVISION_BY_ZERO, 0);
}
return (MathError.NO_ERROR, a / b);
}
function subUInt(uint a, uint b) internal pure returns (MathError, uint) {
if (b <= a) {
return (MathError.NO_ERROR, a - b);
} else {
return (MathError.INTEGER_UNDERFLOW, 0);
}
}
function addUInt(uint a, uint b) internal pure returns (MathError, uint) {
uint c = a + b;
if (c >= a) {
return (MathError.NO_ERROR, c);
} else {
return (MathError.INTEGER_OVERFLOW, 0);
}
}
function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {
(MathError err0, uint sum) = addUInt(a, b);
if (err0 != MathError.NO_ERROR) {
return (err0, 0);
}
return subUInt(sum, c);
}
}
文件 2 的 10:ComptrollerInterface.sol
pragma solidity ^0.5.16;
contract ComptrollerInterface {
bool public constant isComptroller = true;
function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);
function exitMarket(address cToken) external returns (uint);
function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint);
function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external;
function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint);
function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external;
function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint);
function borrowVerify(address cToken, address borrower, uint borrowAmount) external;
function repayBorrowAllowed(
address cToken,
address payer,
address borrower,
uint repayAmount) external returns (uint);
function repayBorrowVerify(
address cToken,
address payer,
address borrower,
uint repayAmount,
uint borrowerIndex) external;
function liquidateBorrowAllowed(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint repayAmount) external returns (uint);
function liquidateBorrowVerify(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint repayAmount,
uint seizeTokens) external;
function seizeAllowed(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint seizeTokens) external returns (uint);
function seizeVerify(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint seizeTokens) external;
function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint);
function transferVerify(address cToken, address src, address dst, uint transferTokens) external;
function liquidateCalculateSeizeTokens(
address cTokenBorrowed,
address cTokenCollateral,
uint repayAmount) external view returns (uint, uint);
}
文件 3 的 10:EIP20Interface.sol
pragma solidity ^0.5.16;
interface EIP20Interface {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256 balance);
function transfer(address dst, uint256 amount) external returns (bool success);
function transferFrom(address src, address dst, uint256 amount) external returns (bool success);
function approve(address spender, uint256 amount) external returns (bool success);
function allowance(address owner, address spender) external view returns (uint256 remaining);
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
}
文件 4 的 10:EIP20NonStandardInterface.sol
pragma solidity ^0.5.16;
interface EIP20NonStandardInterface {
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256 balance);
function transfer(address dst, uint256 amount) external;
function transferFrom(address src, address dst, uint256 amount) external;
function approve(address spender, uint256 amount) external returns (bool success);
function allowance(address owner, address spender) external view returns (uint256 remaining);
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
}
文件 5 的 10:ErrorReporter.sol
pragma solidity ^0.5.16;
contract ComptrollerErrorReporter {
enum Error {
NO_ERROR,
UNAUTHORIZED,
COMPTROLLER_MISMATCH,
INSUFFICIENT_SHORTFALL,
INSUFFICIENT_LIQUIDITY,
INVALID_CLOSE_FACTOR,
INVALID_COLLATERAL_FACTOR,
INVALID_LIQUIDATION_INCENTIVE,
MARKET_NOT_ENTERED,
MARKET_NOT_LISTED,
MARKET_ALREADY_LISTED,
MATH_ERROR,
NONZERO_BORROW_BALANCE,
PRICE_ERROR,
REJECTION,
SNAPSHOT_ERROR,
TOO_MANY_ASSETS,
TOO_MUCH_REPAY
}
enum FailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,
EXIT_MARKET_BALANCE_OWED,
EXIT_MARKET_REJECTION,
SET_CLOSE_FACTOR_OWNER_CHECK,
SET_CLOSE_FACTOR_VALIDATION,
SET_COLLATERAL_FACTOR_OWNER_CHECK,
SET_COLLATERAL_FACTOR_NO_EXISTS,
SET_COLLATERAL_FACTOR_VALIDATION,
SET_COLLATERAL_FACTOR_WITHOUT_PRICE,
SET_IMPLEMENTATION_OWNER_CHECK,
SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,
SET_LIQUIDATION_INCENTIVE_VALIDATION,
SET_MAX_ASSETS_OWNER_CHECK,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_PENDING_IMPLEMENTATION_OWNER_CHECK,
SET_PRICE_ORACLE_OWNER_CHECK,
SUPPORT_MARKET_EXISTS,
SUPPORT_MARKET_OWNER_CHECK,
SET_PAUSE_GUARDIAN_OWNER_CHECK
}
event Failure(uint error, uint info, uint detail);
function fail(Error err, FailureInfo info) internal returns (uint) {
emit Failure(uint(err), uint(info), 0);
return uint(err);
}
function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {
emit Failure(uint(err), uint(info), opaqueError);
return uint(err);
}
}
contract TokenErrorReporter {
enum Error {
NO_ERROR,
UNAUTHORIZED,
BAD_INPUT,
COMPTROLLER_REJECTION,
COMPTROLLER_CALCULATION_ERROR,
INTEREST_RATE_MODEL_ERROR,
INVALID_ACCOUNT_PAIR,
INVALID_CLOSE_AMOUNT_REQUESTED,
INVALID_COLLATERAL_FACTOR,
MATH_ERROR,
MARKET_NOT_FRESH,
MARKET_NOT_LISTED,
TOKEN_INSUFFICIENT_ALLOWANCE,
TOKEN_INSUFFICIENT_BALANCE,
TOKEN_INSUFFICIENT_CASH,
TOKEN_TRANSFER_IN_FAILED,
TOKEN_TRANSFER_OUT_FAILED
}
enum FailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,
ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,
ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,
ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,
BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,
BORROW_ACCRUE_INTEREST_FAILED,
BORROW_CASH_NOT_AVAILABLE,
BORROW_FRESHNESS_CHECK,
BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,
BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,
BORROW_MARKET_NOT_LISTED,
BORROW_COMPTROLLER_REJECTION,
LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,
LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,
LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,
LIQUIDATE_COMPTROLLER_REJECTION,
LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,
LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,
LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,
LIQUIDATE_FRESHNESS_CHECK,
LIQUIDATE_LIQUIDATOR_IS_BORROWER,
LIQUIDATE_REPAY_BORROW_FRESH_FAILED,
LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,
LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,
LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,
LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,
LIQUIDATE_SEIZE_TOO_MUCH,
MINT_ACCRUE_INTEREST_FAILED,
MINT_COMPTROLLER_REJECTION,
MINT_EXCHANGE_CALCULATION_FAILED,
MINT_EXCHANGE_RATE_READ_FAILED,
MINT_FRESHNESS_CHECK,
MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,
MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,
MINT_TRANSFER_IN_FAILED,
MINT_TRANSFER_IN_NOT_POSSIBLE,
REDEEM_ACCRUE_INTEREST_FAILED,
REDEEM_COMPTROLLER_REJECTION,
REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,
REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,
REDEEM_EXCHANGE_RATE_READ_FAILED,
REDEEM_FRESHNESS_CHECK,
REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,
REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,
REDEEM_TRANSFER_OUT_NOT_POSSIBLE,
REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,
REDUCE_RESERVES_ADMIN_CHECK,
REDUCE_RESERVES_CASH_NOT_AVAILABLE,
REDUCE_RESERVES_FRESH_CHECK,
REDUCE_RESERVES_VALIDATION,
REPAY_BEHALF_ACCRUE_INTEREST_FAILED,
REPAY_BORROW_ACCRUE_INTEREST_FAILED,
REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_COMPTROLLER_REJECTION,
REPAY_BORROW_FRESHNESS_CHECK,
REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,
REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,
SET_COLLATERAL_FACTOR_OWNER_CHECK,
SET_COLLATERAL_FACTOR_VALIDATION,
SET_COMPTROLLER_OWNER_CHECK,
SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,
SET_INTEREST_RATE_MODEL_FRESH_CHECK,
SET_INTEREST_RATE_MODEL_OWNER_CHECK,
SET_MAX_ASSETS_OWNER_CHECK,
SET_ORACLE_MARKET_NOT_LISTED,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,
SET_RESERVE_FACTOR_ADMIN_CHECK,
SET_RESERVE_FACTOR_FRESH_CHECK,
SET_RESERVE_FACTOR_BOUNDS_CHECK,
TRANSFER_COMPTROLLER_REJECTION,
TRANSFER_NOT_ALLOWED,
TRANSFER_NOT_ENOUGH,
TRANSFER_TOO_MUCH,
ADD_RESERVES_ACCRUE_INTEREST_FAILED,
ADD_RESERVES_FRESH_CHECK,
ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE
}
event Failure(uint error, uint info, uint detail);
function fail(Error err, FailureInfo info) internal returns (uint) {
emit Failure(uint(err), uint(info), 0);
return uint(err);
}
function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {
emit Failure(uint(err), uint(info), opaqueError);
return uint(err);
}
}
文件 6 的 10:Exponential.sol
pragma solidity ^0.5.16;
import "./CarefulMath.sol";
import "./ExponentialNoError.sol";
contract Exponential is CarefulMath, ExponentialNoError {
function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) {
(MathError err0, uint scaledNumerator) = mulUInt(num, expScale);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({mantissa: 0}));
}
(MathError err1, uint rational) = divUInt(scaledNumerator, denom);
if (err1 != MathError.NO_ERROR) {
return (err1, Exp({mantissa: 0}));
}
return (MathError.NO_ERROR, Exp({mantissa: rational}));
}
function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {
(MathError error, uint result) = addUInt(a.mantissa, b.mantissa);
return (error, Exp({mantissa: result}));
}
function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {
(MathError error, uint result) = subUInt(a.mantissa, b.mantissa);
return (error, Exp({mantissa: result}));
}
function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {
(MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({mantissa: 0}));
}
return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));
}
function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) {
(MathError err, Exp memory product) = mulScalar(a, scalar);
if (err != MathError.NO_ERROR) {
return (err, 0);
}
return (MathError.NO_ERROR, truncate(product));
}
function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) {
(MathError err, Exp memory product) = mulScalar(a, scalar);
if (err != MathError.NO_ERROR) {
return (err, 0);
}
return addUInt(truncate(product), addend);
}
function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) {
(MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({mantissa: 0}));
}
return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));
}
function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) {
(MathError err0, uint numerator) = mulUInt(expScale, scalar);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({mantissa: 0}));
}
return getExp(numerator, divisor.mantissa);
}
function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) {
(MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);
if (err != MathError.NO_ERROR) {
return (err, 0);
}
return (MathError.NO_ERROR, truncate(fraction));
}
function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {
(MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);
if (err0 != MathError.NO_ERROR) {
return (err0, Exp({mantissa: 0}));
}
(MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);
if (err1 != MathError.NO_ERROR) {
return (err1, Exp({mantissa: 0}));
}
(MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);
assert(err2 == MathError.NO_ERROR);
return (MathError.NO_ERROR, Exp({mantissa: product}));
}
function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) {
return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));
}
function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) {
(MathError err, Exp memory ab) = mulExp(a, b);
if (err != MathError.NO_ERROR) {
return (err, ab);
}
return mulExp(ab, c);
}
function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) {
return getExp(a.mantissa, b.mantissa);
}
}
文件 7 的 10:ExponentialNoError.sol
pragma solidity ^0.5.16;
contract ExponentialNoError {
uint constant expScale = 1e18;
uint constant doubleScale = 1e36;
uint constant halfExpScale = expScale/2;
uint constant mantissaOne = expScale;
struct Exp {
uint mantissa;
}
struct Double {
uint mantissa;
}
function truncate(Exp memory exp) pure internal returns (uint) {
return exp.mantissa / expScale;
}
function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {
Exp memory product = mul_(a, scalar);
return truncate(product);
}
function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {
Exp memory product = mul_(a, scalar);
return add_(truncate(product), addend);
}
function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa < right.mantissa;
}
function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa <= right.mantissa;
}
function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa > right.mantissa;
}
function isZeroExp(Exp memory value) pure internal returns (bool) {
return value.mantissa == 0;
}
function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {
require(n < 2**224, errorMessage);
return uint224(n);
}
function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {
return Exp({mantissa: add_(a.mantissa, b.mantissa)});
}
function add_(Double memory a, Double memory b) pure internal returns (Double memory) {
return Double({mantissa: add_(a.mantissa, b.mantissa)});
}
function add_(uint a, uint b) pure internal returns (uint) {
return add_(a, b, "addition overflow");
}
function add_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {
uint c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {
return Exp({mantissa: sub_(a.mantissa, b.mantissa)});
}
function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {
return Double({mantissa: sub_(a.mantissa, b.mantissa)});
}
function sub_(uint a, uint b) pure internal returns (uint) {
return sub_(a, b, "subtraction underflow");
}
function sub_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {
require(b <= a, errorMessage);
return a - b;
}
function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {
return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});
}
function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {
return Exp({mantissa: mul_(a.mantissa, b)});
}
function mul_(uint a, Exp memory b) pure internal returns (uint) {
return mul_(a, b.mantissa) / expScale;
}
function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {
return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});
}
function mul_(Double memory a, uint b) pure internal returns (Double memory) {
return Double({mantissa: mul_(a.mantissa, b)});
}
function mul_(uint a, Double memory b) pure internal returns (uint) {
return mul_(a, b.mantissa) / doubleScale;
}
function mul_(uint a, uint b) pure internal returns (uint) {
return mul_(a, b, "multiplication overflow");
}
function mul_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {
if (a == 0 || b == 0) {
return 0;
}
uint c = a * b;
require(c / a == b, errorMessage);
return c;
}
function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {
return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});
}
function div_(Exp memory a, uint b) pure internal returns (Exp memory) {
return Exp({mantissa: div_(a.mantissa, b)});
}
function div_(uint a, Exp memory b) pure internal returns (uint) {
return div_(mul_(a, expScale), b.mantissa);
}
function div_(Double memory a, Double memory b) pure internal returns (Double memory) {
return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});
}
function div_(Double memory a, uint b) pure internal returns (Double memory) {
return Double({mantissa: div_(a.mantissa, b)});
}
function div_(uint a, Double memory b) pure internal returns (uint) {
return div_(mul_(a, doubleScale), b.mantissa);
}
function div_(uint a, uint b) pure internal returns (uint) {
return div_(a, b, "divide by zero");
}
function div_(uint a, uint b, string memory errorMessage) pure internal returns (uint) {
require(b > 0, errorMessage);
return a / b;
}
function fraction(uint a, uint b) pure internal returns (Double memory) {
return Double({mantissa: div_(mul_(a, doubleScale), b)});
}
}
文件 8 的 10:IINV.sol
pragma solidity ^0.5.16;
interface IINV {
function balanceOf(address) external view returns (uint);
function transfer(address,uint) external returns (bool);
function delegates(address) external view returns (address);
function delegate(address) external;
}
文件 9 的 10:SafeMath.sol
pragma solidity ^0.5.16;
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 add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction underflow");
}
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 mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, errorMessage);
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;
}
}
文件 10 的 10:XINV.sol
pragma solidity ^0.5.16;
import "./ComptrollerInterface.sol";
import "./ErrorReporter.sol";
import "./Exponential.sol";
import "./EIP20Interface.sol";
import "./EIP20NonStandardInterface.sol";
import "./SafeMath.sol";
import "./Governance/IINV.sol";
contract xInvCore is Exponential, TokenErrorReporter {
bool internal _notEntered;
string public name;
string public symbol;
uint8 public decimals;
uint internal constant reserveFactorMaxMantissa = 1e18;
address payable public admin;
address payable public pendingAdmin;
ComptrollerInterface public comptroller;
uint internal initialExchangeRateMantissa;
uint public accrualBlockNumber;
uint public totalSupply;
uint public rewardPerBlock;
address public rewardTreasury;
mapping (address => uint) internal accountTokens;
bool public constant isCToken = true;
event Mint(address minter, uint mintAmount, uint mintTokens);
event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
event NewAdmin(address oldAdmin, address newAdmin);
event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);
event NewRewardTreasury(address oldRewardTreasury, address newRewardTreasury);
event NewRewardPerBlock(uint oldRewardPerBlock, uint newRewardPerBlock);
event Transfer(address indexed from, address indexed to, uint amount);
event Failure(uint error, uint info, uint detail);
function initialize(ComptrollerInterface comptroller_,
uint initialExchangeRateMantissa_,
uint rewardPerBlock_,
address rewardTreasury_,
string memory name_,
string memory symbol_,
uint8 decimals_) internal {
require(msg.sender == admin, "only admin may initialize the market");
require(accrualBlockNumber == 0, "market may only be initialized once");
initialExchangeRateMantissa = initialExchangeRateMantissa_;
require(initialExchangeRateMantissa > 0, "initial exchange rate must be greater than zero.");
uint err = _setComptroller(comptroller_);
require(err == uint(Error.NO_ERROR), "setting comptroller failed");
name = name_;
symbol = symbol_;
decimals = decimals_;
accrualBlockNumber = getBlockNumber();
rewardPerBlock = rewardPerBlock_;
rewardTreasury = rewardTreasury_;
_notEntered = true;
}
function balanceOf(address owner) external view returns (uint256) {
return accountTokens[owner];
}
function balanceOfUnderlying(address owner) external returns (uint) {
Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});
(MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);
require(mErr == MathError.NO_ERROR, "balance could not be calculated");
return balance;
}
function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {
uint cTokenBalance = accountTokens[account];
uint exchangeRateMantissa;
MathError mErr;
(mErr, exchangeRateMantissa) = exchangeRateStoredInternal();
if (mErr != MathError.NO_ERROR) {
return (uint(Error.MATH_ERROR), 0, 0, 0);
}
return (uint(Error.NO_ERROR), cTokenBalance, 0, exchangeRateMantissa);
}
function getBlockNumber() internal view returns (uint) {
return block.number;
}
function exchangeRateCurrent() public nonReentrant returns (uint) {
require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed");
return exchangeRateStored();
}
function exchangeRateStored() public view returns (uint) {
(MathError err, uint result) = exchangeRateStoredInternal();
require(err == MathError.NO_ERROR, "exchangeRateStored: exchangeRateStoredInternal failed");
return result;
}
function exchangeRateStoredInternal() internal view returns (MathError, uint) {
uint _totalSupply = totalSupply;
if (_totalSupply == 0) {
return (MathError.NO_ERROR, initialExchangeRateMantissa);
} else {
uint totalCash = getCashPrior();
Exp memory exchangeRate;
MathError mathErr;
(mathErr, exchangeRate) = getExp(totalCash, _totalSupply);
if (mathErr != MathError.NO_ERROR) {
return (mathErr, 0);
}
return (MathError.NO_ERROR, exchangeRate.mantissa);
}
}
function getCash() external view returns (uint) {
return getCashPrior();
}
function accrueInterest() public returns (uint) {
uint currentBlockNumber = getBlockNumber();
uint accrualBlockNumberPrior = accrualBlockNumber;
if (accrualBlockNumberPrior == currentBlockNumber) {
return uint(Error.NO_ERROR);
}
(MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);
require(mathErr == MathError.NO_ERROR, "could not calculate block delta");
uint reward;
(mathErr, reward) = mulUInt(rewardPerBlock, blockDelta);
require(mathErr == MathError.NO_ERROR, "could not calculate reward");
if(totalSupply > 0 && rewardTreasury != address(0) && canTransferIn(rewardTreasury, reward)) {
doTransferIn(rewardTreasury, reward);
}
accrualBlockNumber = currentBlockNumber;
return uint(Error.NO_ERROR);
}
function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {
uint error = accrueInterest();
if (error != uint(Error.NO_ERROR)) {
return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);
}
return mintFresh(msg.sender, mintAmount);
}
struct MintLocalVars {
Error err;
MathError mathErr;
uint exchangeRateMantissa;
uint mintTokens;
uint totalSupplyNew;
uint accountTokensNew;
uint actualMintAmount;
}
function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {
uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);
if (allowed != 0) {
return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);
}
MintLocalVars memory vars;
(vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();
if (vars.mathErr != MathError.NO_ERROR) {
return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);
}
vars.actualMintAmount = doTransferIn(minter, mintAmount);
(vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(vars.actualMintAmount, Exp({mantissa: vars.exchangeRateMantissa}));
require(vars.mathErr == MathError.NO_ERROR, "MINT_EXCHANGE_CALCULATION_FAILED");
(vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);
require(vars.mathErr == MathError.NO_ERROR, "MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED");
require(vars.totalSupplyNew < 2**96, "MINT_NEW_TOTAL_SUPPLY_OVER_CAPACITY");
(vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);
require(vars.mathErr == MathError.NO_ERROR, "MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED");
totalSupply = vars.totalSupplyNew;
accountTokens[minter] = vars.accountTokensNew;
emit Mint(minter, vars.actualMintAmount, vars.mintTokens);
emit Transfer(address(this), minter, vars.mintTokens);
_moveDelegates(address(0), minter, uint96(vars.mintTokens));
comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);
return (uint(Error.NO_ERROR), vars.actualMintAmount);
}
function redeemInternal(uint redeemTokens, bool useEscrow) internal nonReentrant returns (uint) {
uint error = accrueInterest();
if (error != uint(Error.NO_ERROR)) {
return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);
}
return redeemFresh(msg.sender, redeemTokens, 0, useEscrow);
}
function redeemUnderlyingInternal(uint redeemAmount, bool useEscrow) internal nonReentrant returns (uint) {
uint error = accrueInterest();
if (error != uint(Error.NO_ERROR)) {
return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);
}
return redeemFresh(msg.sender, 0, redeemAmount, useEscrow);
}
struct RedeemLocalVars {
Error err;
MathError mathErr;
uint exchangeRateMantissa;
uint redeemTokens;
uint redeemAmount;
uint totalSupplyNew;
uint accountTokensNew;
}
function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn, bool useEscrow) internal returns (uint) {
require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero");
RedeemLocalVars memory vars;
(vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr));
}
if (redeemTokensIn > 0) {
vars.redeemTokens = redeemTokensIn;
(vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr));
}
} else {
(vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr));
}
vars.redeemAmount = redeemAmountIn;
}
uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);
}
(vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr));
}
(vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);
if (vars.mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr));
}
if (getCashPrior() < vars.redeemAmount) {
return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);
}
doTransferOut(redeemer, vars.redeemAmount, useEscrow);
totalSupply = vars.totalSupplyNew;
accountTokens[redeemer] = vars.accountTokensNew;
emit Transfer(redeemer, address(this), vars.redeemTokens);
emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);
_moveDelegates(redeemer, address(0), uint96(vars.redeemTokens));
comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);
return uint(Error.NO_ERROR);
}
function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {
return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);
}
function seizeInternal(address seizerToken, address liquidator, address borrower, uint seizeTokens) internal returns (uint) {
uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);
if (allowed != 0) {
return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);
}
if (borrower == liquidator) {
return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);
}
MathError mathErr;
uint borrowerTokensNew;
uint liquidatorTokensNew;
(mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);
if (mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));
}
(mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);
if (mathErr != MathError.NO_ERROR) {
return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));
}
accountTokens[borrower] = borrowerTokensNew;
accountTokens[liquidator] = liquidatorTokensNew;
emit Transfer(borrower, liquidator, seizeTokens);
_moveDelegates(borrower, liquidator, uint96(seizeTokens));
comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);
redeemFresh(address(uint160(liquidator)), seizeTokens, 0, false);
return uint(Error.NO_ERROR);
}
function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);
}
address oldPendingAdmin = pendingAdmin;
pendingAdmin = newPendingAdmin;
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
return uint(Error.NO_ERROR);
}
function _acceptAdmin() external returns (uint) {
if (msg.sender != pendingAdmin || msg.sender == address(0)) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);
}
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
admin = pendingAdmin;
pendingAdmin = address(0);
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
return uint(Error.NO_ERROR);
}
function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);
}
ComptrollerInterface oldComptroller = comptroller;
require(newComptroller.isComptroller(), "marker method returned false");
comptroller = newComptroller;
emit NewComptroller(oldComptroller, newComptroller);
return uint(Error.NO_ERROR);
}
function _setRewardTreasury(address newRewardTreasury) public returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);
}
address oldRewardTreasury = rewardTreasury;
rewardTreasury = newRewardTreasury;
emit NewRewardTreasury(oldRewardTreasury, newRewardTreasury);
}
function _setRewardPerBlock(uint newRewardPerBlock) public returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);
}
uint oldRewardPerBlock = rewardPerBlock;
rewardPerBlock = newRewardPerBlock;
emit NewRewardPerBlock(oldRewardPerBlock, newRewardPerBlock);
}
function getCashPrior() internal view returns (uint);
function doTransferIn(address from, uint amount) internal returns (uint);
function canTransferIn(address from, uint amount) internal view returns (bool);
function doTransferOut(address payable to, uint amount, bool useEscrow) internal;
modifier nonReentrant() {
require(_notEntered, "re-entered");
_notEntered = false;
_;
_notEntered = true;
}
mapping (address => address) public delegates;
struct Checkpoint {
uint32 fromBlock;
uint96 votes;
}
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
mapping (address => uint32) public numCheckpoints;
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
mapping (address => uint) public nonces;
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
function delegate(address delegatee) public {
return _delegate(msg.sender, delegatee);
}
function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "INV::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "INV::delegateBySig: invalid nonce");
require(now <= expiry, "INV::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
function getCurrentVotes(address account) external view returns (uint96) {
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {
require(blockNumber < block.number, "INV::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2;
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee) internal {
address currentDelegate = delegates[delegator];
uint96 delegatorBalance = uint96(accountTokens[delegator]);
delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint96 srcRepNew = sub96(srcRepOld, amount, "INV::_moveVotes: vote amount underflows");
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint96 dstRepNew = add96(dstRepOld, amount, "INV::_moveVotes: vote amount overflows");
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {
uint32 blockNumber = safe32(block.number, "INV::_writeCheckpoint: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
}
contract TimelockEscrow {
using SafeMath for uint;
address public underlying;
address public governance;
address public market;
uint public duration = 14 days;
mapping (address => EscrowData) public pendingWithdrawals;
struct EscrowData {
uint withdrawalTimestamp;
uint amount;
}
constructor(address underlying_, address governance_) public {
underlying = underlying_;
governance = governance_;
market = msg.sender;
}
function _setEscrowDuration(uint duration_) public {
require(msg.sender == governance, "only governance can set escrow duration");
duration = duration_;
}
function _setGov(address governance_) public {
require(msg.sender == governance, "only governance can set its new address");
governance = governance_;
}
function escrow(address user, uint amount) public {
require(msg.sender == market, "only market can escrow");
if(duration > 0) {
EscrowData memory withdrawal = pendingWithdrawals[user];
pendingWithdrawals[user] = EscrowData({
withdrawalTimestamp: block.timestamp + duration,
amount: withdrawal.amount.add(amount)
});
emit Escrow(user, block.timestamp + duration, amount);
} else {
EIP20Interface token = EIP20Interface(underlying);
token.transfer(user, amount);
}
}
function withdrawable(address user) public view returns (uint amount) {
EscrowData memory withdrawal = pendingWithdrawals[user];
if(withdrawal.withdrawalTimestamp <= block.timestamp) {
amount = withdrawal.amount;
}
}
function withdraw() public {
uint amount = withdrawable(msg.sender);
require(amount > 0, "Nothing to withdraw");
EIP20Interface token = EIP20Interface(underlying);
delete pendingWithdrawals[msg.sender];
token.transfer(msg.sender, amount);
emit Withdraw(msg.sender, amount);
}
event Escrow(address to, uint withdrawalTimestamp, uint amount);
event Withdraw(address to, uint amount);
}
contract XINV is xInvCore {
address public underlying;
TimelockEscrow public escrow;
constructor(address underlying_,
ComptrollerInterface comptroller_,
uint rewardPerBlock_,
address rewardTreasury_,
string memory name_,
string memory symbol_,
uint8 decimals_,
address payable admin_) public {
admin = msg.sender;
super.initialize(comptroller_, 1e18, rewardPerBlock_, rewardTreasury_, name_, symbol_, decimals_);
underlying = underlying_;
EIP20Interface(underlying).totalSupply();
admin = admin_;
escrow = new TimelockEscrow(underlying_, admin_);
}
function mint(uint mintAmount) external returns (uint) {
(uint err,) = mintInternal(mintAmount);
if(delegates[msg.sender] == address(0)) {
address invDelegate = IINV(underlying).delegates(msg.sender);
if(invDelegate != address(0)) {
_delegate(msg.sender, invDelegate);
}
}
return err;
}
function redeem(uint redeemTokens) external returns (uint) {
return redeemInternal(redeemTokens, true);
}
function redeemUnderlying(uint redeemAmount) external returns (uint) {
return redeemUnderlyingInternal(redeemAmount, true);
}
function getCashPrior() internal view returns (uint) {
EIP20Interface token = EIP20Interface(underlying);
return token.balanceOf(address(this));
}
function doTransferIn(address from, uint amount) internal returns (uint) {
EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);
uint balanceBefore = EIP20Interface(underlying).balanceOf(address(this));
token.transferFrom(from, address(this), amount);
bool success;
assembly {
switch returndatasize()
case 0 {
success := not(0)
}
case 32 {
returndatacopy(0, 0, 32)
success := mload(0)
}
default {
revert(0, 0)
}
}
require(success, "TOKEN_TRANSFER_IN_FAILED");
uint balanceAfter = EIP20Interface(underlying).balanceOf(address(this));
require(balanceAfter >= balanceBefore, "TOKEN_TRANSFER_IN_OVERFLOW");
return balanceAfter - balanceBefore;
}
function canTransferIn(address from, uint amount) internal view returns (bool) {
EIP20Interface token = EIP20Interface(underlying);
uint balance = token.balanceOf(from);
uint allowance = token.allowance(from, address(this));
return balance >= amount && allowance >= amount;
}
function doTransferOut(address payable to, uint amount, bool useEscrow) internal {
EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);
if(useEscrow) {
token.transfer(address(escrow), amount);
} else {
token.transfer(to, amount);
}
bool success;
assembly {
switch returndatasize()
case 0 {
success := not(0)
}
case 32 {
returndatacopy(0, 0, 32)
success := mload(0)
}
default {
revert(0, 0)
}
}
require(success, "TOKEN_TRANSFER_OUT_FAILED");
if(useEscrow) {
escrow.escrow(to, amount);
}
}
function _setTimelockEscrow(TimelockEscrow newTimelockEscrow) public returns (uint) {
require(newTimelockEscrow.market() == address(this), "sanity check: newTimelockEscrow must use this market");
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);
}
TimelockEscrow oldTimelockEscrow = escrow;
escrow = newTimelockEscrow;
emit NewTimelockEscrow(oldTimelockEscrow, newTimelockEscrow);
}
event NewTimelockEscrow(TimelockEscrow oldTimelockEscrow, TimelockEscrow newTimelockEscrow);
}
{
"compilationTarget": {
"contracts/XINV.sol": "XINV"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"underlying_","type":"address"},{"internalType":"contract ComptrollerInterface","name":"comptroller_","type":"address"},{"internalType":"uint256","name":"rewardPerBlock_","type":"uint256"},{"internalType":"address","name":"rewardTreasury_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"address payable","name":"admin_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"error","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"info","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"detail","type":"uint256"}],"name":"Failure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintTokens","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ComptrollerInterface","name":"oldComptroller","type":"address"},{"indexed":false,"internalType":"contract ComptrollerInterface","name":"newComptroller","type":"address"}],"name":"NewComptroller","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRewardPerBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRewardPerBlock","type":"uint256"}],"name":"NewRewardPerBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRewardTreasury","type":"address"},{"indexed":false,"internalType":"address","name":"newRewardTreasury","type":"address"}],"name":"NewRewardTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract TimelockEscrow","name":"oldTimelockEscrow","type":"address"},{"indexed":false,"internalType":"contract TimelockEscrow","name":"newTimelockEscrow","type":"address"}],"name":"NewTimelockEscrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"Redeem","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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"_acceptAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract ComptrollerInterface","name":"newComptroller","type":"address"}],"name":"_setComptroller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newRewardPerBlock","type":"uint256"}],"name":"_setRewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newRewardTreasury","type":"address"}],"name":"_setRewardTreasury","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract TimelockEscrow","name":"newTimelockEscrow","type":"address"}],"name":"_setTimelockEscrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accrualBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"accrueInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint96","name":"votes","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"comptroller","outputs":[{"internalType":"contract ComptrollerInterface","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrow","outputs":[{"internalType":"contract TimelockEscrow","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"exchangeRateCurrent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"exchangeRateStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountSnapshot","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isCToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"redeemTokens","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"redeemUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rewardTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"seizeTokens","type":"uint256"}],"name":"seize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]