Source Code
Latest 25 from a total of 3,738 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Claim Incentive | 14211963 | 38 hrs ago | IN | 0 GLMR | 0.0725685 | ||||
| Claim Incentive | 14211957 | 38 hrs ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14211952 | 38 hrs ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14199459 | 2 days ago | IN | 0 GLMR | 0.0725685 | ||||
| Claim Incentive | 14199448 | 2 days ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14190255 | 3 days ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14190203 | 3 days ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14190194 | 3 days ago | IN | 0 GLMR | 0.0725685 | ||||
| Claim Incentive | 14171305 | 4 days ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14117007 | 9 days ago | IN | 0 GLMR | 0.074011 | ||||
| Claim Incentive | 14108954 | 9 days ago | IN | 0 GLMR | 0.073953 | ||||
| Claim Incentive | 14108680 | 9 days ago | IN | 0 GLMR | 0.073953 | ||||
| Claim Incentive | 14108677 | 9 days ago | IN | 0 GLMR | 0.0725105 | ||||
| Claim Incentive | 14079991 | 12 days ago | IN | 0 GLMR | 0.0725105 | ||||
| Claim Incentive | 14079989 | 12 days ago | IN | 0 GLMR | 0.073953 | ||||
| Claim Incentive | 14031267 | 15 days ago | IN | 0 GLMR | 0.03955079 | ||||
| Claim Incentive | 14031265 | 15 days ago | IN | 0 GLMR | 0.04047414 | ||||
| Claim Incentive | 14031262 | 15 days ago | IN | 0 GLMR | 0.04686683 | ||||
| Claim Incentive | 14031258 | 15 days ago | IN | 0 GLMR | 0.03916174 | ||||
| Claim Incentive | 14009988 | 17 days ago | IN | 0 GLMR | 0.073895 | ||||
| Claim Incentive | 14009985 | 17 days ago | IN | 0 GLMR | 0.0724525 | ||||
| Claim Incentive | 14001683 | 18 days ago | IN | 0 GLMR | 0.0443757 | ||||
| Claim Incentive | 14001682 | 18 days ago | IN | 0 GLMR | 0.04533014 | ||||
| Claim Incentive | 13971282 | 20 days ago | IN | 0 GLMR | 0.073911 | ||||
| Claim Incentive | 13971276 | 20 days ago | IN | 0 GLMR | 0.0689305 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14219277 | 24 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14218914 | 25 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR | ||||
| 14213834 | 35 hrs ago | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Incentive
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/**
*Submitted for verification at moonbeam.moonscan.io on 2023-05-26
*/
// SPDX-License-Identifier: BSD-3-Clause
// File: contracts/Orbiter/ExponentialNoError.sol
pragma solidity ^0.8.10;
/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
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;
}
/**
* @dev Truncates the given exp to a whole number value.
* For example, truncate(Exp{mantissa: 15 * expScale}) = 15
*/
function truncate(Exp memory exp) pure internal returns (uint) {
// Note: We are not using careful math here as we're performing a division that cannot fail
return exp.mantissa / expScale;
}
/**
* @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.
*/
function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {
Exp memory product = mul_(a, scalar);
return truncate(product);
}
/**
* @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.
*/
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);
}
/**
* @dev Checks if first Exp is less than second Exp.
*/
function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa < right.mantissa;
}
/**
* @dev Checks if left Exp <= right Exp.
*/
function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa <= right.mantissa;
}
/**
* @dev Checks if left Exp > right Exp.
*/
function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {
return left.mantissa > right.mantissa;
}
/**
* @dev returns true if Exp is exactly zero
*/
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 a + b;
}
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 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 a * b;
}
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 a / b;
}
function fraction(uint a, uint b) pure internal returns (Double memory) {
return Double({mantissa: div_(mul_(a, doubleScale), b)});
}
}
// File: contracts/Orbiter/ErrorReporter.sol
pragma solidity ^0.8.10;
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, // no longer possible
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,
SET_INCENTIVE_OWNER_CHECK
}
/**
* @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary
* contract-specific code that enables us to report opaque error codes from upgradeable contracts.
**/
event Failure(uint error, uint info, uint detail);
/**
* @dev use this when reporting a known error from the money market or a non-upgradeable collaborator
*/
function fail(Error err, FailureInfo info) internal returns (uint) {
emit Failure(uint(err), uint(info), 0);
return uint(err);
}
/**
* @dev use this when reporting an opaque error from an upgradeable collaborator contract
*/
function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {
emit Failure(uint(err), uint(info), opaqueError);
return uint(err);
}
}
contract TokenErrorReporter {
uint public constant NO_ERROR = 0; // support legacy return codes
error TransferComptrollerRejection(uint256 errorCode);
error TransferNotAllowed();
error TransferNotEnough();
error TransferTooMuch();
error MintComptrollerRejection(uint256 errorCode);
error MintFreshnessCheck();
error MintMinimumLiquid();
error RedeemComptrollerRejection(uint256 errorCode);
error RedeemFreshnessCheck();
error RedeemTransferOutNotPossible();
error BorrowComptrollerRejection(uint256 errorCode);
error BorrowFreshnessCheck();
error BorrowCashNotAvailable();
error RepayBorrowComptrollerRejection(uint256 errorCode);
error RepayBorrowFreshnessCheck();
error LiquidateComptrollerRejection(uint256 errorCode);
error LiquidateFreshnessCheck();
error LiquidateCollateralFreshnessCheck();
error LiquidateAccrueBorrowInterestFailed(uint256 errorCode);
error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);
error LiquidateLiquidatorIsBorrower();
error LiquidateCloseAmountIsZero();
error LiquidateCloseAmountIsUintMax();
error LiquidateRepayBorrowFreshFailed(uint256 errorCode);
error LiquidateSeizeComptrollerRejection(uint256 errorCode);
error LiquidateSeizeLiquidatorIsBorrower();
error AcceptAdminPendingAdminCheck();
error SetComptrollerOwnerCheck();
error SetPendingAdminOwnerCheck();
error SetReserveFactorAdminCheck();
error SetReserveFactorFreshCheck();
error SetReserveFactorBoundsCheck();
error AddReservesFactorFreshCheck(uint256 actualAddAmount);
error ReduceReservesAdminCheck();
error ReduceReservesFreshCheck();
error ReduceReservesCashNotAvailable();
error ReduceReservesCashValidation();
error SetInterestRateModelOwnerCheck();
error SetInterestRateModelFreshCheck();
}
// File: contracts/Orbiter/EIP20NonStandardInterface.sol
pragma solidity ^0.8.10;
/**
* @title EIP20NonStandardInterface
* @dev Version of ERC20 with no return values for `transfer` and `transferFrom`
* See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/
interface EIP20NonStandardInterface {
/**
* @notice Get the total number of tokens in circulation
* @return The supply of tokens
*/
function totalSupply() external view returns (uint256);
/**
* @notice Gets the balance of the specified address
* @param owner The address from which the balance will be retrieved
* @return balance The balance
*/
function balanceOf(address owner) external view returns (uint256 balance);
///
/// !!!!!!!!!!!!!!
/// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification
/// !!!!!!!!!!!!!!
///
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
*/
function transfer(address dst, uint256 amount) external;
///
/// !!!!!!!!!!!!!!
/// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification
/// !!!!!!!!!!!!!!
///
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
*/
function transferFrom(address src, address dst, uint256 amount) external;
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved
* @return success Whether or not the approval succeeded
*/
function approve(address spender, uint256 amount) external returns (bool success);
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return remaining The number of tokens allowed to be spent
*/
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);
}
// File: contracts/Orbiter/InterestRateModel.sol
pragma solidity ^0.8.10;
/**
* @title Compound's InterestRateModel Interface
* @author Compound
*/
abstract contract InterestRateModel {
/// @notice Indicator that this is an InterestRateModel contract (for inspection)
bool public constant isInterestRateModel = true;
/**
* @notice Calculates the current borrow interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @return The borrow rate per block (as a percentage, and scaled by 1e18)
*/
function getBorrowRate(uint cash, uint borrows, uint reserves) virtual external view returns (uint);
/**
* @notice Calculates the current supply interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @param reserveFactorMantissa The current reserve factor the market has
* @return The supply rate per block (as a percentage, and scaled by 1e18)
*/
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual external view returns (uint);
}
// File: contracts/Orbiter/ComptrollerInterface.sol
pragma solidity ^0.8.10;
abstract contract ComptrollerInterface {
/// @notice Indicator that this is a Comptroller contract (for inspection)
bool public constant isComptroller = true;
/*** Assets You Are In ***/
function enterMarkets(address[] calldata cTokens) virtual external returns (uint[] memory);
function exitMarket(address cToken) virtual external returns (uint);
/*** Policy Hooks ***/
function mintAllowed(address cToken, address minter, uint mintAmount) virtual external returns (uint);
function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) virtual external;
function redeemAllowed(address cToken, address redeemer, uint redeemTokens) virtual external returns (uint);
function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) virtual external;
function borrowAllowed(address cToken, address borrower, uint borrowAmount) virtual external returns (uint);
function borrowVerify(address cToken, address borrower, uint borrowAmount) virtual external;
function repayBorrowAllowed(
address cToken,
address payer,
address borrower,
uint repayAmount) virtual external returns (uint);
function repayBorrowVerify(
address cToken,
address payer,
address borrower,
uint repayAmount,
uint borrowerIndex) virtual external;
function liquidateBorrowAllowed(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint repayAmount) virtual external returns (uint);
function liquidateBorrowVerify(
address cTokenBorrowed,
address cTokenCollateral,
address liquidator,
address borrower,
uint repayAmount,
uint seizeTokens) virtual external;
function seizeAllowed(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint seizeTokens) virtual external returns (uint);
function seizeVerify(
address cTokenCollateral,
address cTokenBorrowed,
address liquidator,
address borrower,
uint seizeTokens) virtual external;
function transferAllowed(address cToken, address src, address dst, uint transferTokens) virtual external returns (uint);
function transferVerify(address cToken, address src, address dst, uint transferTokens) virtual external;
/*** Liquidity/Liquidation Calculations ***/
function liquidateCalculateSeizeTokens(
address cTokenBorrowed,
address cTokenCollateral,
uint repayAmount) virtual external view returns (uint, uint);
}
// File: contracts/Orbiter/CTokenInterfaces.sol
pragma solidity ^0.8.10;
contract CTokenStorage {
/**
* @dev Guard variable for re-entrancy checks
*/
bool internal _notEntered;
/**
* @notice EIP-20 token name for this token
*/
string public name;
/**
* @notice EIP-20 token symbol for this token
*/
string public symbol;
/**
* @notice EIP-20 token decimals for this token
*/
uint8 public decimals;
// Maximum borrow rate that can ever be applied (.0005% / block)
uint internal constant borrowRateMaxMantissa = 0.0005e16;
// Maximum fraction of interest that can be set aside for reserves
uint internal constant reserveFactorMaxMantissa = 1e18;
uint public constant MINIMUM_LIQUIDITY = 1e8;
address internal constant DEAD_ADDRESS =
0x000000000000000000000000000000000000dEaD;
/**
* @notice Administrator for this contract
*/
address payable public admin;
/**
* @notice Pending administrator for this contract
*/
address payable public pendingAdmin;
/**
* @notice Contract which oversees inter-cToken operations
*/
ComptrollerInterface public comptroller;
/**
* @notice Model which tells what the current interest rate should be
*/
InterestRateModel public interestRateModel;
// Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)
uint internal initialExchangeRateMantissa;
/**
* @notice Fraction of interest currently set aside for reserves
*/
uint public reserveFactorMantissa;
/**
* @notice Block number that interest was last accrued at
*/
uint public accrualBlockNumber;
/**
* @notice Accumulator of the total earned interest rate since the opening of the market
*/
uint public borrowIndex;
/**
* @notice Total amount of outstanding borrows of the underlying in this market
*/
uint public totalBorrows;
/**
* @notice Total amount of reserves of the underlying held in this market
*/
uint public totalReserves;
/**
* @notice Total number of tokens in circulation
*/
uint public totalSupply;
// Official record of token balances for each account
mapping (address => uint) internal accountTokens;
// Approved token transfer amounts on behalf of others
mapping (address => mapping (address => uint)) internal transferAllowances;
/**
* @notice Container for borrow balance information
* @member principal Total balance (with accrued interest), after applying the most recent balance-changing action
* @member interestIndex Global borrowIndex as of the most recent balance-changing action
*/
struct BorrowSnapshot {
uint principal;
uint interestIndex;
}
// Mapping of account addresses to outstanding borrow balances
mapping(address => BorrowSnapshot) internal accountBorrows;
/**
* @notice Share of seized collateral that is added to reserves
*/
uint public constant protocolSeizeShareMantissa = 2.8e16; //2.8%
}
abstract contract CTokenInterface is CTokenStorage {
/**
* @notice Indicator that this is a CToken contract (for inspection)
*/
bool public constant isCToken = true;
/*** Market Events ***/
/**
* @notice Event emitted when interest is accrued
*/
event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);
/**
* @notice Event emitted when tokens are minted
*/
event Mint(address minter, uint mintAmount, uint mintTokens);
/**
* @notice Event emitted when tokens are redeemed
*/
event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);
/**
* @notice Event emitted when underlying is borrowed
*/
event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);
/**
* @notice Event emitted when a borrow is repaid
*/
event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);
/**
* @notice Event emitted when a borrow is liquidated
*/
event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);
/*** Admin Events ***/
/**
* @notice Event emitted when pendingAdmin is changed
*/
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Event emitted when pendingAdmin is accepted, which means admin is updated
*/
event NewAdmin(address oldAdmin, address newAdmin);
/**
* @notice Event emitted when comptroller is changed
*/
event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);
/**
* @notice Event emitted when interestRateModel is changed
*/
event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);
/**
* @notice Event emitted when the reserve factor is changed
*/
event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);
/**
* @notice Event emitted when the reserves are added
*/
event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);
/**
* @notice Event emitted when the reserves are reduced
*/
event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);
/**
* @notice EIP20 Transfer event
*/
event Transfer(address indexed from, address indexed to, uint amount);
/**
* @notice EIP20 Approval event
*/
event Approval(address indexed owner, address indexed spender, uint amount);
/*** User Interface ***/
function transfer(address dst, uint amount) virtual external returns (bool);
function transferFrom(address src, address dst, uint amount) virtual external returns (bool);
function approve(address spender, uint amount) virtual external returns (bool);
function allowance(address owner, address spender) virtual external view returns (uint);
function balanceOf(address owner) virtual external view returns (uint);
function balanceOfUnderlying(address owner) virtual external returns (uint);
function getAccountSnapshot(address account) virtual external view returns (uint, uint, uint, uint);
function borrowRatePerBlock() virtual external view returns (uint);
function supplyRatePerBlock() virtual external view returns (uint);
function totalBorrowsCurrent() virtual external returns (uint);
function borrowBalanceCurrent(address account) virtual external returns (uint);
function borrowBalanceStored(address account) virtual external view returns (uint);
function exchangeRateCurrent() virtual external returns (uint);
function exchangeRateStored() virtual external view returns (uint);
function getCash() virtual external view returns (uint);
function accrueInterest() virtual external returns (uint);
function seize(address liquidator, address borrower, uint seizeTokens) virtual external returns (uint);
/*** Admin Functions ***/
function _setPendingAdmin(address payable newPendingAdmin) virtual external returns (uint);
function _acceptAdmin() virtual external returns (uint);
function _setComptroller(ComptrollerInterface newComptroller) virtual external returns (uint);
function _setReserveFactor(uint newReserveFactorMantissa) virtual external returns (uint);
function _reduceReserves(uint reduceAmount) virtual external returns (uint);
function _setInterestRateModel(InterestRateModel newInterestRateModel) virtual external returns (uint);
}
contract CErc20Storage {
/**
* @notice Underlying asset for this CToken
*/
address public underlying;
}
abstract contract CErc20Interface is CErc20Storage {
/*** User Interface ***/
function mint(uint mintAmount) virtual external returns (uint);
function redeem(uint redeemTokens) virtual external returns (uint);
function redeemUnderlying(uint redeemAmount) virtual external returns (uint);
function borrow(uint borrowAmount) virtual external returns (uint);
function repayBorrow(uint repayAmount) virtual external returns (uint);
function repayBorrowBehalf(address borrower, uint repayAmount) virtual external returns (uint);
function liquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) virtual external returns (uint);
function sweepToken(EIP20NonStandardInterface token) virtual external;
/*** Admin Functions ***/
function _addReserves(uint addAmount) virtual external returns (uint);
}
contract CDelegationStorage {
/**
* @notice Implementation address for this contract
*/
address public implementation;
}
abstract contract CDelegatorInterface is CDelegationStorage {
/**
* @notice Emitted when implementation is changed
*/
event NewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Called by the admin to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
* @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
* @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
*/
function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) virtual external;
}
abstract contract CDelegateInterface is CDelegationStorage {
/**
* @notice Called by the delegator on a delegate to initialize it for duty
* @dev Should revert if any issues arise which make it unfit for delegation
* @param data The encoded bytes data for any initialization
*/
function _becomeImplementation(bytes memory data) virtual external;
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/
function _resignImplementation() virtual external;
}
// File: contracts/Orbiter/EIP20Interface.sol
pragma solidity ^0.8.10;
/**
* @title ERC 20 Token Standard Interface
* https://eips.ethereum.org/EIPS/eip-20
*/
interface EIP20Interface {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
/**
* @notice Get the total number of tokens in circulation
* @return The supply of tokens
*/
function totalSupply() external view returns (uint256);
/**
* @notice Gets the balance of the specified address
* @param owner The address from which the balance will be retrieved
* @return balance The balance
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return success Whether or not the transfer succeeded
*/
function transfer(address dst, uint256 amount) external returns (bool success);
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return success Whether or not the transfer succeeded
*/
function transferFrom(address src, address dst, uint256 amount) external returns (bool success);
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (-1 means infinite)
* @return success Whether or not the approval succeeded
*/
function approve(address spender, uint256 amount) external returns (bool success);
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return remaining The number of tokens allowed to be spent (-1 means infinite)
*/
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);
}
// File: contracts/Orbiter/CToken.sol
pragma solidity 0.8.10;
/**
* @title Compound's CToken Contract
* @notice Abstract base for CTokens
* @author Compound
*/
abstract contract CToken is
CTokenInterface,
ExponentialNoError,
TokenErrorReporter
{
/**
* @notice Initialize the money market
* @param comptroller_ The address of the Comptroller
* @param interestRateModel_ The address of the interest rate model
* @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18
* @param name_ EIP-20 name of this token
* @param symbol_ EIP-20 symbol of this token
* @param decimals_ EIP-20 decimal precision of this token
*/
function initialize(
ComptrollerInterface comptroller_,
InterestRateModel interestRateModel_,
uint256 initialExchangeRateMantissa_,
string memory name_,
string memory symbol_,
uint8 decimals_
) public {
require(msg.sender == admin, "only admin may initialize the market");
require(
accrualBlockNumber == 0 && borrowIndex == 0,
"market may only be initialized once"
);
// Set initial exchange rate
initialExchangeRateMantissa = initialExchangeRateMantissa_;
require(
initialExchangeRateMantissa > 0,
"initial exchange rate must be greater than zero."
);
// Set the comptroller
uint256 err = _setComptroller(comptroller_);
require(err == NO_ERROR, "setting comptroller failed");
// Initialize block number and borrow index (block number mocks depend on comptroller being set)
accrualBlockNumber = getBlockNumber();
borrowIndex = mantissaOne;
// Set the interest rate model (depends on block number / borrow index)
err = _setInterestRateModelFresh(interestRateModel_);
require(err == NO_ERROR, "setting interest rate model failed");
name = name_;
symbol = symbol_;
decimals = decimals_;
// The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)
_notEntered = true;
}
/**
* @notice Transfer `tokens` tokens from `src` to `dst` by `spender`
* @dev Called by both `transfer` and `transferFrom` internally
* @param spender The address of the account performing the transfer
* @param src The address of the source account
* @param dst The address of the destination account
* @param tokens The number of tokens to transfer
* @return 0 if the transfer succeeded, else revert
*/
function transferTokens(
address spender,
address src,
address dst,
uint256 tokens
) internal returns (uint256) {
/* Fail if transfer not allowed */
uint256 allowed = comptroller.transferAllowed(
address(this),
src,
dst,
tokens
);
if (allowed != 0) {
revert TransferComptrollerRejection(allowed);
}
/* Do not allow self-transfers */
if (src == dst) {
revert TransferNotAllowed();
}
/* Get the allowance, infinite for the account owner */
uint256 startingAllowance = 0;
if (spender == src) {
startingAllowance = type(uint256).max;
} else {
startingAllowance = transferAllowances[src][spender];
}
/* Do the calculations, checking for {under,over}flow */
uint256 allowanceNew = startingAllowance - tokens;
uint256 srcTokensNew = accountTokens[src] - tokens;
uint256 dstTokensNew = accountTokens[dst] + tokens;
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
accountTokens[src] = srcTokensNew;
accountTokens[dst] = dstTokensNew;
/* Eat some of the allowance (if necessary) */
if (startingAllowance != type(uint256).max) {
transferAllowances[src][spender] = allowanceNew;
}
/* We emit a Transfer event */
emit Transfer(src, dst, tokens);
// unused function
// comptroller.transferVerify(address(this), src, dst, tokens);
return NO_ERROR;
}
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transfer(
address dst,
uint256 amount
) external override nonReentrant returns (bool) {
return transferTokens(msg.sender, msg.sender, dst, amount) == NO_ERROR;
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transferFrom(
address src,
address dst,
uint256 amount
) external override nonReentrant returns (bool) {
return transferTokens(msg.sender, src, dst, amount) == NO_ERROR;
}
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (uint256.max means infinite)
* @return Whether or not the approval succeeded
*/
function approve(
address spender,
uint256 amount
) external override returns (bool) {
address src = msg.sender;
transferAllowances[src][spender] = amount;
emit Approval(src, spender, amount);
return true;
}
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return The number of tokens allowed to be spent (-1 means infinite)
*/
function allowance(
address owner,
address spender
) external view override returns (uint256) {
return transferAllowances[owner][spender];
}
/**
* @notice Get the token balance of the `owner`
* @param owner The address of the account to query
* @return The number of tokens owned by `owner`
*/
function balanceOf(address owner) external view override returns (uint256) {
return accountTokens[owner];
}
/**
* @notice Get the underlying balance of the `owner`
* @dev This also accrues interest in a transaction
* @param owner The address of the account to query
* @return The amount of underlying owned by `owner`
*/
function balanceOfUnderlying(
address owner
) external override returns (uint256) {
Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});
return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);
}
/**
* @notice Get a snapshot of the account's balances, and the cached exchange rate
* @dev This is used by comptroller to more efficiently perform liquidity checks.
* @param account Address of the account to snapshot
* @return (possible error, token balance, borrow balance, exchange rate mantissa)
*/
function getAccountSnapshot(
address account
) external view override returns (uint256, uint256, uint256, uint256) {
return (
NO_ERROR,
accountTokens[account],
borrowBalanceStoredInternal(account),
exchangeRateStoredInternal()
);
}
/**
* @dev Function to simply retrieve block number
* This exists mainly for inheriting test contracts to stub this result.
*/
function getBlockNumber() internal view virtual returns (uint256) {
return block.number;
}
/**
* @notice Returns the current per-block borrow interest rate for this cToken
* @return The borrow interest rate per block, scaled by 1e18
*/
function borrowRatePerBlock() external view override returns (uint256) {
return
interestRateModel.getBorrowRate(
getCashPrior(),
totalBorrows,
totalReserves
);
}
/**
* @notice Returns the current per-block supply interest rate for this cToken
* @return The supply interest rate per block, scaled by 1e18
*/
function supplyRatePerBlock() external view override returns (uint256) {
return
interestRateModel.getSupplyRate(
getCashPrior(),
totalBorrows,
totalReserves,
reserveFactorMantissa
);
}
/**
* @notice Returns the current total borrows plus accrued interest
* @return The total borrows with interest
*/
function totalBorrowsCurrent()
external
override
nonReentrant
returns (uint256)
{
accrueInterest();
return totalBorrows;
}
/**
* @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex
* @param account The address whose balance should be calculated after updating borrowIndex
* @return The calculated balance
*/
function borrowBalanceCurrent(
address account
) external override nonReentrant returns (uint256) {
accrueInterest();
return borrowBalanceStored(account);
}
/**
* @notice Return the borrow balance of account based on stored data
* @param account The address whose balance should be calculated
* @return The calculated balance
*/
function borrowBalanceStored(
address account
) public view override returns (uint256) {
return borrowBalanceStoredInternal(account);
}
/**
* @notice Return the borrow balance of account based on stored data
* @param account The address whose balance should be calculated
* @return (error code, the calculated balance or 0 if error code is non-zero)
*/
function borrowBalanceStoredInternal(
address account
) internal view returns (uint256) {
/* Get borrowBalance and borrowIndex */
BorrowSnapshot storage borrowSnapshot = accountBorrows[account];
/* If borrowBalance = 0 then borrowIndex is likely also 0.
* Rather than failing the calculation with a division by 0, we immediately return 0 in this case.
*/
if (borrowSnapshot.principal == 0) {
return 0;
}
/* Calculate new borrow balance using the interest index:
* recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex
*/
uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;
return principalTimesIndex / borrowSnapshot.interestIndex;
}
/**
* @notice Accrue interest then return the up-to-date exchange rate
* @return Calculated exchange rate scaled by 1e18
*/
function exchangeRateCurrent()
public
override
nonReentrant
returns (uint256)
{
accrueInterest();
return exchangeRateStored();
}
/**
* @notice Calculates the exchange rate from the underlying to the CToken
* @dev This function does not accrue interest before calculating the exchange rate
* @return Calculated exchange rate scaled by 1e18
*/
function exchangeRateStored() public view override returns (uint256) {
return exchangeRateStoredInternal();
}
/**
* @notice Calculates the exchange rate from the underlying to the CToken
* @dev This function does not accrue interest before calculating the exchange rate
* @return calculated exchange rate scaled by 1e18
*/
function exchangeRateStoredInternal()
internal
view
virtual
returns (uint256)
{
uint256 _totalSupply = totalSupply;
if (_totalSupply == 0) {
/*
* If there are no tokens minted:
* exchangeRate = initialExchangeRate
*/
return initialExchangeRateMantissa;
} else {
/*
* Otherwise:
* exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply
*/
uint256 totalCash = getCashPrior();
uint256 cashPlusBorrowsMinusReserves = totalCash +
totalBorrows -
totalReserves;
uint256 exchangeRate = (cashPlusBorrowsMinusReserves * expScale) /
_totalSupply;
return exchangeRate;
}
}
/**
* @notice Get cash balance of this cToken in the underlying asset
* @return The quantity of underlying asset owned by this contract
*/
function getCash() external view override returns (uint256) {
return getCashPrior();
}
/**
* @notice Applies accrued interest to total borrows and reserves
* @dev This calculates interest accrued from the last checkpointed block
* up to the current block and writes new checkpoint to storage.
*/
function accrueInterest() public virtual override returns (uint256) {
/* Remember the initial block number */
uint256 currentBlockNumber = getBlockNumber();
uint256 accrualBlockNumberPrior = accrualBlockNumber;
/* Short-circuit accumulating 0 interest */
if (accrualBlockNumberPrior == currentBlockNumber) {
return NO_ERROR;
}
/* Read the previous values out of storage */
uint256 cashPrior = getCashPrior();
uint256 borrowsPrior = totalBorrows;
uint256 reservesPrior = totalReserves;
uint256 borrowIndexPrior = borrowIndex;
/* Calculate the current borrow interest rate */
uint256 borrowRateMantissa = interestRateModel.getBorrowRate(
cashPrior,
borrowsPrior,
reservesPrior
);
require(
borrowRateMantissa <= borrowRateMaxMantissa,
"borrow rate is absurdly high"
);
/* Calculate the number of blocks elapsed since the last accrual */
uint256 blockDelta = currentBlockNumber - accrualBlockNumberPrior;
/*
* Calculate the interest accumulated into borrows and reserves and the new index:
* simpleInterestFactor = borrowRate * blockDelta
* interestAccumulated = simpleInterestFactor * totalBorrows
* totalBorrowsNew = interestAccumulated + totalBorrows
* totalReservesNew = interestAccumulated * reserveFactor + totalReserves
* borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex
*/
Exp memory simpleInterestFactor = mul_(
Exp({mantissa: borrowRateMantissa}),
blockDelta
);
uint256 interestAccumulated = mul_ScalarTruncate(
simpleInterestFactor,
borrowsPrior
);
uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;
uint256 totalReservesNew = mul_ScalarTruncateAddUInt(
Exp({mantissa: reserveFactorMantissa}),
interestAccumulated,
reservesPrior
);
uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(
simpleInterestFactor,
borrowIndexPrior,
borrowIndexPrior
);
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We write the previously calculated values into storage */
accrualBlockNumber = currentBlockNumber;
borrowIndex = borrowIndexNew;
totalBorrows = totalBorrowsNew;
totalReserves = totalReservesNew;
/* We emit an AccrueInterest event */
emit AccrueInterest(
cashPrior,
interestAccumulated,
borrowIndexNew,
totalBorrowsNew
);
return NO_ERROR;
}
/**
* @notice Sender supplies assets into the market and receives cTokens in exchange
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param mintAmount The amount of the underlying asset to supply
*/
function mintInternal(uint256 mintAmount) internal nonReentrant {
accrueInterest();
// mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to
mintFresh(msg.sender, mintAmount);
}
/**
* @notice User supplies assets into the market and receives cTokens in exchange
* @dev Assumes interest has already been accrued up to the current block
* @param minter The address of the account which is supplying the assets
* @param mintAmount The amount of the underlying asset to supply
*/
function mintFresh(address minter, uint256 mintAmount) internal {
/* Fail if mint not allowed */
uint256 allowed = comptroller.mintAllowed(
address(this),
minter,
mintAmount
);
if (allowed != 0) {
revert MintComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert MintFreshnessCheck();
}
Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});
uint256 mintTokensTemp = div_(mintAmount, exchangeRate);
uint256 _totalSupply = totalSupply;
if (_totalSupply == 0) {
totalSupply = totalSupply + MINIMUM_LIQUIDITY;
accountTokens[DEAD_ADDRESS] = MINIMUM_LIQUIDITY;
if (MINIMUM_LIQUIDITY > mintTokensTemp) {
revert MintMinimumLiquid();
}
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We call `doTransferIn` for the minter and the mintAmount.
* Note: The cToken must handle variations between ERC-20 and ETH underlying.
* `doTransferIn` reverts if anything goes wrong, since we can't be sure if
* side-effects occurred. The function returns the amount actually transferred,
* in case of a fee. On success, the cToken holds an additional `actualMintAmount`
* of cash.
*/
uint256 actualMintAmount = doTransferIn(minter, mintAmount);
/*
* We get the current exchange rate and calculate the number of cTokens to be minted:
* mintTokens = actualMintAmount / exchangeRate
*/
uint256 mintTokens = div_(actualMintAmount, exchangeRate);
if (_totalSupply == 0) {
mintTokens = mintTokens - MINIMUM_LIQUIDITY;
}
/*
* We calculate the new total supply of cTokens and minter token balance, checking for overflow:
* totalSupplyNew = totalSupply + mintTokens
* accountTokensNew = accountTokens[minter] + mintTokens
* And write them into storage
*/
totalSupply = totalSupply + mintTokens;
accountTokens[minter] = accountTokens[minter] + mintTokens;
/* We emit a Mint event, and a Transfer event */
emit Mint(minter, actualMintAmount, mintTokens);
emit Transfer(address(this), minter, mintTokens);
/* We call the defense hook */
// unused function
// comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);
}
/**
* @notice Sender redeems cTokens in exchange for the underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemTokens The number of cTokens to redeem into underlying
*/
function redeemInternal(uint256 redeemTokens) internal nonReentrant {
accrueInterest();
// redeemFresh emits redeem-specific logs on errors, so we don't need to
redeemFresh(payable(msg.sender), redeemTokens, 0);
}
/**
* @notice Sender redeems cTokens in exchange for a specified amount of underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemAmount The amount of underlying to receive from redeeming cTokens
*/
function redeemUnderlyingInternal(
uint256 redeemAmount
) internal nonReentrant {
accrueInterest();
// redeemFresh emits redeem-specific logs on errors, so we don't need to
redeemFresh(payable(msg.sender), 0, redeemAmount);
}
/**
* @notice User redeems cTokens in exchange for the underlying asset
* @dev Assumes interest has already been accrued up to the current block
* @param redeemer The address of the account which is redeeming the tokens
* @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)
* @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)
*/
function redeemFresh(
address payable redeemer,
uint256 redeemTokensIn,
uint256 redeemAmountIn
) internal {
require(
redeemTokensIn == 0 || redeemAmountIn == 0,
"one of redeemTokensIn or redeemAmountIn must be zero"
);
/* exchangeRate = invoke Exchange Rate Stored() */
Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});
uint256 redeemTokens;
uint256 redeemAmount;
/* If redeemTokensIn > 0: */
if (redeemTokensIn > 0) {
/*
* We calculate the exchange rate and the amount of underlying to be redeemed:
* redeemTokens = redeemTokensIn
* redeemAmount = redeemTokensIn x exchangeRateCurrent
*/
redeemTokens = redeemTokensIn;
redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokensIn);
} else {
/*
* We get the current exchange rate and calculate the amount to be redeemed:
* redeemTokens = redeemAmountIn / exchangeRate
* redeemAmount = redeemAmountIn
*/
redeemTokens = div_(redeemAmountIn, exchangeRate);
redeemAmount = redeemAmountIn;
}
/* Fail if redeem not allowed */
uint256 allowed = comptroller.redeemAllowed(
address(this),
redeemer,
redeemTokens
);
if (allowed != 0) {
revert RedeemComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert RedeemFreshnessCheck();
}
/* Fail gracefully if protocol has insufficient cash */
if (getCashPrior() < redeemAmount) {
revert RedeemTransferOutNotPossible();
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We write the previously calculated values into storage.
* Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.
*/
totalSupply = totalSupply - redeemTokens;
accountTokens[redeemer] = accountTokens[redeemer] - redeemTokens;
/*
* We invoke doTransferOut for the redeemer and the redeemAmount.
* Note: The cToken must handle variations between ERC-20 and ETH underlying.
* On success, the cToken has redeemAmount less of cash.
* doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.
*/
doTransferOut(redeemer, redeemAmount);
/* We emit a Transfer event, and a Redeem event */
emit Transfer(redeemer, address(this), redeemTokens);
emit Redeem(redeemer, redeemAmount, redeemTokens);
/* We call the defense hook */
comptroller.redeemVerify(
address(this),
redeemer,
redeemAmount,
redeemTokens
);
}
/**
* @notice Sender borrows assets from the protocol to their own address
* @param borrowAmount The amount of the underlying asset to borrow
*/
function borrowInternal(uint256 borrowAmount) internal nonReentrant {
accrueInterest();
// borrowFresh emits borrow-specific logs on errors, so we don't need to
borrowFresh(payable(msg.sender), borrowAmount);
}
/**
* @notice Users borrow assets from the protocol to their own address
* @param borrowAmount The amount of the underlying asset to borrow
*/
function borrowFresh(
address payable borrower,
uint256 borrowAmount
) internal {
/* Fail if borrow not allowed */
uint256 allowed = comptroller.borrowAllowed(
address(this),
borrower,
borrowAmount
);
if (allowed != 0) {
revert BorrowComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert BorrowFreshnessCheck();
}
/* Fail gracefully if protocol has insufficient underlying cash */
if (getCashPrior() < borrowAmount) {
revert BorrowCashNotAvailable();
}
/*
* We calculate the new borrower and total borrow balances, failing on overflow:
* accountBorrowNew = accountBorrow + borrowAmount
* totalBorrowsNew = totalBorrows + borrowAmount
*/
uint256 accountBorrowsPrev = borrowBalanceStoredInternal(borrower);
uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;
uint256 totalBorrowsNew = totalBorrows + borrowAmount;
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We write the previously calculated values into storage.
* Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.
`*/
accountBorrows[borrower].principal = accountBorrowsNew;
accountBorrows[borrower].interestIndex = borrowIndex;
totalBorrows = totalBorrowsNew;
/*
* We invoke doTransferOut for the borrower and the borrowAmount.
* Note: The cToken must handle variations between ERC-20 and ETH underlying.
* On success, the cToken borrowAmount less of cash.
* doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.
*/
doTransferOut(borrower, borrowAmount);
/* We emit a Borrow event */
emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);
}
/**
* @notice Sender repays their own borrow
* @param repayAmount The amount to repay, or -1 for the full outstanding amount
*/
function repayBorrowInternal(uint256 repayAmount) internal nonReentrant {
accrueInterest();
// repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to
repayBorrowFresh(msg.sender, msg.sender, repayAmount);
}
/**
* @notice Sender repays a borrow belonging to borrower
* @param borrower the account with the debt being payed off
* @param repayAmount The amount to repay, or -1 for the full outstanding amount
*/
function repayBorrowBehalfInternal(
address borrower,
uint256 repayAmount
) internal nonReentrant {
accrueInterest();
// repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to
repayBorrowFresh(msg.sender, borrower, repayAmount);
}
/**
* @notice Borrows are repaid by another user (possibly the borrower).
* @param payer the account paying off the borrow
* @param borrower the account with the debt being payed off
* @param repayAmount the amount of underlying tokens being returned, or -1 for the full outstanding amount
* @return (uint) the actual repayment amount.
*/
function repayBorrowFresh(
address payer,
address borrower,
uint256 repayAmount
) internal returns (uint256) {
/* Fail if repayBorrow not allowed */
uint256 allowed = comptroller.repayBorrowAllowed(
address(this),
payer,
borrower,
repayAmount
);
if (allowed != 0) {
revert RepayBorrowComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert RepayBorrowFreshnessCheck();
}
/* We fetch the amount the borrower owes, with accumulated interest */
uint256 accountBorrowsPrev = borrowBalanceStoredInternal(borrower);
/* If repayAmount == -1, repayAmount = accountBorrows */
uint256 repayAmountFinal = repayAmount == type(uint256).max
? accountBorrowsPrev
: repayAmount;
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We call doTransferIn for the payer and the repayAmount
* Note: The cToken must handle variations between ERC-20 and ETH underlying.
* On success, the cToken holds an additional repayAmount of cash.
* doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.
* it returns the amount actually transferred, in case of a fee.
*/
uint256 actualRepayAmount = doTransferIn(payer, repayAmountFinal);
/*
* We calculate the new borrower and total borrow balances, failing on underflow:
* accountBorrowsNew = accountBorrows - actualRepayAmount
* totalBorrowsNew = totalBorrows - actualRepayAmount
*/
uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;
uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;
/* We write the previously calculated values into storage */
accountBorrows[borrower].principal = accountBorrowsNew;
accountBorrows[borrower].interestIndex = borrowIndex;
totalBorrows = totalBorrowsNew;
/* We emit a RepayBorrow event */
emit RepayBorrow(
payer,
borrower,
actualRepayAmount,
accountBorrowsNew,
totalBorrowsNew
);
return actualRepayAmount;
}
/**
* @notice The sender liquidates the borrowers collateral.
* The collateral seized is transferred to the liquidator.
* @param borrower The borrower of this cToken to be liquidated
* @param cTokenCollateral The market in which to seize collateral from the borrower
* @param repayAmount The amount of the underlying borrowed asset to repay
*/
function liquidateBorrowInternal(
address borrower,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) internal nonReentrant {
accrueInterest();
uint256 error = cTokenCollateral.accrueInterest();
if (error != NO_ERROR) {
// accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed
revert LiquidateAccrueCollateralInterestFailed(error);
}
// liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to
liquidateBorrowFresh(
msg.sender,
borrower,
repayAmount,
cTokenCollateral
);
}
/**
* @notice The liquidator liquidates the borrowers collateral.
* The collateral seized is transferred to the liquidator.
* @param borrower The borrower of this cToken to be liquidated
* @param liquidator The address repaying the borrow and seizing collateral
* @param cTokenCollateral The market in which to seize collateral from the borrower
* @param repayAmount The amount of the underlying borrowed asset to repay
*/
function liquidateBorrowFresh(
address liquidator,
address borrower,
uint256 repayAmount,
CTokenInterface cTokenCollateral
) internal {
/* Fail if liquidate not allowed */
uint256 allowed = comptroller.liquidateBorrowAllowed(
address(this),
address(cTokenCollateral),
liquidator,
borrower,
repayAmount
);
if (allowed != 0) {
revert LiquidateComptrollerRejection(allowed);
}
/* Verify market's block number equals current block number */
if (accrualBlockNumber != getBlockNumber()) {
revert LiquidateFreshnessCheck();
}
/* Verify cTokenCollateral market's block number equals current block number */
if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {
revert LiquidateCollateralFreshnessCheck();
}
/* Fail if borrower = liquidator */
if (borrower == liquidator) {
revert LiquidateLiquidatorIsBorrower();
}
/* Fail if repayAmount = 0 */
if (repayAmount == 0) {
revert LiquidateCloseAmountIsZero();
}
/* Fail if repayAmount = -1 */
if (repayAmount == type(uint256).max) {
revert LiquidateCloseAmountIsUintMax();
}
/* Fail if repayBorrow fails */
uint256 actualRepayAmount = repayBorrowFresh(
liquidator,
borrower,
repayAmount
);
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We calculate the number of collateral tokens that will be seized */
(uint256 amountSeizeError, uint256 seizeTokens) = comptroller
.liquidateCalculateSeizeTokens(
address(this),
address(cTokenCollateral),
actualRepayAmount
);
require(
amountSeizeError == NO_ERROR,
"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED"
);
/* Revert if borrower collateral token balance < seizeTokens */
require(
cTokenCollateral.balanceOf(borrower) >= seizeTokens,
"LIQUIDATE_SEIZE_TOO_MUCH"
);
// If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call
if (address(cTokenCollateral) == address(this)) {
seizeInternal(address(this), liquidator, borrower, seizeTokens);
} else {
require(
cTokenCollateral.seize(liquidator, borrower, seizeTokens) ==
NO_ERROR,
"token seizure failed"
);
}
/* We emit a LiquidateBorrow event */
emit LiquidateBorrow(
liquidator,
borrower,
actualRepayAmount,
address(cTokenCollateral),
seizeTokens
);
}
/**
* @notice Transfers collateral tokens (this market) to the liquidator.
* @dev Will fail unless called by another cToken during the process of liquidation.
* Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.
* @param liquidator The account receiving seized collateral
* @param borrower The account having collateral seized
* @param seizeTokens The number of cTokens to seize
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function seize(
address liquidator,
address borrower,
uint256 seizeTokens
) external override nonReentrant returns (uint256) {
seizeInternal(msg.sender, liquidator, borrower, seizeTokens);
return NO_ERROR;
}
/**
* @notice Transfers collateral tokens (this market) to the liquidator.
* @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another CToken.
* Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.
* @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)
* @param liquidator The account receiving seized collateral
* @param borrower The account having collateral seized
* @param seizeTokens The number of cTokens to seize
*/
function seizeInternal(
address seizerToken,
address liquidator,
address borrower,
uint256 seizeTokens
) internal {
/* Fail if seize not allowed */
uint256 allowed = comptroller.seizeAllowed(
address(this),
seizerToken,
liquidator,
borrower,
seizeTokens
);
if (allowed != 0) {
revert LiquidateSeizeComptrollerRejection(allowed);
}
/* Fail if borrower = liquidator */
if (borrower == liquidator) {
revert LiquidateSeizeLiquidatorIsBorrower();
}
/*
* We calculate the new borrower and liquidator token balances, failing on underflow/overflow:
* borrowerTokensNew = accountTokens[borrower] - seizeTokens
* liquidatorTokensNew = accountTokens[liquidator] + seizeTokens
*/
uint256 protocolSeizeTokens = mul_(
seizeTokens,
Exp({mantissa: protocolSeizeShareMantissa})
);
uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;
Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});
uint256 protocolSeizeAmount = mul_ScalarTruncate(
exchangeRate,
protocolSeizeTokens
);
uint256 totalReservesNew = totalReserves + protocolSeizeAmount;
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/* We write the calculated values into storage */
totalReserves = totalReservesNew;
totalSupply = totalSupply - protocolSeizeTokens;
accountTokens[borrower] = accountTokens[borrower] - seizeTokens;
accountTokens[liquidator] =
accountTokens[liquidator] +
liquidatorSeizeTokens;
/* Emit a Transfer event */
emit Transfer(borrower, liquidator, liquidatorSeizeTokens);
emit Transfer(borrower, address(this), protocolSeizeTokens);
emit ReservesAdded(
address(this),
protocolSeizeAmount,
totalReservesNew
);
}
/*** Admin Functions ***/
/**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setPendingAdmin(
address payable newPendingAdmin
) external override returns (uint256) {
// Check caller = admin
if (msg.sender != admin) {
revert SetPendingAdminOwnerCheck();
}
// Save current value, if any, for inclusion in log
address oldPendingAdmin = pendingAdmin;
// Store pendingAdmin with value newPendingAdmin
pendingAdmin = newPendingAdmin;
// Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
return NO_ERROR;
}
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _acceptAdmin() external override returns (uint256) {
// Check caller is pendingAdmin and pendingAdmin ≠ address(0)
if (msg.sender != pendingAdmin || msg.sender == address(0)) {
revert AcceptAdminPendingAdminCheck();
}
// Save current values for inclusion in log
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
// Store admin with value pendingAdmin
admin = pendingAdmin;
// Clear the pending value
pendingAdmin = payable(address(0));
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
return NO_ERROR;
}
/**
* @notice Sets a new comptroller for the market
* @dev Admin function to set a new comptroller
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setComptroller(
ComptrollerInterface newComptroller
) public override returns (uint256) {
// Check caller is admin
if (msg.sender != admin) {
revert SetComptrollerOwnerCheck();
}
ComptrollerInterface oldComptroller = comptroller;
// Ensure invoke comptroller.isComptroller() returns true
require(newComptroller.isComptroller(), "marker method returned false");
// Set market's comptroller to newComptroller
comptroller = newComptroller;
// Emit NewComptroller(oldComptroller, newComptroller)
emit NewComptroller(oldComptroller, newComptroller);
return NO_ERROR;
}
/**
* @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh
* @dev Admin function to accrue interest and set a new reserve factor
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setReserveFactor(
uint256 newReserveFactorMantissa
) external override nonReentrant returns (uint256) {
accrueInterest();
// _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.
return _setReserveFactorFresh(newReserveFactorMantissa);
}
/**
* @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)
* @dev Admin function to set a new reserve factor
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setReserveFactorFresh(
uint256 newReserveFactorMantissa
) internal returns (uint256) {
// Check caller is admin
if (msg.sender != admin) {
revert SetReserveFactorAdminCheck();
}
// Verify market's block number equals current block number
if (accrualBlockNumber != getBlockNumber()) {
revert SetReserveFactorFreshCheck();
}
// Check newReserveFactor ≤ maxReserveFactor
if (newReserveFactorMantissa > reserveFactorMaxMantissa) {
revert SetReserveFactorBoundsCheck();
}
uint256 oldReserveFactorMantissa = reserveFactorMantissa;
reserveFactorMantissa = newReserveFactorMantissa;
emit NewReserveFactor(
oldReserveFactorMantissa,
newReserveFactorMantissa
);
return NO_ERROR;
}
/**
* @notice Accrues interest and reduces reserves by transferring from msg.sender
* @param addAmount Amount of addition to reserves
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _addReservesInternal(
uint256 addAmount
) internal nonReentrant returns (uint256) {
accrueInterest();
// _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.
_addReservesFresh(addAmount);
return NO_ERROR;
}
/**
* @notice Add reserves by transferring from caller
* @dev Requires fresh interest accrual
* @param addAmount Amount of addition to reserves
* @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees
*/
function _addReservesFresh(
uint256 addAmount
) internal returns (uint256, uint256) {
// totalReserves + actualAddAmount
uint256 totalReservesNew;
uint256 actualAddAmount;
// We fail gracefully unless market's block number equals current block number
if (accrualBlockNumber != getBlockNumber()) {
revert AddReservesFactorFreshCheck(actualAddAmount);
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
/*
* We call doTransferIn for the caller and the addAmount
* Note: The cToken must handle variations between ERC-20 and ETH underlying.
* On success, the cToken holds an additional addAmount of cash.
* doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.
* it returns the amount actually transferred, in case of a fee.
*/
actualAddAmount = doTransferIn(msg.sender, addAmount);
totalReservesNew = totalReserves + actualAddAmount;
// Store reserves[n+1] = reserves[n] + actualAddAmount
totalReserves = totalReservesNew;
/* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */
emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);
/* Return (NO_ERROR, actualAddAmount) */
return (NO_ERROR, actualAddAmount);
}
/**
* @notice Accrues interest and reduces reserves by transferring to admin
* @param reduceAmount Amount of reduction to reserves
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _reduceReserves(
uint256 reduceAmount
) external override nonReentrant returns (uint256) {
accrueInterest();
// _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.
return _reduceReservesFresh(reduceAmount);
}
/**
* @notice Reduces reserves by transferring to admin
* @dev Requires fresh interest accrual
* @param reduceAmount Amount of reduction to reserves
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _reduceReservesFresh(
uint256 reduceAmount
) internal returns (uint256) {
// totalReserves - reduceAmount
uint256 totalReservesNew;
// Check caller is admin
if (msg.sender != admin) {
revert ReduceReservesAdminCheck();
}
// We fail gracefully unless market's block number equals current block number
if (accrualBlockNumber != getBlockNumber()) {
revert ReduceReservesFreshCheck();
}
// Fail gracefully if protocol has insufficient underlying cash
if (getCashPrior() < reduceAmount) {
revert ReduceReservesCashNotAvailable();
}
// Check reduceAmount ≤ reserves[n] (totalReserves)
if (reduceAmount > totalReserves) {
revert ReduceReservesCashValidation();
}
/////////////////////////
// EFFECTS & INTERACTIONS
// (No safe failures beyond this point)
totalReservesNew = totalReserves - reduceAmount;
// Store reserves[n+1] = reserves[n] - reduceAmount
totalReserves = totalReservesNew;
// doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.
doTransferOut(admin, reduceAmount);
emit ReservesReduced(admin, reduceAmount, totalReservesNew);
return NO_ERROR;
}
/**
* @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh
* @dev Admin function to accrue interest and update the interest rate model
* @param newInterestRateModel the new interest rate model to use
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setInterestRateModel(
InterestRateModel newInterestRateModel
) public override returns (uint256) {
accrueInterest();
// _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.
return _setInterestRateModelFresh(newInterestRateModel);
}
/**
* @notice updates the interest rate model (*requires fresh interest accrual)
* @dev Admin function to update the interest rate model
* @param newInterestRateModel the new interest rate model to use
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setInterestRateModelFresh(
InterestRateModel newInterestRateModel
) internal returns (uint256) {
// Used to store old model for use in the event that is emitted on success
InterestRateModel oldInterestRateModel;
// Check caller is admin
if (msg.sender != admin) {
revert SetInterestRateModelOwnerCheck();
}
// We fail gracefully unless market's block number equals current block number
if (accrualBlockNumber != getBlockNumber()) {
revert SetInterestRateModelFreshCheck();
}
// Track the market's current interest rate model
oldInterestRateModel = interestRateModel;
// Ensure invoke newInterestRateModel.isInterestRateModel() returns true
require(
newInterestRateModel.isInterestRateModel(),
"marker method returned false"
);
// Set the interest rate model to newInterestRateModel
interestRateModel = newInterestRateModel;
// Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)
emit NewMarketInterestRateModel(
oldInterestRateModel,
newInterestRateModel
);
return NO_ERROR;
}
/*** Safe Token ***/
/**
* @notice Gets balance of this contract in terms of the underlying
* @dev This excludes the value of the current message, if any
* @return The quantity of underlying owned by this contract
*/
function getCashPrior() internal view virtual returns (uint256);
/**
* @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.
* This may revert due to insufficient balance or insufficient allowance.
*/
function doTransferIn(
address from,
uint256 amount
) internal virtual returns (uint256);
/**
* @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.
* If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.
* If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.
*/
function doTransferOut(address payable to, uint256 amount) internal virtual;
/*** Reentrancy Guard ***/
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant() {
require(_notEntered, "re-entered");
_notEntered = false;
_;
_notEntered = true; // get a gas-refund post-Istanbul
}
}
// File: @openzeppelin/contracts/utils/Context.sol
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: contracts/Orbiter/Incentive.sol
pragma solidity 0.8.10;
abstract contract IComp {
struct Market {
// Whether or not this market is listed
bool isListed;
// Multiplier representing the most one can borrow against their collateral in this market.
// For instance, 0.9 to allow borrowing 90% of collateral value.
// Must be between 0 and 1, and stored as a mantissa.
uint256 collateralFactorMantissa;
// Per-market mapping of "accounts in this asset"
mapping(address => bool) accountMembership;
// Whether or not this market receives COMP
bool isComped;
}
bool public constant isComptroller = true;
mapping(address => Market) public markets;
function getAllMarkets() public view virtual returns (CToken[] memory);
function getAccountLiquidity(
address account
) public view virtual returns (uint256, uint256, uint256);
function checkMembership(
address account,
CToken cToken
) external view virtual returns (bool);
}
contract Incentive is Ownable, ExponentialNoError {
IComp public comptroller;
struct RewardMarketState {
uint224 index;
uint32 block;
}
event DistributedSupplierReward(
address indexed incentive,
CToken indexed cToken,
address indexed supplier,
uint256 delta,
uint256 supplyIndex
);
event DistributedBorrowerReward(
address indexed incentive,
CToken indexed cToken,
address indexed borrower,
uint256 delta,
uint256 borrowIndex
);
event RewardGranted(address incentive, address recipient, uint256 amount);
uint224 public constant rewardInitialIndex = 1e36;
address[] public supportIncentive;
mapping(address => bool) public isExcludedReward;
mapping(address => mapping(address => uint)) public supplyRewardSpeeds;
mapping(address => mapping(address => uint)) public borrowRewardSpeeds;
mapping(address => mapping(address => RewardMarketState))
public rewardSupplyState;
mapping(address => mapping(address => RewardMarketState))
public rewardBorrowState;
mapping(address => mapping(address => mapping(address => uint)))
public rewardSupplierIndex;
mapping(address => mapping(address => mapping(address => uint)))
public rewardBorrowerIndex;
mapping(address => mapping(address => uint)) public rewardAccrued;
modifier isComptroller(address _comptroller) {
require(
IComp(_comptroller).isComptroller() == true,
"Incentive::constructor: contract is not comptroller"
);
_;
}
modifier isSupportIncentive(address _incentiveAsset) {
bool findInventive = false;
for (uint256 i = 0; i < supportIncentive.length; i++) {
if (supportIncentive[i] == _incentiveAsset) {
findInventive = true;
break;
}
}
require(findInventive, "Incentive asset is not supported");
_;
}
modifier isNotSupportIncentive(address _incentiveAsset) {
bool findInventive = false;
for (uint256 i = 0; i < supportIncentive.length; i++) {
if (supportIncentive[i] == _incentiveAsset) {
findInventive = true;
break;
}
}
require(!findInventive, "Incentive asset already support");
_;
}
modifier isExcludeAccountReward(address _account) {
require(
!isExcludedReward[_account],
"Incentive::distribute: account excludes reward"
);
_;
}
constructor(address _comptroller) isComptroller(_comptroller) {
comptroller = IComp(_comptroller);
}
function getBlockNumber() public view virtual returns (uint256) {
return block.number;
}
function getAllSupportIncentives() public view returns (address[] memory) {
return supportIncentive;
}
function setComptroller(
address _comptroller
) external onlyOwner isComptroller(_comptroller) {
comptroller = IComp(_comptroller);
}
function excludeAccountReward(
address _account,
bool _flag
) external onlyOwner {
isExcludedReward[_account] = _flag;
}
function supportIncentiveAsset(
address _asset
) external onlyOwner isNotSupportIncentive(_asset) {
EIP20Interface(_asset).totalSupply();
supportIncentive.push(_asset);
}
function deleteIncentive(uint _index) external onlyOwner {
supportIncentive[_index] = supportIncentive[
supportIncentive.length - 1
];
supportIncentive.pop();
}
function setRewardSpeed(
address _incentiveAsset,
CToken _cToken,
uint256 _supplyRewardSpeed,
uint256 _borrowRewardSpeed
) public isSupportIncentive(_incentiveAsset) onlyOwner {
setRewardSpeedInternal(
_incentiveAsset,
_cToken,
_supplyRewardSpeed,
_borrowRewardSpeed
);
}
function setRewardSpeedInternal(
address incentiveAsset,
CToken cToken,
uint256 supplySpeed,
uint256 borrowSpeed
) internal {
(bool isListed, , ) = comptroller.markets(address(cToken));
require(isListed, "market is not listed");
if (
supplyRewardSpeeds[incentiveAsset][address(cToken)] != supplySpeed
) {
updateRewardSupplyIndex(incentiveAsset, address(cToken));
supplyRewardSpeeds[incentiveAsset][address(cToken)] = supplySpeed;
}
if (
borrowRewardSpeeds[incentiveAsset][address(cToken)] != borrowSpeed
) {
Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});
updateRewardBorrowIndex(
incentiveAsset,
address(cToken),
borrowIndex
);
borrowRewardSpeeds[incentiveAsset][address(cToken)] = borrowSpeed;
}
}
function updateRewardSupplyIndex(
address incentiveAsset,
address cToken
) internal {
RewardMarketState storage supplyState = rewardSupplyState[
incentiveAsset
][cToken];
uint256 supplySpeed = supplyRewardSpeeds[incentiveAsset][cToken];
uint32 blockNumber = safe32(
getBlockNumber(),
"block number exceeds 32 bits"
);
uint256 deltaBlocks = sub_(
uint256(blockNumber),
uint256(supplyState.block)
);
if (deltaBlocks > 0 && supplySpeed > 0) {
uint256 supplyTokens = CToken(cToken).totalSupply();
uint256 assetAccrued = mul_(deltaBlocks, supplySpeed);
Double memory ratio = supplyTokens > 0
? fraction(assetAccrued, supplyTokens)
: Double({mantissa: 0});
supplyState.index = safe224(
add_(Double({mantissa: supplyState.index}), ratio).mantissa,
"new index exceeds 224 bits"
);
supplyState.block = blockNumber;
} else if (deltaBlocks > 0) {
supplyState.block = blockNumber;
}
}
function updateRewardBorrowIndex(
address incentiveAsset,
address cToken,
Exp memory marketBorrowIndex
) internal {
RewardMarketState storage borrowState = rewardBorrowState[
incentiveAsset
][cToken];
uint256 borrowSpeed = borrowRewardSpeeds[incentiveAsset][cToken];
uint32 blockNumber = safe32(
getBlockNumber(),
"block number exceeds 32 bits"
);
uint256 deltaBlocks = sub_(
uint256(blockNumber),
uint256(borrowState.block)
);
if (deltaBlocks > 0 && borrowSpeed > 0) {
uint256 borrowAmount = div_(
CToken(cToken).totalBorrows(),
marketBorrowIndex
);
uint256 assetAccrued = mul_(deltaBlocks, borrowSpeed);
Double memory ratio = borrowAmount > 0
? fraction(assetAccrued, borrowAmount)
: Double({mantissa: 0});
borrowState.index = safe224(
add_(Double({mantissa: borrowState.index}), ratio).mantissa,
"new index exceeds 224 bits"
);
borrowState.block = blockNumber;
} else if (deltaBlocks > 0) {
borrowState.block = blockNumber;
}
}
function distributeSupplierReward(
address incentive,
address cToken,
address supplier
) internal {
RewardMarketState storage supplyState = rewardSupplyState[incentive][
cToken
];
uint256 supplyIndex = supplyState.index;
uint256 supplierIndex = rewardSupplierIndex[incentive][cToken][
supplier
];
rewardSupplierIndex[incentive][cToken][supplier] = supplyIndex;
if (supplierIndex == 0 && supplyIndex >= rewardInitialIndex) {
supplierIndex = rewardInitialIndex;
}
Double memory deltaIndex = Double({
mantissa: sub_(supplyIndex, supplierIndex)
});
uint256 supplierTokens = CToken(cToken).balanceOf(supplier);
uint256 supplierDelta = mul_(supplierTokens, deltaIndex);
uint256 supplierAccrued = add_(
rewardAccrued[incentive][supplier],
supplierDelta
);
rewardAccrued[incentive][supplier] = supplierAccrued;
emit DistributedSupplierReward(
incentive,
CToken(cToken),
supplier,
supplierDelta,
supplyIndex
);
}
function distributeBorrowerReward(
address incentive,
address cToken,
address borrower,
Exp memory marketBorrowIndex
) internal {
RewardMarketState storage borrowState = rewardBorrowState[incentive][
cToken
];
uint256 borrowIndex = borrowState.index;
uint256 borrowerIndex = rewardBorrowerIndex[incentive][cToken][
borrower
];
rewardBorrowerIndex[incentive][cToken][borrower] = borrowIndex;
if (borrowerIndex == 0 && borrowIndex >= rewardInitialIndex) {
borrowerIndex = rewardInitialIndex;
}
Double memory deltaIndex = Double({
mantissa: sub_(borrowIndex, borrowerIndex)
});
uint256 borrowerAmount = div_(
CToken(cToken).borrowBalanceStored(borrower),
marketBorrowIndex
);
uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);
uint256 borrowerAccrued = add_(
rewardAccrued[incentive][borrower],
borrowerDelta
);
rewardAccrued[incentive][borrower] = borrowerAccrued;
emit DistributedBorrowerReward(
incentive,
CToken(cToken),
borrower,
borrowerDelta,
borrowIndex
);
}
function distributeSupplier(address cToken, address supplier) external {
for (uint256 i = 0; i < supportIncentive.length; i++) {
updateRewardSupplyIndex(supportIncentive[i], cToken);
if (isExcludedReward[supplier] == false) {
distributeSupplierReward(supportIncentive[i], cToken, supplier);
}
}
}
function distributeBorrower(address cToken, address borrower) external {
Exp memory borrowIndex = Exp({mantissa: CToken(cToken).borrowIndex()});
for (uint256 i = 0; i < supportIncentive.length; i++) {
updateRewardBorrowIndex(supportIncentive[i], cToken, borrowIndex);
if (isExcludedReward[borrower] == false) {
distributeBorrowerReward(
supportIncentive[i],
cToken,
borrower,
borrowIndex
);
}
}
}
function claimIncentive(
address incentive,
address holder
) public isSupportIncentive(incentive) isExcludeAccountReward(holder) {
return claimIncentive(incentive, holder, comptroller.getAllMarkets());
}
function claimIncentive(
address incentive,
address holder,
CToken[] memory cTokens
) public isSupportIncentive(incentive) isExcludeAccountReward(holder) {
address[] memory holders = new address[](1);
holders[0] = holder;
claimIncentive(incentive, holders, cTokens, true, true);
}
function claimIncentive(
address incentive,
address[] memory holders,
CToken[] memory cTokens,
bool borrowers,
bool suppliers
) public isSupportIncentive(incentive) {
for (uint256 j = 0; j < holders.length; j++) {
require(
!isExcludedReward[holders[j]],
"Incentive::distributeSupplier: supplier excludes reward"
);
}
for (uint256 i = 0; i < cTokens.length; i++) {
CToken cToken = cTokens[i];
(bool isListed, , ) = comptroller.markets(address(cToken));
require(isListed, "market must be listed");
if (borrowers == true) {
Exp memory borrowIndex = Exp({mantissa: cToken.borrowIndex()});
updateRewardBorrowIndex(
incentive,
address(cToken),
borrowIndex
);
for (uint256 j = 0; j < holders.length; j++) {
distributeBorrowerReward(
incentive,
address(cToken),
holders[j],
borrowIndex
);
}
}
if (suppliers == true) {
updateRewardSupplyIndex(incentive, address(cToken));
for (uint256 j = 0; j < holders.length; j++) {
distributeSupplierReward(
incentive,
address(cToken),
holders[j]
);
}
}
}
for (uint256 j = 0; j < holders.length; j++) {
rewardAccrued[incentive][holders[j]] = grantRewardInternal(
incentive,
holders[j],
rewardAccrued[incentive][holders[j]]
);
}
}
function grantRewardInternal(
address incentive,
address user,
uint256 amount
) internal returns (uint256) {
EIP20Interface asset = EIP20Interface(incentive);
uint256 rewardRemaining = asset.balanceOf(address(this));
if (amount > 0 && amount <= rewardRemaining) {
asset.transfer(user, amount);
return 0;
}
return amount;
}
function _grantReward(
address incentive,
address recipient,
uint256 amount
) public onlyOwner {
uint256 amountLeft = grantRewardInternal(incentive, recipient, amount);
require(amountLeft == 0, "insufficient incentive for grant");
emit RewardGranted(incentive, recipient, amount);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_comptroller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"incentive","type":"address"},{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"delta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowIndex","type":"uint256"}],"name":"DistributedBorrowerReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"incentive","type":"address"},{"indexed":true,"internalType":"contract CToken","name":"cToken","type":"address"},{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":false,"internalType":"uint256","name":"delta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supplyIndex","type":"uint256"}],"name":"DistributedSupplierReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"incentive","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardGranted","type":"event"},{"inputs":[{"internalType":"address","name":"incentive","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"_grantReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"borrowRewardSpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"incentive","type":"address"},{"internalType":"address","name":"holder","type":"address"}],"name":"claimIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"incentive","type":"address"},{"internalType":"address[]","name":"holders","type":"address[]"},{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"},{"internalType":"bool","name":"borrowers","type":"bool"},{"internalType":"bool","name":"suppliers","type":"bool"}],"name":"claimIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"incentive","type":"address"},{"internalType":"address","name":"holder","type":"address"},{"internalType":"contract CToken[]","name":"cTokens","type":"address[]"}],"name":"claimIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"comptroller","outputs":[{"internalType":"contract IComp","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"deleteIncentive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"borrower","type":"address"}],"name":"distributeBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"address","name":"supplier","type":"address"}],"name":"distributeSupplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"excludeAccountReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllSupportIncentives","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isExcludedReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewardAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewardBorrowState","outputs":[{"internalType":"uint224","name":"index","type":"uint224"},{"internalType":"uint32","name":"block","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewardBorrowerIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardInitialIndex","outputs":[{"internalType":"uint224","name":"","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewardSupplierIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewardSupplyState","outputs":[{"internalType":"uint224","name":"index","type":"uint224"},{"internalType":"uint32","name":"block","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_comptroller","type":"address"}],"name":"setComptroller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incentiveAsset","type":"address"},{"internalType":"contract CToken","name":"_cToken","type":"address"},{"internalType":"uint256","name":"_supplyRewardSpeed","type":"uint256"},{"internalType":"uint256","name":"_borrowRewardSpeed","type":"uint256"}],"name":"setRewardSpeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"supplyRewardSpeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportIncentive","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"supportIncentiveAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200297638038062002976833981016040819052620000349162000197565b6200003f3362000147565b80806001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200007e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a49190620001c9565b1515600114620001205760405162461bcd60e51b815260206004820152603360248201527f496e63656e746976653a3a636f6e7374727563746f723a20636f6e747261637460448201527f206973206e6f7420636f6d7074726f6c6c657200000000000000000000000000606482015260840160405180910390fd5b50600180546001600160a01b0319166001600160a01b0392909216919091179055620001ed565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620001aa57600080fd5b81516001600160a01b0381168114620001c257600080fd5b9392505050565b600060208284031215620001dc57600080fd5b81518015158114620001c257600080fd5b61277980620001fd6000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c8063773907de116100f9578063c47d603611610097578063cdcf0bf911610071578063cdcf0bf914610472578063e5029dc81461049d578063f2fde38b146104e0578063f9d8d849146104f357600080fd5b8063c47d603614610439578063c73200f11461044c578063c8be1e851461045f57600080fd5b80638bad38dd116100d35780638bad38dd146103ef5780638da5cb5b146104025780639ad0a42d146104135780639c223ace1461042657600080fd5b8063773907de1461039657806388088483146103a9578063882f1ba4146103bc57600080fd5b80633f22ddea116101665780635fe3b567116101405780635fe3b5671461030557806360777a4f1461033057806366f91a2414610361578063715018a61461038e57600080fd5b80633f22ddea146102d957806342cbb15c146102ec5780635d5bfe18146102f257600080fd5b80630bda5be1146101ae5780631ad964ed146101ec578063246467e81461021d57806327ee5210146102325780633068172d14610247578063317d2abc14610272575b600080fd5b6101d96101bc36600461204e565b600a60209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101d96101fa366004612087565b600860209081526000938452604080852082529284528284209052825290205481565b61023061022b3660046120d2565b610506565b005b61023a6105e7565b6040516101e39190612113565b6101d961025536600461204e565b600560209081526000928352604080842090915290825290205481565b6102b561028036600461204e565b60066020908152600092835260408084209091529082529020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016101e3565b6102306102e736600461204e565b610649565b436101d9565b61023061030036600461204e565b6106f0565b600154610318906001600160a01b031681565b6040516001600160a01b0390911681526020016101e3565b6101d961033e366004612087565b600960209081526000938452604080852082529284528284209052825290205481565b6103766a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016101e3565b610230610832565b6102306103a4366004612160565b610868565b6102306103b736600461217d565b6109fb565b6103df6103ca366004612160565b60036020526000908152604090205460ff1681565b60405190151581526020016101e3565b6102306103fd366004612160565b610ab9565b6000546001600160a01b0316610318565b6102306104213660046121e1565b610bd5565b6102306104343660046122ee565b610c2a565b61023061044736600461204e565b6110a8565b61031861045a3660046123e6565b6111c5565b61023061046d3660046123ff565b6111ef565b6101d961048036600461204e565b600460209081526000928352604080842090915290825290205481565b6102b56104ab36600461204e565b60076020908152600092835260408084209091529082529020546001600160e01b03811690600160e01b900463ffffffff1682565b6102306104ee366004612160565b611317565b6102306105013660046123e6565b6113b2565b6000546001600160a01b031633146105395760405162461bcd60e51b815260040161053090612461565b60405180910390fd5b600061054684848461148c565b905080156105965760405162461bcd60e51b815260206004820181905260248201527f696e73756666696369656e7420696e63656e7469766520666f72206772616e746044820152606401610530565b604080516001600160a01b038087168252851660208201529081018390527f6123969dd9705ebe9fca0229b85009158c92cae456c32d917d8d435748f3abd39060600160405180910390a150505050565b6060600280548060200260200160405190810160405280929190818152602001828054801561063f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610621575b5050505050905090565b60005b6002548110156106eb576106876002828154811061066c5761066c612496565b6000918252602090912001546001600160a01b03168461159e565b6001600160a01b03821660009081526003602052604090205460ff166106d9576106d9600282815481106106bd576106bd612496565b6000918252602090912001546001600160a01b031684846117a1565b806106e3816124c2565b91505061064c565b505050565b816000805b60025481101561075257826001600160a01b03166002828154811061071c5761071c612496565b6000918252602090912001546001600160a01b031614156107405760019150610752565b8061074a816124c2565b9150506106f5565b50806107705760405162461bcd60e51b8152600401610530906124dd565b6001600160a01b038316600090815260036020526040902054839060ff16156107ab5760405162461bcd60e51b815260040161053090612512565b61082b8585600160009054906101000a90046001600160a01b03166001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610803573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261046d9190810190612560565b5050505050565b6000546001600160a01b0316331461085c5760405162461bcd60e51b815260040161053090612461565b6108666000611971565b565b6000546001600160a01b031633146108925760405162461bcd60e51b815260040161053090612461565b806000805b6002548110156108f457826001600160a01b0316600282815481106108be576108be612496565b6000918252602090912001546001600160a01b031614156108e257600191506108f4565b806108ec816124c2565b915050610897565b5080156109435760405162461bcd60e51b815260206004820152601f60248201527f496e63656e7469766520617373657420616c726561647920737570706f7274006044820152606401610530565b826001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a591906125fa565b5050600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b03939093169290921790915550565b836000805b600254811015610a5d57826001600160a01b031660028281548110610a2757610a27612496565b6000918252602090912001546001600160a01b03161415610a4b5760019150610a5d565b80610a55816124c2565b915050610a00565b5080610a7b5760405162461bcd60e51b8152600401610530906124dd565b6000546001600160a01b03163314610aa55760405162461bcd60e51b815260040161053090612461565b610ab1868686866119c1565b505050505050565b6000546001600160a01b03163314610ae35760405162461bcd60e51b815260040161053090612461565b80806001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b459190612613565b1515600114610bb25760405162461bcd60e51b815260206004820152603360248201527f496e63656e746976653a3a636f6e7374727563746f723a20636f6e74726163746044820152721034b9903737ba1031b7b6b83a3937b63632b960691b6064820152608401610530565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610bff5760405162461bcd60e51b815260040161053090612461565b6001600160a01b03919091166000908152600360205260409020805460ff1916911515919091179055565b846000805b600254811015610c8c57826001600160a01b031660028281548110610c5657610c56612496565b6000918252602090912001546001600160a01b03161415610c7a5760019150610c8c565b80610c84816124c2565b915050610c2f565b5080610caa5760405162461bcd60e51b8152600401610530906124dd565b60005b8651811015610d785760036000888381518110610ccc57610ccc612496565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615610d665760405162461bcd60e51b815260206004820152603760248201527f496e63656e746976653a3a64697374726962757465537570706c6965723a207360448201527f7570706c696572206578636c75646573207265776172640000000000000000006064820152608401610530565b80610d70816124c2565b915050610cad565b5060005b8551811015610f9e576000868281518110610d9957610d99612496565b6020908102919091010151600154604051638e8f294b60e01b81526001600160a01b03808416600483015292935060009290911690638e8f294b90602401606060405180830381865afa158015610df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e189190612630565b5050905080610e615760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b6044820152606401610530565b60018715151415610f305760006040518060200160405280846001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb91906125fa565b90529050610eea8b8483611bb1565b60005b8a51811015610f2d57610f1b8c858d8481518110610f0d57610f0d612496565b602002602001015185611d4d565b80610f25816124c2565b915050610eed565b50505b60018615151415610f8957610f458a8361159e565b60005b8951811015610f8757610f758b848c8481518110610f6857610f68612496565b60200260200101516117a1565b80610f7f816124c2565b915050610f48565b505b50508080610f96906124c2565b915050610d7c565b5060005b865181101561109e5761103088888381518110610fc157610fc1612496565b6020026020010151600a60008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b868151811061100257611002612496565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205461148c565b6001600160a01b0389166000908152600a6020526040812089519091908a908590811061105f5761105f612496565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080611096906124c2565b915050610fa2565b5050505050505050565b60006040518060200160405280846001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111791906125fa565b9052905060005b6002548110156111bf5761115a6002828154811061113e5761113e612496565b6000918252602090912001546001600160a01b03168584611bb1565b6001600160a01b03831660009081526003602052604090205460ff166111ad576111ad6002828154811061119057611190612496565b6000918252602090912001546001600160a01b0316858585611d4d565b806111b7816124c2565b91505061111e565b50505050565b600281815481106111d557600080fd5b6000918252602090912001546001600160a01b0316905081565b826000805b60025481101561125157826001600160a01b03166002828154811061121b5761121b612496565b6000918252602090912001546001600160a01b0316141561123f5760019150611251565b80611249816124c2565b9150506111f4565b508061126f5760405162461bcd60e51b8152600401610530906124dd565b6001600160a01b038416600090815260036020526040902054849060ff16156112aa5760405162461bcd60e51b815260040161053090612512565b6040805160018082528183019092526000916020808301908036833701905050905085816000815181106112e0576112e0612496565b60200260200101906001600160a01b031690816001600160a01b03168152505061130e878287600180610c2a565b50505050505050565b6000546001600160a01b031633146113415760405162461bcd60e51b815260040161053090612461565b6001600160a01b0381166113a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610530565b6113af81611971565b50565b6000546001600160a01b031633146113dc5760405162461bcd60e51b815260040161053090612461565b600280546113ec90600190612668565b815481106113fc576113fc612496565b600091825260209091200154600280546001600160a01b03909216918390811061142857611428612496565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060028054806114675761146761267f565b600082815260209020810160001990810180546001600160a01b031916905501905550565b6040516370a0823160e01b8152306004820152600090849082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156114d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fb91906125fa565b905060008411801561150d5750808411155b156115915760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af1158015611561573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115859190612613565b50600092505050611597565b83925050505b9392505050565b6001600160a01b0382811660008181526006602090815260408083209486168084529482528083209383526004825280832094835293905291822054909161161c435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250611eff565b835490915060009061163e9063ffffffff80851691600160e01b900416611f2f565b90506000811180156116505750600083115b15611776576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611695573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b991906125fa565b905060006116c78386611f3b565b905060008083116116e757604051806020016040528060008152506116f1565b6116f18284611f47565b604080516020810190915288546001600160e01b031681529091506117549061171a9083611f8b565b5160408051808201909152601a81527f6e657720696e64657820657863656564732032323420626974730000000000006020820152611fb7565b6001600160e01b0316600160e01b63ffffffff87160217875550610ab1915050565b8015610ab157835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b038381166000818152600660209081526040808320878616808552908352818420805495855260088452828520918552908352818420958716845294909152902080546001600160e01b0390921690819055908015801561181757506a0c097ce7bc90715b34b9f160241b8210155b1561182d57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806118448585611f2f565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa158015611892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b691906125fa565b905060006118c48284611fde565b6001600160a01b03808b166000908152600a60209081526040808320938c16835292905290812054919250906118fa9083612007565b6001600160a01b038b81166000818152600a602090815260408083208e86168085529083529281902086905580518881529182018c90529495509093928d16927fb747d7740fe7478f458c4b26b4c599bf7ca13bc8724401bec9aae61f61a0ac28910160405180910390a450505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600154604051638e8f294b60e01b81526001600160a01b0385811660048301526000921690638e8f294b90602401606060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a309190612630565b5050905080611a785760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610530565b6001600160a01b038086166000908152600460209081526040808320938816835292905220548314611ad757611aae858561159e565b6001600160a01b0380861660009081526004602090815260408083209388168352929052208390555b6001600160a01b03808616600090815260056020908152604080832093881683529290522054821461082b5760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7291906125fa565b90529050611b81868683611bb1565b506001600160a01b0380861660009081526005602090815260408083209388168352929052208290555050505050565b6001600160a01b03838116600081815260076020908152604080832094871680845294825280832093835260058252808320948352939052918220549091611bf8436115e1565b8354909150600090611c1a9063ffffffff80851691600160e01b900416611f2f565b9050600081118015611c2c5750600083115b15611d21576000611c9e876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9891906125fa565b87612013565b90506000611cac8386611f3b565b90506000808311611ccc5760405180602001604052806000815250611cd6565b611cd68284611f47565b604080516020810190915288546001600160e01b03168152909150611cff9061171a9083611f8b565b6001600160e01b0316600160e01b63ffffffff8716021787555061130e915050565b801561130e57835463ffffffff8316600160e01b026001600160e01b0390911617845550505050505050565b6001600160a01b038481166000818152600760209081526040808320888616808552908352818420805495855260098452828520918552908352818420958816845294909152902080546001600160e01b03909216908190559080158015611dc357506a0c097ce7bc90715b34b9f160241b8210155b15611dd957506a0c097ce7bc90715b34b9f160241b5b60006040518060200160405280611df08585611f2f565b90526040516395dd919360e01b81526001600160a01b038881166004830152919250600091611e4391908a16906395dd919390602401602060405180830381865afa158015611c74573d6000803e3d6000fd5b90506000611e518284611fde565b6001600160a01b03808c166000908152600a60209081526040808320938d1683529290529081205491925090611e879083612007565b6001600160a01b038c81166000818152600a602090815260408083208f86168085529083529281902086905580518881529182018c90529495509093928e16927f73e3042ca0aa96f95577fa58264971501c6d270a701646ef4ce5ddfa0d8b5498910160405180910390a45050505050505050505050565b6000816401000000008410611f275760405162461bcd60e51b81526004016105309190612695565b509192915050565b60006115978284612668565b600061159782846126ea565b6040805160208101909152600081526040518060200160405280611f82611f7c866a0c097ce7bc90715b34b9f160241b611f3b565b8561202d565b90529392505050565b6040805160208101909152600081526040518060200160405280611f8285600001518560000151612007565b600081600160e01b8410611f275760405162461bcd60e51b81526004016105309190612695565b60006a0c097ce7bc90715b34b9f160241b611ffd848460000151611f3b565b6115979190612709565b6000611597828461272b565b600061159761202a84670de0b6b3a7640000611f3b565b83515b60006115978284612709565b6001600160a01b03811681146113af57600080fd5b6000806040838503121561206157600080fd5b823561206c81612039565b9150602083013561207c81612039565b809150509250929050565b60008060006060848603121561209c57600080fd5b83356120a781612039565b925060208401356120b781612039565b915060408401356120c781612039565b809150509250925092565b6000806000606084860312156120e757600080fd5b83356120f281612039565b9250602084013561210281612039565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b818110156121545783516001600160a01b03168352928401929184019160010161212f565b50909695505050505050565b60006020828403121561217257600080fd5b813561159781612039565b6000806000806080858703121561219357600080fd5b843561219e81612039565b935060208501356121ae81612039565b93969395505050506040820135916060013590565b80151581146113af57600080fd5b80356121dc816121c3565b919050565b600080604083850312156121f457600080fd5b82356121ff81612039565b9150602083013561207c816121c3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561224e5761224e61220f565b604052919050565b600067ffffffffffffffff8211156122705761227061220f565b5060051b60200190565b600082601f83011261228b57600080fd5b813560206122a061229b83612256565b612225565b82815260059290921b840181019181810190868411156122bf57600080fd5b8286015b848110156122e35780356122d681612039565b83529183019183016122c3565b509695505050505050565b600080600080600060a0868803121561230657600080fd5b853561231181612039565b945060208681013567ffffffffffffffff8082111561232f57600080fd5b818901915089601f83011261234357600080fd5b813561235161229b82612256565b81815260059190911b8301840190848101908c83111561237057600080fd5b938501935b8285101561239757843561238881612039565b82529385019390850190612375565b9850505060408901359250808311156123af57600080fd5b50506123bd8882890161227a565b9350506123cc606087016121d1565b91506123da608087016121d1565b90509295509295909350565b6000602082840312156123f857600080fd5b5035919050565b60008060006060848603121561241457600080fd5b833561241f81612039565b9250602084013561242f81612039565b9150604084013567ffffffffffffffff81111561244b57600080fd5b6124578682870161227a565b9150509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156124d6576124d66124ac565b5060010190565b6020808252818101527f496e63656e74697665206173736574206973206e6f7420737570706f72746564604082015260600190565b6020808252602e908201527f496e63656e746976653a3a646973747269627574653a206163636f756e74206560408201526d1e18db1d59195cc81c995dd85c9960921b606082015260800190565b6000602080838503121561257357600080fd5b825167ffffffffffffffff81111561258a57600080fd5b8301601f8101851361259b57600080fd5b80516125a961229b82612256565b81815260059190911b820183019083810190878311156125c857600080fd5b928401925b828410156125ef5783516125e081612039565b825292840192908401906125cd565b979650505050505050565b60006020828403121561260c57600080fd5b5051919050565b60006020828403121561262557600080fd5b8151611597816121c3565b60008060006060848603121561264557600080fd5b8351612650816121c3565b6020850151604086015191945092506120c7816121c3565b60008282101561267a5761267a6124ac565b500390565b634e487b7160e01b600052603160045260246000fd5b600060208083528351808285015260005b818110156126c2578581018301518582016040015282016126a6565b818111156126d4576000604083870101525b50601f01601f1916929092016040019392505050565b6000816000190483118215151615612704576127046124ac565b500290565b60008261272657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561273e5761273e6124ac565b50019056fea264697066735822122027ac4f6b5eb080299fd19395d4ef991c8253a74becc1ef7bc525436f5a44da7764736f6c634300080a003300000000000000000000000027dc3dadbfb40adc677a2d5ef192d40ad7c4c97d
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101a95760003560e01c8063773907de116100f9578063c47d603611610097578063cdcf0bf911610071578063cdcf0bf914610472578063e5029dc81461049d578063f2fde38b146104e0578063f9d8d849146104f357600080fd5b8063c47d603614610439578063c73200f11461044c578063c8be1e851461045f57600080fd5b80638bad38dd116100d35780638bad38dd146103ef5780638da5cb5b146104025780639ad0a42d146104135780639c223ace1461042657600080fd5b8063773907de1461039657806388088483146103a9578063882f1ba4146103bc57600080fd5b80633f22ddea116101665780635fe3b567116101405780635fe3b5671461030557806360777a4f1461033057806366f91a2414610361578063715018a61461038e57600080fd5b80633f22ddea146102d957806342cbb15c146102ec5780635d5bfe18146102f257600080fd5b80630bda5be1146101ae5780631ad964ed146101ec578063246467e81461021d57806327ee5210146102325780633068172d14610247578063317d2abc14610272575b600080fd5b6101d96101bc36600461204e565b600a60209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101d96101fa366004612087565b600860209081526000938452604080852082529284528284209052825290205481565b61023061022b3660046120d2565b610506565b005b61023a6105e7565b6040516101e39190612113565b6101d961025536600461204e565b600560209081526000928352604080842090915290825290205481565b6102b561028036600461204e565b60066020908152600092835260408084209091529082529020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016101e3565b6102306102e736600461204e565b610649565b436101d9565b61023061030036600461204e565b6106f0565b600154610318906001600160a01b031681565b6040516001600160a01b0390911681526020016101e3565b6101d961033e366004612087565b600960209081526000938452604080852082529284528284209052825290205481565b6103766a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016101e3565b610230610832565b6102306103a4366004612160565b610868565b6102306103b736600461217d565b6109fb565b6103df6103ca366004612160565b60036020526000908152604090205460ff1681565b60405190151581526020016101e3565b6102306103fd366004612160565b610ab9565b6000546001600160a01b0316610318565b6102306104213660046121e1565b610bd5565b6102306104343660046122ee565b610c2a565b61023061044736600461204e565b6110a8565b61031861045a3660046123e6565b6111c5565b61023061046d3660046123ff565b6111ef565b6101d961048036600461204e565b600460209081526000928352604080842090915290825290205481565b6102b56104ab36600461204e565b60076020908152600092835260408084209091529082529020546001600160e01b03811690600160e01b900463ffffffff1682565b6102306104ee366004612160565b611317565b6102306105013660046123e6565b6113b2565b6000546001600160a01b031633146105395760405162461bcd60e51b815260040161053090612461565b60405180910390fd5b600061054684848461148c565b905080156105965760405162461bcd60e51b815260206004820181905260248201527f696e73756666696369656e7420696e63656e7469766520666f72206772616e746044820152606401610530565b604080516001600160a01b038087168252851660208201529081018390527f6123969dd9705ebe9fca0229b85009158c92cae456c32d917d8d435748f3abd39060600160405180910390a150505050565b6060600280548060200260200160405190810160405280929190818152602001828054801561063f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610621575b5050505050905090565b60005b6002548110156106eb576106876002828154811061066c5761066c612496565b6000918252602090912001546001600160a01b03168461159e565b6001600160a01b03821660009081526003602052604090205460ff166106d9576106d9600282815481106106bd576106bd612496565b6000918252602090912001546001600160a01b031684846117a1565b806106e3816124c2565b91505061064c565b505050565b816000805b60025481101561075257826001600160a01b03166002828154811061071c5761071c612496565b6000918252602090912001546001600160a01b031614156107405760019150610752565b8061074a816124c2565b9150506106f5565b50806107705760405162461bcd60e51b8152600401610530906124dd565b6001600160a01b038316600090815260036020526040902054839060ff16156107ab5760405162461bcd60e51b815260040161053090612512565b61082b8585600160009054906101000a90046001600160a01b03166001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610803573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261046d9190810190612560565b5050505050565b6000546001600160a01b0316331461085c5760405162461bcd60e51b815260040161053090612461565b6108666000611971565b565b6000546001600160a01b031633146108925760405162461bcd60e51b815260040161053090612461565b806000805b6002548110156108f457826001600160a01b0316600282815481106108be576108be612496565b6000918252602090912001546001600160a01b031614156108e257600191506108f4565b806108ec816124c2565b915050610897565b5080156109435760405162461bcd60e51b815260206004820152601f60248201527f496e63656e7469766520617373657420616c726561647920737570706f7274006044820152606401610530565b826001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a591906125fa565b5050600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b03939093169290921790915550565b836000805b600254811015610a5d57826001600160a01b031660028281548110610a2757610a27612496565b6000918252602090912001546001600160a01b03161415610a4b5760019150610a5d565b80610a55816124c2565b915050610a00565b5080610a7b5760405162461bcd60e51b8152600401610530906124dd565b6000546001600160a01b03163314610aa55760405162461bcd60e51b815260040161053090612461565b610ab1868686866119c1565b505050505050565b6000546001600160a01b03163314610ae35760405162461bcd60e51b815260040161053090612461565b80806001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b459190612613565b1515600114610bb25760405162461bcd60e51b815260206004820152603360248201527f496e63656e746976653a3a636f6e7374727563746f723a20636f6e74726163746044820152721034b9903737ba1031b7b6b83a3937b63632b960691b6064820152608401610530565b50600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610bff5760405162461bcd60e51b815260040161053090612461565b6001600160a01b03919091166000908152600360205260409020805460ff1916911515919091179055565b846000805b600254811015610c8c57826001600160a01b031660028281548110610c5657610c56612496565b6000918252602090912001546001600160a01b03161415610c7a5760019150610c8c565b80610c84816124c2565b915050610c2f565b5080610caa5760405162461bcd60e51b8152600401610530906124dd565b60005b8651811015610d785760036000888381518110610ccc57610ccc612496565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615610d665760405162461bcd60e51b815260206004820152603760248201527f496e63656e746976653a3a64697374726962757465537570706c6965723a207360448201527f7570706c696572206578636c75646573207265776172640000000000000000006064820152608401610530565b80610d70816124c2565b915050610cad565b5060005b8551811015610f9e576000868281518110610d9957610d99612496565b6020908102919091010151600154604051638e8f294b60e01b81526001600160a01b03808416600483015292935060009290911690638e8f294b90602401606060405180830381865afa158015610df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e189190612630565b5050905080610e615760405162461bcd60e51b81526020600482015260156024820152741b585c9ad95d081b5d5cdd081899481b1a5cdd1959605a1b6044820152606401610530565b60018715151415610f305760006040518060200160405280846001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edb91906125fa565b90529050610eea8b8483611bb1565b60005b8a51811015610f2d57610f1b8c858d8481518110610f0d57610f0d612496565b602002602001015185611d4d565b80610f25816124c2565b915050610eed565b50505b60018615151415610f8957610f458a8361159e565b60005b8951811015610f8757610f758b848c8481518110610f6857610f68612496565b60200260200101516117a1565b80610f7f816124c2565b915050610f48565b505b50508080610f96906124c2565b915050610d7c565b5060005b865181101561109e5761103088888381518110610fc157610fc1612496565b6020026020010151600a60008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008b868151811061100257611002612496565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205461148c565b6001600160a01b0389166000908152600a6020526040812089519091908a908590811061105f5761105f612496565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080611096906124c2565b915050610fa2565b5050505050505050565b60006040518060200160405280846001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111791906125fa565b9052905060005b6002548110156111bf5761115a6002828154811061113e5761113e612496565b6000918252602090912001546001600160a01b03168584611bb1565b6001600160a01b03831660009081526003602052604090205460ff166111ad576111ad6002828154811061119057611190612496565b6000918252602090912001546001600160a01b0316858585611d4d565b806111b7816124c2565b91505061111e565b50505050565b600281815481106111d557600080fd5b6000918252602090912001546001600160a01b0316905081565b826000805b60025481101561125157826001600160a01b03166002828154811061121b5761121b612496565b6000918252602090912001546001600160a01b0316141561123f5760019150611251565b80611249816124c2565b9150506111f4565b508061126f5760405162461bcd60e51b8152600401610530906124dd565b6001600160a01b038416600090815260036020526040902054849060ff16156112aa5760405162461bcd60e51b815260040161053090612512565b6040805160018082528183019092526000916020808301908036833701905050905085816000815181106112e0576112e0612496565b60200260200101906001600160a01b031690816001600160a01b03168152505061130e878287600180610c2a565b50505050505050565b6000546001600160a01b031633146113415760405162461bcd60e51b815260040161053090612461565b6001600160a01b0381166113a65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610530565b6113af81611971565b50565b6000546001600160a01b031633146113dc5760405162461bcd60e51b815260040161053090612461565b600280546113ec90600190612668565b815481106113fc576113fc612496565b600091825260209091200154600280546001600160a01b03909216918390811061142857611428612496565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060028054806114675761146761267f565b600082815260209020810160001990810180546001600160a01b031916905501905550565b6040516370a0823160e01b8152306004820152600090849082906001600160a01b038316906370a0823190602401602060405180830381865afa1580156114d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fb91906125fa565b905060008411801561150d5750808411155b156115915760405163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905283169063a9059cbb906044016020604051808303816000875af1158015611561573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115859190612613565b50600092505050611597565b83925050505b9392505050565b6001600160a01b0382811660008181526006602090815260408083209486168084529482528083209383526004825280832094835293905291822054909161161c435b6040518060400160405280601c81526020017f626c6f636b206e756d6265722065786365656473203332206269747300000000815250611eff565b835490915060009061163e9063ffffffff80851691600160e01b900416611f2f565b90506000811180156116505750600083115b15611776576000856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611695573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b991906125fa565b905060006116c78386611f3b565b905060008083116116e757604051806020016040528060008152506116f1565b6116f18284611f47565b604080516020810190915288546001600160e01b031681529091506117549061171a9083611f8b565b5160408051808201909152601a81527f6e657720696e64657820657863656564732032323420626974730000000000006020820152611fb7565b6001600160e01b0316600160e01b63ffffffff87160217875550610ab1915050565b8015610ab157835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b6001600160a01b038381166000818152600660209081526040808320878616808552908352818420805495855260088452828520918552908352818420958716845294909152902080546001600160e01b0390921690819055908015801561181757506a0c097ce7bc90715b34b9f160241b8210155b1561182d57506a0c097ce7bc90715b34b9f160241b5b600060405180602001604052806118448585611f2f565b90526040516370a0823160e01b81526001600160a01b0387811660048301529192506000918816906370a0823190602401602060405180830381865afa158015611892573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b691906125fa565b905060006118c48284611fde565b6001600160a01b03808b166000908152600a60209081526040808320938c16835292905290812054919250906118fa9083612007565b6001600160a01b038b81166000818152600a602090815260408083208e86168085529083529281902086905580518881529182018c90529495509093928d16927fb747d7740fe7478f458c4b26b4c599bf7ca13bc8724401bec9aae61f61a0ac28910160405180910390a450505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600154604051638e8f294b60e01b81526001600160a01b0385811660048301526000921690638e8f294b90602401606060405180830381865afa158015611a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a309190612630565b5050905080611a785760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610530565b6001600160a01b038086166000908152600460209081526040808320938816835292905220548314611ad757611aae858561159e565b6001600160a01b0380861660009081526004602090815260408083209388168352929052208390555b6001600160a01b03808616600090815260056020908152604080832093881683529290522054821461082b5760006040518060200160405280866001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7291906125fa565b90529050611b81868683611bb1565b506001600160a01b0380861660009081526005602090815260408083209388168352929052208290555050505050565b6001600160a01b03838116600081815260076020908152604080832094871680845294825280832093835260058252808320948352939052918220549091611bf8436115e1565b8354909150600090611c1a9063ffffffff80851691600160e01b900416611f2f565b9050600081118015611c2c5750600083115b15611d21576000611c9e876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9891906125fa565b87612013565b90506000611cac8386611f3b565b90506000808311611ccc5760405180602001604052806000815250611cd6565b611cd68284611f47565b604080516020810190915288546001600160e01b03168152909150611cff9061171a9083611f8b565b6001600160e01b0316600160e01b63ffffffff8716021787555061130e915050565b801561130e57835463ffffffff8316600160e01b026001600160e01b0390911617845550505050505050565b6001600160a01b038481166000818152600760209081526040808320888616808552908352818420805495855260098452828520918552908352818420958816845294909152902080546001600160e01b03909216908190559080158015611dc357506a0c097ce7bc90715b34b9f160241b8210155b15611dd957506a0c097ce7bc90715b34b9f160241b5b60006040518060200160405280611df08585611f2f565b90526040516395dd919360e01b81526001600160a01b038881166004830152919250600091611e4391908a16906395dd919390602401602060405180830381865afa158015611c74573d6000803e3d6000fd5b90506000611e518284611fde565b6001600160a01b03808c166000908152600a60209081526040808320938d1683529290529081205491925090611e879083612007565b6001600160a01b038c81166000818152600a602090815260408083208f86168085529083529281902086905580518881529182018c90529495509093928e16927f73e3042ca0aa96f95577fa58264971501c6d270a701646ef4ce5ddfa0d8b5498910160405180910390a45050505050505050505050565b6000816401000000008410611f275760405162461bcd60e51b81526004016105309190612695565b509192915050565b60006115978284612668565b600061159782846126ea565b6040805160208101909152600081526040518060200160405280611f82611f7c866a0c097ce7bc90715b34b9f160241b611f3b565b8561202d565b90529392505050565b6040805160208101909152600081526040518060200160405280611f8285600001518560000151612007565b600081600160e01b8410611f275760405162461bcd60e51b81526004016105309190612695565b60006a0c097ce7bc90715b34b9f160241b611ffd848460000151611f3b565b6115979190612709565b6000611597828461272b565b600061159761202a84670de0b6b3a7640000611f3b565b83515b60006115978284612709565b6001600160a01b03811681146113af57600080fd5b6000806040838503121561206157600080fd5b823561206c81612039565b9150602083013561207c81612039565b809150509250929050565b60008060006060848603121561209c57600080fd5b83356120a781612039565b925060208401356120b781612039565b915060408401356120c781612039565b809150509250925092565b6000806000606084860312156120e757600080fd5b83356120f281612039565b9250602084013561210281612039565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b818110156121545783516001600160a01b03168352928401929184019160010161212f565b50909695505050505050565b60006020828403121561217257600080fd5b813561159781612039565b6000806000806080858703121561219357600080fd5b843561219e81612039565b935060208501356121ae81612039565b93969395505050506040820135916060013590565b80151581146113af57600080fd5b80356121dc816121c3565b919050565b600080604083850312156121f457600080fd5b82356121ff81612039565b9150602083013561207c816121c3565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561224e5761224e61220f565b604052919050565b600067ffffffffffffffff8211156122705761227061220f565b5060051b60200190565b600082601f83011261228b57600080fd5b813560206122a061229b83612256565b612225565b82815260059290921b840181019181810190868411156122bf57600080fd5b8286015b848110156122e35780356122d681612039565b83529183019183016122c3565b509695505050505050565b600080600080600060a0868803121561230657600080fd5b853561231181612039565b945060208681013567ffffffffffffffff8082111561232f57600080fd5b818901915089601f83011261234357600080fd5b813561235161229b82612256565b81815260059190911b8301840190848101908c83111561237057600080fd5b938501935b8285101561239757843561238881612039565b82529385019390850190612375565b9850505060408901359250808311156123af57600080fd5b50506123bd8882890161227a565b9350506123cc606087016121d1565b91506123da608087016121d1565b90509295509295909350565b6000602082840312156123f857600080fd5b5035919050565b60008060006060848603121561241457600080fd5b833561241f81612039565b9250602084013561242f81612039565b9150604084013567ffffffffffffffff81111561244b57600080fd5b6124578682870161227a565b9150509250925092565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156124d6576124d66124ac565b5060010190565b6020808252818101527f496e63656e74697665206173736574206973206e6f7420737570706f72746564604082015260600190565b6020808252602e908201527f496e63656e746976653a3a646973747269627574653a206163636f756e74206560408201526d1e18db1d59195cc81c995dd85c9960921b606082015260800190565b6000602080838503121561257357600080fd5b825167ffffffffffffffff81111561258a57600080fd5b8301601f8101851361259b57600080fd5b80516125a961229b82612256565b81815260059190911b820183019083810190878311156125c857600080fd5b928401925b828410156125ef5783516125e081612039565b825292840192908401906125cd565b979650505050505050565b60006020828403121561260c57600080fd5b5051919050565b60006020828403121561262557600080fd5b8151611597816121c3565b60008060006060848603121561264557600080fd5b8351612650816121c3565b6020850151604086015191945092506120c7816121c3565b60008282101561267a5761267a6124ac565b500390565b634e487b7160e01b600052603160045260246000fd5b600060208083528351808285015260005b818110156126c2578581018301518582016040015282016126a6565b818111156126d4576000604083870101525b50601f01601f1916929092016040019392505050565b6000816000190483118215151615612704576127046124ac565b500290565b60008261272657634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561273e5761273e6124ac565b50019056fea264697066735822122027ac4f6b5eb080299fd19395d4ef991c8253a74becc1ef7bc525436f5a44da7764736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000027dc3dadbfb40adc677a2d5ef192d40ad7c4c97d
-----Decoded View---------------
Arg [0] : _comptroller (address): 0x27DC3DAdBfb40ADc677A2D5ef192d40aD7c4c97D
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000027dc3dadbfb40adc677a2d5ef192d40ad7c4c97d
Deployed Bytecode Sourcemap
88789:14749:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90188:65;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;689:25:1;;;677:2;662:18;90188:65:0;;;;;;;;89970:100;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103189:346;;;;;;:::i;:::-;;:::i;:::-;;91745:116;;;:::i;:::-;;;;;;;:::i;89691:70::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;89770:91;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;89770:91:0;;;-1:-1:-1;;;89770:91:0;;;;;;;;;;-1:-1:-1;;;;;2573:32:1;;;2555:51;;2654:10;2642:23;;;2637:2;2622:18;;2615:51;2528:18;89770:91:0;2383:289:1;99215:375:0;;;;;;:::i;:::-;;:::i;91635:102::-;91717:12;91635:102;;100191:240;;;;;;:::i;:::-;;:::i;88846:24::-;;;;;-1:-1:-1;;;;;88846:24:0;;;;;;-1:-1:-1;;;;;2855:32:1;;;2837:51;;2825:2;2810:18;88846:24:0;2677:217:1;90079:100:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89457:49;;-1:-1:-1;;;89457:49:0;;;;;-1:-1:-1;;;;;3063:32:1;;;3045:51;;3033:2;3018:18;89457:49:0;2899:203:1;87039:94:0;;;:::i;92203:209::-;;;;;;:::i;:::-;;:::i;92633:387::-;;;;;;:::i;:::-;;:::i;89555:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4069:14:1;;4062:22;4044:41;;4032:2;4017:18;89555:48:0;3904:187:1;91869:161:0;;;;;;:::i;:::-;;:::i;86388:87::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;86388:87;;92038:157;;;;;;:::i;:::-;;:::i;100791:1952::-;;;;;;:::i;:::-;;:::i;99598:585::-;;;;;;:::i;:::-;;:::i;89515:33::-;;;;;;:::i;:::-;;:::i;100439:344::-;;;;;;:::i;:::-;;:::i;89612:70::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;89870:91;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;89870:91:0;;;-1:-1:-1;;;89870:91:0;;;;;;87288:192;;;;;;:::i;:::-;;:::i;92420:205::-;;;;;;:::i;:::-;;:::i;103189:346::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;;;;;;;;;103327:18:::1;103348:49;103368:9;103379;103390:6;103348:19;:49::i;:::-;103327:70:::0;-1:-1:-1;103416:15:0;;103408:60:::1;;;::::0;-1:-1:-1;;;103408:60:0;;9217:2:1;103408:60:0::1;::::0;::::1;9199:21:1::0;;;9236:18;;;9229:30;9295:34;9275:18;;;9268:62;9347:18;;103408:60:0::1;9015:356:1::0;103408:60:0::1;103484:43;::::0;;-1:-1:-1;;;;;9634:15:1;;;9616:34;;9686:15;;9681:2;9666:18;;9659:43;9718:18;;;9711:34;;;103484:43:0::1;::::0;9566:2:1;9551:18;103484:43:0::1;;;;;;;103316:219;103189:346:::0;;;:::o;91745:116::-;91801:16;91837;91830:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91830:23:0;;;;;;;;;;;;;;;;;;;;;;;91745:116;:::o;99215:375::-;99302:9;99297:286;99321:16;:23;99317:27;;99297:286;;;99366:52;99390:16;99407:1;99390:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;99390:19:0;99411:6;99366:23;:52::i;:::-;-1:-1:-1;;;;;99437:26:0;;;;;;:16;:26;;;;;;;;99433:139;;99493:63;99518:16;99535:1;99518:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;99518:19:0;99539:6;99547:8;99493:24;:63::i;:::-;99346:3;;;;:::i;:::-;;;;99297:286;;;;99215:375;;:::o;100191:240::-;100301:9;90556:18;90598:9;90593:203;90617:16;:23;90613:27;;90593:203;;;90689:15;-1:-1:-1;;;;;90666:38:0;:16;90683:1;90666:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;90666:19:0;:38;90662:123;;;90741:4;90725:20;;90764:5;;90662:123;90642:3;;;;:::i;:::-;;;;90593:203;;;;90814:13;90806:58;;;;-1:-1:-1;;;90806:58:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91383:26:0;::::1;;::::0;;;:16:::1;:26;::::0;;;;;100335:6;;91383:26:::1;;91382:27;91360:123;;;;-1:-1:-1::0;;;91360:123:0::1;;;;;;;:::i;:::-;100361:62:::2;100376:9;100387:6;100395:11;;;;;;;;;-1:-1:-1::0;;;;;100395:11:0::2;-1:-1:-1::0;;;;;100395:25:0::2;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;::::0;;::::2;-1:-1:-1::0;;100395:27:0::2;::::0;::::2;;::::0;::::2;::::0;;;::::2;::::0;::::2;:::i;100361:62::-;90877:1:::1;90545:341:::0;100191:240;;;:::o;87039:94::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;87104:21:::1;87122:1;87104:9;:21::i;:::-;87039:94::o:0;92203:209::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;92307:6:::1;90961:18;91003:9:::0;90998:203:::1;91022:16;:23:::0;91018:27;::::1;90998:203;;;91094:15;-1:-1:-1::0;;;;;91071:38:0::1;:16;91088:1;91071:19;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;91071:19:0::1;:38;91067:123;;;91146:4;91130:20;;91169:5;;91067:123;91047:3:::0;::::1;::::0;::::1;:::i;:::-;;;;90998:203;;;;91220:13;91219:14;91211:58;;;::::0;-1:-1:-1;;;91211:58:0;;12114:2:1;91211:58:0::1;::::0;::::1;12096:21:1::0;12153:2;12133:18;;;12126:30;12192:33;12172:18;;;12165:61;12243:18;;91211:58:0::1;11912:355:1::0;91211:58:0::1;92341:6:::2;-1:-1:-1::0;;;;;92326:34:0::2;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;92375:16:0::2;:29:::0;;::::2;::::0;::::2;::::0;;-1:-1:-1;92375:29:0;;;;;::::2;::::0;;-1:-1:-1;;;;;;92375:29:0::2;-1:-1:-1::0;;;;;92375:29:0;;;::::2;::::0;;;::::2;::::0;;;-1:-1:-1;92203:209:0:o;92633:387::-;92823:15;90556:18;90598:9;90593:203;90617:16;:23;90613:27;;90593:203;;;90689:15;-1:-1:-1;;;;;90666:38:0;:16;90683:1;90666:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;90666:19:0;:38;90662:123;;;90741:4;90725:20;;90764:5;;90662:123;90642:3;;;;:::i;:::-;;;;90593:203;;;;90814:13;90806:58;;;;-1:-1:-1;;;90806:58:0;;;;;;;:::i;:::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23:::1;86600:68;;;;-1:-1:-1::0;;;86600:68:0::1;;;;;;;:::i;:::-;92861:151:::2;92898:15;92928:7;92950:18;92983;92861:22;:151::i;:::-;90545:341:::0;92633:387;;;;;:::o;91869:161::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;91964:12:::1;90346;-1:-1:-1::0;;;;;90340:33:0::1;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:43;;90379:4;90340:43;90318:144;;;::::0;-1:-1:-1;;;90318:144:0;;12913:2:1;90318:144:0::1;::::0;::::1;12895:21:1::0;12952:2;12932:18;;;12925:30;12991:34;12971:18;;;12964:62;-1:-1:-1;;;13042:18:1;;;13035:49;13101:19;;90318:144:0::1;12711:415:1::0;90318:144:0::1;-1:-1:-1::0;91989:11:0::2;:33:::0;;-1:-1:-1;;;;;;91989:33:0::2;-1:-1:-1::0;;;;;91989:33:0;;;::::2;::::0;;;::::2;::::0;;91869:161::o;92038:157::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;92153:26:0;;;::::1;;::::0;;;:16:::1;:26;::::0;;;;:34;;-1:-1:-1;;92153:34:0::1;::::0;::::1;;::::0;;;::::1;::::0;;92038:157::o;100791:1952::-;100995:9;90556:18;90598:9;90593:203;90617:16;:23;90613:27;;90593:203;;;90689:15;-1:-1:-1;;;;;90666:38:0;:16;90683:1;90666:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;90666:19:0;:38;90662:123;;;90741:4;90725:20;;90764:5;;90662:123;90642:3;;;;:::i;:::-;;;;90593:203;;;;90814:13;90806:58;;;;-1:-1:-1;;;90806:58:0;;;;;;;:::i;:::-;101022:9:::1;101017:218;101041:7;:14;101037:1;:18;101017:218;;;101104:16;:28;101121:7;101129:1;101121:10;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;;;101104:28:0::1;::::0;;;::::1;::::0;;;;;;-1:-1:-1;101104:28:0;;::::1;;101103:29;101077:146;;;::::0;-1:-1:-1;;;101077:146:0;;13333:2:1;101077:146:0::1;::::0;::::1;13315:21:1::0;13372:2;13352:18;;;13345:30;13411:34;13391:18;;;13384:62;13482:25;13462:18;;;13455:53;13525:19;;101077:146:0::1;13131:419:1::0;101077:146:0::1;101057:3:::0;::::1;::::0;::::1;:::i;:::-;;;;101017:218;;;;101250:9;101245:1224;101269:7;:14;101265:1;:18;101245:1224;;;101305:13;101321:7;101329:1;101321:10;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;101368:11:::1;::::0;:36:::1;::::0;-1:-1:-1;;;101368:36:0;;-1:-1:-1;;;;;2855:32:1;;;101368:36:0::1;::::0;::::1;2837:51:1::0;101321:10:0;;-1:-1:-1;101347:13:0::1;::::0;101368:11;;::::1;::::0;:19:::1;::::0;2810:18:1;;101368:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101346:58;;;;101427:8;101419:42;;;::::0;-1:-1:-1;;;101419:42:0;;14196:2:1;101419:42:0::1;::::0;::::1;14178:21:1::0;14235:2;14215:18;;;14208:30;-1:-1:-1;;;14254:18:1;;;14247:51;14315:18;;101419:42:0::1;13994:345:1::0;101419:42:0::1;101493:4;101480:17:::0;::::1;;;101476:591;;;101518:22;101543:37;;;;;;;;101558:6;-1:-1:-1::0;;;;;101558:18:0::1;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101543:37:::0;;101518:62;-1:-1:-1;101599:146:0::1;101645:9:::0;101685:6;101518:62;101599:23:::1;:146::i;:::-;101769:9;101764:288;101788:7;:14;101784:1;:18;101764:288;;;101832:200;101883:9;101927:6;101961:7;101969:1;101961:10;;;;;;;;:::i;:::-;;;;;;;101998:11;101832:24;:200::i;:::-;101804:3:::0;::::1;::::0;::::1;:::i;:::-;;;;101764:288;;;;101499:568;101476:591;102098:4;102085:17:::0;::::1;;;102081:377;;;102123:51;102147:9;102166:6;102123:23;:51::i;:::-;102198:9;102193:250;102217:7;:14;102213:1;:18;102193:250;;;102261:162;102312:9;102356:6;102390:7;102398:1;102390:10;;;;;;;;:::i;:::-;;;;;;;102261:24;:162::i;:::-;102233:3:::0;::::1;::::0;::::1;:::i;:::-;;;;102193:250;;;;102081:377;101290:1179;;101285:3;;;;;:::i;:::-;;;;101245:1224;;;;102484:9;102479:257;102503:7;:14;102499:1;:18;102479:257;;;102578:146;102616:9;102644:7;102652:1;102644:10;;;;;;;;:::i;:::-;;;;;;;102673:13;:24;102687:9;-1:-1:-1::0;;;;;102673:24:0::1;-1:-1:-1::0;;;;;102673:24:0::1;;;;;;;;;;;;:36;102698:7;102706:1;102698:10;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;102673:36:0::1;-1:-1:-1::0;;;;;102673:36:0::1;;;;;;;;;;;;;102578:19;:146::i;:::-;-1:-1:-1::0;;;;;102539:24:0;::::1;;::::0;;;:13:::1;:24;::::0;;;;102564:10;;102539:24;;;102564:7;;102572:1;;102564:10;::::1;;;;;:::i;:::-;;;;;;;-1:-1:-1::0;;;;;102539:36:0::1;-1:-1:-1::0;;;;;102539:36:0::1;;;;;;;;;;;;:185;;;;102519:3;;;;;:::i;:::-;;;;102479:257;;;;90545:341:::0;100791:1952;;;;;;:::o;99598:585::-;99680:22;99705:45;;;;;;;;99727:6;-1:-1:-1;;;;;99720:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99705:45;;99680:70;-1:-1:-1;99766:9:0;99761:415;99785:16;:23;99781:27;;99761:415;;;99830:65;99854:16;99871:1;99854:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;99854:19:0;99875:6;99883:11;99830:23;:65::i;:::-;-1:-1:-1;;;;;99914:26:0;;;;;;:16;:26;;;;;;;;99910:255;;99970:179;100017:16;100034:1;100017:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;100017:19:0;100059:6;100088:8;100119:11;99970:24;:179::i;:::-;99810:3;;;;:::i;:::-;;;;99761:415;;;;99669:514;99598:585;;:::o;89515:33::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;89515:33:0;;-1:-1:-1;89515:33:0;:::o;100439:344::-;100583:9;90556:18;90598:9;90593:203;90617:16;:23;90613:27;;90593:203;;;90689:15;-1:-1:-1;;;;;90666:38:0;:16;90683:1;90666:19;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;90666:19:0;:38;90662:123;;;90741:4;90725:20;;90764:5;;90662:123;90642:3;;;;:::i;:::-;;;;90593:203;;;;90814:13;90806:58;;;;-1:-1:-1;;;90806:58:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91383:26:0;::::1;;::::0;;;:16:::1;:26;::::0;;;;;100617:6;;91383:26:::1;;91382:27;91360:123;;;;-1:-1:-1::0;;;91360:123:0::1;;;;;;;:::i;:::-;100663:16:::2;::::0;;100677:1:::2;100663:16:::0;;;;;::::2;::::0;;;100636:24:::2;::::0;100663:16:::2;::::0;;::::2;::::0;;::::2;::::0;::::2;;::::0;-1:-1:-1;100663:16:0::2;100636:43;;100703:6;100690:7;100698:1;100690:10;;;;;;;;:::i;:::-;;;;;;:19;-1:-1:-1::0;;;;;100690:19:0::2;;;-1:-1:-1::0;;;;;100690:19:0::2;;;::::0;::::2;100720:55;100735:9;100746:7;100755;100764:4;100770::::0;100720:14:::2;:55::i;:::-;100625:158;90877:1:::1;90545:341:::0;100439:344;;;;:::o;87288:192::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;87377:22:0;::::1;87369:73;;;::::0;-1:-1:-1;;;87369:73:0;;14546:2:1;87369:73:0::1;::::0;::::1;14528:21:1::0;14585:2;14565:18;;;14558:30;14624:34;14604:18;;;14597:62;-1:-1:-1;;;14675:18:1;;;14668:36;14721:19;;87369:73:0::1;14344:402:1::0;87369:73:0::1;87453:19;87463:8;87453:9;:19::i;:::-;87288:192:::0;:::o;92420:205::-;86434:7;86461:6;-1:-1:-1;;;;;86461:6:0;85256:10;86608:23;86600:68;;;;-1:-1:-1;;;86600:68:0;;;;;;;:::i;:::-;92515:16:::1;92546:23:::0;;:27:::1;::::0;92572:1:::1;::::0;92546:27:::1;:::i;:::-;92515:69;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;92488:16:::1;:24:::0;;-1:-1:-1;;;;;92515:69:0;;::::1;::::0;92505:6;;92488:24;::::1;;;;;:::i;:::-;;;;;;;;;:96;;;;;-1:-1:-1::0;;;;;92488:96:0::1;;;;;-1:-1:-1::0;;;;;92488:96:0::1;;;;;;92595:16;:22;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;-1:-1:-1;;92595:22:0;;;;;-1:-1:-1;;;;;;92595:22:0::1;::::0;;;;;-1:-1:-1;92420:205:0:o;102751:430::-;102986:30;;-1:-1:-1;;;102986:30:0;;103010:4;102986:30;;;2837:51:1;102881:7:0;;102939:9;;102881:7;;-1:-1:-1;;;;;102986:15:0;;;;;2810:18:1;;102986:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102960:56;;103040:1;103031:6;:10;:39;;;;;103055:15;103045:6;:25;;103031:39;103027:123;;;103087:28;;-1:-1:-1;;;103087:28:0;;-1:-1:-1;;;;;15205:32:1;;;103087:28:0;;;15187:51:1;15254:18;;;15247:34;;;103087:14:0;;;;;15160:18:1;;103087:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;103137:1;103130:8;;;;;;103027:123;103167:6;103160:13;;;;102751:430;;;;;;:::o;94030:1214::-;-1:-1:-1;;;;;94188:57:0;;;94148:37;94188:57;;;:17;:57;;;;;;;;:65;;;;;;;;;;;;94286:34;;;:18;:34;;;;;:42;;;;;;;;;;94188:65;;94360:93;91717:12;94381:16;94360:93;;;;;;;;;;;;;;;;;:6;:93::i;:::-;94548:17;;94339:114;;-1:-1:-1;94464:19:0;;94486:91;;94505:20;;;;;-1:-1:-1;;;94548:17:0;;;94486:4;:91::i;:::-;94464:113;;94606:1;94592:11;:15;:34;;;;;94625:1;94611:11;:15;94592:34;94588:649;;;94643:20;94673:6;-1:-1:-1;;;;;94666:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94643:51;;94709:20;94732:30;94737:11;94750;94732:4;:30::i;:::-;94709:53;;94777:19;94814:1;94799:12;:16;:113;;94891:21;;;;;;;;94909:1;94891:21;;;94799:113;;;94835:36;94844:12;94858;94835:8;:36::i;:::-;94978:37;;;;;;;;;94996:17;;-1:-1:-1;;;;;94996:17:0;94978:37;;94777:135;;-1:-1:-1;94947:147:0;;94973:50;;94777:135;94973:4;:50::i;:::-;:59;94947:147;;;;;;;;;;;;;;;;;:7;:147::i;:::-;-1:-1:-1;;;;;94927:167:0;-1:-1:-1;;;95109:31:0;;;;;;;-1:-1:-1;94588:649:0;;-1:-1:-1;;94588:649:0;;95162:15;;95158:79;;95194:31;;;;;-1:-1:-1;;;95194:31:0;-1:-1:-1;;;;;95194:31:0;;;;;;94137:1107;;;;94030:1214;;:::o;96588:1250::-;-1:-1:-1;;;;;96769:28:0;;;96729:37;96769:28;;;:17;:28;;;;;;;;:60;;;;;;;;;;;;96862:17;;96914:30;;;:19;:30;;;;;:38;;;;;;;;;:72;;;;;;;;;;;;;-1:-1:-1;;;;;96862:17:0;;;96999:62;;;;96862:17;97078:18;;:55;;;;-1:-1:-1;;;;97100:33:0;;;97078:55;97074:122;;;-1:-1:-1;;;;97074:122:0;97208:24;97235:76;;;;;;;;97267:32;97272:11;97285:13;97267:4;:32::i;:::-;97235:76;;97349:34;;-1:-1:-1;;;97349:34:0;;-1:-1:-1;;;;;2855:32:1;;;97349:34:0;;;2837:51:1;97208:103:0;;-1:-1:-1;97324:22:0;;97349:24;;;;;2810:18:1;;97349:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97324:59;;97396:21;97420:32;97425:14;97441:10;97420:4;:32::i;:::-;-1:-1:-1;;;;;97510:24:0;;;97465:23;97510:24;;;:13;:24;;;;;;;;:34;;;;;;;;;;;;97396:56;;-1:-1:-1;97465:23:0;97491:92;;97396:56;97491:4;:92::i;:::-;-1:-1:-1;;;;;97594:24:0;;;;;;;:13;:24;;;;;;;;:34;;;;;;;;;;;;;:52;;;97664:166;;15466:25:1;;;15507:18;;;15500:34;;;97594:52:0;;-1:-1:-1;97594:34:0;;97664:166;;;;;;15439:18:1;97664:166:0;;;;;;;96718:1120;;;;;;;96588:1250;;;:::o;87488:173::-;87544:16;87563:6;;-1:-1:-1;;;;;87580:17:0;;;-1:-1:-1;;;;;;87580:17:0;;;;;;87613:40;;87563:6;;;;;;;87613:40;;87544:16;87613:40;87533:128;87488:173;:::o;93028:994::-;93226:11;;:36;;-1:-1:-1;;;93226:36:0;;-1:-1:-1;;;;;2855:32:1;;;93226:36:0;;;2837:51:1;93205:13:0;;93226:11;;:19;;2810:18:1;;93226:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93204:58;;;;93281:8;93273:41;;;;-1:-1:-1;;;93273:41:0;;15747:2:1;93273:41:0;;;15729:21:1;15786:2;15766:18;;;15759:30;-1:-1:-1;;;15805:18:1;;;15798:50;15865:18;;93273:41:0;15545:344:1;93273:41:0;-1:-1:-1;;;;;93345:34:0;;;;;;;:18;:34;;;;;;;;:51;;;;;;;;;;:66;;93327:259;;93438:56;93462:14;93486:6;93438:23;:56::i;:::-;-1:-1:-1;;;;;93509:34:0;;;;;;;:18;:34;;;;;;;;:51;;;;;;;;;:65;;;93327:259;-1:-1:-1;;;;;93616:34:0;;;;;;;:18;:34;;;;;;;;:51;;;;;;;;;;:66;;93598:417;;93709:22;93734:37;;;;;;;;93749:6;-1:-1:-1;;;;;93749:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93734:37;;93709:62;-1:-1:-1;93786:135:0;93828:14;93869:6;93709:62;93786:23;:135::i;:::-;-1:-1:-1;;;;;;93938:34:0;;;;;;;:18;:34;;;;;;;;:51;;;;;;;;;:65;;;93193:829;93028:994;;;;:::o;95252:1328::-;-1:-1:-1;;;;;95449:57:0;;;95409:37;95449:57;;;:17;:57;;;;;;;;:65;;;;;;;;;;;;95547:34;;;:18;:34;;;;;:42;;;;;;;;;;95449:65;;95621:93;91717:12;95642:16;91635:102;95621:93;95809:17;;95600:114;;-1:-1:-1;95725:19:0;;95747:91;;95766:20;;;;;-1:-1:-1;;;95809:17:0;;;95747:4;:91::i;:::-;95725:113;;95867:1;95853:11;:15;:34;;;;;95886:1;95872:11;:15;95853:34;95849:724;;;95904:20;95927:103;95957:6;-1:-1:-1;;;;;95950:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95998:17;95927:4;:103::i;:::-;95904:126;;96045:20;96068:30;96073:11;96086;96068:4;:30::i;:::-;96045:53;;96113:19;96150:1;96135:12;:16;:113;;96227:21;;;;;;;;96245:1;96227:21;;;96135:113;;;96171:36;96180:12;96194;96171:8;:36::i;:::-;96314:37;;;;;;;;;96332:17;;-1:-1:-1;;;;;96332:17:0;96314:37;;96113:135;;-1:-1:-1;96283:147:0;;96309:50;;96113:135;96309:4;:50::i;96283:147::-;-1:-1:-1;;;;;96263:167:0;-1:-1:-1;;;96445:31:0;;;;;;;-1:-1:-1;95849:724:0;;-1:-1:-1;;95849:724:0;;96498:15;;96494:79;;96530:31;;;;;-1:-1:-1;;;96530:31:0;-1:-1:-1;;;;;96530:31:0;;;;;;95398:1182;;;;95252:1328;;;:::o;97846:1361::-;-1:-1:-1;;;;;98066:28:0;;;98026:37;98066:28;;;:17;:28;;;;;;;;:60;;;;;;;;;;;;98159:17;;98211:30;;;:19;:30;;;;;:38;;;;;;;;;:72;;;;;;;;;;;;;-1:-1:-1;;;;;98159:17:0;;;98296:62;;;;98159:17;98375:18;;:55;;;;-1:-1:-1;;;;98397:33:0;;;98375:55;98371:122;;;-1:-1:-1;;;;98371:122:0;98505:24;98532:76;;;;;;;;98564:32;98569:11;98582:13;98564:4;:32::i;:::-;98532:76;;98665:44;;-1:-1:-1;;;98665:44:0;;-1:-1:-1;;;;;2855:32:1;;;98665:44:0;;;2837:51:1;98505:103:0;;-1:-1:-1;98621:22:0;;98646:106;;98665:34;;;;;;2810:18:1;;98665:44:0;;;;;;;;;;;;;;;;;;;;;;98646:106;98621:131;;98765:21;98789:32;98794:14;98810:10;98789:4;:32::i;:::-;-1:-1:-1;;;;;98879:24:0;;;98834:23;98879:24;;;:13;:24;;;;;;;;:34;;;;;;;;;;;;98765:56;;-1:-1:-1;98834:23:0;98860:92;;98765:56;98860:4;:92::i;:::-;-1:-1:-1;;;;;98963:24:0;;;;;;;:13;:24;;;;;;;;:34;;;;;;;;;;;;;:52;;;99033:166;;15466:25:1;;;15507:18;;;15500:34;;;98963:52:0;;-1:-1:-1;98963:34:0;;99033:166;;;;;;15439:18:1;99033:166:0;;;;;;;98015:1192;;;;;;;97846:1361;;;;:::o;2794:161::-;2869:6;2907:12;2900:5;2896:9;;2888:32;;;;-1:-1:-1;;;2888:32:0;;;;;;;;:::i;:::-;-1:-1:-1;2945:1:0;;2794:161;-1:-1:-1;;2794:161:0:o;3709:90::-;3762:4;3786:5;3790:1;3786;:5;:::i;4711:90::-;4764:4;4788:5;4792:1;4788;:5;:::i;5831:147::-;-1:-1:-1;;;;;;;;;;;;5921:49:0;;;;;;;;5939:29;5944:20;5949:1;-1:-1:-1;;;5944:4:0;:20::i;:::-;5966:1;5939:4;:29::i;:::-;5921:49;;5914:56;5831:147;-1:-1:-1;;;5831:147:0:o;3119:160::-;-1:-1:-1;;;;;;;;;;;;3223:48:0;;;;;;;;3241:28;3246:1;:10;;;3258:1;:10;;;3241:4;:28::i;2621:165::-;2697:7;2737:12;-1:-1:-1;;;2725:10:0;;2717:33;;;;-1:-1:-1;;;2717:33:0;;;;;;;;:::i;4576:127::-;4638:4;-1:-1:-1;;;4662:19:0;4667:1;4670;:10;;;4662:4;:19::i;:::-;:33;;;;:::i;3287:90::-;3340:4;3364:5;3368:1;3364;:5;:::i;5122:126::-;5181:4;5205:35;5210:17;5215:1;517:4;5210;:17::i;:::-;5229:10;;5733:90;5786:4;5810:5;5814:1;5810;:5;:::i;14:131:1:-;-1:-1:-1;;;;;89:31:1;;79:42;;69:70;;135:1;132;125:12;150:388;218:6;226;279:2;267:9;258:7;254:23;250:32;247:52;;;295:1;292;285:12;247:52;334:9;321:23;353:31;378:5;353:31;:::i;:::-;403:5;-1:-1:-1;460:2:1;445:18;;432:32;473:33;432:32;473:33;:::i;:::-;525:7;515:17;;;150:388;;;;;:::o;725:529::-;802:6;810;818;871:2;859:9;850:7;846:23;842:32;839:52;;;887:1;884;877:12;839:52;926:9;913:23;945:31;970:5;945:31;:::i;:::-;995:5;-1:-1:-1;1052:2:1;1037:18;;1024:32;1065:33;1024:32;1065:33;:::i;:::-;1117:7;-1:-1:-1;1176:2:1;1161:18;;1148:32;1189:33;1148:32;1189:33;:::i;:::-;1241:7;1231:17;;;725:529;;;;;:::o;1259:456::-;1336:6;1344;1352;1405:2;1393:9;1384:7;1380:23;1376:32;1373:52;;;1421:1;1418;1411:12;1373:52;1460:9;1447:23;1479:31;1504:5;1479:31;:::i;:::-;1529:5;-1:-1:-1;1586:2:1;1571:18;;1558:32;1599:33;1558:32;1599:33;:::i;:::-;1259:456;;1651:7;;-1:-1:-1;;;1705:2:1;1690:18;;;;1677:32;;1259:456::o;1720:658::-;1891:2;1943:21;;;2013:13;;1916:18;;;2035:22;;;1862:4;;1891:2;2114:15;;;;2088:2;2073:18;;;1862:4;2157:195;2171:6;2168:1;2165:13;2157:195;;;2236:13;;-1:-1:-1;;;;;2232:39:1;2220:52;;2327:15;;;;2292:12;;;;2268:1;2186:9;2157:195;;;-1:-1:-1;2369:3:1;;1720:658;-1:-1:-1;;;;;;1720:658:1:o;3107:247::-;3166:6;3219:2;3207:9;3198:7;3194:23;3190:32;3187:52;;;3235:1;3232;3225:12;3187:52;3274:9;3261:23;3293:31;3318:5;3293:31;:::i;3359:540::-;3460:6;3468;3476;3484;3537:3;3525:9;3516:7;3512:23;3508:33;3505:53;;;3554:1;3551;3544:12;3505:53;3593:9;3580:23;3612:31;3637:5;3612:31;:::i;:::-;3662:5;-1:-1:-1;3719:2:1;3704:18;;3691:32;3732:33;3691:32;3732:33;:::i;:::-;3359:540;;3784:7;;-1:-1:-1;;;;3838:2:1;3823:18;;3810:32;;3889:2;3874:18;3861:32;;3359:540::o;4304:118::-;4390:5;4383:13;4376:21;4369:5;4366:32;4356:60;;4412:1;4409;4402:12;4427:128;4492:20;;4521:28;4492:20;4521:28;:::i;:::-;4427:128;;;:::o;4560:382::-;4625:6;4633;4686:2;4674:9;4665:7;4661:23;4657:32;4654:52;;;4702:1;4699;4692:12;4654:52;4741:9;4728:23;4760:31;4785:5;4760:31;:::i;:::-;4810:5;-1:-1:-1;4867:2:1;4852:18;;4839:32;4880:30;4839:32;4880:30;:::i;4947:127::-;5008:10;5003:3;4999:20;4996:1;4989:31;5039:4;5036:1;5029:15;5063:4;5060:1;5053:15;5079:275;5150:2;5144:9;5215:2;5196:13;;-1:-1:-1;;5192:27:1;5180:40;;5250:18;5235:34;;5271:22;;;5232:62;5229:88;;;5297:18;;:::i;:::-;5333:2;5326:22;5079:275;;-1:-1:-1;5079:275:1:o;5359:183::-;5419:4;5452:18;5444:6;5441:30;5438:56;;;5474:18;;:::i;:::-;-1:-1:-1;5519:1:1;5515:14;5531:4;5511:25;;5359:183::o;5547:745::-;5609:5;5662:3;5655:4;5647:6;5643:17;5639:27;5629:55;;5680:1;5677;5670:12;5629:55;5716:6;5703:20;5742:4;5766:60;5782:43;5822:2;5782:43;:::i;:::-;5766:60;:::i;:::-;5860:15;;;5946:1;5942:10;;;;5930:23;;5926:32;;;5891:12;;;;5970:15;;;5967:35;;;5998:1;5995;5988:12;5967:35;6034:2;6026:6;6022:15;6046:217;6062:6;6057:3;6054:15;6046:217;;;6142:3;6129:17;6159:31;6184:5;6159:31;:::i;:::-;6203:18;;6241:12;;;;6079;;6046:217;;;-1:-1:-1;6281:5:1;5547:745;-1:-1:-1;;;;;;5547:745:1:o;6297:1515::-;6451:6;6459;6467;6475;6483;6536:3;6524:9;6515:7;6511:23;6507:33;6504:53;;;6553:1;6550;6543:12;6504:53;6592:9;6579:23;6611:31;6636:5;6611:31;:::i;:::-;6661:5;-1:-1:-1;6685:2:1;6723:18;;;6710:32;6761:18;6791:14;;;6788:34;;;6818:1;6815;6808:12;6788:34;6856:6;6845:9;6841:22;6831:32;;6901:7;6894:4;6890:2;6886:13;6882:27;6872:55;;6923:1;6920;6913:12;6872:55;6959:2;6946:16;6982:60;6998:43;7038:2;6998:43;:::i;6982:60::-;7076:15;;;7158:1;7154:10;;;;7146:19;;7142:28;;;7107:12;;;;7182:19;;;7179:39;;;7214:1;7211;7204:12;7179:39;7238:11;;;;7258:223;7274:6;7269:3;7266:15;7258:223;;;7356:3;7343:17;7373:33;7398:7;7373:33;:::i;:::-;7419:20;;7291:12;;;;7459;;;;7258:223;;;7500:5;-1:-1:-1;;;7558:2:1;7543:18;;7530:32;;-1:-1:-1;7574:16:1;;;7571:36;;;7603:1;7600;7593:12;7571:36;;;7626:71;7689:7;7678:8;7667:9;7663:24;7626:71;:::i;:::-;7616:81;;;7716:35;7747:2;7736:9;7732:18;7716:35;:::i;:::-;7706:45;;7770:36;7801:3;7790:9;7786:19;7770:36;:::i;:::-;7760:46;;6297:1515;;;;;;;;:::o;7817:180::-;7876:6;7929:2;7917:9;7908:7;7904:23;7900:32;7897:52;;;7945:1;7942;7935:12;7897:52;-1:-1:-1;7968:23:1;;7817:180;-1:-1:-1;7817:180:1:o;8002:647::-;8119:6;8127;8135;8188:2;8176:9;8167:7;8163:23;8159:32;8156:52;;;8204:1;8201;8194:12;8156:52;8243:9;8230:23;8262:31;8287:5;8262:31;:::i;:::-;8312:5;-1:-1:-1;8369:2:1;8354:18;;8341:32;8382:33;8341:32;8382:33;:::i;:::-;8434:7;-1:-1:-1;8492:2:1;8477:18;;8464:32;8519:18;8508:30;;8505:50;;;8551:1;8548;8541:12;8505:50;8574:69;8635:7;8626:6;8615:9;8611:22;8574:69;:::i;:::-;8564:79;;;8002:647;;;;;:::o;8654:356::-;8856:2;8838:21;;;8875:18;;;8868:30;8934:34;8929:2;8914:18;;8907:62;9001:2;8986:18;;8654:356::o;9756:127::-;9817:10;9812:3;9808:20;9805:1;9798:31;9848:4;9845:1;9838:15;9872:4;9869:1;9862:15;9888:127;9949:10;9944:3;9940:20;9937:1;9930:31;9980:4;9977:1;9970:15;10004:4;10001:1;9994:15;10020:135;10059:3;-1:-1:-1;;10080:17:1;;10077:43;;;10100:18;;:::i;:::-;-1:-1:-1;10147:1:1;10136:13;;10020:135::o;10160:356::-;10362:2;10344:21;;;10381:18;;;10374:30;10440:34;10435:2;10420:18;;10413:62;10507:2;10492:18;;10160:356::o;10521:410::-;10723:2;10705:21;;;10762:2;10742:18;;;10735:30;10801:34;10796:2;10781:18;;10774:62;-1:-1:-1;;;10867:2:1;10852:18;;10845:44;10921:3;10906:19;;10521:410::o;10936:971::-;11046:6;11077:2;11120;11108:9;11099:7;11095:23;11091:32;11088:52;;;11136:1;11133;11126:12;11088:52;11169:9;11163:16;11202:18;11194:6;11191:30;11188:50;;;11234:1;11231;11224:12;11188:50;11257:22;;11310:4;11302:13;;11298:27;-1:-1:-1;11288:55:1;;11339:1;11336;11329:12;11288:55;11368:2;11362:9;11391:60;11407:43;11447:2;11407:43;:::i;11391:60::-;11485:15;;;11567:1;11563:10;;;;11555:19;;11551:28;;;11516:12;;;;11591:19;;;11588:39;;;11623:1;11620;11613:12;11588:39;11647:11;;;;11667:210;11683:6;11678:3;11675:15;11667:210;;;11756:3;11750:10;11773:31;11798:5;11773:31;:::i;:::-;11817:18;;11700:12;;;;11855;;;;11667:210;;;11896:5;10936:971;-1:-1:-1;;;;;;;10936:971:1:o;12272:184::-;12342:6;12395:2;12383:9;12374:7;12370:23;12366:32;12363:52;;;12411:1;12408;12401:12;12363:52;-1:-1:-1;12434:16:1;;12272:184;-1:-1:-1;12272:184:1:o;12461:245::-;12528:6;12581:2;12569:9;12560:7;12556:23;12552:32;12549:52;;;12597:1;12594;12587:12;12549:52;12629:9;12623:16;12648:28;12670:5;12648:28;:::i;13555:434::-;13637:6;13645;13653;13706:2;13694:9;13685:7;13681:23;13677:32;13674:52;;;13722:1;13719;13712:12;13674:52;13754:9;13748:16;13773:28;13795:5;13773:28;:::i;:::-;13865:2;13850:18;;13844:25;13914:2;13899:18;;13893:25;13820:5;;-1:-1:-1;13844:25:1;-1:-1:-1;13927:30:1;13893:25;13927:30;:::i;14751:125::-;14791:4;14819:1;14816;14813:8;14810:34;;;14824:18;;:::i;:::-;-1:-1:-1;14861:9:1;;14751:125::o;14881:127::-;14942:10;14937:3;14933:20;14930:1;14923:31;14973:4;14970:1;14963:15;14997:4;14994:1;14987:15;15894:597;16006:4;16035:2;16064;16053:9;16046:21;16096:6;16090:13;16139:6;16134:2;16123:9;16119:18;16112:34;16164:1;16174:140;16188:6;16185:1;16182:13;16174:140;;;16283:14;;;16279:23;;16273:30;16249:17;;;16268:2;16245:26;16238:66;16203:10;;16174:140;;;16332:6;16329:1;16326:13;16323:91;;;16402:1;16397:2;16388:6;16377:9;16373:22;16369:31;16362:42;16323:91;-1:-1:-1;16475:2:1;16454:15;-1:-1:-1;;16450:29:1;16435:45;;;;16482:2;16431:54;;15894:597;-1:-1:-1;;;15894:597:1:o;16496:168::-;16536:7;16602:1;16598;16594:6;16590:14;16587:1;16584:21;16579:1;16572:9;16565:17;16561:45;16558:71;;;16609:18;;:::i;:::-;-1:-1:-1;16649:9:1;;16496:168::o;16669:217::-;16709:1;16735;16725:132;;16779:10;16774:3;16770:20;16767:1;16760:31;16814:4;16811:1;16804:15;16842:4;16839:1;16832:15;16725:132;-1:-1:-1;16871:9:1;;16669:217::o;16891:128::-;16931:3;16962:1;16958:6;16955:1;16952:13;16949:39;;;16968:18;;:::i;:::-;-1:-1:-1;17004:9:1;;16891:128::o
Swarm Source
ipfs://27ac4f6b5eb080299fd19395d4ef991c8253a74becc1ef7bc525436f5a44da77
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$47.15
Net Worth in GLMR
Token Allocations
USDC
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| GLMR | 100.00% | $0.999608 | 47.1683 | $47.15 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.