Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
FundV5
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/math/Math.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "../utils/SafeDecimalMath.sol"; import "../utils/CoreUtility.sol"; import "../interfaces/IPrimaryMarketV3.sol"; import "../interfaces/IFundV5.sol"; import "../interfaces/IFundForPrimaryMarketV4.sol"; import "../interfaces/IFundForStrategyV2.sol"; import "../interfaces/IShareV2.sol"; import "../interfaces/ITwapOracleV2.sol"; import "../interfaces/IAprOracle.sol"; import "../interfaces/IVotingEscrow.sol"; import "./FundRolesV2.sol"; contract FundV5 is IFundV5, IFundForPrimaryMarketV4, IFundForStrategyV2, Ownable, ReentrancyGuard, FundRolesV2, CoreUtility { using Math for uint256; using SafeMath for uint256; using SafeDecimalMath for uint256; using SafeERC20 for IERC20; event ProfitReported(uint256 profit, uint256 totalFee, uint256 totalFeeQ, uint256 strategyFeeQ); event LossReported(uint256 loss); event TwapOracleUpdated(address newTwapOracle); event AprOracleUpdated(address newAprOracle); event FeeCollectorUpdated(address newFeeCollector); event ActivityDelayTimeUpdated(uint256 delayTime); event SplitRatioUpdated(uint256 newSplitRatio); event TotalDebtUpdated(uint256 newTotalDebt); event Frozen(); uint256 private constant UNIT = 1e18; uint256 private constant MAX_INTEREST_RATE = 0.001e18; // 0.1% daily uint256 public immutable override weightB; uint256 public immutable settlementPeriod; /// @notice Address of the underlying token. address public immutable override tokenUnderlying; /// @notice A multipler that normalizes an underlying balance to 18 decimal places. uint256 public immutable override underlyingDecimalMultiplier; /// @notice TwapOracle address for the underlying asset. ITwapOracleV2 public override twapOracle; /// @notice AprOracle address. IAprOracle public aprOracle; /// @notice Fee Collector address. address public override feeCollector; /// @notice End timestamp of the current trading day. /// A trading day starts at UTC time `SETTLEMENT_TIME` of a day (inclusive) /// and ends at the same time of the next day (exclusive). uint256 public override currentDay; /// @notice The amount of ROOK received by splitting one QUEEN. /// This ratio changes on every rebalance. uint256 public override splitRatio; /// @dev Mapping of rebalance version => splitRatio. mapping(uint256 => uint256) private _historicalSplitRatio; /// @notice Start timestamp of the current activity window. uint256 public override fundActivityStartTime; uint256 public activityDelayTimeAfterRebalance; bool public override frozen = false; /// @dev Historical rebalances. Rebalances are often accessed in loops with bounds checking. /// So we store them in a fixed-length array, in order to make compiler-generated /// bounds checking on every access cheaper. The actual length of this array is stored in /// `_rebalanceSize` and should be explicitly checked when necessary. Rebalance[65535] private _rebalances; /// @dev Historical rebalance count. uint256 private _rebalanceSize; /// @dev Total share supply of the three tranches. They are always rebalanced to the latest /// version. uint256[TRANCHE_COUNT] private _totalSupplies; /// @dev Mapping of account => share balance of the three tranches. /// Rebalance versions are stored in a separate mapping `_balanceVersions`. mapping(address => uint256[TRANCHE_COUNT]) private _balances; /// @dev Rebalance version mapping for `_balances`. mapping(address => uint256) private _balanceVersions; /// @dev Mapping of owner => spender => share allowance of the three tranches. /// Rebalance versions are stored in a separate mapping `_allowanceVersions`. mapping(address => mapping(address => uint256[TRANCHE_COUNT])) private _allowances; /// @dev Rebalance version mapping for `_allowances`. mapping(address => mapping(address => uint256)) private _allowanceVersions; /// @dev Mapping of trading day => NAV of BISHOP. mapping(uint256 => uint256) private _historicalNavB; /// @dev Mapping of trading day => NAV of ROOK. mapping(uint256 => uint256) private _historicalNavR; /// @notice Mapping of trading day => equivalent BISHOP supply. /// /// Key is the end timestamp of a trading day. Value is the total supply of BISHOP, /// as if all QUEEN are split. mapping(uint256 => uint256) public override historicalEquivalentTotalB; /// @notice Mapping of trading day => underlying assets in the fund. /// /// Key is the end timestamp of a trading day. Value is the underlying assets in /// the fund after settlement of that trading day. mapping(uint256 => uint256) public override historicalUnderlying; /// @notice Mapping of trading week => interest rate of BISHOP. /// /// Key is the end timestamp of a trading day. Value is the interest rate captured /// after settlement of that day, which will be effective until the next settlement. mapping(uint256 => uint256) public historicalInterestRate; /// @dev Amount of redemption underlying that the fund owes the primary market uint256 private _totalDebt; uint256 private _strategyUnderlying; struct ConstructorParameters { uint256 weightB; uint256 settlementPeriod; address tokenUnderlying; uint256 underlyingDecimals; address tokenQ; address tokenB; address tokenR; address primaryMarket; address strategy; address twapOracle; address aprOracle; address feeCollector; } constructor( ConstructorParameters memory params ) public Ownable() FundRolesV2( params.tokenQ, params.tokenB, params.tokenR, params.primaryMarket, params.strategy ) { weightB = params.weightB; require(params.settlementPeriod % 1 days == 0); settlementPeriod = params.settlementPeriod; tokenUnderlying = params.tokenUnderlying; require(params.underlyingDecimals <= 18, "Underlying decimals larger than 18"); underlyingDecimalMultiplier = 10 ** (18 - params.underlyingDecimals); _updateTwapOracle(params.twapOracle); _updateAprOracle(params.aprOracle); _updateFeeCollector(params.feeCollector); _updateActivityDelayTime(30 minutes); } function initialize( uint256 newSplitRatio, uint256 lastNavB, uint256 lastNavR, uint256 strategyUnderlying ) external onlyOwner { require(splitRatio == 0 && currentDay == 0, "Already initialized"); require(newSplitRatio != 0 && lastNavB >= UNIT, "Invalid parameters"); splitRatio = newSplitRatio; _historicalSplitRatio[0] = newSplitRatio; emit SplitRatioUpdated(newSplitRatio); uint256 lastDay = endOfDay(block.timestamp) - 1 days; currentDay = lastDay + settlementPeriod; uint256 lastDayPrice = twapOracle.getTwap(lastDay); require(lastDayPrice != 0, "Price not available"); // required to do the first creation _historicalNavB[lastDay] = lastNavB; _historicalNavR[lastDay] = lastNavR; _strategyUnderlying = strategyUnderlying; uint256 lastInterestRate = _updateInterestRate(lastDay); historicalInterestRate[lastDay] = lastInterestRate; emit Settled(lastDay, lastNavB, lastNavR, lastInterestRate); fundActivityStartTime = lastDay; } /// @notice UTC time of a day when the fund settles. function settlementTime() external pure returns (uint256) { return SETTLEMENT_TIME; } /// @notice Return end timestamp of the trading day containing a given timestamp. /// /// A trading day starts at UTC time `SETTLEMENT_TIME` of a day (inclusive) /// and ends at the same time of the next day (exclusive). /// @param timestamp The given timestamp /// @return End timestamp of the trading day. function endOfDay(uint256 timestamp) public pure override returns (uint256) { return ((timestamp.add(1 days) - SETTLEMENT_TIME) / 1 days) * 1 days + SETTLEMENT_TIME; } /// @notice Return end timestamp of the trading week containing a given timestamp. /// /// A trading week starts at UTC time `SETTLEMENT_TIME` on a Thursday (inclusive) /// and ends at the same time of the next Thursday (exclusive). /// @param timestamp The given timestamp /// @return End timestamp of the trading week. function endOfWeek(uint256 timestamp) external pure returns (uint256) { return _endOfWeek(timestamp); } function tokenQ() external view override returns (address) { return _tokenQ; } function tokenB() external view override returns (address) { return _tokenB; } function tokenR() external view override returns (address) { return _tokenR; } function tokenShare(uint256 tranche) external view override returns (address) { return _getShare(tranche); } function primaryMarket() external view override returns (address) { return _primaryMarket; } function primaryMarketUpdateProposal() external view override returns (address, uint256) { return (_proposedPrimaryMarket, _proposedPrimaryMarketTimestamp); } function strategy() external view override returns (address) { return _strategy; } function strategyUpdateProposal() external view override returns (address, uint256) { return (_proposedStrategy, _proposedStrategyTimestamp); } /// @notice Return the status of the fund contract. /// @param timestamp Timestamp to assess /// @return True if the fund contract is active function isFundActive(uint256 timestamp) public view override returns (bool) { return timestamp >= fundActivityStartTime; } function getTotalUnderlying() public view override returns (uint256) { uint256 hot = IERC20(tokenUnderlying).balanceOf(address(this)); return hot.add(_strategyUnderlying).sub(_totalDebt); } function getStrategyUnderlying() external view override returns (uint256) { return _strategyUnderlying; } /// @notice Get the amount of redemption underlying that the fund owes the primary market. function getTotalDebt() external view override returns (uint256) { return _totalDebt; } /// @notice Equivalent ROOK supply, as if all QUEEN are split. function getEquivalentTotalR() public view override returns (uint256) { return _totalSupplies[TRANCHE_Q].multiplyDecimal(splitRatio).add(_totalSupplies[TRANCHE_R]); } /// @notice Equivalent BISHOP supply, as if all QUEEN are split. function getEquivalentTotalB() public view override returns (uint256) { return getEquivalentTotalR().mul(weightB); } /// @notice Equivalent QUEEN supply, as if all BISHOP and ROOK are merged. function getEquivalentTotalQ() public view override returns (uint256) { return _totalSupplies[TRANCHE_R].divideDecimal(splitRatio).add(_totalSupplies[TRANCHE_Q]); } /// @notice Return the rebalance matrix at a given index. A zero struct is returned /// if `index` is out of bound. /// @param index Rebalance index /// @return A rebalance matrix function getRebalance(uint256 index) external view override returns (Rebalance memory) { return _rebalances[index]; } /// @notice Return timestamp of the transaction triggering the rebalance at a given index. /// Zero is returned if `index` is out of bound. /// @param index Rebalance index /// @return Timestamp of the rebalance function getRebalanceTimestamp(uint256 index) external view override returns (uint256) { return _rebalances[index].timestamp; } /// @notice Return the number of historical rebalances. function getRebalanceSize() external view override returns (uint256) { return _rebalanceSize; } function getSettledDay() public view override returns (uint256) { return currentDay - settlementPeriod; } /// @notice Return split ratio at a given version. /// Zero is returned if `version` is invalid. /// @param version Rebalance version /// @return Split ratio of the version function historicalSplitRatio(uint256 version) external view override returns (uint256) { return _historicalSplitRatio[version]; } /// @notice Return NAV of BISHOP and ROOK of the given trading day. /// @param day End timestamp of a trading day /// @return navB NAV of BISHOP /// @return navR NAV of ROOK function historicalNavs( uint256 day ) external view override returns (uint256 navB, uint256 navR) { return (_historicalNavB[day], _historicalNavR[day]); } /// @notice Estimate the current NAV of all tranches, considering underlying price change, /// and accrued interest since the previous settlement. /// /// The extrapolation uses simple interest instead of daily compound interest in /// calculating BISHOP's interest. There may be significant error /// in the returned values when `timestamp` is far beyond the last settlement. /// @param price Price of the underlying asset (18 decimal places) /// @return navSum Sum of navB * weightB and the estimated NAV of ROOK /// @return navB Estimated NAV of BISHOP /// @return navROrZero Estimated NAV of ROOK, or zero if the NAV is negative function extrapolateNav( uint256 price ) external view override returns (uint256 navSum, uint256 navB, uint256 navROrZero) { uint256 settledDay = getSettledDay(); uint256 underlying = getTotalUnderlying(); return _extrapolateNav(block.timestamp, settledDay, price, getEquivalentTotalR(), underlying); } function _extrapolateNav( uint256 timestamp, uint256 settledDay, uint256 price, uint256 equivalentTotalR, uint256 underlying ) private view returns (uint256 navSum, uint256 navB, uint256 navROrZero) { navB = _historicalNavB[settledDay]; if (equivalentTotalR > 0) { navSum = price.mul(underlying.mul(underlyingDecimalMultiplier)).div(equivalentTotalR); navB = navB.multiplyDecimal( historicalInterestRate[settledDay].mul(timestamp - settledDay).div(1 days).add(UNIT) ); navROrZero = navSum >= navB.mul(weightB) ? navSum - navB * weightB : 0; } else { // If the fund is empty, use NAV in the last day navROrZero = _historicalNavR[settledDay]; navSum = navB.mul(weightB) + navROrZero; } } /// @notice Transform share amounts according to the rebalance at a given index. /// This function performs no bounds checking on the given index. A non-existent /// rebalance transforms anything to a zero vector. /// @param amountQ Amount of QUEEN before the rebalance /// @param amountB Amount of BISHOP before the rebalance /// @param amountR Amount of ROOK before the rebalance /// @param index Rebalance index /// @return newAmountQ Amount of QUEEN after the rebalance /// @return newAmountB Amount of BISHOP after the rebalance /// @return newAmountR Amount of ROOK after the rebalance function doRebalance( uint256 amountQ, uint256 amountB, uint256 amountR, uint256 index ) public view override returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR) { Rebalance storage rebalance = _rebalances[index]; newAmountQ = amountQ.add(amountB.multiplyDecimal(rebalance.ratioB2Q)).add( amountR.multiplyDecimal(rebalance.ratioR2Q) ); uint256 ratioBR = rebalance.ratioBR; // Gas saver newAmountB = amountB.multiplyDecimal(ratioBR); newAmountR = amountR.multiplyDecimal(ratioBR); } /// @notice Transform share amounts according to rebalances in a given index range, /// This function performs no bounds checking on the given indices. The original amounts /// are returned if `fromIndex` is no less than `toIndex`. A zero vector is returned /// if `toIndex` is greater than the number of existing rebalances. /// @param amountQ Amount of QUEEN before the rebalance /// @param amountB Amount of BISHOP before the rebalance /// @param amountR Amount of ROOK before the rebalance /// @param fromIndex Starting of the rebalance index range, inclusive /// @param toIndex End of the rebalance index range, exclusive /// @return newAmountQ Amount of QUEEN after the rebalance /// @return newAmountB Amount of BISHOP after the rebalance /// @return newAmountR Amount of ROOK after the rebalance function batchRebalance( uint256 amountQ, uint256 amountB, uint256 amountR, uint256 fromIndex, uint256 toIndex ) external view override returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR) { for (uint256 i = fromIndex; i < toIndex; i++) { (amountQ, amountB, amountR) = doRebalance(amountQ, amountB, amountR, i); } newAmountQ = amountQ; newAmountB = amountB; newAmountR = amountR; } /// @notice Transform share balance to a given rebalance version, or to the latest version /// if `targetVersion` is zero. /// @param account Account of the balance to rebalance /// @param targetVersion The target rebalance version, or zero for the latest version function refreshBalance(address account, uint256 targetVersion) external override { if (targetVersion > 0) { require(targetVersion <= _rebalanceSize, "Target version out of bound"); } _refreshBalance(account, targetVersion); } /// @notice Transform allowance to a given rebalance version, or to the latest version /// if `targetVersion` is zero. /// @param owner Owner of the allowance to rebalance /// @param spender Spender of the allowance to rebalance /// @param targetVersion The target rebalance version, or zero for the latest version function refreshAllowance( address owner, address spender, uint256 targetVersion ) external override { if (targetVersion > 0) { require(targetVersion <= _rebalanceSize, "Target version out of bound"); } _refreshAllowance(owner, spender, targetVersion); } function trancheBalanceOf( uint256 tranche, address account ) external view override returns (uint256) { uint256 latestVersion = _rebalanceSize; uint256 userVersion = _balanceVersions[account]; if (userVersion == latestVersion) { // Fast path return _balances[account][tranche]; } uint256 amountQ = _balances[account][TRANCHE_Q]; uint256 amountB = _balances[account][TRANCHE_B]; uint256 amountR = _balances[account][TRANCHE_R]; for (uint256 i = userVersion; i < latestVersion; i++) { (amountQ, amountB, amountR) = doRebalance(amountQ, amountB, amountR, i); } if (tranche == TRANCHE_Q) { return amountQ; } else if (tranche == TRANCHE_B) { return amountB; } else if (tranche == TRANCHE_R) { return amountR; } else { revert("Invalid tranche"); } } /// @notice Return all three share balances transformed to the latest rebalance version. /// @param account Owner of the shares function trancheAllBalanceOf( address account ) external view override returns (uint256, uint256, uint256) { uint256 amountQ = _balances[account][TRANCHE_Q]; uint256 amountB = _balances[account][TRANCHE_B]; uint256 amountR = _balances[account][TRANCHE_R]; uint256 size = _rebalanceSize; // Gas saver for (uint256 i = _balanceVersions[account]; i < size; i++) { (amountQ, amountB, amountR) = doRebalance(amountQ, amountB, amountR, i); } return (amountQ, amountB, amountR); } function trancheBalanceVersion(address account) external view override returns (uint256) { return _balanceVersions[account]; } function trancheAllowance( uint256 tranche, address owner, address spender ) external view override returns (uint256) { uint256 allowance = _allowances[owner][spender][tranche]; if (tranche != TRANCHE_Q) { uint256 size = _rebalanceSize; // Gas saver for (uint256 i = _allowanceVersions[owner][spender]; i < size; i++) { allowance = _rebalanceAllowanceBR(allowance, i); } } return allowance; } function trancheAllowanceVersion( address owner, address spender ) external view override returns (uint256) { return _allowanceVersions[owner][spender]; } function trancheTransfer( uint256 tranche, address recipient, uint256 amount, uint256 version ) external override onlyCurrentVersion(version) { _refreshBalance(msg.sender, version); if (tranche != TRANCHE_Q) { _refreshBalance(recipient, version); } _transfer(tranche, msg.sender, recipient, amount); } function trancheTransferFrom( uint256 tranche, address sender, address recipient, uint256 amount, uint256 version ) external override onlyCurrentVersion(version) { _refreshBalance(sender, version); if (tranche != TRANCHE_Q) { _refreshAllowance(sender, msg.sender, version); _refreshBalance(recipient, version); } uint256 newAllowance = _allowances[sender][msg.sender][tranche].sub( amount, "ERC20: transfer amount exceeds allowance" ); _approve(tranche, sender, msg.sender, newAllowance); _transfer(tranche, sender, recipient, amount); } function trancheApprove( uint256 tranche, address spender, uint256 amount, uint256 version ) external override onlyCurrentVersion(version) { if (tranche != TRANCHE_Q) { _refreshAllowance(msg.sender, spender, version); } _approve(tranche, msg.sender, spender, amount); } function trancheTotalSupply(uint256 tranche) external view override returns (uint256) { return _totalSupplies[tranche]; } function primaryMarketMint( uint256 tranche, address account, uint256 amount, uint256 version ) external override onlyPrimaryMarket onlyCurrentVersion(version) { if (tranche != TRANCHE_Q) { _refreshBalance(account, version); } _mint(tranche, account, amount); } function primaryMarketBurn( uint256 tranche, address account, uint256 amount, uint256 version ) external override onlyPrimaryMarket onlyCurrentVersion(version) { // Unlike `primaryMarketMint()`, `_refreshBalance()` is required even if we are burning // QUEEN tokens, because a rebalance may increase the user's QUEEN balance if the user // owns BISHOP or ROOK tokens beforehand. _refreshBalance(account, version); _burn(tranche, account, amount); } function shareTransfer(address sender, address recipient, uint256 amount) public override { uint256 tranche = _getTranche(msg.sender); if (tranche != TRANCHE_Q) { require(isFundActive(block.timestamp), "Transfer is inactive"); _refreshBalance(recipient, _rebalanceSize); } _refreshBalance(sender, _rebalanceSize); _transfer(tranche, sender, recipient, amount); } function shareTransferFrom( address spender, address sender, address recipient, uint256 amount ) external override returns (uint256 newAllowance) { uint256 tranche = _getTranche(msg.sender); shareTransfer(sender, recipient, amount); if (tranche != TRANCHE_Q) { _refreshAllowance(sender, spender, _rebalanceSize); } newAllowance = _allowances[sender][spender][tranche].sub( amount, "ERC20: transfer amount exceeds allowance" ); _approve(tranche, sender, spender, newAllowance); } function shareApprove(address owner, address spender, uint256 amount) external override { uint256 tranche = _getTranche(msg.sender); if (tranche != TRANCHE_Q) { _refreshAllowance(owner, spender, _rebalanceSize); } _approve(tranche, owner, spender, amount); } function shareIncreaseAllowance( address sender, address spender, uint256 addedValue ) external override returns (uint256 newAllowance) { uint256 tranche = _getTranche(msg.sender); if (tranche != TRANCHE_Q) { _refreshAllowance(sender, spender, _rebalanceSize); } newAllowance = _allowances[sender][spender][tranche].add(addedValue); _approve(tranche, sender, spender, newAllowance); } function shareDecreaseAllowance( address sender, address spender, uint256 subtractedValue ) external override returns (uint256 newAllowance) { uint256 tranche = _getTranche(msg.sender); if (tranche != TRANCHE_Q) { _refreshAllowance(sender, spender, _rebalanceSize); } newAllowance = _allowances[sender][spender][tranche].sub(subtractedValue); _approve(tranche, sender, spender, newAllowance); } function _transfer(uint256 tranche, address sender, address recipient, uint256 amount) private { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender][tranche] = _balances[sender][tranche].sub( amount, "ERC20: transfer amount exceeds balance" ); _balances[recipient][tranche] = _balances[recipient][tranche].add(amount); IShareV2(_getShare(tranche)).fundEmitTransfer(sender, recipient, amount); } function _mint(uint256 tranche, address account, uint256 amount) private { require(account != address(0), "ERC20: mint to the zero address"); _totalSupplies[tranche] = _totalSupplies[tranche].add(amount); _balances[account][tranche] = _balances[account][tranche].add(amount); IShareV2(_getShare(tranche)).fundEmitTransfer(address(0), account, amount); } function _burn(uint256 tranche, address account, uint256 amount) private { require(account != address(0), "ERC20: burn from the zero address"); _balances[account][tranche] = _balances[account][tranche].sub( amount, "ERC20: burn amount exceeds balance" ); _totalSupplies[tranche] = _totalSupplies[tranche].sub(amount); IShareV2(_getShare(tranche)).fundEmitTransfer(account, address(0), amount); } function _approve(uint256 tranche, address owner, address spender, uint256 amount) private { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender][tranche] = amount; IShareV2(_getShare(tranche)).fundEmitApproval(owner, spender, amount); } /// @notice Freeze up the fund when ROOK nav falls below zero. This function is meant for /// emergency use only, and can be called by anyone. function freeze() external { require(!frozen, "Already frozen"); uint256 day = currentDay; require(day != 0, "Not initialized"); uint256 price = twapOracle.getLatest(); // Calculate NAV uint256 underlying = getTotalUnderlying(); (, , uint256 navR) = _extrapolateNav( block.timestamp, day - settlementPeriod, price, getEquivalentTotalR(), underlying ); require(navR == 0, "Not to be frozen"); frozen = true; emit Frozen(); } /// @notice Settle the current trading day. Settlement includes the following changes /// to the fund. /// /// 1. Settle all pending creations and redemptions from the primary market. /// 2. Calculate NAV of the day and trigger rebalance if necessary. /// 3. Capture new interest rate for BISHOP. function settle() external nonReentrant onlyNotFrozen { uint256 day = currentDay; require(day != 0, "Not initialized"); require(block.timestamp >= day, "The current trading year does not end yet"); uint256 price = twapOracle.getTwap(day); require(price != 0, "Underlying price for settlement is not ready yet"); IPrimaryMarketV3(_primaryMarket).settle(day); // Calculate NAV uint256 underlying = getTotalUnderlying(); (uint256 navSum, uint256 navB, uint256 navR) = _extrapolateNav( day, day - settlementPeriod, price, getEquivalentTotalR(), underlying ); require(navR > 0, "To be frozen"); uint256 newSplitRatio = splitRatio.multiplyDecimal(navSum) / (weightB + 1); _triggerRebalance(day, navSum, navB, navR, newSplitRatio); navB = UNIT; navR = UNIT; fundActivityStartTime = day + activityDelayTimeAfterRebalance; historicalEquivalentTotalB[day] = getEquivalentTotalB(); historicalUnderlying[day] = underlying; _historicalNavB[day] = navB; _historicalNavR[day] = navR; uint256 interestRate = _updateInterestRate(day); historicalInterestRate[day] = interestRate; currentDay = day + settlementPeriod; emit Settled(day, navB, navR, interestRate); } function transferToStrategy(uint256 amount) external override onlyStrategy { _strategyUnderlying = _strategyUnderlying.add(amount); IERC20(tokenUnderlying).safeTransfer(_strategy, amount); } function transferFromStrategy(uint256 amount) external override onlyStrategy { _strategyUnderlying = _strategyUnderlying.sub(amount); IERC20(tokenUnderlying).safeTransferFrom(_strategy, address(this), amount); } function primaryMarketTransferUnderlying( address recipient, uint256 amount, uint256 feeQ ) external override onlyPrimaryMarket { IERC20(tokenUnderlying).safeTransfer(recipient, amount); _mint(TRANCHE_Q, feeCollector, feeQ); } function primaryMarketAddDebtAndFee( uint256 amount, uint256 feeQ ) external override onlyPrimaryMarket { _mint(TRANCHE_Q, feeCollector, feeQ); _updateTotalDebt(_totalDebt.add(amount)); } function primaryMarketPayDebt(uint256 amount) external override onlyPrimaryMarket { _updateTotalDebt(_totalDebt.sub(amount)); IERC20(tokenUnderlying).safeTransfer(msg.sender, amount); } function reportProfit( uint256 profit, uint256 totalFee, uint256 strategyFee ) external override onlyStrategy returns (uint256 strategyFeeQ) { require(profit >= totalFee && totalFee >= strategyFee, "Fee cannot exceed profit"); _strategyUnderlying = _strategyUnderlying.add(profit); uint256 equivalentTotalQ = getEquivalentTotalQ(); uint256 totalUnderlyingAfterFee = getTotalUnderlying() - totalFee; uint256 totalFeeQ = totalFee.mul(equivalentTotalQ).div(totalUnderlyingAfterFee); strategyFeeQ = strategyFee.mul(equivalentTotalQ).div(totalUnderlyingAfterFee); _mint(TRANCHE_Q, feeCollector, totalFeeQ.sub(strategyFeeQ)); _mint(TRANCHE_Q, msg.sender, strategyFeeQ); emit ProfitReported(profit, totalFee, totalFeeQ, strategyFeeQ); } function reportLoss(uint256 loss) external override onlyStrategy { _strategyUnderlying = _strategyUnderlying.sub(loss); emit LossReported(loss); } function proposePrimaryMarketUpdate(address newPrimaryMarket) external onlyOwner { _proposePrimaryMarketUpdate(newPrimaryMarket); } function applyPrimaryMarketUpdate(address newPrimaryMarket) external onlyOwner { require( IPrimaryMarketV3(_primaryMarket).canBeRemovedFromFund(), "Cannot update primary market" ); _applyPrimaryMarketUpdate(newPrimaryMarket); } function proposeStrategyUpdate(address newStrategy) external onlyOwner { _proposeStrategyUpdate(newStrategy); } function applyStrategyUpdate(address newStrategy) external onlyOwner { require(_totalDebt == 0, "Cannot update strategy with debt"); _applyStrategyUpdate(newStrategy); } function _updateTwapOracle(address newTwapOracle) private { twapOracle = ITwapOracleV2(newTwapOracle); emit TwapOracleUpdated(newTwapOracle); } function updateTwapOracle(address newTwapOracle) external onlyOwner { _updateTwapOracle(newTwapOracle); } function _updateAprOracle(address newAprOracle) private { aprOracle = IAprOracle(newAprOracle); emit AprOracleUpdated(newAprOracle); } function updateAprOracle(address newAprOracle) external onlyOwner { _updateAprOracle(newAprOracle); } function _updateFeeCollector(address newFeeCollector) private { feeCollector = newFeeCollector; emit FeeCollectorUpdated(newFeeCollector); } function updateFeeCollector(address newFeeCollector) external onlyOwner { _updateFeeCollector(newFeeCollector); } function _updateActivityDelayTime(uint256 delayTime) private { require( delayTime >= 30 minutes && delayTime <= 12 hours, "Exceed allowed delay time range" ); activityDelayTimeAfterRebalance = delayTime; emit ActivityDelayTimeUpdated(delayTime); } function updateActivityDelayTime(uint256 delayTime) external onlyOwner { _updateActivityDelayTime(delayTime); } /// @dev Create a new rebalance that resets NAV of all tranches to 1. Total supplies are /// rebalanced immediately. /// @param day Trading day that triggers this rebalance /// @param navB BISHOP's NAV before this rebalance /// @param navR ROOK's NAV before this rebalance /// @param newSplitRatio The new split ratio after this rebalance function _triggerRebalance( uint256 day, uint256 navSum, uint256 navB, uint256 navR, uint256 newSplitRatio ) private { Rebalance memory rebalance = _calculateRebalance(navB, navR, newSplitRatio); uint256 oldSize = _rebalanceSize; splitRatio = newSplitRatio; _historicalSplitRatio[oldSize + 1] = newSplitRatio; emit SplitRatioUpdated(newSplitRatio); _rebalances[oldSize] = rebalance; _rebalanceSize = oldSize + 1; emit RebalanceTriggered( oldSize, day, navSum, navB, navR, rebalance.ratioB2Q, rebalance.ratioR2Q, rebalance.ratioBR ); ( _totalSupplies[TRANCHE_Q], _totalSupplies[TRANCHE_B], _totalSupplies[TRANCHE_R] ) = doRebalance( _totalSupplies[TRANCHE_Q], _totalSupplies[TRANCHE_B], _totalSupplies[TRANCHE_R], oldSize ); _refreshBalance(address(this), oldSize + 1); } /// @dev Create a new rebalance matrix that resets given NAVs to (1, 1). /// @param navB BISHOP's NAV before the rebalance /// @param navR ROOK's NAV before the rebalance /// @param newSplitRatio The new split ratio after this rebalance /// @return The rebalance matrix function _calculateRebalance( uint256 navB, uint256 navR, uint256 newSplitRatio ) private view returns (Rebalance memory) { uint256 ratioBR; uint256 ratioB2Q; uint256 ratioR2Q; if (navR <= navB) { ratioBR = navR; ratioB2Q = (navB - navR).divideDecimal(newSplitRatio) / (weightB + 1); ratioR2Q = 0; } else { ratioBR = navB; ratioB2Q = 0; ratioR2Q = (navR - navB).divideDecimal(newSplitRatio) / (weightB + 1); } return Rebalance({ ratioB2Q: ratioB2Q, ratioR2Q: ratioR2Q, ratioBR: ratioBR, timestamp: block.timestamp }); } function _updateInterestRate(uint256) private returns (uint256) { uint256 rate = MAX_INTEREST_RATE.min(aprOracle.capture()); emit InterestRateUpdated(rate, 0); return rate; } function _updateTotalDebt(uint256 newTotalDebt) private { _totalDebt = newTotalDebt; emit TotalDebtUpdated(newTotalDebt); } /// @dev Transform share balance to a given rebalance version, or to the latest version /// if `targetVersion` is zero. This function does no bound check on `targetVersion`. /// @param account Account of the balance to rebalance /// @param targetVersion The target rebalance version, or zero for the latest version function _refreshBalance(address account, uint256 targetVersion) private { if (targetVersion == 0) { targetVersion = _rebalanceSize; } uint256 oldVersion = _balanceVersions[account]; if (oldVersion >= targetVersion) { return; } uint256[TRANCHE_COUNT] storage balanceTuple = _balances[account]; uint256 balanceQ = balanceTuple[TRANCHE_Q]; uint256 balanceB = balanceTuple[TRANCHE_B]; uint256 balanceR = balanceTuple[TRANCHE_R]; _balanceVersions[account] = targetVersion; if (balanceB == 0 && balanceR == 0) { // Fast path for zero BISHOP and ROOK balance return; } for (uint256 i = oldVersion; i < targetVersion; i++) { (balanceQ, balanceB, balanceR) = doRebalance(balanceQ, balanceB, balanceR, i); } balanceTuple[TRANCHE_Q] = balanceQ; balanceTuple[TRANCHE_B] = balanceB; balanceTuple[TRANCHE_R] = balanceR; emit BalancesRebalanced(account, targetVersion, balanceQ, balanceB, balanceR); } /// @dev Transform allowance to a given rebalance version, or to the latest version /// if `targetVersion` is zero. This function does no bound check on `targetVersion`. /// @param owner Owner of the allowance to rebalance /// @param spender Spender of the allowance to rebalance /// @param targetVersion The target rebalance version, or zero for the latest version function _refreshAllowance(address owner, address spender, uint256 targetVersion) private { if (targetVersion == 0) { targetVersion = _rebalanceSize; } uint256 oldVersion = _allowanceVersions[owner][spender]; if (oldVersion >= targetVersion) { return; } uint256[TRANCHE_COUNT] storage allowanceTuple = _allowances[owner][spender]; uint256 allowanceB = allowanceTuple[TRANCHE_B]; uint256 allowanceR = allowanceTuple[TRANCHE_R]; _allowanceVersions[owner][spender] = targetVersion; if (allowanceB == 0 && allowanceR == 0) { // Fast path for empty BISHOP and ROOK allowance return; } for (uint256 i = oldVersion; i < targetVersion; i++) { allowanceB = _rebalanceAllowanceBR(allowanceB, i); allowanceR = _rebalanceAllowanceBR(allowanceR, i); } allowanceTuple[TRANCHE_B] = allowanceB; allowanceTuple[TRANCHE_R] = allowanceR; emit AllowancesRebalanced( owner, spender, targetVersion, allowanceTuple[TRANCHE_Q], allowanceB, allowanceR ); } function _rebalanceAllowanceBR( uint256 allowance, uint256 index ) private view returns (uint256) { Rebalance storage rebalance = _rebalances[index]; /// @dev using saturating arithmetic to avoid unconscious overflow revert return allowance.saturatingMultiplyDecimal(rebalance.ratioBR); } modifier onlyCurrentVersion(uint256 version) { require(_rebalanceSize == version, "Only current version"); _; } modifier onlyNotFrozen() { require(!frozen, "Frozen"); _; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @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 () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), 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 { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; import "../interfaces/ITrancheIndexV2.sol"; abstract contract FundRolesV2 is ITrancheIndexV2 { event PrimaryMarketUpdateProposed( address indexed newPrimaryMarket, uint256 minTimestamp, uint256 maxTimestamp ); event PrimaryMarketUpdated( address indexed previousPrimaryMarket, address indexed newPrimaryMarket ); event StrategyUpdateProposed( address indexed newStrategy, uint256 minTimestamp, uint256 maxTimestamp ); event StrategyUpdated(address indexed previousStrategy, address indexed newStrategy); uint256 private constant ROLE_UPDATE_MIN_DELAY = 3 days; uint256 private constant ROLE_UPDATE_MAX_DELAY = 15 days; address internal immutable _tokenQ; address internal immutable _tokenB; address internal immutable _tokenR; address internal _primaryMarket; address internal _proposedPrimaryMarket; uint256 internal _proposedPrimaryMarketTimestamp; address internal _strategy; address internal _proposedStrategy; uint256 internal _proposedStrategyTimestamp; constructor( address tokenQ_, address tokenB_, address tokenR_, address primaryMarket_, address strategy_ ) public { _tokenQ = tokenQ_; _tokenB = tokenB_; _tokenR = tokenR_; _primaryMarket = primaryMarket_; _strategy = strategy_; emit PrimaryMarketUpdated(address(0), primaryMarket_); emit StrategyUpdated(address(0), strategy_); } function _getTranche(address share) internal view returns (uint256) { if (share == _tokenQ) { return TRANCHE_Q; } else if (share == _tokenB) { return TRANCHE_B; } else if (share == _tokenR) { return TRANCHE_R; } else { revert("Only share"); } } function _getShare(uint256 tranche) internal view returns (address) { if (tranche == TRANCHE_Q) { return _tokenQ; } else if (tranche == TRANCHE_B) { return _tokenB; } else if (tranche == TRANCHE_R) { return _tokenR; } else { revert("Invalid tranche"); } } modifier onlyPrimaryMarket() { require(msg.sender == _primaryMarket, "Only primary market"); _; } function _proposePrimaryMarketUpdate(address newPrimaryMarket) internal { require(newPrimaryMarket != _primaryMarket); _proposedPrimaryMarket = newPrimaryMarket; _proposedPrimaryMarketTimestamp = block.timestamp; emit PrimaryMarketUpdateProposed( newPrimaryMarket, block.timestamp + ROLE_UPDATE_MIN_DELAY, block.timestamp + ROLE_UPDATE_MAX_DELAY ); } function _applyPrimaryMarketUpdate(address newPrimaryMarket) internal { require(_proposedPrimaryMarket == newPrimaryMarket, "Proposed address mismatch"); require( block.timestamp >= _proposedPrimaryMarketTimestamp + ROLE_UPDATE_MIN_DELAY && block.timestamp < _proposedPrimaryMarketTimestamp + ROLE_UPDATE_MAX_DELAY, "Not ready to update" ); emit PrimaryMarketUpdated(_primaryMarket, newPrimaryMarket); _primaryMarket = newPrimaryMarket; _proposedPrimaryMarket = address(0); _proposedPrimaryMarketTimestamp = 0; } modifier onlyStrategy() { require(msg.sender == _strategy, "Only strategy"); _; } function _proposeStrategyUpdate(address newStrategy) internal { require(newStrategy != _strategy); _proposedStrategy = newStrategy; _proposedStrategyTimestamp = block.timestamp; emit StrategyUpdateProposed( newStrategy, block.timestamp + ROLE_UPDATE_MIN_DELAY, block.timestamp + ROLE_UPDATE_MAX_DELAY ); } function _applyStrategyUpdate(address newStrategy) internal { require(_proposedStrategy == newStrategy, "Proposed address mismatch"); require( block.timestamp >= _proposedStrategyTimestamp + ROLE_UPDATE_MIN_DELAY && block.timestamp < _proposedStrategyTimestamp + ROLE_UPDATE_MAX_DELAY, "Not ready to update" ); emit StrategyUpdated(_strategy, newStrategy); _strategy = newStrategy; _proposedStrategy = address(0); _proposedStrategyTimestamp = 0; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; interface IAprOracle { function capture() external returns (uint256 dailyRate); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; interface IFundForPrimaryMarketV4 { function primaryMarketMint( uint256 tranche, address account, uint256 amount, uint256 version ) external; function primaryMarketBurn( uint256 tranche, address account, uint256 amount, uint256 version ) external; function primaryMarketTransferUnderlying( address recipient, uint256 amount, uint256 feeQ ) external; function primaryMarketAddDebtAndFee(uint256 amount, uint256 feeQ) external; function primaryMarketPayDebt(uint256 amount) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; interface IFundForStrategyV2 { function transferToStrategy(uint256 amount) external; function transferFromStrategy(uint256 amount) external; function reportProfit( uint256 profit, uint256 totalFee, uint256 strategyFee ) external returns (uint256 outQ); function reportLoss(uint256 loss) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; pragma experimental ABIEncoderV2; import "./ITwapOracleV2.sol"; interface IFundV3 { /// @notice A linear transformation matrix that represents a rebalance. /// /// ``` /// [ 1 0 0 ] /// R = [ ratioB2Q ratioBR 0 ] /// [ ratioR2Q 0 ratioBR ] /// ``` /// /// Amounts of the three tranches `q`, `b` and `r` can be rebalanced by multiplying the matrix: /// /// ``` /// [ q', b', r' ] = [ q, b, r ] * R /// ``` struct Rebalance { uint256 ratioB2Q; uint256 ratioR2Q; uint256 ratioBR; uint256 timestamp; } function tokenUnderlying() external view returns (address); function tokenQ() external view returns (address); function tokenB() external view returns (address); function tokenR() external view returns (address); function tokenShare(uint256 tranche) external view returns (address); function primaryMarket() external view returns (address); function primaryMarketUpdateProposal() external view returns (address, uint256); function strategy() external view returns (address); function strategyUpdateProposal() external view returns (address, uint256); function underlyingDecimalMultiplier() external view returns (uint256); function twapOracle() external view returns (ITwapOracleV2); function feeCollector() external view returns (address); function endOfDay(uint256 timestamp) external pure returns (uint256); function trancheTotalSupply(uint256 tranche) external view returns (uint256); function trancheBalanceOf(uint256 tranche, address account) external view returns (uint256); function trancheAllBalanceOf(address account) external view returns (uint256, uint256, uint256); function trancheBalanceVersion(address account) external view returns (uint256); function trancheAllowance( uint256 tranche, address owner, address spender ) external view returns (uint256); function trancheAllowanceVersion( address owner, address spender ) external view returns (uint256); function trancheTransfer( uint256 tranche, address recipient, uint256 amount, uint256 version ) external; function trancheTransferFrom( uint256 tranche, address sender, address recipient, uint256 amount, uint256 version ) external; function trancheApprove( uint256 tranche, address spender, uint256 amount, uint256 version ) external; function getRebalanceSize() external view returns (uint256); function getRebalance(uint256 index) external view returns (Rebalance memory); function getRebalanceTimestamp(uint256 index) external view returns (uint256); function currentDay() external view returns (uint256); function splitRatio() external view returns (uint256); function historicalSplitRatio(uint256 version) external view returns (uint256); function fundActivityStartTime() external view returns (uint256); function isFundActive(uint256 timestamp) external view returns (bool); function getEquivalentTotalB() external view returns (uint256); function getEquivalentTotalQ() external view returns (uint256); function historicalEquivalentTotalB(uint256 timestamp) external view returns (uint256); function historicalNavs(uint256 timestamp) external view returns (uint256 navB, uint256 navR); function extrapolateNav(uint256 price) external view returns (uint256, uint256, uint256); function doRebalance( uint256 amountQ, uint256 amountB, uint256 amountR, uint256 index ) external view returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR); function batchRebalance( uint256 amountQ, uint256 amountB, uint256 amountR, uint256 fromIndex, uint256 toIndex ) external view returns (uint256 newAmountQ, uint256 newAmountB, uint256 newAmountR); function refreshBalance(address account, uint256 targetVersion) external; function refreshAllowance(address owner, address spender, uint256 targetVersion) external; function shareTransfer(address sender, address recipient, uint256 amount) external; function shareTransferFrom( address spender, address sender, address recipient, uint256 amount ) external returns (uint256 newAllowance); function shareIncreaseAllowance( address sender, address spender, uint256 addedValue ) external returns (uint256 newAllowance); function shareDecreaseAllowance( address sender, address spender, uint256 subtractedValue ) external returns (uint256 newAllowance); function shareApprove(address owner, address spender, uint256 amount) external; function historicalUnderlying(uint256 timestamp) external view returns (uint256); function getTotalUnderlying() external view returns (uint256); function getStrategyUnderlying() external view returns (uint256); function getTotalDebt() external view returns (uint256); event RebalanceTriggered( uint256 indexed index, uint256 indexed day, uint256 navSum, uint256 navB, uint256 navROrZero, uint256 ratioB2Q, uint256 ratioR2Q, uint256 ratioBR ); event Settled(uint256 indexed day, uint256 navB, uint256 navR, uint256 interestRate); event InterestRateUpdated(uint256 baseInterestRate, uint256 floatingInterestRate); event BalancesRebalanced( address indexed account, uint256 version, uint256 balanceQ, uint256 balanceB, uint256 balanceR ); event AllowancesRebalanced( address indexed owner, address indexed spender, uint256 version, uint256 allowanceQ, uint256 allowanceB, uint256 allowanceR ); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; import "./IFundV3.sol"; interface IFundV5 is IFundV3 { function weightB() external view returns (uint256); function getSettledDay() external view returns (uint256); function getEquivalentTotalR() external view returns (uint256); function frozen() external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; interface IPrimaryMarketV3 { function fund() external view returns (address); function getCreation(uint256 underlying) external view returns (uint256 outQ); function getCreationForQ(uint256 minOutQ) external view returns (uint256 underlying); function getRedemption(uint256 inQ) external view returns (uint256 underlying, uint256 fee); function getRedemptionForUnderlying(uint256 minUnderlying) external view returns (uint256 inQ); function getSplit(uint256 inQ) external view returns (uint256 outB); function getSplitForB(uint256 minOutB) external view returns (uint256 inQ); function getMerge(uint256 inB) external view returns (uint256 outQ, uint256 feeQ); function getMergeForQ(uint256 minOutQ) external view returns (uint256 inB); function canBeRemovedFromFund() external view returns (bool); function create( address recipient, uint256 minOutQ, uint256 version ) external returns (uint256 outQ); function redeem( address recipient, uint256 inQ, uint256 minUnderlying, uint256 version ) external returns (uint256 underlying); function redeemAndUnwrap( address recipient, uint256 inQ, uint256 minUnderlying, uint256 version ) external returns (uint256 underlying); function queueRedemption( address recipient, uint256 inQ, uint256 minUnderlying, uint256 version ) external returns (uint256 underlying, uint256 index); function claimRedemptions( address account, uint256[] calldata indices ) external returns (uint256 underlying); function claimRedemptionsAndUnwrap( address account, uint256[] calldata indices ) external returns (uint256 underlying); function split(address recipient, uint256 inQ, uint256 version) external returns (uint256 outB); function merge(address recipient, uint256 inB, uint256 version) external returns (uint256 outQ); function settle(uint256 day) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IShareV2 is IERC20 { function fundEmitTransfer(address sender, address recipient, uint256 amount) external; function fundEmitApproval(address owner, address spender, uint256 amount) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; /// @notice Amounts of QUEEN, BISHOP and ROOK are sometimes stored in a `uint256[3]` array. /// This contract defines index of each tranche in this array. /// /// Solidity does not allow constants to be defined in interfaces. So this contract follows /// the naming convention of interfaces but is implemented as an `abstract contract`. abstract contract ITrancheIndexV2 { uint256 internal constant TRANCHE_Q = 0; uint256 internal constant TRANCHE_B = 1; uint256 internal constant TRANCHE_R = 2; uint256 internal constant TRANCHE_COUNT = 3; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; interface ITwapOracle { enum UpdateType { PRIMARY, SECONDARY, OWNER, CHAINLINK, UNISWAP_V2 } function getTwap(uint256 timestamp) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; import "./ITwapOracle.sol"; interface ITwapOracleV2 is ITwapOracle { function getLatest() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; pragma experimental ABIEncoderV2; interface IAddressWhitelist { function check(address account) external view returns (bool); } interface IVotingEscrowCallback { function syncWithVotingEscrow(address account) external; } interface IVotingEscrow { struct LockedBalance { uint256 amount; uint256 unlockTime; } function token() external view returns (address); function maxTime() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function totalSupply() external view returns (uint256); function balanceOfAtTimestamp( address account, uint256 timestamp ) external view returns (uint256); function getTimestampDropBelow( address account, uint256 threshold ) external view returns (uint256); function getLockedBalance(address account) external view returns (LockedBalance memory); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.10 <0.8.0; import "@openzeppelin/contracts/math/SafeMath.sol"; abstract contract CoreUtility { using SafeMath for uint256; /// @dev UTC time of a day when the fund settles. uint256 internal constant SETTLEMENT_TIME = 14 hours; /// @dev Return end timestamp of the trading week containing a given timestamp. /// /// A trading week starts at UTC time `SETTLEMENT_TIME` on a Thursday (inclusive) /// and ends at the same time of the next Thursday (exclusive). /// @param timestamp The given timestamp /// @return End timestamp of the trading week. function _endOfWeek(uint256 timestamp) internal pure returns (uint256) { return ((timestamp.add(1 weeks) - SETTLEMENT_TIME) / 1 weeks) * 1 weeks + SETTLEMENT_TIME; } }
// SPDX-License-Identifier: MIT // // Copyright (c) 2019 Synthetix // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.10 <0.8.0; import "@openzeppelin/contracts/math/SafeMath.sol"; library SafeDecimalMath { using SafeMath for uint256; /* Number of decimal places in the representations. */ uint256 private constant decimals = 18; uint256 private constant highPrecisionDecimals = 27; /* The number representing 1.0. */ uint256 private constant UNIT = 10 ** uint256(decimals); /* The number representing 1.0 for higher fidelity numbers. */ uint256 private constant PRECISE_UNIT = 10 ** uint256(highPrecisionDecimals); uint256 private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10 ** uint256(highPrecisionDecimals - decimals); /** * @return The result of multiplying x and y, interpreting the operands as fixed-point * decimals. * * @dev A unit factor is divided out after the product of x and y is evaluated, * so that product must be less than 2**256. As this is an integer division, * the internal division always rounds down. This helps save on gas. Rounding * is more expensive on gas. */ function multiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y).div(UNIT); } function multiplyDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y).div(PRECISE_UNIT); } /** * @return The result of safely dividing x and y. The return value is a high * precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and UNIT must be less than 2**256. As * this is an integer division, the result is always rounded down. * This helps save on gas. Rounding is more expensive on gas. */ function divideDecimal(uint256 x, uint256 y) internal pure returns (uint256) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(UNIT).div(y); } function divideDecimalPrecise(uint256 x, uint256 y) internal pure returns (uint256) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(PRECISE_UNIT).div(y); } /** * @dev Convert a standard decimal representation to a high precision one. */ function decimalToPreciseDecimal(uint256 i) internal pure returns (uint256) { return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); } /** * @dev Convert a high precision decimal to a standard decimal representation. */ function preciseDecimalToDecimal(uint256 i) internal pure returns (uint256) { uint256 quotientTimesTen = i.mul(10).div(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); if (quotientTimesTen % 10 >= 5) { quotientTimesTen = quotientTimesTen.add(10); } return quotientTimesTen.div(10); } /** * @dev Returns the multiplication of two unsigned integers, and the max value of * uint256 on overflow. */ function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; return c / a != b ? type(uint256).max : c; } function saturatingMultiplyDecimal(uint256 x, uint256 y) internal pure returns (uint256) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return saturatingMul(x, y).div(UNIT); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"uint256","name":"weightB","type":"uint256"},{"internalType":"uint256","name":"settlementPeriod","type":"uint256"},{"internalType":"address","name":"tokenUnderlying","type":"address"},{"internalType":"uint256","name":"underlyingDecimals","type":"uint256"},{"internalType":"address","name":"tokenQ","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"address","name":"tokenR","type":"address"},{"internalType":"address","name":"primaryMarket","type":"address"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"twapOracle","type":"address"},{"internalType":"address","name":"aprOracle","type":"address"},{"internalType":"address","name":"feeCollector","type":"address"}],"internalType":"struct FundV5.ConstructorParameters","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delayTime","type":"uint256"}],"name":"ActivityDelayTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowanceQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowanceB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allowanceR","type":"uint256"}],"name":"AllowancesRebalanced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAprOracle","type":"address"}],"name":"AprOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceR","type":"uint256"}],"name":"BalancesRebalanced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newFeeCollector","type":"address"}],"name":"FeeCollectorUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Frozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baseInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"floatingInterestRate","type":"uint256"}],"name":"InterestRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"loss","type":"uint256"}],"name":"LossReported","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":true,"internalType":"address","name":"newPrimaryMarket","type":"address"},{"indexed":false,"internalType":"uint256","name":"minTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxTimestamp","type":"uint256"}],"name":"PrimaryMarketUpdateProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousPrimaryMarket","type":"address"},{"indexed":true,"internalType":"address","name":"newPrimaryMarket","type":"address"}],"name":"PrimaryMarketUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalFeeQ","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"strategyFeeQ","type":"uint256"}],"name":"ProfitReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navSum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navROrZero","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ratioB2Q","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ratioR2Q","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ratioBR","type":"uint256"}],"name":"RebalanceTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"day","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"navR","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"}],"name":"Settled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newSplitRatio","type":"uint256"}],"name":"SplitRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newStrategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"minTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxTimestamp","type":"uint256"}],"name":"StrategyUpdateProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousStrategy","type":"address"},{"indexed":true,"internalType":"address","name":"newStrategy","type":"address"}],"name":"StrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTotalDebt","type":"uint256"}],"name":"TotalDebtUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTwapOracle","type":"address"}],"name":"TwapOracleUpdated","type":"event"},{"inputs":[],"name":"activityDelayTimeAfterRebalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newPrimaryMarket","type":"address"}],"name":"applyPrimaryMarketUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"name":"applyStrategyUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"aprOracle","outputs":[{"internalType":"contract IAprOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"fromIndex","type":"uint256"},{"internalType":"uint256","name":"toIndex","type":"uint256"}],"name":"batchRebalance","outputs":[{"internalType":"uint256","name":"newAmountQ","type":"uint256"},{"internalType":"uint256","name":"newAmountB","type":"uint256"},{"internalType":"uint256","name":"newAmountR","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountQ","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountR","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"doRebalance","outputs":[{"internalType":"uint256","name":"newAmountQ","type":"uint256"},{"internalType":"uint256","name":"newAmountB","type":"uint256"},{"internalType":"uint256","name":"newAmountR","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"endOfDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"endOfWeek","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"extrapolateNav","outputs":[{"internalType":"uint256","name":"navSum","type":"uint256"},{"internalType":"uint256","name":"navB","type":"uint256"},{"internalType":"uint256","name":"navROrZero","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundActivityStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEquivalentTotalB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEquivalentTotalQ","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEquivalentTotalR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRebalance","outputs":[{"components":[{"internalType":"uint256","name":"ratioB2Q","type":"uint256"},{"internalType":"uint256","name":"ratioR2Q","type":"uint256"},{"internalType":"uint256","name":"ratioBR","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct IFundV3.Rebalance","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRebalanceSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRebalanceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSettledDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategyUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalEquivalentTotalB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalInterestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"day","type":"uint256"}],"name":"historicalNavs","outputs":[{"internalType":"uint256","name":"navB","type":"uint256"},{"internalType":"uint256","name":"navR","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"historicalSplitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSplitRatio","type":"uint256"},{"internalType":"uint256","name":"lastNavB","type":"uint256"},{"internalType":"uint256","name":"lastNavR","type":"uint256"},{"internalType":"uint256","name":"strategyUnderlying","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"isFundActive","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":"primaryMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeQ","type":"uint256"}],"name":"primaryMarketAddDebtAndFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"primaryMarketBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"primaryMarketMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"primaryMarketPayDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeQ","type":"uint256"}],"name":"primaryMarketTransferUnderlying","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"primaryMarketUpdateProposal","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newPrimaryMarket","type":"address"}],"name":"proposePrimaryMarketUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newStrategy","type":"address"}],"name":"proposeStrategyUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"targetVersion","type":"uint256"}],"name":"refreshAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"targetVersion","type":"uint256"}],"name":"refreshBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loss","type":"uint256"}],"name":"reportLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profit","type":"uint256"},{"internalType":"uint256","name":"totalFee","type":"uint256"},{"internalType":"uint256","name":"strategyFee","type":"uint256"}],"name":"reportProfit","outputs":[{"internalType":"uint256","name":"strategyFeeQ","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlementPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"settlementTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"shareApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"shareDecreaseAllowance","outputs":[{"internalType":"uint256","name":"newAllowance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"shareIncreaseAllowance","outputs":[{"internalType":"uint256","name":"newAllowance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"shareTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"shareTransferFrom","outputs":[{"internalType":"uint256","name":"newAllowance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"splitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyUpdateProposal","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenQ","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"}],"name":"tokenShare","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenUnderlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"trancheAllBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"trancheAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"trancheAllowanceVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"trancheApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"trancheBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"trancheBalanceVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"}],"name":"trancheTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"trancheTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tranche","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"trancheTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFromStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapOracle","outputs":[{"internalType":"contract ITwapOracleV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingDecimalMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"delayTime","type":"uint256"}],"name":"updateActivityDelayTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAprOracle","type":"address"}],"name":"updateAprOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeCollector","type":"address"}],"name":"updateFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTwapOracle","type":"address"}],"name":"updateTwapOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weightB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101606040526010805460ff191690553480156200001c57600080fd5b5060405162004d4338038062004d438339810160408190526200003f91620003a9565b608081015160a082015160c083015160e08401516101008501516000620000656200022a565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180556001600160601b0319606086811b821660805285811b821660a05284901b1660c052600280546001600160a01b038481166001600160a01b0319928316811790935560058054918516919092161790556040516000907fce937feb4a560f179aae1a1090dcb38dab6dbb4c72cce5b6e3553d530f93685f908290a36040516001600160a01b038216906000907fe4cec16b1a7e6b7979e923da619a8b1e5fd0f0fb6e5c1cf647f350430ee61ca9908290a35050835160e0525050506020810151620151809006156200018457600080fd5b60208101516101005260408101516001600160601b0319606091821b166101205281015160121015620001d45760405162461bcd60e51b8152600401620001cb90620004b5565b60405180910390fd5b6060810151601203600a0a61014052610120810151620001f4906200022e565b610140810151620002059062000286565b6101608101516200021690620002d3565b6200022361070862000320565b506200055e565b3390565b600880546001600160a01b0319166001600160a01b0383161790556040517f8a8e0da24663134a95560b62466bb31935cfc0788a6686d10667f684ed810fb2906200027b908390620004a1565b60405180910390a150565b600980546001600160a01b0319166001600160a01b0383161790556040517f2629f592256aaf49e3c60966d01cf4c7897d640c00ae94b0472d458c2a647a55906200027b908390620004a1565b600a80546001600160a01b0319166001600160a01b0383161790556040517fe5693914d19c789bdee50a362998c0bc8d035a835f9871da5d51152f0582c34f906200027b908390620004a1565b610708811015801562000335575061a8c08111155b620003545760405162461bcd60e51b8152600401620001cb90620004f7565b600f8190556040517fbb681a7fb16d51d6d0928d6ce178fbca96144ec836f09f63977a33a0271080bf906200027b9083906200052e565b80516001600160a01b0381168114620003a357600080fd5b92915050565b6000610180808385031215620003bd578182fd5b620003c88162000537565b90508251815260208301516020820152620003e784604085016200038b565b6040820152606083015160608201526200040584608085016200038b565b6080820152620004198460a085016200038b565b60a08201526200042d8460c085016200038b565b60c0820152620004418460e085016200038b565b60e082015261010062000457858286016200038b565b908201526101206200046c858583016200038b565b9082015261014062000481858583016200038b565b9082015261016062000496858583016200038b565b908201529392505050565b6001600160a01b0391909116815260200190565b60208082526022908201527f556e6465726c79696e6720646563696d616c73206c6172676572207468616e20604082015261062760f31b606082015260800190565b6020808252601f908201527f45786365656420616c6c6f7765642064656c61792074696d652072616e676500604082015260600190565b90815260200190565b6040518181016001600160401b03811182821017156200055657600080fd5b604052919050565b60805160601c60a05160601c60c05160601c60e051610100516101205160601c6101405161470d62000636600039806109ae5280612ae5525080610f50528061102552806110d15280611d445280611e49528061221b525080610a605280610cd75280610df8528061146e52806116c252806122bb525080610a895280610d31528061246a5280612b615280612b955280612bd9528061368e52806136d85250806115ca5280612818528061364f52508061133252806127d6528061361f525080611058528061279452806135ef525061470d6000f3fe608060405234801561001057600080fd5b506004361061048b5760003560e01c806375a7bb8011610262578063b9dedc6a11610151578063dee1c6be116100ce578063eed9a17911610092578063eed9a17914610928578063f2fde38b14610949578063f42b68bb1461095c578063f4db872b14610964578063fb73de9314610977578063fd4fc82f1461098a5761048b565b8063dee1c6be146108d4578063e89900bc146108dc578063e8e62fbb146108ef578063ed056e2114610902578063ed547c6d146109155761048b565b8063cb15d6ec11610115578063cb15d6ec14610880578063d2c35ce814610893578063d8e66062146108a6578063db77e2b2146108b9578063ddd6d260146108c15761048b565b8063b9dedc6a14610837578063bc270ca91461084a578063c01238d314610852578063c2051e8e14610865578063c415b95c146108785761048b565b80639d657d6e116101df578063a8c62e76116101a3578063a8c62e76146107ee578063ad65048f146107f6578063aebd878a14610809578063b40494e51461081c578063b61557b1146108245761048b565b80639d657d6e1461078f5780639dc7262e146107a2578063a2f90183146107b5578063a69f7d6e146107c8578063a736985a146107db5761048b565b80639043292a116102265780639043292a1461074657806394990bd81461074e5780639a3ddf26146107565780639ae1119f146107695780639c6ff4f31461077c5761048b565b806375a7bb80146106fd5780637bccd12414610705578063846f1f49146107185780638da5c0bf1461072b5780638da5cb5b1461073e5761048b565b806334ce998a1161037e5780635c9302c9116102fb5780636809de6b116102bf5780636809de6b146106a9578063714351a4146106bc578063715018a6146106cf57806371da3c1d146106d757806371e3dca4146106ea5761048b565b80635c9302c9146106765780635f64b55b1461067e57806360a2da441461068657806360f880351461069957806362a5af3b146106a15761048b565b80635264e681116103425780635264e6811461063857806352fd7f35146106405780635532da8d14610653578063586b3941146106665780635c59f3bb1461066e5761048b565b806334ce998a146105ef5780633bd353e7146105f75780633d760bdb1461060a57806343f334cf1461061257806351ca852a146106255761048b565b806312e778b61161040c57806323c794cb116103d057806323c794cb14610599578063287ad849146105ac57806329174f5c146105cc5780632af4b0c0146105df5780632d78e8b1146105e75761048b565b806312e778b614610534578063133b5f751461053c578063170d35231461055e5780631e77ceda1461057157806320826734146105865761048b565b80630f1071be116104535780630f1071be146104f35780631003d387146104fb5780631027be2b1461050357806311da60b414610516578063123dafcc1461051e5761048b565b8063054f7d9c146104905780630553d604146104ae578063094fc921146104c35780630a68a9ce146104cb5780630cde859c146104e0575b600080fd5b61049861099d565b6040516104a59190613d16565b60405180910390f35b6104b66109a6565b6040516104a591906145b6565b6104b66109ac565b6104de6104d9366004613bb6565b6109d0565b005b6104b66104ee366004613ad3565b610a43565b6104b6610a5e565b6104b6610a82565b6104b6610511366004613a16565b610abb565b6104de610b34565b610526610e69565b6040516104a5929190613cfd565b6104b6610e7d565b61054f61054a366004613ad3565b610ea2565b6040516104a5939291906145cd565b6104b661056c366004613ad3565b610ee1565b610579610ef2565b6040516104a59190613cc5565b6104de610594366004613ad3565b610f01565b6104986105a7366004613ad3565b610f7a565b6105bf6105ba366004613ad3565b610f82565b6040516104a5919061458b565b6104de6105da366004613ad3565b610fd6565b6104b661104e565b610579611056565b6104b661107a565b6104de610605366004613ad3565b611082565b6104b66110fb565b6104de610620366004613977565b611101565b6104de610633366004613a16565b611149565b6104b661117d565b61054f61064e366004613977565b611185565b6104b6610661366004613c13565b6111f9565b6104b661131e565b6104b6611324565b6104b661132a565b610579611330565b6104de610694366004613c3e565b611354565b6105796115c8565b6104de6115ec565b61054f6106b7366004613c3e565b611752565b6104de6106ca366004613977565b6117ca565b6104de611834565b6104de6106e5366004613977565b6118bd565b6104b66106f8366004613ad3565b6119a7565b6104b66119bb565b6104b6610713366004613992565b6119da565b6104de610726366004613bf2565b611a07565b6104de610739366004613977565b611a61565b610579611aa9565b610579611ab8565b610579611ac7565b6104de610764366004613bb6565b611ad6565b6104b66107773660046139c6565b611b20565b6104de61078a366004613a16565b611bbd565b6104b661079d366004613ad3565b611bf7565b6104b66107b0366004613b26565b611c21565b6104b66107c3366004613ad3565b611cb8565b6104de6107d6366004613bb6565b611ccc565b6104de6107e9366004613a80565b611d0d565b610579611d84565b6104de610804366004613977565b611d93565b6104de610817366004613bb6565b611ddb565b6104b6611e44565b6104de610832366004613977565b611f10565b6104de610845366004613a16565b611f58565b610526611fb8565b6104de610860366004613b67565b611fcc565b6104b6610873366004613977565b612087565b6105796120a4565b6104b661088e366004613ad3565b6120b3565b6104de6108a1366004613977565b6120d2565b6104b66108b4366004613b03565b61211a565b610579612219565b6104de6108cf366004613ad3565b61223d565b6104b66122b6565b6104b66108ea366004613ad3565b6122df565b6104b66108fd366004613ad3565b6122f3565b61054f610910366004613c6f565b612305565b6104de610923366004613ad3565b61233d565b61093b610936366004613ad3565b612385565b6040516104a59291906145bf565b6104de610957366004613977565b6123a8565b6104b6612468565b6104b6610972366004613a16565b61248c565b610579610985366004613ad3565b6124ef565b6104de610998366004613a56565b6124fa565b60105460ff1681565b61c4e090565b7f000000000000000000000000000000000000000000000000000000000000000081565b6002546001600160a01b03163314610a035760405162461bcd60e51b81526004016109fa90613d54565b60405180910390fd5b80806204000d5414610a275760405162461bcd60e51b81526004016109fa906144a6565b610a31848361252a565b610a3c85858561263c565b5050505050565b60006204000e8260038110610a5457fe5b015490505b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ab67f0000000000000000000000000000000000000000000000000000000000000000610ab06119bb565b90612756565b905090565b600080610ac733612790565b90508015610ade57610ade85856204000d54612870565b6001600160a01b0380861660009081526204001360209081526040808320938816835292905220610b1e9084908360038110610b1657fe5b0154906129a9565b9150610b2c818686856129ce565b509392505050565b60026001541415610b575760405162461bcd60e51b81526004016109fa9061446f565b600260015560105460ff1615610b7f5760405162461bcd60e51b81526004016109fa90614103565b600b5480610b9f5760405162461bcd60e51b81526004016109fa90614123565b80421015610bbf5760405162461bcd60e51b81526004016109fa906144d4565b600854604051639f05715160e01b81526000916001600160a01b031690639f05715190610bf09085906004016145b6565b60206040518083038186803b158015610c0857600080fd5b505afa158015610c1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c409190613aeb565b905080610c5f5760405162461bcd60e51b81526004016109fa90613e5b565b6002546040516211bf0560eb1b81526001600160a01b0390911690638df8280090610c8e9085906004016145b6565b600060405180830381600087803b158015610ca857600080fd5b505af1158015610cbc573d6000803e3d6000fd5b505050506000610cca611e44565b90506000806000610d07867f0000000000000000000000000000000000000000000000000000000000000000880387610d016119bb565b88612ac0565b92509250925060008111610d2d5760405162461bcd60e51b81526004016109fa906142a3565b60007f0000000000000000000000000000000000000000000000000000000000000000600101610d6885600c54612c0c90919063ffffffff16565b81610d6f57fe5b049050610d7f8785858585612c24565b600f548701600e55670de0b6b3a76400009250829150610d9d610a82565b6000888152620400176020908152604080832093909355620400188152828220889055620400158152828220869055620400169052908120839055610de188612d62565b6000898152620400196020526040908190208290557f00000000000000000000000000000000000000000000000000000000000000008a01600b555190915088907f0b88c5bd74fc625a4f651904bf835063c6a449220be319924685261fb7709dd590610e53908790879086906145cd565b60405180910390a2505060018055505050505050565b6003546004546001600160a01b0390911691565b6204000e54600c546204001054600092610ab6929091610e9c91612e40565b906129a9565b600080600080610eb06122b6565b90506000610ebc611e44565b9050610ed2428388610ecc6119bb565b85612ac0565b94509450945050509193909250565b6000610eec82612e58565b92915050565b6002546001600160a01b031690565b6002546001600160a01b03163314610f2b5760405162461bcd60e51b81526004016109fa90613d54565b6204001a54610f4390610f3e9083612e82565b612eaa565b610f776001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612ee1565b50565b600e54111590565b610f8a613938565b60118261ffff8110610f9857fe5b600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050919050565b6005546001600160a01b031633146110005760405162461bcd60e51b81526004016109fa906141d9565b6204001b5461100f90826129a9565b6204001b55600554610f77906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683612ee1565b6204001b5490565b7f000000000000000000000000000000000000000000000000000000000000000090565b6204001a5490565b6005546001600160a01b031633146110ac5760405162461bcd60e51b81526004016109fa906141d9565b6204001b546110bb9082612e82565b6204001b55600554610f77906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691163084612f37565b600e5481565b611109612f58565b6001600160a01b031661111a611aa9565b6001600160a01b0316146111405760405162461bcd60e51b81526004016109fa9061426e565b610f7781612f5c565b600061115433612790565b9050801561116b5761116b84846204000d54612870565b611177818585856129ce565b50505050565b6204000d5490565b6001600160a01b03811660009081526204001160209081526040808320805460018201546002909201546204000d54620400129095529285205485948594929392915b818110156111eb576111dc85858584611752565b919650945092506001016111c8565b509297919650945092505050565b6005546000906001600160a01b031633146112265760405162461bcd60e51b81526004016109fa906141d9565b8284101580156112365750818310155b6112525760405162461bcd60e51b81526004016109fa90613ded565b6204001b5461126190856129a9565b6204001b556000611270610e7d565b905060008461127d611e44565b0390506000611296826112908886612756565b90612fe1565b90506112a6826112908786612756565b600a549094506112cb906000906001600160a01b03166112c68488612e82565b613013565b6112d760003386613013565b7ffef68dfebd892147056f2f1346892955854e67b190cf0b3c3dcfe2972109d82c8787838760405161130c94939291906145e3565b60405180910390a15050509392505050565b600f5481565b600c5481565b600b5481565b7f000000000000000000000000000000000000000000000000000000000000000090565b61135c612f58565b6001600160a01b031661136d611aa9565b6001600160a01b0316146113935760405162461bcd60e51b81526004016109fa9061426e565b600c541580156113a35750600b54155b6113bf5760405162461bcd60e51b81526004016109fa906143ca565b83158015906113d65750670de0b6b3a76400008310155b6113f25760405162461bcd60e51b81526004016109fa9061414c565b600c84905560008052600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee8490556040517fa9cc843da7a73fc99a9077d9af92c4e351b84959afc9a104e7cee3ff4a76c0db906114549086906145b6565b60405180910390a160006201518061146b42611bf7565b037f00000000000000000000000000000000000000000000000000000000000000008101600b55600854604051639f05715160e01b81529192506000916001600160a01b0390911690639f057151906114c89085906004016145b6565b60206040518083038186803b1580156114e057600080fd5b505afa1580156114f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115189190613aeb565b9050806115375760405162461bcd60e51b81526004016109fa90613fc5565b600082815262040015602090815260408083208890556204001690915281208590556204001b84905561156983612d62565b6000848152620400196020526040908190208290555190915083907f0b88c5bd74fc625a4f651904bf835063c6a449220be319924685261fb7709dd5906115b5908990899086906145cd565b60405180910390a25050600e5550505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b60105460ff161561160f5760405162461bcd60e51b81526004016109fa906140db565b600b548061162f5760405162461bcd60e51b81526004016109fa90614123565b6008546040805163061b57a360e51b815290516000926001600160a01b03169163c36af460916004808301926020929190829003018186803b15801561167457600080fd5b505afa158015611688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ac9190613aeb565b905060006116b8611e44565b905060006116f2427f00000000000000000000000000000000000000000000000000000000000000008603856116ec6119bb565b86612ac0565b92505050806000146117165760405162461bcd60e51b81526004016109fa906141af565b6010805460ff191660011790556040517fa8cab3d1893ed53071b052fafa843143492f25d1d6b0170d460789f7ab1954be90600090a150505050565b60008060008060118561ffff811061176657fe5b60040201905061179e611786826001015488612c0c90919063ffffffff16565b8254610e9c90611797908b90612c0c565b8b906129a9565b60028201549094506117b08882612c0c565b93506117bc8782612c0c565b925050509450945094915050565b6117d2612f58565b6001600160a01b03166117e3611aa9565b6001600160a01b0316146118095760405162461bcd60e51b81526004016109fa9061426e565b6204001a541561182b5760405162461bcd60e51b81526004016109fa9061406f565b610f77816130e8565b61183c612f58565b6001600160a01b031661184d611aa9565b6001600160a01b0316146118735760405162461bcd60e51b81526004016109fa9061426e565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6118c5612f58565b6001600160a01b03166118d6611aa9565b6001600160a01b0316146118fc5760405162461bcd60e51b81526004016109fa9061426e565b600260009054906101000a90046001600160a01b03166001600160a01b0316636c8fcfa26040518163ffffffff1660e01b815260040160206040518083038186803b15801561194a57600080fd5b505afa15801561195e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119829190613ab3565b61199e5760405162461bcd60e51b81526004016109fa90613e24565b610f77816131b6565b620400176020526000908152604090205481565b6204001054600c546204000e54600092610ab6929091610e9c91612c0c565b6001600160a01b039182166000908152620400146020908152604080832093909416825291909152205490565b6002546001600160a01b03163314611a315760405162461bcd60e51b81526004016109fa90613d54565b600a54611a4a906000906001600160a01b031683613013565b6204001a54611a5d90610f3e90846129a9565b5050565b611a69612f58565b6001600160a01b0316611a7a611aa9565b6001600160a01b031614611aa05760405162461bcd60e51b81526004016109fa9061426e565b610f7781613284565b6000546001600160a01b031690565b6008546001600160a01b031681565b6009546001600160a01b031681565b80806204000d5414611afa5760405162461bcd60e51b81526004016109fa906144a6565b611b04338361252a565b8415611b1457611b14848361252a565b610a3c853386866132cf565b600080611b2c33612790565b9050611b39858585611f58565b8015611b4e57611b4e85876204000d54612870565b611ba6836040518060600160405280602881526020016146b0602891396001600160a01b0380891660009081526204001360209081526040808320938d168352929052208460038110611b9d57fe5b0154919061340e565b9150611bb4818688856129ce565b50949350505050565b8015611be7576204000d54811115611be75760405162461bcd60e51b81526004016109fa90614178565b611bf2838383612870565b505050565b600061c4e06201518081611c0b85836129a9565b0381611c1357fe5b046201518002019050919050565b6001600160a01b0380831660009081526204001360209081526040808320938516835292905290812081908560038110611c5757fe5b015490508415611cae576204000d546001600160a01b0380861660009081526204001460209081526040808320938816835292905220545b81811015611cab57611ca1838261343a565b9250600101611c8f565b50505b90505b9392505050565b620400186020526000908152604090205481565b80806204000d5414611cf05760405162461bcd60e51b81526004016109fa906144a6565b8415611d0157611d01338584612870565b610a3c853386866129ce565b6002546001600160a01b03163314611d375760405162461bcd60e51b81526004016109fa90613d54565b611d6b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168484612ee1565b600a54611bf2906000906001600160a01b031683613013565b6005546001600160a01b031690565b611d9b612f58565b6001600160a01b0316611dac611aa9565b6001600160a01b031614611dd25760405162461bcd60e51b81526004016109fa9061426e565b610f7781613470565b6002546001600160a01b03163314611e055760405162461bcd60e51b81526004016109fa90613d54565b80806204000d5414611e295760405162461bcd60e51b81526004016109fa906144a6565b8415611e3957611e39848361252a565b610a3c858585613013565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611e939190613cc5565b60206040518083038186803b158015611eab57600080fd5b505afa158015611ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee39190613aeb565b9050611f0a6204001a54611f046204001b54846129a990919063ffffffff16565b90612e82565b91505090565b611f18612f58565b6001600160a01b0316611f29611aa9565b6001600160a01b031614611f4f5760405162461bcd60e51b81526004016109fa9061426e565b610f77816134bb565b6000611f6333612790565b90508015611f9e57611f7442610f7a565b611f905760405162461bcd60e51b81526004016109fa90614441565b611f9e836204000d5461252a565b611fac846204000d5461252a565b611177818585856132cf565b6006546007546001600160a01b0390911691565b80806204000d5414611ff05760405162461bcd60e51b81526004016109fa906144a6565b611ffa858361252a565b85156120155761200b853384612870565b612015848361252a565b6000612064846040518060600160405280602881526020016146b0602891396001600160a01b0389166000908152620400136020908152604080832033845290915290208a60038110611b9d57fe5b9050612072878733846129ce565b61207e878787876132cf565b50505050505050565b6001600160a01b0316600090815262040012602052604090205490565b600a546001600160a01b031681565b600060118261ffff81106120c357fe5b60040201600301549050919050565b6120da612f58565b6001600160a01b03166120eb611aa9565b6001600160a01b0316146121115760405162461bcd60e51b81526004016109fa9061426e565b610f7781613535565b6204000d546001600160a01b038216600090815262040012602052604081205490919080821415612175576001600160a01b03841660009081526204001160205260409020856003811061216a57fe5b015492505050610eec565b6001600160a01b0384166000908152620400116020526040902080546001820154600290920154909190835b858110156121c4576121b584848484611752565b919550935091506001016121a1565b50876121d7578295505050505050610eec565b60018814156121ec57509350610eec92505050565b6002881415612201579450610eec9350505050565b60405162461bcd60e51b81526004016109fa90613dc4565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005546001600160a01b031633146122675760405162461bcd60e51b81526004016109fa906141d9565b6204001b546122769082612e82565b6204001b556040517f3743c9e9a14de8dfa6e52fac936fe2cbf23e8e43d0d4c46ef57bcff3b377967e906122ab9083906145b6565b60405180910390a150565b600b547f0000000000000000000000000000000000000000000000000000000000000000900390565b620400196020526000908152604090205481565b6000908152600d602052604090205490565b60008080845b8481101561232e5761231f89898984611752565b919a509850965060010161230b565b50969795965093949350505050565b612345612f58565b6001600160a01b0316612356611aa9565b6001600160a01b03161461237c5760405162461bcd60e51b81526004016109fa9061426e565b610f7781613580565b600090815262040015602090815260408083205462040016909252909120549091565b6123b0612f58565b6001600160a01b03166123c1611aa9565b6001600160a01b0316146123e75760405162461bcd60e51b81526004016109fa9061426e565b6001600160a01b03811661240d5760405162461bcd60e51b81526004016109fa90613eab565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008061249833612790565b905080156124af576124af85856204000d54612870565b6001600160a01b0380861660009081526204001360209081526040808320938816835292905220610b1e90849083600381106124e757fe5b015490612e82565b6000610eec826135e5565b8015612524576204000d548111156125245760405162461bcd60e51b81526004016109fa90614178565b611a5d82825b8061253657506204000d545b6001600160a01b038216600090815262040012602052604090205481811061255e5750611a5d565b6001600160a01b0383166000908152620400116020908152604080832080546001820154600283015462040012909552929094208690559291811580156125a3575080155b156125b2575050505050611a5d565b845b868110156125d7576125c884848484611752565b919550935091506001016125b4565b508284600001558184600101558084600201556040516001600160a01b038816907fd3f04497b42e4930518874144f53da3a7b078a70d319cb2a210e34f4b8dfd24e9061262b9089908790879087906145e3565b60405180910390a250505050505050565b6001600160a01b0382166126625760405162461bcd60e51b81526004016109fa906142c9565b6126a481604051806060016040528060228152602001614668602291396001600160a01b038516600090815262040011602052604090208660038110611b9d57fe5b6001600160a01b0383166000908152620400116020526040902084600381106126c957fe5b01556126de816204000e85600381106124e757fe5b6204000e84600381106126ed57fe5b01556126f8836135e5565b6001600160a01b031663dd5645b6836000846040518463ffffffff1660e01b815260040161272893929190613cd9565b600060405180830381600087803b15801561274257600080fd5b505af115801561207e573d6000803e3d6000fd5b60008261276557506000610eec565b8282028284828161277257fe5b0414611cb15760405162461bcd60e51b81526004016109fa9061422d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156127d457506000610a59565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316141561281657506001610a59565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316141561285857506002610a59565b60405162461bcd60e51b81526004016109fa90613f33565b8061287c57506204000d545b6001600160a01b0380841660009081526204001460209081526040808320938616835292905220548181106128b15750611bf2565b6001600160a01b0384811660008181526204001360209081526040808320948816808452948252808320600181015460028201549585526204001484528285209685529590925290912085905591908115801561290c575080155b1561291a5750505050611bf2565b835b858110156129445761292e838261343a565b925061293a828261343a565b915060010161291c565b508183600101558083600201556001600160a01b038087169088167f8fa162daa8095482092c801a2fbf4a0351846b94fe2d2e0c3ab60dbb9b6693ae878660000154868660405161299894939291906145e3565b60405180910390a350505050505050565b600082820183811015611cb15760405162461bcd60e51b81526004016109fa90613f8e565b6001600160a01b0383166129f45760405162461bcd60e51b81526004016109fa9061434f565b6001600160a01b038216612a1a5760405162461bcd60e51b81526004016109fa90613ef1565b6001600160a01b038084166000908152620400136020908152604080832093861683529290522081908560038110612a4e57fe5b0155612a59846135e5565b6001600160a01b031663c0a755b98484846040518463ffffffff1660e01b8152600401612a8893929190613cd9565b600060405180830381600087803b158015612aa257600080fd5b505af1158015612ab6573d6000803e3d6000fd5b5050505050505050565b6000848152620400156020526040812054818415612bc057612b1085611290612b09877f0000000000000000000000000000000000000000000000000000000000000000612756565b8990612756565b9250612b59612b52670de0b6b3a7640000610e9c620151806112908c8e036204001960008f81526020019081526020016000205461275690919063ffffffff16565b8390612c0c565b9150612b85827f0000000000000000000000000000000000000000000000000000000000000000612756565b831015612b93576000612bb9565b7f0000000000000000000000000000000000000000000000000000000000000000820283035b9050612c01565b50600086815262040016602052604090205480612bfd837f0000000000000000000000000000000000000000000000000000000000000000612756565b0192505b955095509592505050565b6000611cb1670de0b6b3a76400006112908585612756565b612c2c613938565b612c37848484613673565b6204000d54600c849055600181016000908152600d60205260409081902085905551919250907fa9cc843da7a73fc99a9077d9af92c4e351b84959afc9a104e7cee3ff4a76c0db90612c8a9085906145b6565b60405180910390a18160118261ffff8110612ca157fe5b6004020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050806001016204000d8190555086817fe3df43951e14c0a4004438a979718a41a3501704f5326c446949863c51da9961888888876000015188602001518960400151604051612d23969594939291906145fe565b60405180910390a36204000e546204000f546204001054612d4692919084611752565b62040010556204000f556204000e5561207e306001830161252a565b600080612dfe600960009054906101000a90046001600160a01b03166001600160a01b031663d4a3e9d76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612db857600080fd5b505af1158015612dcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df09190613aeb565b66038d7ea4c6800090613738565b90507f41e376fd99913dea7fda140f5c0bd997515b1a181acc58737320322548ec6e72816000604051612e329291906145bf565b60405180910390a192915050565b6000611cb18261129085670de0b6b3a7640000612756565b600061c4e062093a8081612e6c85836129a9565b0381612e7457fe5b0462093a8002019050919050565b600082821115612ea45760405162461bcd60e51b81526004016109fa90613ff2565b50900390565b6204001a8190556040517f8457e683d800c4f496806b8972b297b7e3fac279363c2f89bd90dde4133b154f906122ab9083906145b6565b611bf28363a9059cbb60e01b8484604051602401612f00929190613cfd565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261374e565b611177846323b872dd60e01b858585604051602401612f0093929190613cd9565b3390565b6005546001600160a01b0382811691161415612f7757600080fd5b600680546001600160a01b0319166001600160a01b0383169081179091554260078190556040517f32ae77edfd0636915483336791468b5cd4f156b427e632138786afbdfdafc04d91612fd6916203f4808201916213c68001906145bf565b60405180910390a250565b60008082116130025760405162461bcd60e51b81526004016109fa906140a4565b81838161300b57fe5b049392505050565b6001600160a01b0382166130395760405162461bcd60e51b81526004016109fa90614554565b61304c816204000e8560038110610b1657fe5b6204000e846003811061305b57fe5b01556001600160a01b038216600090815262040011602052604090206130889082908560038110610b1657fe5b6001600160a01b0383166000908152620400116020526040902084600381106130ad57fe5b01556130b8836135e5565b6001600160a01b031663dd5645b6600084846040518463ffffffff1660e01b815260040161272893929190613cd9565b6006546001600160a01b038281169116146131155760405162461bcd60e51b81526004016109fa90613f57565b6203f48060075401421015801561313257506213c6806007540142105b61314e5760405162461bcd60e51b81526004016109fa90614200565b6005546040516001600160a01b038084169216907fe4cec16b1a7e6b7979e923da619a8b1e5fd0f0fb6e5c1cf647f350430ee61ca990600090a3600580546001600160a01b039092166001600160a01b03199283161790556006805490911690556000600755565b6003546001600160a01b038281169116146131e35760405162461bcd60e51b81526004016109fa90613f57565b6203f48060045401421015801561320057506213c6806004540142105b61321c5760405162461bcd60e51b81526004016109fa90614200565b6002546040516001600160a01b038084169216907fce937feb4a560f179aae1a1090dcb38dab6dbb4c72cce5b6e3553d530f93685f90600090a3600280546001600160a01b039092166001600160a01b03199283161790556003805490911690556000600455565b600880546001600160a01b0319166001600160a01b0383161790556040517f8a8e0da24663134a95560b62466bb31935cfc0788a6686d10667f684ed810fb2906122ab908390613cc5565b6001600160a01b0383166132f55760405162461bcd60e51b81526004016109fa9061430a565b6001600160a01b03821661331b5760405162461bcd60e51b81526004016109fa90613d81565b61335d8160405180606001604052806026815260200161468a602691396001600160a01b038616600090815262040011602052604090208760038110611b9d57fe5b6001600160a01b03841660009081526204001160205260409020856003811061338257fe5b01556001600160a01b038216600090815262040011602052604090206133af9082908660038110610b1657fe5b6001600160a01b0383166000908152620400116020526040902085600381106133d457fe5b01556133df846135e5565b6001600160a01b031663dd5645b68484846040518463ffffffff1660e01b8152600401612a8893929190613cd9565b600081848411156134325760405162461bcd60e51b81526004016109fa9190613d21565b505050900390565b60008060118361ffff811061344b57fe5b6004020190506134688160020154856137dd90919063ffffffff16565b949350505050565b600980546001600160a01b0319166001600160a01b0383161790556040517f2629f592256aaf49e3c60966d01cf4c7897d640c00ae94b0472d458c2a647a55906122ab908390613cc5565b6002546001600160a01b03828116911614156134d657600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091554260048190556040517f2e6b5912c3dac53b95017557cebcd0618fa7a13f4c8d1d96c5afb31b15d693f191612fd6916203f4808201916213c68001906145bf565b600a80546001600160a01b0319166001600160a01b0383161790556040517fe5693914d19c789bdee50a362998c0bc8d035a835f9871da5d51152f0582c34f906122ab908390613cc5565b6107088110158015613594575061a8c08111155b6135b05760405162461bcd60e51b81526004016109fa9061451d565b600f8190556040517fbb681a7fb16d51d6d0928d6ce178fbca96144ec836f09f63977a33a0271080bf906122ab9083906145b6565b60008161361357507f0000000000000000000000000000000000000000000000000000000000000000610a59565b600182141561364357507f0000000000000000000000000000000000000000000000000000000000000000610a59565b600282141561220157507f0000000000000000000000000000000000000000000000000000000000000000610a59565b61367b613938565b60008060008686116136cd5785925060017f0000000000000000000000000000000000000000000000000000000000000000016136ba84890387612e40565b816136c157fe5b0491506000905061370f565b8692506000915060017f00000000000000000000000000000000000000000000000000000000000000000161370484880387612e40565b8161370b57fe5b0490505b604080516080810182529283526020830191909152810191909152426060820152949350505050565b60008183106137475781611cb1565b5090919050565b60606137a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137f59092919063ffffffff16565b805190915015611bf257808060200190518101906137c19190613ab3565b611bf25760405162461bcd60e51b81526004016109fa906143f7565b6000611cb1670de0b6b3a76400006112908585613804565b6060611cae8484600085613838565b60008261381357506000610eec565b8282028284828161382057fe5b04141561382d5780613468565b506000199392505050565b60608247101561385a5760405162461bcd60e51b81526004016109fa90614029565b613863856138f9565b61387f5760405162461bcd60e51b81526004016109fa90614393565b60006060866001600160a01b0316858760405161389c9190613ca9565b60006040518083038185875af1925050503d80600081146138d9576040519150601f19603f3d011682016040523d82523d6000602084013e6138de565b606091505b50915091506138ee8282866138ff565b979650505050505050565b3b151590565b6060831561390e575081611cb1565b82511561391e5782518084602001fd5b8160405162461bcd60e51b81526004016109fa9190613d21565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b80356001600160a01b0381168114610eec57600080fd5b600060208284031215613988578081fd5b611cb18383613960565b600080604083850312156139a4578081fd5b6139ae8484613960565b91506139bd8460208501613960565b90509250929050565b600080600080608085870312156139db578182fd5b84356139e681614652565b935060208501356139f681614652565b92506040850135613a0681614652565b9396929550929360600135925050565b600080600060608486031215613a2a578283fd5b8335613a3581614652565b92506020840135613a4581614652565b929592945050506040919091013590565b60008060408385031215613a68578182fd5b613a728484613960565b946020939093013593505050565b600080600060608486031215613a94578283fd5b613a9e8585613960565b95602085013595506040909401359392505050565b600060208284031215613ac4578081fd5b81518015158114611cb1578182fd5b600060208284031215613ae4578081fd5b5035919050565b600060208284031215613afc578081fd5b5051919050565b60008060408385031215613b15578182fd5b823591506139bd8460208501613960565b600080600060608486031215613b3a578283fd5b833592506020840135613b4c81614652565b91506040840135613b5c81614652565b809150509250925092565b600080600080600060a08688031215613b7e578081fd5b85359450613b8f8760208801613960565b9350613b9e8760408801613960565b94979396509394606081013594506080013592915050565b60008060008060808587031215613bcb578384fd5b843593506020850135613bdd81614652565b93969395505050506040820135916060013590565b60008060408385031215613c04578182fd5b50508035926020909101359150565b600080600060608486031215613c27578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215613c53578182fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215613c86578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008251613cbb818460208701614626565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082528251806020840152613d40816040850160208701614626565b601f01601f19169190910160400192915050565b60208082526013908201527213db9b1e481c1c9a5b585c9e481b585c9ad95d606a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6020808252600f908201526e496e76616c6964207472616e63686560881b604082015260600190565b60208082526018908201527f4665652063616e6e6f74206578636565642070726f6669740000000000000000604082015260600190565b6020808252601c908201527f43616e6e6f7420757064617465207072696d617279206d61726b657400000000604082015260600190565b60208082526030908201527f556e6465726c79696e6720707269636520666f7220736574746c656d656e742060408201526f1a5cc81b9bdd081c9958591e481e595d60821b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252600a90820152694f6e6c7920736861726560b01b604082015260600190565b60208082526019908201527f50726f706f7365642061646472657373206d69736d6174636800000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601390820152725072696365206e6f7420617661696c61626c6560681b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252818101527f43616e6e6f742075706461746520737472617465677920776974682064656274604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600e908201526d20b63932b0b23c90333937bd32b760911b604082015260600190565b602080825260069082015265233937bd32b760d11b604082015260600190565b6020808252600f908201526e139bdd081a5b9a5d1a585b1a5e9959608a1b604082015260600190565b602080825260129082015271496e76616c696420706172616d657465727360701b604082015260600190565b6020808252601b908201527f5461726765742076657273696f6e206f7574206f6620626f756e640000000000604082015260600190565b60208082526010908201526f2737ba103a3790313290333937bd32b760811b604082015260600190565b6020808252600d908201526c4f6e6c7920737472617465677960981b604082015260600190565b6020808252601390820152724e6f7420726561647920746f2075706461746560681b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600c908201526b2a3790313290333937bd32b760a11b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b602080825260139082015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601490820152735472616e7366657220697320696e61637469766560601b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526014908201527327b7363c9031bab93932b73a103b32b939b4b7b760611b604082015260600190565b60208082526029908201527f5468652063757272656e742074726164696e67207965617220646f6573206e6f6040820152681d08195b99081e595d60ba1b606082015260800190565b6020808252601f908201527f45786365656420616c6c6f7765642064656c61792074696d652072616e676500604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b8151815260208083015190820152604080830151908201526060918201519181019190915260800190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b958652602086019490945260408501929092526060840152608083015260a082015260c00190565b60005b83811015614641578181015183820152602001614629565b838111156111775750506000910152565b6001600160a01b0381168114610f7757600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a26469706673582212205b0e01f779c9b936362d162508336ab9d67b9da147ee8fa7249711be7d72be1964736f6c634300060c003300000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000001e133800000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca000000000000000000000000000000000000000000000000000000000000000120000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c000000000000000000000000d2df8d600f7b32b8e708900646f8898c52158690000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d3934000000000000000000000000a8be5ab62794a647254e1e62844201efc8477e220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c32f23ee32cb5681eca5e84c2ae728c3f0b0149f00000000000000000000000037473872769ff711bd6d800e518061fae67e10a900000000000000000000000096ccae5662de55c50b997f13396e6a183074f9d5
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061048b5760003560e01c806375a7bb8011610262578063b9dedc6a11610151578063dee1c6be116100ce578063eed9a17911610092578063eed9a17914610928578063f2fde38b14610949578063f42b68bb1461095c578063f4db872b14610964578063fb73de9314610977578063fd4fc82f1461098a5761048b565b8063dee1c6be146108d4578063e89900bc146108dc578063e8e62fbb146108ef578063ed056e2114610902578063ed547c6d146109155761048b565b8063cb15d6ec11610115578063cb15d6ec14610880578063d2c35ce814610893578063d8e66062146108a6578063db77e2b2146108b9578063ddd6d260146108c15761048b565b8063b9dedc6a14610837578063bc270ca91461084a578063c01238d314610852578063c2051e8e14610865578063c415b95c146108785761048b565b80639d657d6e116101df578063a8c62e76116101a3578063a8c62e76146107ee578063ad65048f146107f6578063aebd878a14610809578063b40494e51461081c578063b61557b1146108245761048b565b80639d657d6e1461078f5780639dc7262e146107a2578063a2f90183146107b5578063a69f7d6e146107c8578063a736985a146107db5761048b565b80639043292a116102265780639043292a1461074657806394990bd81461074e5780639a3ddf26146107565780639ae1119f146107695780639c6ff4f31461077c5761048b565b806375a7bb80146106fd5780637bccd12414610705578063846f1f49146107185780638da5c0bf1461072b5780638da5cb5b1461073e5761048b565b806334ce998a1161037e5780635c9302c9116102fb5780636809de6b116102bf5780636809de6b146106a9578063714351a4146106bc578063715018a6146106cf57806371da3c1d146106d757806371e3dca4146106ea5761048b565b80635c9302c9146106765780635f64b55b1461067e57806360a2da441461068657806360f880351461069957806362a5af3b146106a15761048b565b80635264e681116103425780635264e6811461063857806352fd7f35146106405780635532da8d14610653578063586b3941146106665780635c59f3bb1461066e5761048b565b806334ce998a146105ef5780633bd353e7146105f75780633d760bdb1461060a57806343f334cf1461061257806351ca852a146106255761048b565b806312e778b61161040c57806323c794cb116103d057806323c794cb14610599578063287ad849146105ac57806329174f5c146105cc5780632af4b0c0146105df5780632d78e8b1146105e75761048b565b806312e778b614610534578063133b5f751461053c578063170d35231461055e5780631e77ceda1461057157806320826734146105865761048b565b80630f1071be116104535780630f1071be146104f35780631003d387146104fb5780631027be2b1461050357806311da60b414610516578063123dafcc1461051e5761048b565b8063054f7d9c146104905780630553d604146104ae578063094fc921146104c35780630a68a9ce146104cb5780630cde859c146104e0575b600080fd5b61049861099d565b6040516104a59190613d16565b60405180910390f35b6104b66109a6565b6040516104a591906145b6565b6104b66109ac565b6104de6104d9366004613bb6565b6109d0565b005b6104b66104ee366004613ad3565b610a43565b6104b6610a5e565b6104b6610a82565b6104b6610511366004613a16565b610abb565b6104de610b34565b610526610e69565b6040516104a5929190613cfd565b6104b6610e7d565b61054f61054a366004613ad3565b610ea2565b6040516104a5939291906145cd565b6104b661056c366004613ad3565b610ee1565b610579610ef2565b6040516104a59190613cc5565b6104de610594366004613ad3565b610f01565b6104986105a7366004613ad3565b610f7a565b6105bf6105ba366004613ad3565b610f82565b6040516104a5919061458b565b6104de6105da366004613ad3565b610fd6565b6104b661104e565b610579611056565b6104b661107a565b6104de610605366004613ad3565b611082565b6104b66110fb565b6104de610620366004613977565b611101565b6104de610633366004613a16565b611149565b6104b661117d565b61054f61064e366004613977565b611185565b6104b6610661366004613c13565b6111f9565b6104b661131e565b6104b6611324565b6104b661132a565b610579611330565b6104de610694366004613c3e565b611354565b6105796115c8565b6104de6115ec565b61054f6106b7366004613c3e565b611752565b6104de6106ca366004613977565b6117ca565b6104de611834565b6104de6106e5366004613977565b6118bd565b6104b66106f8366004613ad3565b6119a7565b6104b66119bb565b6104b6610713366004613992565b6119da565b6104de610726366004613bf2565b611a07565b6104de610739366004613977565b611a61565b610579611aa9565b610579611ab8565b610579611ac7565b6104de610764366004613bb6565b611ad6565b6104b66107773660046139c6565b611b20565b6104de61078a366004613a16565b611bbd565b6104b661079d366004613ad3565b611bf7565b6104b66107b0366004613b26565b611c21565b6104b66107c3366004613ad3565b611cb8565b6104de6107d6366004613bb6565b611ccc565b6104de6107e9366004613a80565b611d0d565b610579611d84565b6104de610804366004613977565b611d93565b6104de610817366004613bb6565b611ddb565b6104b6611e44565b6104de610832366004613977565b611f10565b6104de610845366004613a16565b611f58565b610526611fb8565b6104de610860366004613b67565b611fcc565b6104b6610873366004613977565b612087565b6105796120a4565b6104b661088e366004613ad3565b6120b3565b6104de6108a1366004613977565b6120d2565b6104b66108b4366004613b03565b61211a565b610579612219565b6104de6108cf366004613ad3565b61223d565b6104b66122b6565b6104b66108ea366004613ad3565b6122df565b6104b66108fd366004613ad3565b6122f3565b61054f610910366004613c6f565b612305565b6104de610923366004613ad3565b61233d565b61093b610936366004613ad3565b612385565b6040516104a59291906145bf565b6104de610957366004613977565b6123a8565b6104b6612468565b6104b6610972366004613a16565b61248c565b610579610985366004613ad3565b6124ef565b6104de610998366004613a56565b6124fa565b60105460ff1681565b61c4e090565b7f000000000000000000000000000000000000000000000000000000000000000181565b6002546001600160a01b03163314610a035760405162461bcd60e51b81526004016109fa90613d54565b60405180910390fd5b80806204000d5414610a275760405162461bcd60e51b81526004016109fa906144a6565b610a31848361252a565b610a3c85858561263c565b5050505050565b60006204000e8260038110610a5457fe5b015490505b919050565b7f0000000000000000000000000000000000000000000000000000000001e1338081565b6000610ab67f0000000000000000000000000000000000000000000000000000000000000009610ab06119bb565b90612756565b905090565b600080610ac733612790565b90508015610ade57610ade85856204000d54612870565b6001600160a01b0380861660009081526204001360209081526040808320938816835292905220610b1e9084908360038110610b1657fe5b0154906129a9565b9150610b2c818686856129ce565b509392505050565b60026001541415610b575760405162461bcd60e51b81526004016109fa9061446f565b600260015560105460ff1615610b7f5760405162461bcd60e51b81526004016109fa90614103565b600b5480610b9f5760405162461bcd60e51b81526004016109fa90614123565b80421015610bbf5760405162461bcd60e51b81526004016109fa906144d4565b600854604051639f05715160e01b81526000916001600160a01b031690639f05715190610bf09085906004016145b6565b60206040518083038186803b158015610c0857600080fd5b505afa158015610c1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c409190613aeb565b905080610c5f5760405162461bcd60e51b81526004016109fa90613e5b565b6002546040516211bf0560eb1b81526001600160a01b0390911690638df8280090610c8e9085906004016145b6565b600060405180830381600087803b158015610ca857600080fd5b505af1158015610cbc573d6000803e3d6000fd5b505050506000610cca611e44565b90506000806000610d07867f0000000000000000000000000000000000000000000000000000000001e13380880387610d016119bb565b88612ac0565b92509250925060008111610d2d5760405162461bcd60e51b81526004016109fa906142a3565b60007f0000000000000000000000000000000000000000000000000000000000000009600101610d6885600c54612c0c90919063ffffffff16565b81610d6f57fe5b049050610d7f8785858585612c24565b600f548701600e55670de0b6b3a76400009250829150610d9d610a82565b6000888152620400176020908152604080832093909355620400188152828220889055620400158152828220869055620400169052908120839055610de188612d62565b6000898152620400196020526040908190208290557f0000000000000000000000000000000000000000000000000000000001e133808a01600b555190915088907f0b88c5bd74fc625a4f651904bf835063c6a449220be319924685261fb7709dd590610e53908790879086906145cd565b60405180910390a2505060018055505050505050565b6003546004546001600160a01b0390911691565b6204000e54600c546204001054600092610ab6929091610e9c91612e40565b906129a9565b600080600080610eb06122b6565b90506000610ebc611e44565b9050610ed2428388610ecc6119bb565b85612ac0565b94509450945050509193909250565b6000610eec82612e58565b92915050565b6002546001600160a01b031690565b6002546001600160a01b03163314610f2b5760405162461bcd60e51b81526004016109fa90613d54565b6204001a54610f4390610f3e9083612e82565b612eaa565b610f776001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0163383612ee1565b50565b600e54111590565b610f8a613938565b60118261ffff8110610f9857fe5b600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050919050565b6005546001600160a01b031633146110005760405162461bcd60e51b81526004016109fa906141d9565b6204001b5461100f90826129a9565b6204001b55600554610f77906001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca08116911683612ee1565b6204001b5490565b7f0000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c90565b6204001a5490565b6005546001600160a01b031633146110ac5760405162461bcd60e51b81526004016109fa906141d9565b6204001b546110bb9082612e82565b6204001b55600554610f77906001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0811691163084612f37565b600e5481565b611109612f58565b6001600160a01b031661111a611aa9565b6001600160a01b0316146111405760405162461bcd60e51b81526004016109fa9061426e565b610f7781612f5c565b600061115433612790565b9050801561116b5761116b84846204000d54612870565b611177818585856129ce565b50505050565b6204000d5490565b6001600160a01b03811660009081526204001160209081526040808320805460018201546002909201546204000d54620400129095529285205485948594929392915b818110156111eb576111dc85858584611752565b919650945092506001016111c8565b509297919650945092505050565b6005546000906001600160a01b031633146112265760405162461bcd60e51b81526004016109fa906141d9565b8284101580156112365750818310155b6112525760405162461bcd60e51b81526004016109fa90613ded565b6204001b5461126190856129a9565b6204001b556000611270610e7d565b905060008461127d611e44565b0390506000611296826112908886612756565b90612fe1565b90506112a6826112908786612756565b600a549094506112cb906000906001600160a01b03166112c68488612e82565b613013565b6112d760003386613013565b7ffef68dfebd892147056f2f1346892955854e67b190cf0b3c3dcfe2972109d82c8787838760405161130c94939291906145e3565b60405180910390a15050509392505050565b600f5481565b600c5481565b600b5481565b7f000000000000000000000000d2df8d600f7b32b8e708900646f8898c5215869090565b61135c612f58565b6001600160a01b031661136d611aa9565b6001600160a01b0316146113935760405162461bcd60e51b81526004016109fa9061426e565b600c541580156113a35750600b54155b6113bf5760405162461bcd60e51b81526004016109fa906143ca565b83158015906113d65750670de0b6b3a76400008310155b6113f25760405162461bcd60e51b81526004016109fa9061414c565b600c84905560008052600d6020527f81955a0a11e65eac625c29e8882660bae4e165a75d72780094acae8ece9a29ee8490556040517fa9cc843da7a73fc99a9077d9af92c4e351b84959afc9a104e7cee3ff4a76c0db906114549086906145b6565b60405180910390a160006201518061146b42611bf7565b037f0000000000000000000000000000000000000000000000000000000001e133808101600b55600854604051639f05715160e01b81529192506000916001600160a01b0390911690639f057151906114c89085906004016145b6565b60206040518083038186803b1580156114e057600080fd5b505afa1580156114f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115189190613aeb565b9050806115375760405162461bcd60e51b81526004016109fa90613fc5565b600082815262040015602090815260408083208890556204001690915281208590556204001b84905561156983612d62565b6000848152620400196020526040908190208290555190915083907f0b88c5bd74fc625a4f651904bf835063c6a449220be319924685261fb7709dd5906115b5908990899086906145cd565b60405180910390a25050600e5550505050565b7f000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d393490565b60105460ff161561160f5760405162461bcd60e51b81526004016109fa906140db565b600b548061162f5760405162461bcd60e51b81526004016109fa90614123565b6008546040805163061b57a360e51b815290516000926001600160a01b03169163c36af460916004808301926020929190829003018186803b15801561167457600080fd5b505afa158015611688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ac9190613aeb565b905060006116b8611e44565b905060006116f2427f0000000000000000000000000000000000000000000000000000000001e133808603856116ec6119bb565b86612ac0565b92505050806000146117165760405162461bcd60e51b81526004016109fa906141af565b6010805460ff191660011790556040517fa8cab3d1893ed53071b052fafa843143492f25d1d6b0170d460789f7ab1954be90600090a150505050565b60008060008060118561ffff811061176657fe5b60040201905061179e611786826001015488612c0c90919063ffffffff16565b8254610e9c90611797908b90612c0c565b8b906129a9565b60028201549094506117b08882612c0c565b93506117bc8782612c0c565b925050509450945094915050565b6117d2612f58565b6001600160a01b03166117e3611aa9565b6001600160a01b0316146118095760405162461bcd60e51b81526004016109fa9061426e565b6204001a541561182b5760405162461bcd60e51b81526004016109fa9061406f565b610f77816130e8565b61183c612f58565b6001600160a01b031661184d611aa9565b6001600160a01b0316146118735760405162461bcd60e51b81526004016109fa9061426e565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6118c5612f58565b6001600160a01b03166118d6611aa9565b6001600160a01b0316146118fc5760405162461bcd60e51b81526004016109fa9061426e565b600260009054906101000a90046001600160a01b03166001600160a01b0316636c8fcfa26040518163ffffffff1660e01b815260040160206040518083038186803b15801561194a57600080fd5b505afa15801561195e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119829190613ab3565b61199e5760405162461bcd60e51b81526004016109fa90613e24565b610f77816131b6565b620400176020526000908152604090205481565b6204001054600c546204000e54600092610ab6929091610e9c91612c0c565b6001600160a01b039182166000908152620400146020908152604080832093909416825291909152205490565b6002546001600160a01b03163314611a315760405162461bcd60e51b81526004016109fa90613d54565b600a54611a4a906000906001600160a01b031683613013565b6204001a54611a5d90610f3e90846129a9565b5050565b611a69612f58565b6001600160a01b0316611a7a611aa9565b6001600160a01b031614611aa05760405162461bcd60e51b81526004016109fa9061426e565b610f7781613284565b6000546001600160a01b031690565b6008546001600160a01b031681565b6009546001600160a01b031681565b80806204000d5414611afa5760405162461bcd60e51b81526004016109fa906144a6565b611b04338361252a565b8415611b1457611b14848361252a565b610a3c853386866132cf565b600080611b2c33612790565b9050611b39858585611f58565b8015611b4e57611b4e85876204000d54612870565b611ba6836040518060600160405280602881526020016146b0602891396001600160a01b0380891660009081526204001360209081526040808320938d168352929052208460038110611b9d57fe5b0154919061340e565b9150611bb4818688856129ce565b50949350505050565b8015611be7576204000d54811115611be75760405162461bcd60e51b81526004016109fa90614178565b611bf2838383612870565b505050565b600061c4e06201518081611c0b85836129a9565b0381611c1357fe5b046201518002019050919050565b6001600160a01b0380831660009081526204001360209081526040808320938516835292905290812081908560038110611c5757fe5b015490508415611cae576204000d546001600160a01b0380861660009081526204001460209081526040808320938816835292905220545b81811015611cab57611ca1838261343a565b9250600101611c8f565b50505b90505b9392505050565b620400186020526000908152604090205481565b80806204000d5414611cf05760405162461bcd60e51b81526004016109fa906144a6565b8415611d0157611d01338584612870565b610a3c853386866129ce565b6002546001600160a01b03163314611d375760405162461bcd60e51b81526004016109fa90613d54565b611d6b6001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0168484612ee1565b600a54611bf2906000906001600160a01b031683613013565b6005546001600160a01b031690565b611d9b612f58565b6001600160a01b0316611dac611aa9565b6001600160a01b031614611dd25760405162461bcd60e51b81526004016109fa9061426e565b610f7781613470565b6002546001600160a01b03163314611e055760405162461bcd60e51b81526004016109fa90613d54565b80806204000d5414611e295760405162461bcd60e51b81526004016109fa906144a6565b8415611e3957611e39848361252a565b610a3c858585613013565b6000807f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611e939190613cc5565b60206040518083038186803b158015611eab57600080fd5b505afa158015611ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee39190613aeb565b9050611f0a6204001a54611f046204001b54846129a990919063ffffffff16565b90612e82565b91505090565b611f18612f58565b6001600160a01b0316611f29611aa9565b6001600160a01b031614611f4f5760405162461bcd60e51b81526004016109fa9061426e565b610f77816134bb565b6000611f6333612790565b90508015611f9e57611f7442610f7a565b611f905760405162461bcd60e51b81526004016109fa90614441565b611f9e836204000d5461252a565b611fac846204000d5461252a565b611177818585856132cf565b6006546007546001600160a01b0390911691565b80806204000d5414611ff05760405162461bcd60e51b81526004016109fa906144a6565b611ffa858361252a565b85156120155761200b853384612870565b612015848361252a565b6000612064846040518060600160405280602881526020016146b0602891396001600160a01b0389166000908152620400136020908152604080832033845290915290208a60038110611b9d57fe5b9050612072878733846129ce565b61207e878787876132cf565b50505050505050565b6001600160a01b0316600090815262040012602052604090205490565b600a546001600160a01b031681565b600060118261ffff81106120c357fe5b60040201600301549050919050565b6120da612f58565b6001600160a01b03166120eb611aa9565b6001600160a01b0316146121115760405162461bcd60e51b81526004016109fa9061426e565b610f7781613535565b6204000d546001600160a01b038216600090815262040012602052604081205490919080821415612175576001600160a01b03841660009081526204001160205260409020856003811061216a57fe5b015492505050610eec565b6001600160a01b0384166000908152620400116020526040902080546001820154600290920154909190835b858110156121c4576121b584848484611752565b919550935091506001016121a1565b50876121d7578295505050505050610eec565b60018814156121ec57509350610eec92505050565b6002881415612201579450610eec9350505050565b60405162461bcd60e51b81526004016109fa90613dc4565b7f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b6005546001600160a01b031633146122675760405162461bcd60e51b81526004016109fa906141d9565b6204001b546122769082612e82565b6204001b556040517f3743c9e9a14de8dfa6e52fac936fe2cbf23e8e43d0d4c46ef57bcff3b377967e906122ab9083906145b6565b60405180910390a150565b600b547f0000000000000000000000000000000000000000000000000000000001e13380900390565b620400196020526000908152604090205481565b6000908152600d602052604090205490565b60008080845b8481101561232e5761231f89898984611752565b919a509850965060010161230b565b50969795965093949350505050565b612345612f58565b6001600160a01b0316612356611aa9565b6001600160a01b03161461237c5760405162461bcd60e51b81526004016109fa9061426e565b610f7781613580565b600090815262040015602090815260408083205462040016909252909120549091565b6123b0612f58565b6001600160a01b03166123c1611aa9565b6001600160a01b0316146123e75760405162461bcd60e51b81526004016109fa9061426e565b6001600160a01b03811661240d5760405162461bcd60e51b81526004016109fa90613eab565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b7f000000000000000000000000000000000000000000000000000000000000000981565b60008061249833612790565b905080156124af576124af85856204000d54612870565b6001600160a01b0380861660009081526204001360209081526040808320938816835292905220610b1e90849083600381106124e757fe5b015490612e82565b6000610eec826135e5565b8015612524576204000d548111156125245760405162461bcd60e51b81526004016109fa90614178565b611a5d82825b8061253657506204000d545b6001600160a01b038216600090815262040012602052604090205481811061255e5750611a5d565b6001600160a01b0383166000908152620400116020908152604080832080546001820154600283015462040012909552929094208690559291811580156125a3575080155b156125b2575050505050611a5d565b845b868110156125d7576125c884848484611752565b919550935091506001016125b4565b508284600001558184600101558084600201556040516001600160a01b038816907fd3f04497b42e4930518874144f53da3a7b078a70d319cb2a210e34f4b8dfd24e9061262b9089908790879087906145e3565b60405180910390a250505050505050565b6001600160a01b0382166126625760405162461bcd60e51b81526004016109fa906142c9565b6126a481604051806060016040528060228152602001614668602291396001600160a01b038516600090815262040011602052604090208660038110611b9d57fe5b6001600160a01b0383166000908152620400116020526040902084600381106126c957fe5b01556126de816204000e85600381106124e757fe5b6204000e84600381106126ed57fe5b01556126f8836135e5565b6001600160a01b031663dd5645b6836000846040518463ffffffff1660e01b815260040161272893929190613cd9565b600060405180830381600087803b15801561274257600080fd5b505af115801561207e573d6000803e3d6000fd5b60008261276557506000610eec565b8282028284828161277257fe5b0414611cb15760405162461bcd60e51b81526004016109fa9061422d565b60007f0000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c6001600160a01b0316826001600160a01b031614156127d457506000610a59565b7f000000000000000000000000d2df8d600f7b32b8e708900646f8898c521586906001600160a01b0316826001600160a01b0316141561281657506001610a59565b7f000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d39346001600160a01b0316826001600160a01b0316141561285857506002610a59565b60405162461bcd60e51b81526004016109fa90613f33565b8061287c57506204000d545b6001600160a01b0380841660009081526204001460209081526040808320938616835292905220548181106128b15750611bf2565b6001600160a01b0384811660008181526204001360209081526040808320948816808452948252808320600181015460028201549585526204001484528285209685529590925290912085905591908115801561290c575080155b1561291a5750505050611bf2565b835b858110156129445761292e838261343a565b925061293a828261343a565b915060010161291c565b508183600101558083600201556001600160a01b038087169088167f8fa162daa8095482092c801a2fbf4a0351846b94fe2d2e0c3ab60dbb9b6693ae878660000154868660405161299894939291906145e3565b60405180910390a350505050505050565b600082820183811015611cb15760405162461bcd60e51b81526004016109fa90613f8e565b6001600160a01b0383166129f45760405162461bcd60e51b81526004016109fa9061434f565b6001600160a01b038216612a1a5760405162461bcd60e51b81526004016109fa90613ef1565b6001600160a01b038084166000908152620400136020908152604080832093861683529290522081908560038110612a4e57fe5b0155612a59846135e5565b6001600160a01b031663c0a755b98484846040518463ffffffff1660e01b8152600401612a8893929190613cd9565b600060405180830381600087803b158015612aa257600080fd5b505af1158015612ab6573d6000803e3d6000fd5b5050505050505050565b6000848152620400156020526040812054818415612bc057612b1085611290612b09877f0000000000000000000000000000000000000000000000000000000000000001612756565b8990612756565b9250612b59612b52670de0b6b3a7640000610e9c620151806112908c8e036204001960008f81526020019081526020016000205461275690919063ffffffff16565b8390612c0c565b9150612b85827f0000000000000000000000000000000000000000000000000000000000000009612756565b831015612b93576000612bb9565b7f0000000000000000000000000000000000000000000000000000000000000009820283035b9050612c01565b50600086815262040016602052604090205480612bfd837f0000000000000000000000000000000000000000000000000000000000000009612756565b0192505b955095509592505050565b6000611cb1670de0b6b3a76400006112908585612756565b612c2c613938565b612c37848484613673565b6204000d54600c849055600181016000908152600d60205260409081902085905551919250907fa9cc843da7a73fc99a9077d9af92c4e351b84959afc9a104e7cee3ff4a76c0db90612c8a9085906145b6565b60405180910390a18160118261ffff8110612ca157fe5b6004020160008201518160000155602082015181600101556040820151816002015560608201518160030155905050806001016204000d8190555086817fe3df43951e14c0a4004438a979718a41a3501704f5326c446949863c51da9961888888876000015188602001518960400151604051612d23969594939291906145fe565b60405180910390a36204000e546204000f546204001054612d4692919084611752565b62040010556204000f556204000e5561207e306001830161252a565b600080612dfe600960009054906101000a90046001600160a01b03166001600160a01b031663d4a3e9d76040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612db857600080fd5b505af1158015612dcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df09190613aeb565b66038d7ea4c6800090613738565b90507f41e376fd99913dea7fda140f5c0bd997515b1a181acc58737320322548ec6e72816000604051612e329291906145bf565b60405180910390a192915050565b6000611cb18261129085670de0b6b3a7640000612756565b600061c4e062093a8081612e6c85836129a9565b0381612e7457fe5b0462093a8002019050919050565b600082821115612ea45760405162461bcd60e51b81526004016109fa90613ff2565b50900390565b6204001a8190556040517f8457e683d800c4f496806b8972b297b7e3fac279363c2f89bd90dde4133b154f906122ab9083906145b6565b611bf28363a9059cbb60e01b8484604051602401612f00929190613cfd565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261374e565b611177846323b872dd60e01b858585604051602401612f0093929190613cd9565b3390565b6005546001600160a01b0382811691161415612f7757600080fd5b600680546001600160a01b0319166001600160a01b0383169081179091554260078190556040517f32ae77edfd0636915483336791468b5cd4f156b427e632138786afbdfdafc04d91612fd6916203f4808201916213c68001906145bf565b60405180910390a250565b60008082116130025760405162461bcd60e51b81526004016109fa906140a4565b81838161300b57fe5b049392505050565b6001600160a01b0382166130395760405162461bcd60e51b81526004016109fa90614554565b61304c816204000e8560038110610b1657fe5b6204000e846003811061305b57fe5b01556001600160a01b038216600090815262040011602052604090206130889082908560038110610b1657fe5b6001600160a01b0383166000908152620400116020526040902084600381106130ad57fe5b01556130b8836135e5565b6001600160a01b031663dd5645b6600084846040518463ffffffff1660e01b815260040161272893929190613cd9565b6006546001600160a01b038281169116146131155760405162461bcd60e51b81526004016109fa90613f57565b6203f48060075401421015801561313257506213c6806007540142105b61314e5760405162461bcd60e51b81526004016109fa90614200565b6005546040516001600160a01b038084169216907fe4cec16b1a7e6b7979e923da619a8b1e5fd0f0fb6e5c1cf647f350430ee61ca990600090a3600580546001600160a01b039092166001600160a01b03199283161790556006805490911690556000600755565b6003546001600160a01b038281169116146131e35760405162461bcd60e51b81526004016109fa90613f57565b6203f48060045401421015801561320057506213c6806004540142105b61321c5760405162461bcd60e51b81526004016109fa90614200565b6002546040516001600160a01b038084169216907fce937feb4a560f179aae1a1090dcb38dab6dbb4c72cce5b6e3553d530f93685f90600090a3600280546001600160a01b039092166001600160a01b03199283161790556003805490911690556000600455565b600880546001600160a01b0319166001600160a01b0383161790556040517f8a8e0da24663134a95560b62466bb31935cfc0788a6686d10667f684ed810fb2906122ab908390613cc5565b6001600160a01b0383166132f55760405162461bcd60e51b81526004016109fa9061430a565b6001600160a01b03821661331b5760405162461bcd60e51b81526004016109fa90613d81565b61335d8160405180606001604052806026815260200161468a602691396001600160a01b038616600090815262040011602052604090208760038110611b9d57fe5b6001600160a01b03841660009081526204001160205260409020856003811061338257fe5b01556001600160a01b038216600090815262040011602052604090206133af9082908660038110610b1657fe5b6001600160a01b0383166000908152620400116020526040902085600381106133d457fe5b01556133df846135e5565b6001600160a01b031663dd5645b68484846040518463ffffffff1660e01b8152600401612a8893929190613cd9565b600081848411156134325760405162461bcd60e51b81526004016109fa9190613d21565b505050900390565b60008060118361ffff811061344b57fe5b6004020190506134688160020154856137dd90919063ffffffff16565b949350505050565b600980546001600160a01b0319166001600160a01b0383161790556040517f2629f592256aaf49e3c60966d01cf4c7897d640c00ae94b0472d458c2a647a55906122ab908390613cc5565b6002546001600160a01b03828116911614156134d657600080fd5b600380546001600160a01b0319166001600160a01b0383169081179091554260048190556040517f2e6b5912c3dac53b95017557cebcd0618fa7a13f4c8d1d96c5afb31b15d693f191612fd6916203f4808201916213c68001906145bf565b600a80546001600160a01b0319166001600160a01b0383161790556040517fe5693914d19c789bdee50a362998c0bc8d035a835f9871da5d51152f0582c34f906122ab908390613cc5565b6107088110158015613594575061a8c08111155b6135b05760405162461bcd60e51b81526004016109fa9061451d565b600f8190556040517fbb681a7fb16d51d6d0928d6ce178fbca96144ec836f09f63977a33a0271080bf906122ab9083906145b6565b60008161361357507f0000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c610a59565b600182141561364357507f000000000000000000000000d2df8d600f7b32b8e708900646f8898c52158690610a59565b600282141561220157507f000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d3934610a59565b61367b613938565b60008060008686116136cd5785925060017f0000000000000000000000000000000000000000000000000000000000000009016136ba84890387612e40565b816136c157fe5b0491506000905061370f565b8692506000915060017f00000000000000000000000000000000000000000000000000000000000000090161370484880387612e40565b8161370b57fe5b0490505b604080516080810182529283526020830191909152810191909152426060820152949350505050565b60008183106137475781611cb1565b5090919050565b60606137a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137f59092919063ffffffff16565b805190915015611bf257808060200190518101906137c19190613ab3565b611bf25760405162461bcd60e51b81526004016109fa906143f7565b6000611cb1670de0b6b3a76400006112908585613804565b6060611cae8484600085613838565b60008261381357506000610eec565b8282028284828161382057fe5b04141561382d5780613468565b506000199392505050565b60608247101561385a5760405162461bcd60e51b81526004016109fa90614029565b613863856138f9565b61387f5760405162461bcd60e51b81526004016109fa90614393565b60006060866001600160a01b0316858760405161389c9190613ca9565b60006040518083038185875af1925050503d80600081146138d9576040519150601f19603f3d011682016040523d82523d6000602084013e6138de565b606091505b50915091506138ee8282866138ff565b979650505050505050565b3b151590565b6060831561390e575081611cb1565b82511561391e5782518084602001fd5b8160405162461bcd60e51b81526004016109fa9190613d21565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b80356001600160a01b0381168114610eec57600080fd5b600060208284031215613988578081fd5b611cb18383613960565b600080604083850312156139a4578081fd5b6139ae8484613960565b91506139bd8460208501613960565b90509250929050565b600080600080608085870312156139db578182fd5b84356139e681614652565b935060208501356139f681614652565b92506040850135613a0681614652565b9396929550929360600135925050565b600080600060608486031215613a2a578283fd5b8335613a3581614652565b92506020840135613a4581614652565b929592945050506040919091013590565b60008060408385031215613a68578182fd5b613a728484613960565b946020939093013593505050565b600080600060608486031215613a94578283fd5b613a9e8585613960565b95602085013595506040909401359392505050565b600060208284031215613ac4578081fd5b81518015158114611cb1578182fd5b600060208284031215613ae4578081fd5b5035919050565b600060208284031215613afc578081fd5b5051919050565b60008060408385031215613b15578182fd5b823591506139bd8460208501613960565b600080600060608486031215613b3a578283fd5b833592506020840135613b4c81614652565b91506040840135613b5c81614652565b809150509250925092565b600080600080600060a08688031215613b7e578081fd5b85359450613b8f8760208801613960565b9350613b9e8760408801613960565b94979396509394606081013594506080013592915050565b60008060008060808587031215613bcb578384fd5b843593506020850135613bdd81614652565b93969395505050506040820135916060013590565b60008060408385031215613c04578182fd5b50508035926020909101359150565b600080600060608486031215613c27578081fd5b505081359360208301359350604090920135919050565b60008060008060808587031215613c53578182fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215613c86578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008251613cbb818460208701614626565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082528251806020840152613d40816040850160208701614626565b601f01601f19169190910160400192915050565b60208082526013908201527213db9b1e481c1c9a5b585c9e481b585c9ad95d606a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6020808252600f908201526e496e76616c6964207472616e63686560881b604082015260600190565b60208082526018908201527f4665652063616e6e6f74206578636565642070726f6669740000000000000000604082015260600190565b6020808252601c908201527f43616e6e6f7420757064617465207072696d617279206d61726b657400000000604082015260600190565b60208082526030908201527f556e6465726c79696e6720707269636520666f7220736574746c656d656e742060408201526f1a5cc81b9bdd081c9958591e481e595d60821b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252600a90820152694f6e6c7920736861726560b01b604082015260600190565b60208082526019908201527f50726f706f7365642061646472657373206d69736d6174636800000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601390820152725072696365206e6f7420617661696c61626c6560681b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252818101527f43616e6e6f742075706461746520737472617465677920776974682064656274604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252600e908201526d20b63932b0b23c90333937bd32b760911b604082015260600190565b602080825260069082015265233937bd32b760d11b604082015260600190565b6020808252600f908201526e139bdd081a5b9a5d1a585b1a5e9959608a1b604082015260600190565b602080825260129082015271496e76616c696420706172616d657465727360701b604082015260600190565b6020808252601b908201527f5461726765742076657273696f6e206f7574206f6620626f756e640000000000604082015260600190565b60208082526010908201526f2737ba103a3790313290333937bd32b760811b604082015260600190565b6020808252600d908201526c4f6e6c7920737472617465677960981b604082015260600190565b6020808252601390820152724e6f7420726561647920746f2075706461746560681b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600c908201526b2a3790313290333937bd32b760a11b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b602080825260139082015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601490820152735472616e7366657220697320696e61637469766560601b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526014908201527327b7363c9031bab93932b73a103b32b939b4b7b760611b604082015260600190565b60208082526029908201527f5468652063757272656e742074726164696e67207965617220646f6573206e6f6040820152681d08195b99081e595d60ba1b606082015260800190565b6020808252601f908201527f45786365656420616c6c6f7765642064656c61792074696d652072616e676500604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b8151815260208083015190820152604080830151908201526060918201519181019190915260800190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b958652602086019490945260408501929092526060840152608083015260a082015260c00190565b60005b83811015614641578181015183820152602001614629565b838111156111775750506000910152565b6001600160a01b0381168114610f7757600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a26469706673582212205b0e01f779c9b936362d162508336ab9d67b9da147ee8fa7249711be7d72be1964736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000001e133800000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca000000000000000000000000000000000000000000000000000000000000000120000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c000000000000000000000000d2df8d600f7b32b8e708900646f8898c52158690000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d3934000000000000000000000000a8be5ab62794a647254e1e62844201efc8477e220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c32f23ee32cb5681eca5e84c2ae728c3f0b0149f00000000000000000000000037473872769ff711bd6d800e518061fae67e10a900000000000000000000000096ccae5662de55c50b997f13396e6a183074f9d5
-----Decoded View---------------
Arg [0] : params (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [1] : 0000000000000000000000000000000000000000000000000000000001e13380
Arg [2] : 0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [4] : 0000000000000000000000006aff2526d50fa742ca08ed1cf6e3cf7987a30f5c
Arg [5] : 000000000000000000000000d2df8d600f7b32b8e708900646f8898c52158690
Arg [6] : 000000000000000000000000379e8d9f6a8a045a8654169fabff8bcfec0d3934
Arg [7] : 000000000000000000000000a8be5ab62794a647254e1e62844201efc8477e22
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [9] : 000000000000000000000000c32f23ee32cb5681eca5e84c2ae728c3f0b0149f
Arg [10] : 00000000000000000000000037473872769ff711bd6d800e518061fae67e10a9
Arg [11] : 00000000000000000000000096ccae5662de55c50b997f13396e6a183074f9d5
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,868.7 | 95.7246 | $274,605.03 |
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.