Contract Overview
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0xdb68cfd0d9e624cb91f3946c57241f2b893f3e9103e1f61ee12ab38cc47df5eb | 42161064 | 267 days 18 hrs ago | 0x6539519e69343535a2af6583d9bae3ad74c6a293 | Contract Creation | 0 FTM |
[ Download CSV Export ]
Contract Name:
ReaperVaultV2
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.11; import "./interfaces/IStrategy.sol"; import "./interfaces/IERC4626.sol"; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import {FixedPointMathLib} from "./library/FixedPointMathLib.sol"; /** * @notice Implementation of a vault to deposit funds for yield optimizing. * This is the contract that receives funds and that users interface with. * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. */ contract ReaperVaultV2 is IERC4626, ERC20, ReentrancyGuard, AccessControlEnumerable { using SafeERC20 for IERC20Metadata; using FixedPointMathLib for uint256; struct StrategyParams { uint256 activation; // Activation block.timestamp uint256 allocBPS; // Allocation in BPS of vault's total assets uint256 allocated; // Amount of capital allocated to this strategy uint256 gains; // Total returns that Strategy has realized for Vault uint256 losses; // Total losses that Strategy has realized for Vault uint256 lastReport; // block.timestamp of the last time a report occured } mapping(address => StrategyParams) public strategies; // mapping strategies to their strategy parameters address[] public withdrawalQueue; // Ordering that `withdraw` uses to determine which strategies to pull funds from uint256 public constant DEGRADATION_COEFFICIENT = 10 ** 18; // The unit for calculating profit degradation. uint256 public constant PERCENT_DIVISOR = 10_000; // Basis point unit, for calculating slippage and strategy allocations uint256 public tvlCap; // The maximum amount of assets the vault can hold while still allowing deposits uint256 public totalAllocBPS; // Sum of allocBPS across all strategies (in BPS, <= 10k) uint256 public totalAllocated; // Amount of tokens that have been allocated to all strategies uint256 public lastReport; // block.timestamp of last report from any strategy uint256 public constructionTime; // The time the vault was deployed - for front-end bool public emergencyShutdown; // Emergency shutdown - when true funds are pulled out of strategies to the vault address public immutable asset; // The asset the vault accepts and looks to maximize. uint256 public withdrawMaxLoss = 1; // Max slippage(loss) allowed when withdrawing, in BPS (0.01%) uint256 public lockedProfitDegradation; // rate per block of degradation. DEGRADATION_COEFFICIENT is 100% per block uint256 public lockedProfit; // how much profit is locked and cant be withdrawn /** * Reaper Roles in increasing order of privilege. * {STRATEGIST} - Role conferred to strategists, allows for tweaking non-critical params. * {GUARDIAN} - Multisig requiring 2 signatures for emergency measures such as pausing and panicking. * {ADMIN}- Multisig requiring 3 signatures for unpausing and changing TVL cap. * * The DEFAULT_ADMIN_ROLE (in-built access control role) will be granted to a multisig requiring 4 * signatures. This role would have the ability to add strategies, as well as the ability to grant any other * roles. * * Also note that roles are cascading. So any higher privileged role should be able to perform all the functions * of any lower privileged role. */ bytes32 public constant STRATEGIST = keccak256("STRATEGIST"); bytes32 public constant GUARDIAN = keccak256("GUARDIAN"); bytes32 public constant ADMIN = keccak256("ADMIN"); bytes32[] private cascadingAccess; event TvlCapUpdated(uint256 newTvlCap); event LockedProfitDegradationUpdated(uint256 degradation); event StrategyReported( address indexed strategy, int256 roi, uint256 repayment, uint256 gains, uint256 losses, uint256 allocated, uint256 allocBPS ); event StrategyAdded(address indexed strategy, uint256 allocBPS); event StrategyAllocBPSUpdated(address indexed strategy, uint256 allocBPS); event StrategyRevoked(address indexed strategy); event UpdateWithdrawalQueue(address[] withdrawalQueue); event WithdrawMaxLossUpdated(uint256 withdrawMaxLoss); event EmergencyShutdown(bool active); event InCaseTokensGetStuckCalled(address token, uint256 amount); /** * @notice Initializes the vault's own 'RF' asset. * This asset is minted when someone does a deposit. It is burned in order * to withdraw the corresponding portion of the underlying assets. * @param _asset the asset to maximize. * @param _name the name of the vault asset. * @param _symbol the symbol of the vault asset. * @param _tvlCap initial deposit cap for scaling TVL safely. */ constructor( address _asset, string memory _name, string memory _symbol, uint256 _tvlCap, address[] memory _strategists, address[] memory _multisigRoles ) ERC20(string(_name), string(_symbol)) { asset = _asset; constructionTime = block.timestamp; lastReport = block.timestamp; tvlCap = _tvlCap; lockedProfitDegradation = DEGRADATION_COEFFICIENT * 46 / 10 ** 6; // 6 hours in blocks for (uint256 i = 0; i < _strategists.length; i = _uncheckedInc(i)) { _grantRole(STRATEGIST, _strategists[i]); } _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(DEFAULT_ADMIN_ROLE, _multisigRoles[0]); _grantRole(ADMIN, _multisigRoles[1]); _grantRole(GUARDIAN, _multisigRoles[2]); cascadingAccess = [DEFAULT_ADMIN_ROLE, ADMIN, GUARDIAN, STRATEGIST]; } /** * @notice It calculates the total underlying value of {asset} held by the system. * It takes into account the vault contract balance, and the balance deployed across * all the strategies. * @return totalManagedAssets - the total amount of assets managed by the vault. */ function totalAssets() public view returns (uint256) { return IERC20Metadata(asset).balanceOf(address(this)) + totalAllocated; } /** * @notice It calculates the amount of free funds available after profit locking. * For calculating share price and making withdrawals. * @return freeFunds - the total amount of free funds available. */ function _freeFunds() internal view returns (uint256) { return totalAssets() - _calculateLockedProfit(); } /** * @notice It calculates the amount of locked profit from recent harvests. * @return the amount of locked profit. */ function _calculateLockedProfit() internal view returns (uint256) { uint256 lockedFundsRatio = (block.timestamp - lastReport) * lockedProfitDegradation; if(lockedFundsRatio < DEGRADATION_COEFFICIENT) { return lockedProfit - ( lockedFundsRatio * lockedProfit / DEGRADATION_COEFFICIENT ); } else { return 0; } } /** * @notice The amount of shares that the Vault would exchange for the amount of assets provided, * in an ideal scenario where all the conditions are met. * @param assets The amount of underlying assets to convert to shares. * @return shares - the amount of shares given for the amount of assets. */ function convertToShares(uint256 assets) public view returns (uint256) { uint256 _totalSupply = totalSupply(); uint256 freeFunds = _freeFunds(); if (freeFunds == 0 || _totalSupply == 0) return assets; return assets.mulDivDown(_totalSupply, freeFunds); } /** * @notice The amount of assets that the Vault would exchange for the amount of shares provided, * in an ideal scenario where all the conditions are met. * @param shares The amount of shares to convert to underlying assets. * @return assets - the amount of assets given for the amount of shares. */ function convertToAssets(uint256 shares) public view returns (uint256) { uint256 _totalSupply = totalSupply(); if (_totalSupply == 0) return shares; // Initially the price is 1:1 return shares.mulDivDown(_freeFunds(), _totalSupply); } /** * @notice Maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * @param receiver The depositor, unused in this case but here as part of the ERC4626 spec. * @return maxAssets - the maximum depositable assets. */ function maxDeposit(address receiver) public view returns (uint256) { uint256 _totalAssets = totalAssets(); if (_totalAssets > tvlCap) { return 0; } return tvlCap - _totalAssets; } /** * @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, * given current on-chain conditions. * @param assets The amount of assets to deposit. * @return shares - the amount of shares given for the amount of assets. */ function previewDeposit(uint256 assets) public view returns (uint256) { return convertToShares(assets); } /** * @notice A helper function to call deposit() with all the sender's funds. */ function depositAll() external { deposit(IERC20Metadata(asset).balanceOf(msg.sender), msg.sender); } /** * @notice The entrypoint of funds into the system. People deposit with this function * into the vault. * @param assets The amount of assets to deposit * @param receiver The receiver of the minted shares * @return shares - the amount of shares issued from the deposit. */ function deposit(uint256 assets, address receiver) public nonReentrant returns (uint256 shares) { require(!emergencyShutdown, "Cannot deposit during emergency shutdown"); require(assets != 0, "please provide amount"); uint256 _pool = totalAssets(); require(_pool + assets <= tvlCap, "vault is full!"); shares = previewDeposit(assets); IERC20Metadata(asset).safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); } /** * @notice Maximum amount of shares that can be minted from the Vault for the receiver, through a mint call. * @param receiver The minter, unused in this case but here as part of the ERC4626 spec. * @return shares - the maximum amount of shares issued from calling mint. */ function maxMint(address receiver) public view virtual returns (uint256) { return convertToShares(maxDeposit(address(0))); } /** * @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, * given current on-chain conditions. * @param shares The amount of shares to mint. * @return assets - the amount of assets given for the amount of shares. */ function previewMint(uint256 shares) public view returns (uint256) { uint256 _totalSupply = totalSupply(); if (_totalSupply == 0) return shares; // Initially the price is 1:1 return shares.mulDivUp(_freeFunds(), _totalSupply); } /** * @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * @param shares The amount of shares to mint. * @param receiver The receiver of the minted shares. * @return assets - the amount of assets transferred from the mint. */ function mint(uint256 shares, address receiver) external nonReentrant returns (uint256) { require(!emergencyShutdown, "Cannot mint during emergency shutdown"); require(shares != 0, "please provide amount"); uint256 assets = previewMint(shares); uint256 _pool = totalAssets(); require(_pool + assets <= tvlCap, "vault is full!"); if (_freeFunds() == 0) assets = shares; IERC20Metadata(asset).safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); return assets; } /** * @notice Maximum amount of the underlying asset that can be withdrawn from the owner balance in the Vault, * through a withdraw call. * @param owner The owner of the shares to withdraw. * @return maxAssets - the maximum amount of assets transferred from calling withdraw. */ function maxWithdraw(address owner) external view returns (uint256) { return convertToAssets(balanceOf(owner)); } /** * @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * @param assets The amount of assets to withdraw. * @return shares - the amount of shares burned for the amount of assets. */ function previewWithdraw(uint256 assets) public view returns (uint256) { uint256 _totalSupply = totalSupply(); if (totalSupply() == 0) return 0; uint256 freeFunds = _freeFunds(); if (freeFunds == 0) return assets; return assets.mulDivUp(_totalSupply, freeFunds); } /** * @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. * @param assets The amount of assets to withdraw. * @param receiver The receiver of the withdrawn assets. * @param owner The owner of the shares to withdraw. * @return shares - the amount of shares burned. */ function withdraw(uint256 assets, address receiver, address owner) external nonReentrant returns (uint256 shares) { require(assets != 0, "please provide amount"); shares = previewWithdraw(assets); _withdraw(assets, shares, receiver, owner); return shares; } /** * @notice Helper function used by both withdraw and redeem to withdraw assets. * @param assets The amount of assets to withdraw. * @param shares The amount of shares to burn. * @param receiver The receiver of the withdrawn assets. * @param owner The owner of the shares to withdraw. * @return assets - the amount of assets withdrawn. */ function _withdraw(uint256 assets, uint256 shares, address receiver, address owner) internal returns (uint256) { _burn(owner, shares); if (assets > IERC20Metadata(asset).balanceOf(address(this))) { uint256 totalLoss = 0; uint256 queueLength = withdrawalQueue.length; uint256 vaultBalance = 0; for (uint256 i = 0; i < queueLength; i = _uncheckedInc(i)) { vaultBalance = IERC20Metadata(asset).balanceOf(address(this)); if (assets <= vaultBalance) { break; } address stratAddr = withdrawalQueue[i]; uint256 strategyBal = strategies[stratAddr].allocated; if (strategyBal == 0) { continue; } uint256 remaining = assets - vaultBalance; uint256 loss = IStrategy(stratAddr).withdraw(Math.min(remaining, strategyBal)); uint256 actualWithdrawn = IERC20Metadata(asset).balanceOf(address(this)) - vaultBalance; // Withdrawer incurs any losses from withdrawing as reported by strat if (loss != 0) { assets -= loss; totalLoss += loss; _reportLoss(stratAddr, loss); } strategies[stratAddr].allocated -= actualWithdrawn; totalAllocated -= actualWithdrawn; } vaultBalance = IERC20Metadata(asset).balanceOf(address(this)); if (assets > vaultBalance) { assets = vaultBalance; } require(totalLoss <= ((assets + totalLoss) * withdrawMaxLoss) / PERCENT_DIVISOR, "Cannot exceed the maximum allowed withdraw slippage"); } IERC20Metadata(asset).safeTransfer(receiver, assets); emit Withdraw(msg.sender, receiver, owner, assets, shares); return assets; } /** * @notice Maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * @param owner The owner of the shares to redeem. * @return maxShares - the amount of redeemable shares. */ function maxRedeem(address owner) external view returns (uint256) { return balanceOf(owner); } /** * @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * @param shares The amount of shares to redeem. * @return assets - the amount of assets redeemed from the amount of shares. */ function previewRedeem(uint256 shares) public view returns (uint256) { return convertToAssets(shares); } /** * @notice Function for various UIs to display the current value of one of our yield tokens. * @return pricePerFullShare - a uint256 of how much underlying asset one vault share represents. */ function getPricePerFullShare() external view returns (uint256) { return convertToAssets(10 ** decimals()); } /** * @notice A helper function to call redeem() with all the sender's funds. */ function redeemAll() external { redeem(balanceOf(msg.sender), msg.sender, msg.sender); } /** * @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. * @param shares The amount of shares to redeem. * @param receiver The receiver of the redeemed assets. * @param owner The owner of the shares to redeem. * @return assets - the amount of assets redeemed. */ function redeem(uint256 shares, address receiver, address owner) public nonReentrant returns (uint256 assets) { require(shares != 0, "please provide amount"); assets = previewRedeem(shares); return _withdraw(assets, shares, receiver, owner); } /** * @notice Adds a new strategy to the vault with a given allocation amount in basis points. * @param strategy The strategy to add. * @param allocBPS The strategy allocation in basis points. */ function addStrategy(address strategy, uint256 allocBPS) external { _atLeastRole(DEFAULT_ADMIN_ROLE); require(!emergencyShutdown, "Cannot add a strategy during emergency shutdown"); require(strategy != address(0), "Cannot add the zero address"); require(strategies[strategy].activation == 0, "Strategy must not be added already"); require(address(this) == IStrategy(strategy).vault(), "The strategy must use this vault"); require(asset == IStrategy(strategy).want(), "The strategy must use the same want"); require(allocBPS + totalAllocBPS <= PERCENT_DIVISOR, "Total allocation points are over 100%"); strategies[strategy] = StrategyParams({ activation: block.timestamp, allocBPS: allocBPS, allocated: 0, gains: 0, losses: 0, lastReport: block.timestamp }); totalAllocBPS += allocBPS; withdrawalQueue.push(strategy); emit StrategyAdded(strategy, allocBPS); } /** * @notice Updates the allocation points for a given strategy. * @param strategy The strategy to update. * @param allocBPS The strategy allocation in basis points. */ function updateStrategyAllocBPS(address strategy, uint256 allocBPS) external { _atLeastRole(STRATEGIST); require(strategies[strategy].activation != 0, "Strategy must be active"); totalAllocBPS -= strategies[strategy].allocBPS; strategies[strategy].allocBPS = allocBPS; totalAllocBPS += allocBPS; require(totalAllocBPS <= PERCENT_DIVISOR, "Total allocation points are over 100%"); emit StrategyAllocBPSUpdated(strategy, allocBPS); } /** * @notice Removes any allocation to a given strategy. * @param strategy The strategy to revoke. */ function revokeStrategy(address strategy) external { if (!(msg.sender == strategy)) { _atLeastRole(GUARDIAN); } if (strategies[strategy].allocBPS == 0) { return; } totalAllocBPS -= strategies[strategy].allocBPS; strategies[strategy].allocBPS = 0; emit StrategyRevoked(strategy); } /** * @notice Called by a strategy to determine the amount of capital that the vault is * able to provide it. A positive amount means that vault has excess capital to provide * the strategy, while a negative amount means that the strategy has a balance owing to * the vault. * @return availableCapital - the amount of capital the vault can provide the strategy. */ function availableCapital() public view returns (int256) { address stratAddr = msg.sender; if (totalAllocBPS == 0 || emergencyShutdown) { return -int256(strategies[stratAddr].allocated); } uint256 stratMaxAllocation = (strategies[stratAddr].allocBPS * totalAssets()) / PERCENT_DIVISOR; uint256 stratCurrentAllocation = strategies[stratAddr].allocated; if (stratCurrentAllocation > stratMaxAllocation) { return -int256(stratCurrentAllocation - stratMaxAllocation); } else if (stratCurrentAllocation < stratMaxAllocation) { uint256 vaultMaxAllocation = (totalAllocBPS * totalAssets()) / PERCENT_DIVISOR; uint256 vaultCurrentAllocation = totalAllocated; if (vaultCurrentAllocation >= vaultMaxAllocation) { return 0; } uint256 available = stratMaxAllocation - stratCurrentAllocation; available = Math.min(available, vaultMaxAllocation - vaultCurrentAllocation); available = Math.min(available, IERC20Metadata(asset).balanceOf(address(this))); return int256(available); } else { return 0; } } /** * @notice Updates the withdrawalQueue to match the addresses and order specified. * @param _withdrawalQueue The new withdrawalQueue to update to. */ function setWithdrawalQueue(address[] calldata _withdrawalQueue) external { _atLeastRole(STRATEGIST); uint256 queueLength = _withdrawalQueue.length; require(queueLength != 0, "Cannot set an empty withdrawal queue"); delete withdrawalQueue; for (uint256 i = 0; i < queueLength; i = _uncheckedInc(i)) { address strategy = _withdrawalQueue[i]; StrategyParams storage params = strategies[strategy]; require(params.activation != 0, "Can only use active strategies in the withdrawal queue"); withdrawalQueue.push(strategy); } emit UpdateWithdrawalQueue(withdrawalQueue); } /** * @notice Helper function to report a loss by a given strategy. * @param strategy The strategy to report the loss for. * @param loss The amount lost. */ function _reportLoss(address strategy, uint256 loss) internal { StrategyParams storage stratParams = strategies[strategy]; // Loss can only be up the amount of capital allocated to the strategy uint256 allocation = stratParams.allocated; require(loss <= allocation, "Strategy cannot loose more than what was allocated to it"); if (totalAllocBPS != 0) { // reduce strat's allocBPS proportional to loss uint256 bpsChange = Math.min((loss * totalAllocBPS) / totalAllocated, stratParams.allocBPS); // If the loss is too small, bpsChange will be 0 if (bpsChange != 0) { stratParams.allocBPS -= bpsChange; totalAllocBPS -= bpsChange; } } // Finally, adjust our strategy's parameters by the loss stratParams.losses += loss; stratParams.allocated -= loss; totalAllocated -= loss; } /** * @notice Helper function to report the strategy returns on a harvest. * @param roi The return on investment (positive or negative) given as the total amount * gained or lost from the harvest. * @param repayment The repayment of debt by the strategy. * @return debt - the strategy debt to the vault. */ function report(int256 roi, uint256 repayment) external returns (uint256) { address stratAddr = msg.sender; StrategyParams storage strategy = strategies[stratAddr]; require(strategy.activation != 0, "Only active strategies can report"); uint256 loss = 0; uint256 gain = 0; if (roi < 0) { loss = uint256(-roi); _reportLoss(stratAddr, loss); } else { gain = uint256(roi); strategy.gains += uint256(roi); } int256 available = availableCapital(); uint256 debt = 0; uint256 credit = 0; if (available < 0) { debt = uint256(-available); repayment = Math.min(debt, repayment); if (repayment != 0) { strategy.allocated -= repayment; totalAllocated -= repayment; debt -= repayment; } } else { credit = uint256(available); strategy.allocated += credit; totalAllocated += credit; } uint256 freeWantInStrat = repayment; if (roi > 0) { freeWantInStrat += uint256(roi); } if (credit > freeWantInStrat) { IERC20Metadata(asset).safeTransfer(stratAddr, credit - freeWantInStrat); } else if (credit < freeWantInStrat) { IERC20Metadata(asset).safeTransferFrom(stratAddr, address(this), freeWantInStrat - credit); } uint256 lockedProfitBeforeLoss = _calculateLockedProfit() + gain; if (lockedProfitBeforeLoss > loss) { lockedProfit = lockedProfitBeforeLoss - loss; } else { lockedProfit = 0; } strategy.lastReport = block.timestamp; lastReport = block.timestamp; emit StrategyReported( stratAddr, roi, repayment, strategy.gains, strategy.losses, strategy.allocated, strategy.allocBPS ); if (strategy.allocBPS == 0 || emergencyShutdown) { return IStrategy(stratAddr).balanceOf(); } return debt; } /** * @notice Updates the withdrawMaxLoss which is the maximum allowed slippage. * @param _withdrawMaxLoss The new value, in basis points. */ function updateWithdrawMaxLoss(uint256 _withdrawMaxLoss) external { _atLeastRole(STRATEGIST); require(_withdrawMaxLoss <= PERCENT_DIVISOR, "withdrawMaxLoss cannot be greater than 100%"); withdrawMaxLoss = _withdrawMaxLoss; emit WithdrawMaxLossUpdated(withdrawMaxLoss); } /** * @notice Updates the vault tvl cap (the max amount of assets held by the vault). * @dev pass in max value of uint to effectively remove TVL cap. * @param newTvlCap The new tvl cap. */ function updateTvlCap(uint256 newTvlCap) public { _atLeastRole(ADMIN); tvlCap = newTvlCap; emit TvlCapUpdated(tvlCap); } /** * @notice Helper function to remove TVL cap. */ function removeTvlCap() external { _atLeastRole(ADMIN); updateTvlCap(type(uint256).max); } /** * @notice Activates or deactivates Vault mode where all Strategies go into full * withdrawal. * During Emergency Shutdown: * 1. No Users may deposit into the Vault (but may withdraw as usual.) * 2. New Strategies may not be added. * 3. Each Strategy must pay back their debt as quickly as reasonable to * minimally affect their position. * * If true, the Vault goes into Emergency Shutdown. If false, the Vault * goes back into Normal Operation. * @param active If emergencyShutdown is active or not. */ function setEmergencyShutdown(bool active) external { if (active == true) { _atLeastRole(GUARDIAN); } else { _atLeastRole(ADMIN); } emergencyShutdown = active; emit EmergencyShutdown(emergencyShutdown); } /** * @notice Rescues random funds stuck that the strat can't handle. * @param token address of the asset to rescue. */ function inCaseTokensGetStuck(address token) external { _atLeastRole(STRATEGIST); require(token != asset, "!asset"); uint256 amount = IERC20Metadata(token).balanceOf(address(this)); IERC20Metadata(token).safeTransfer(msg.sender, amount); emit InCaseTokensGetStuckCalled(token, amount); } /** * @notice Overrides the default 18 decimals for the vault ERC20 to * match the same decimals as the underlying asset used. * @return decimals - the amount of decimals used by the vault ERC20. */ function decimals() public view override returns (uint8) { return IERC20Metadata(asset).decimals(); } /** * @notice Changes the locked profit degradation. * match the same decimals as the underlying asset used. * @param degradation - The rate of degradation in percent per second scaled to 1e18. */ function setLockedProfitDegradation(uint256 degradation) external { _atLeastRole(STRATEGIST); require(degradation <= DEGRADATION_COEFFICIENT, "Degradation cannot be more than 100%"); lockedProfitDegradation = degradation; emit LockedProfitDegradationUpdated(degradation); } /** * @notice Internal function that checks cascading role privileges. Any higher privileged role * should be able to perform all the functions of any lower privileged role. This is * accomplished using the {cascadingAccess} array that lists all roles from most privileged * to least privileged. * @param role - The role in bytes from the keccak256 hash of the role name */ function _atLeastRole(bytes32 role) internal view { uint256 numRoles = cascadingAccess.length; uint256 specifiedRoleIndex; for (uint256 i = 0; i < numRoles; i = _uncheckedInc(i)) { if (role == cascadingAccess[i]) { specifiedRoleIndex = i; break; } else if (i == numRoles - 1) { revert(); } } for (uint256 i = 0; i <= specifiedRoleIndex; i = _uncheckedInc(i)) { if (hasRole(cascadingAccess[i], msg.sender)) { break; } else if (i == specifiedRoleIndex) { revert(); } } } /** * @notice For doing an unchecked increment of an index for gas optimization purposes * @param i - The number to increment * @return The incremented number */ function _uncheckedInc(uint256 i) internal pure returns (uint256) { unchecked { return i + 1; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IStrategy { //vault only - withdraws funds from the strategy function withdraw(uint256 _amount) external returns (uint256 loss); //claims rewards, charges fees, and re-deposits; returns caller fee amount. function harvest() external returns (uint256 callerFee); //returns the balance of all tokens managed by the strategy function balanceOf() external view returns (uint256); //returns the address of the vault that the strategy is serving function vault() external view returns (address); //returns the address of the token that the strategy needs to operate function want() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.11; interface IERC4626 { function asset() external view returns (address assetTokenAddress); function totalAssets() external view returns (uint256 totalManagedAssets); function convertToShares(uint256 assets) external view returns (uint256 shares); function convertToAssets(uint256 shares) external view returns (uint256 assets); function maxDeposit(address receiver) external view returns (uint256 maxAssets); function previewDeposit(uint256 assets) external view returns (uint256 shares); function deposit(uint256 assets, address receiver) external returns (uint256 shares); function maxMint(address receiver) external view returns (uint256 maxShares); function previewMint(uint256 shares) external view returns (uint256 assets); function mint(uint256 shares, address receiver) external returns (uint256 assets); function maxWithdraw(address owner) external view returns (uint256 maxAssets); function previewWithdraw(uint256 assets) external view returns (uint256 shares); function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); function maxRedeem(address owner) external view returns (uint256 maxShares); function previewRedeem(uint256 shares) external view returns (uint256 assets); function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares); event Withdraw(address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { // Start off with z at 1. z := 1 // Used below to help find a nearby power of 2. let y := x // Find the lowest power of 2 that is at least sqrt(x). if iszero(lt(y, 0x100000000000000000000000000000000)) { y := shr(128, y) // Like dividing by 2 ** 128. z := shl(64, z) // Like multiplying by 2 ** 64. } if iszero(lt(y, 0x10000000000000000)) { y := shr(64, y) // Like dividing by 2 ** 64. z := shl(32, z) // Like multiplying by 2 ** 32. } if iszero(lt(y, 0x100000000)) { y := shr(32, y) // Like dividing by 2 ** 32. z := shl(16, z) // Like multiplying by 2 ** 16. } if iszero(lt(y, 0x10000)) { y := shr(16, y) // Like dividing by 2 ** 16. z := shl(8, z) // Like multiplying by 2 ** 8. } if iszero(lt(y, 0x100)) { y := shr(8, y) // Like dividing by 2 ** 8. z := shl(4, z) // Like multiplying by 2 ** 4. } if iszero(lt(y, 0x10)) { y := shr(4, y) // Like dividing by 2 ** 4. z := shl(2, z) // Like multiplying by 2 ** 2. } if iszero(lt(y, 0x8)) { // Equivalent to 2 ** z. z := shl(1, z) } // Shifting right by 1 is like dividing by 2. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // Compute a rounded down version of z. let zRoundDown := div(x, z) // If zRoundDown is smaller, use it. if lt(zRoundDown, z) { z := zRoundDown } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^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() { _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 making 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: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.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 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' 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) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _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 require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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"); (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"); (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"); (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"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol) pragma solidity ^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. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } }
{ "metadata": { "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_tvlCap","type":"uint256"},{"internalType":"address[]","name":"_strategists","type":"address[]"},{"internalType":"address[]","name":"_multisigRoles","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"EmergencyShutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InCaseTokensGetStuckCalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"degradation","type":"uint256"}],"name":"LockedProfitDegradationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"allocBPS","type":"uint256"}],"name":"StrategyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"allocBPS","type":"uint256"}],"name":"StrategyAllocBPSUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"int256","name":"roi","type":"int256"},{"indexed":false,"internalType":"uint256","name":"repayment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gains","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"losses","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocBPS","type":"uint256"}],"name":"StrategyReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTvlCap","type":"uint256"}],"name":"TvlCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"withdrawalQueue","type":"address[]"}],"name":"UpdateWithdrawalQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawMaxLoss","type":"uint256"}],"name":"WithdrawMaxLossUpdated","type":"event"},{"inputs":[],"name":"ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEGRADATION_COEFFICIENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRATEGIST","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"strategy","type":"address"},{"internalType":"uint256","name":"allocBPS","type":"uint256"}],"name":"addStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"availableCapital","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"constructionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPricePerFullShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"inCaseTokensGetStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastReport","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedProfitDegradation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeTvlCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"roi","type":"int256"},{"internalType":"uint256","name":"repayment","type":"uint256"}],"name":"report","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategy","type":"address"}],"name":"revokeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"active","type":"bool"}],"name":"setEmergencyShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"degradation","type":"uint256"}],"name":"setLockedProfitDegradation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_withdrawalQueue","type":"address[]"}],"name":"setWithdrawalQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategies","outputs":[{"internalType":"uint256","name":"activation","type":"uint256"},{"internalType":"uint256","name":"allocBPS","type":"uint256"},{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"uint256","name":"gains","type":"uint256"},{"internalType":"uint256","name":"losses","type":"uint256"},{"internalType":"uint256","name":"lastReport","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tvlCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"strategy","type":"address"},{"internalType":"uint256","name":"allocBPS","type":"uint256"}],"name":"updateStrategyAllocBPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTvlCap","type":"uint256"}],"name":"updateTvlCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawMaxLoss","type":"uint256"}],"name":"updateWithdrawMaxLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawMaxLoss","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalQueue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405260016010553480156200001657600080fd5b50604051620049d0380380620049d08339810160408190526200003991620005dd565b845185908590620000529060039060208501906200036e565b508051620000689060049060208401906200036e565b50506001600555506001600160a01b03861660805242600e819055600d55600a839055620f4240620000a4670de0b6b3a7640000602e620006b2565b620000b09190620006e0565b60115560005b82518110156200010657620000fd600080516020620049b0833981519152848381518110620000e957620000e962000703565b60200260200101516200021460201b60201c565b600101620000b6565b506200011460003362000214565b620001326000801b82600081518110620000e957620000e962000703565b6200015c6000805160206200499083398151915282600181518110620000e957620000e962000703565b620001977f8b5b16d04624687fcf0d0228f19993c9157c1ed07b41d8d430fd9100eb099fe882600281518110620000e957620000e962000703565b60408051608081018252600081526000805160206200499083398151915260208201527f8b5b16d04624687fcf0d0228f19993c9157c1ed07b41d8d430fd9100eb099fe891810191909152600080516020620049b0833981519152606082015262000207906013906004620003fd565b5050505050505062000756565b6200022b82826200025760201b620024e71760201c565b6000828152600760209081526040909120620002529183906200256d620002fc821b17901c565b505050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff16620002f85760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620002b73390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600062000313836001600160a01b0384166200031c565b90505b92915050565b6000818152600183016020526040812054620003655750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000316565b50600062000316565b8280546200037c9062000719565b90600052602060002090601f016020900481019282620003a05760008555620003eb565b82601f10620003bb57805160ff1916838001178555620003eb565b82800160010185558215620003eb579182015b82811115620003eb578251825591602001919060010190620003ce565b50620003f99291506200043a565b5090565b828054828255906000526020600020908101928215620003eb5791602002820182811115620003eb578251825591602001919060010190620003ce565b5b80821115620003f957600081556001016200043b565b80516001600160a01b03811681146200046957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620004af57620004af6200046e565b604052919050565b600082601f830112620004c957600080fd5b81516001600160401b03811115620004e557620004e56200046e565b6020620004fb601f8301601f1916820162000484565b82815285828487010111156200051057600080fd5b60005b838110156200053057858101830151828201840152820162000513565b83811115620005425760008385840101525b5095945050505050565b600082601f8301126200055e57600080fd5b815160206001600160401b038211156200057c576200057c6200046e565b8160051b6200058d82820162000484565b9283528481018201928281019087851115620005a857600080fd5b83870192505b84831015620005d257620005c28362000451565b82529183019190830190620005ae565b979650505050505050565b60008060008060008060c08789031215620005f757600080fd5b620006028762000451565b60208801519096506001600160401b03808211156200062057600080fd5b6200062e8a838b01620004b7565b965060408901519150808211156200064557600080fd5b620006538a838b01620004b7565b95506060890151945060808901519150808211156200067157600080fd5b6200067f8a838b016200054c565b935060a08901519150808211156200069657600080fd5b50620006a589828a016200054c565b9150509295509295509295565b6000816000190483118215151615620006db57634e487b7160e01b600052601160045260246000fd5b500290565b600082620006fe57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200072e57607f821691505b602082108114156200075057634e487b7160e01b600052602260045260246000fd5b50919050565b6080516141b5620007db600039600081816105790152818161099301528181610cff01528181610d4c015281816110bb015281816111ce01528181611645015281816118ff015281816120a80152818161231a015281816123ac01528181612e0201528181612ea20152818161301e0152818161312a015261324c01526141b56000f3fe608060405234801561001057600080fd5b50600436106103f05760003560e01c80636e553f6511610215578063ba08765211610125578063ce96cb77116100b8578063dd62ed3e11610087578063dd62ed3e146108d2578063de5f6268146108e5578063def68a9c146108ed578063ef8b30f714610900578063f06c56101461091357600080fd5b8063ce96cb771461088a578063d250f0881461089d578063d547741f146108ac578063d905777e146108bf57600080fd5b8063c6e6f592116100f4578063c6e6f5921461083e578063c822adda14610851578063c9411e2214610864578063ca15c8731461087757600080fd5b8063ba087652146107fc578063bb994d481461080f578063c3535b5214610822578063c63d75b61461082b57600080fd5b806394bf804d116101a8578063a457c2d711610177578063a457c2d71461079d578063a9059cbb146107b0578063ac579b77146107c3578063b3d7f6b9146107d6578063b460af94146107e957600080fd5b806394bf804d1461076557806395d89b41146107785780639cfdede314610780578063a217fddf1461079557600080fd5b806377c7b8fc116101e457806377c7b8fc146107245780637a5503651461072c5780639010d07c1461073f57806391d148541461075257600080fd5b80636e553f65146106b85780636f9c94a8146106cb57806370a08231146106d4578063724c184c146106fd57600080fd5b80632f4350c211610310578063402d267d116102a3578063462f82f411610272578063462f82f41461066d578063483b6031146106805780634870dd9a146106895780634cdad506146106925780635f3d3a0e146106a557600080fd5b8063402d267d1461063f578063422327161461065257806344b813961461065b57806345f7f2491461066457600080fd5b806338d52e0f116102df57806338d52e0f1461057457806339509351146105b357806339ebf823146105c65780633f23fa1a1461063657600080fd5b80632f4350c214610532578063313ce5671461053a5780633403c2fc1461055457806336568abe1461056157600080fd5b806314c6440211610388578063248a9ca311610357578063248a9ca3146104df57806329b9d694146105025780632a0acc6a1461050a5780632f2ff15d1461051f57600080fd5b806314c64402146104a957806318160ddd146104bc578063199cb7d8146104c457806323b872dd146104cc57600080fd5b806307a2d13a116103c457806307a2d13a1461045d578063095ea7b3146104705780630a28a477146104835780630f3d249d1461049657600080fd5b8062272d81146103f557806301e1d1141461040a57806301ffc9a71461042557806306fdde0314610448575b600080fd5b610408610403366004613a70565b61091c565b005b61041261096f565b6040519081526020015b60405180910390f35b610438610433366004613a89565b610a0d565b604051901515815260200161041c565b610450610a38565b60405161041c9190613adf565b61041261046b366004613a70565b610aca565b61043861047e366004613b27565b610afe565b610412610491366004613a70565b610b16565b6104126104a4366004613b53565b610b66565b6104086104b7366004613b83565b610ed3565b600254610412565b610412610f6a565b6104386104da366004613ba0565b61113b565b6104126104ed366004613a70565b60009081526006602052604090206001015490565b61040861115f565b61041260008051602061414083398151915281565b61040861052d366004613be1565b611183565b6104086111ad565b6105426111ca565b60405160ff909116815260200161041c565b600f546104389060ff1681565b61040861056f366004613be1565b61124e565b61059b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161041c565b6104386105c1366004613b27565b6112cc565b6106096105d4366004613c11565b600860205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909186565b604080519687526020870195909552938501929092526060840152608083015260a082015260c00161041c565b610412600a5481565b61041261064d366004613c11565b6112ee565b61041260115481565b61041260125481565b610412600c5481565b61040861067b366004613a70565b61131c565b61041260105481565b61041261271081565b6104126106a0366004613a70565b6113ce565b6104086106b3366004613b27565b6113d9565b6104126106c6366004613be1565b611529565b610412600b5481565b6104126106e2366004613c11565b6001600160a01b031660009081526020819052604090205490565b6104127f8b5b16d04624687fcf0d0228f19993c9157c1ed07b41d8d430fd9100eb099fe881565b6104126116c9565b61040861073a366004613a70565b6116e1565b61059b61074d366004613b53565b611791565b610438610760366004613be1565b6117a9565b610412610773366004613be1565b6117d4565b610450611984565b61041260008051602061416083398151915281565b610412600081565b6104386107ab366004613b27565b611993565b6104386107be366004613b27565b611a0e565b6104086107d1366004613c2e565b611a1c565b6104126107e4366004613a70565b611bed565b6104126107f7366004613ca3565b611c1a565b61041261080a366004613ca3565b611c85565b61040861081d366004613c11565b611cf0565b610412600d5481565b610412610839366004613c11565b611dc7565b61041261084c366004613a70565b611dd6565b61059b61085f366004613a70565b611e13565b610408610872366004613b27565b611e3d565b610412610885366004613a70565b61225a565b610412610898366004613c11565b612271565b610412670de0b6b3a764000081565b6104086108ba366004613be1565b612293565b6104126108cd366004613c11565b6122b8565b6104126108e0366004613ce5565b6122d6565b610408612301565b6104086108fb366004613c11565b612393565b61041261090e366004613a70565b6124dc565b610412600e5481565b610933600080516020614140833981519152612582565b600a8190556040518181527f2923cecec41b7140eaf657a035af4abb23ed61d16b1fc20a986838eb3ad99bd0906020015b60405180910390a150565b600c546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156109da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fe9190613d13565b610a089190613d42565b905090565b60006001600160e01b03198216635a05180f60e01b1480610a325750610a3282612634565b92915050565b606060038054610a4790613d5a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7390613d5a565b8015610ac05780601f10610a9557610100808354040283529160200191610ac0565b820191906000526020600020905b815481529060010190602001808311610aa357829003601f168201915b5050505050905090565b600080610ad660025490565b905080610ae4575090919050565b610af7610aef612669565b849083612685565b9392505050565b600033610b0c8185856126a4565b5060019392505050565b600080610b2260025490565b9050610b2d60025490565b610b3a5750600092915050565b6000610b44612669565b905080610b5357509192915050565b610b5e8483836127c8565b949350505050565b3360008181526008602052604081208054919291610bd55760405162461bcd60e51b815260206004820152602160248201527f4f6e6c792061637469766520737472617465676965732063616e207265706f726044820152601d60fa1b60648201526084015b60405180910390fd5b6000806000871215610bfb57610bea87613d95565b9150610bf684836127f6565b610c18565b86905086836003016000828254610c129190613d42565b90915550505b6000610c22610f6a565b90506000806000831215610c9257610c3983613d95565b9150610c45828a61294b565b98508815610c8d5788866002016000828254610c619190613db2565b9250508190555088600c6000828254610c7a9190613db2565b90915550610c8a90508983613db2565b91505b610cc8565b82905080866002016000828254610ca99190613d42565b9250508190555080600c6000828254610cc29190613d42565b90915550505b8860008b1315610cdf57610cdc8b82613d42565b90505b80821115610d2b57610d2688610cf58385613db2565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190612961565b610d74565b80821015610d7457610d748830610d428585613db2565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169291906129c4565b600085610d7f6129fc565b610d899190613d42565b905086811115610da557610d9d8782613db2565b601255610dab565b60006012555b42886005018190555042600d81905550886001600160a01b03167fa42f52b692d89d13df3f5c859a3a9abb10ed8b2a804cddd5313217dc2f617e168d8d8b600301548c600401548d600201548e60010154604051610e3196959493929190958652602086019490945260408501929092526060840152608083015260a082015260c00190565b60405180910390a260018801541580610e4c5750600f5460ff165b15610ec357886001600160a01b031663722713f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb39190613d13565b9950505050505050505050610a32565b50919a9950505050505050505050565b60018115151415610f0c57610f077f8b5b16d04624687fcf0d0228f19993c9157c1ed07b41d8d430fd9100eb099fe8612582565b610f23565b610f23600080516020614140833981519152612582565b600f805460ff191682151590811790915560405160ff909116151581527fba40372a3a724dca3c57156128ef1e896724b65b37a17f190b1ad5de68f3a4f390602001610964565b600b5460009033901580610f805750600f5460ff165b15610fb0576001600160a01b038116600090815260086020526040902060020154610faa90613d95565b91505090565b6000612710610fbd61096f565b6001600160a01b038416600090815260086020526040902060010154610fe39190613dc9565b610fed9190613de8565b6001600160a01b0383166000908152600860205260409020600201549091508181111561102f5761101e8282613db2565b61102790613d95565b935050505090565b8181101561113157600061271061104461096f565b600b546110519190613dc9565b61105b9190613de8565b600c549091508181106110745760009550505050505090565b60006110808486613db2565b9050611095816110908486613db2565b61294b565b6040516370a0823160e01b81523060048201529091506111269082906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611102573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110909190613d13565b979650505050505050565b6000935050505090565b600033611149858285612a66565b611154858585612ada565b506001949350505050565b611176600080516020614140833981519152612582565b61118160001961091c565b565b60008281526006602052604090206001015461119e81612ca8565b6111a88383612cb2565b505050565b336000818152602081905260409020546111c79180611c85565b50565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561122a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a089190613e0a565b6001600160a01b03811633146112be5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610bcc565b6112c88282612cd4565b5050565b600033610b0c8185856112df83836122d6565b6112e99190613d42565b6126a4565b6000806112f961096f565b9050600a5481111561130e5750600092915050565b80600a54610af79190613db2565b611333600080516020614160833981519152612582565b6127108111156113995760405162461bcd60e51b815260206004820152602b60248201527f77697468647261774d61784c6f73732063616e6e6f742062652067726561746560448201526a72207468616e203130302560a81b6064820152608401610bcc565b60108190556040518181527f23e1382e62459214e4b3240fe95817b36865752f45f7569957018fe5a105f7b590602001610964565b6000610a3282610aca565b6113f0600080516020614160833981519152612582565b6001600160a01b0382166000908152600860205260409020546114555760405162461bcd60e51b815260206004820152601760248201527f5374726174656779206d757374206265206163746976650000000000000000006044820152606401610bcc565b6001600160a01b038216600090815260086020526040812060010154600b805491929091611484908490613db2565b90915550506001600160a01b0382166000908152600860205260408120600101829055600b80548392906114b9908490613d42565b9091555050600b5461271010156114e25760405162461bcd60e51b8152600401610bcc90613e2d565b816001600160a01b03167f437afd93b1abdad7ff741b69dde7efdd15dba7fb6999ba3471db17fd029dced98260405161151d91815260200190565b60405180910390a25050565b60006002600554141561154e5760405162461bcd60e51b8152600401610bcc90613e72565b6002600555600f5460ff16156115b75760405162461bcd60e51b815260206004820152602860248201527f43616e6e6f74206465706f73697420647572696e6720656d657267656e63792060448201526739b43aba3237bbb760c11b6064820152608401610bcc565b826115d45760405162461bcd60e51b8152600401610bcc90613ea9565b60006115de61096f565b600a549091506115ee8583613d42565b111561162d5760405162461bcd60e51b815260206004820152600e60248201526d7661756c742069732066756c6c2160901b6044820152606401610bcc565b611636846124dc565b915061166d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330876129c4565b6116778383612cf6565b60408051858152602081018490526001600160a01b0385169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a350600160055592915050565b6000610a086116d66111ca565b61046b90600a613fbc565b6116f8600080516020614160833981519152612582565b670de0b6b3a764000081111561175c5760405162461bcd60e51b8152602060048201526024808201527f4465677261646174696f6e2063616e6e6f74206265206d6f7265207468616e206044820152633130302560e01b6064820152608401610bcc565b60118190556040518181527f056863905a721211fc4dda1d688efc8f120b4b689d2e41da8249cf6eff20069190602001610964565b6000828152600760205260408120610af79083612dd5565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000600260055414156117f95760405162461bcd60e51b8152600401610bcc90613e72565b6002600555600f5460ff161561185f5760405162461bcd60e51b815260206004820152602560248201527f43616e6e6f74206d696e7420647572696e6720656d657267656e6379207368756044820152643a3237bbb760d91b6064820152608401610bcc565b8261187c5760405162461bcd60e51b8152600401610bcc90613ea9565b600061188784611bed565b9050600061189361096f565b600a549091506118a38383613d42565b11156118e25760405162461bcd60e51b815260206004820152600e60248201526d7661756c742069732066756c6c2160901b6044820152606401610bcc565b6118ea612669565b6118f2578491505b6119276001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330856129c4565b6119318486612cf6565b60408051838152602081018790526001600160a01b0386169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a35060016005559392505050565b606060048054610a4790613d5a565b600033816119a182866122d6565b905083811015611a015760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610bcc565b61115482868684036126a4565b600033610b0c818585612ada565b611a33600080516020614160833981519152612582565b8080611a8d5760405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742073657420616e20656d707479207769746864726177616c20716044820152637565756560e01b6064820152608401610bcc565b611a9960096000613a42565b60005b81811015611baf576000848483818110611ab857611ab8613fcb565b9050602002016020810190611acd9190613c11565b6001600160a01b0381166000908152600860205260409020805491925090611b565760405162461bcd60e51b815260206004820152603660248201527f43616e206f6e6c792075736520616374697665207374726174656769657320696044820152756e20746865207769746864726177616c20717565756560501b6064820152608401610bcc565b5060098054600180820183556000929092527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0319166001600160a01b03939093169290921790915501611a9c565b507fe159a1b5cb3e0bbe2f0caa53bcf2cd9ea0bc25a8c7b8302b1ac510f29cac8baa6009604051611be09190613fe1565b60405180910390a1505050565b600080611bf960025490565b905080611c07575090919050565b610af7611c12612669565b8490836127c8565b600060026005541415611c3f5760405162461bcd60e51b8152600401610bcc90613e72565b600260055583611c615760405162461bcd60e51b8152600401610bcc90613ea9565b611c6a84610b16565b9050611c7884828585612de1565b5060016005559392505050565b600060026005541415611caa5760405162461bcd60e51b8152600401610bcc90613e72565b600260055583611ccc5760405162461bcd60e51b8152600401610bcc90613ea9565b611cd5846113ce565b9050611ce381858585612de1565b6001600555949350505050565b336001600160a01b03821614611d2957611d297f8b5b16d04624687fcf0d0228f19993c9157c1ed07b41d8d430fd9100eb099fe8612582565b6001600160a01b038116600090815260086020526040902060010154611d4c5750565b6001600160a01b038116600090815260086020526040812060010154600b805491929091611d7b908490613db2565b90915550506001600160a01b038116600081815260086020526040808220600101829055517f4201c688d84c01154d321afa0c72f1bffe9eef53005c9de9d035074e71e9b32a9190a250565b6000610a3261084c60006112ee565b600080611de260025490565b90506000611dee612669565b9050801580611dfb575081155b15611e0857509192915050565b610b5e848383612685565b60098181548110611e2357600080fd5b6000918252602090912001546001600160a01b0316905081565b611e476000612582565b600f5460ff1615611eb25760405162461bcd60e51b815260206004820152602f60248201527f43616e6e6f7420616464206120737472617465677920647572696e6720656d6560448201526e3933b2b731bc9039b43aba3237bbb760891b6064820152608401610bcc565b6001600160a01b038216611f085760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742061646420746865207a65726f206164647265737300000000006044820152606401610bcc565b6001600160a01b03821660009081526008602052604090205415611f795760405162461bcd60e51b815260206004820152602260248201527f5374726174656779206d757374206e6f7420626520616464656420616c726561604482015261647960f01b6064820152608401610bcc565b816001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdb9190614031565b6001600160a01b0316306001600160a01b03161461203b5760405162461bcd60e51b815260206004820181905260248201527f546865207374726174656779206d757374207573652074686973207661756c746044820152606401610bcc565b816001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015612079573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209d9190614031565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146121295760405162461bcd60e51b815260206004820152602360248201527f546865207374726174656779206d75737420757365207468652073616d652077604482015262185b9d60ea1b6064820152608401610bcc565b612710600b548261213a9190613d42565b11156121585760405162461bcd60e51b8152600401610bcc90613e2d565b6040805160c0810182524280825260208083018581526000848601818152606086018281526080870183815260a088019687526001600160a01b038b16845260089095529682209551865591516001860155905160028501559351600384015551600483015551600590910155600b80548392906121d7908490613d42565b9091555050600980546001810182556000919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b0319166001600160a01b0384169081179091556040518281527f2f564a83158ad1831793ad3e69257b52f39ece5d49cb0d8746708ecb9ef964da9060200161151d565b6000818152600760205260408120610a32906132c7565b6001600160a01b038116600090815260208190526040812054610a3290610aca565b6000828152600660205260409020600101546122ae81612ca8565b6111a88383612cd4565b6001600160a01b038116600090815260208190526040812054610a32565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6040516370a0823160e01b81523360048201526111c7907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238d9190613d13565b33611529565b6123aa600080516020614160833981519152612582565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614156124155760405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606401610bcc565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561245c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124809190613d13565b90506124966001600160a01b0383163383612961565b604080516001600160a01b0384168152602081018390527f741ee845808813887c0b0d54aa20a3d0f670bebce7b6a1face577afbc00d1d6c910160405180910390a15050565b6000610a3282611dd6565b6124f182826117a9565b6112c85760008281526006602090815260408083206001600160a01b03851684529091529020805460ff191660011790556125293390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610af7836001600160a01b0384166132d1565b6013546000805b828110156125dd57601381815481106125a4576125a4613fcb565b90600052602060002001548414156125be578091506125dd565b6125c9600184613db2565b8114156125d557600080fd5b600101612589565b5060005b81811161262e5761260f601382815481106125fe576125fe613fcb565b9060005260206000200154336117a9565b156126195761262e565b8181141561262657600080fd5b6001016125e1565b50505050565b60006001600160e01b03198216637965db0b60e01b1480610a3257506301ffc9a760e01b6001600160e01b0319831614610a32565b60006126736129fc565b61267b61096f565b610a089190613db2565b82820281151584158583048514171661269d57600080fd5b0492915050565b6001600160a01b0383166127065760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610bcc565b6001600160a01b0382166127675760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610bcc565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b8282028115158415858304851417166127e057600080fd5b6001826001830304018115150290509392505050565b6001600160a01b03821660009081526008602052604090206002810154808311156128895760405162461bcd60e51b815260206004820152603860248201527f53747261746567792063616e6e6f74206c6f6f7365206d6f7265207468616e2060448201527f776861742077617320616c6c6f636174656420746f20697400000000000000006064820152608401610bcc565b600b54156128f85760006128bb600c54600b54866128a79190613dc9565b6128b19190613de8565b846001015461294b565b905080156128f657808360010160008282546128d79190613db2565b9250508190555080600b60008282546128f09190613db2565b90915550505b505b8282600401600082825461290c9190613d42565b92505081905550828260020160008282546129279190613db2565b9250508190555082600c60008282546129409190613db2565b909155505050505050565b600081831061295a5781610af7565b5090919050565b6040516001600160a01b0383166024820152604481018290526111a890849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613320565b6040516001600160a01b038085166024830152831660448201526064810182905261262e9085906323b872dd60e01b9060840161298d565b600080601154600d5442612a109190613db2565b612a1a9190613dc9565b9050670de0b6b3a7640000811015612a5a57670de0b6b3a764000060125482612a439190613dc9565b612a4d9190613de8565b601254610faa9190613db2565b600091505090565b5090565b6000612a7284846122d6565b9050600019811461262e5781811015612acd5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610bcc565b61262e84848484036126a4565b6001600160a01b038316612b3e5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610bcc565b6001600160a01b038216612ba05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610bcc565b6001600160a01b03831660009081526020819052604090205481811015612c185760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610bcc565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290612c4f908490613d42565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612c9b91815260200190565b60405180910390a361262e565b6111c781336133f2565b612cbc82826124e7565b60008281526007602052604090206111a8908261256d565b612cde8282613456565b60008281526007602052604090206111a890826134bd565b6001600160a01b038216612d4c5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610bcc565b8060026000828254612d5e9190613d42565b90915550506001600160a01b03821660009081526020819052604081208054839290612d8b908490613d42565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6000610af783836134d2565b6000612ded82856134fc565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612e51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e759190613d13565b85111561323f5760095460009081805b82811015613114576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f159190613d13565b9150818911612f2357613114565b600060098281548110612f3857612f38613fcb565b60009182526020808320909101546001600160a01b0316808352600890915260409091206002015490915080612f6f57505061310c565b6000612f7b858d613db2565b90506000836001600160a01b0316632e1a7d4d612f98848661294b565b6040518263ffffffff1660e01b8152600401612fb691815260200190565b6020604051808303816000875af1158015612fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff99190613d13565b6040516370a0823160e01b815230600482015290915060009087906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015613065573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130899190613d13565b6130939190613db2565b905081156130bd576130a5828f613db2565b9d506130b1828a613d42565b98506130bd85836127f6565b6001600160a01b038516600090815260086020526040812060020180548392906130e8908490613db2565b9250508190555080600c60008282546131019190613db2565b909155505050505050505b600101612e85565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319d9190613d13565b9050808811156131ab578097505b601054612710906131bc858b613d42565b6131c69190613dc9565b6131d09190613de8565b83111561323b5760405162461bcd60e51b815260206004820152603360248201527f43616e6e6f742065786365656420746865206d6178696d756d20616c6c6f77656044820152726420776974686472617720736c69707061676560681b6064820152608401610bcc565b5050505b6132736001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168487612961565b60408051868152602081018690526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a450929392505050565b6000610a32825490565b600081815260018301602052604081205461331857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a32565b506000610a32565b6000613375826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661364a9092919063ffffffff16565b8051909150156111a85780806020019051810190613393919061404e565b6111a85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610bcc565b6133fc82826117a9565b6112c857613414816001600160a01b03166014613659565b61341f836020613659565b60405160200161343092919061406b565b60408051601f198184030181529082905262461bcd60e51b8252610bcc91600401613adf565b61346082826117a9565b156112c85760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610af7836001600160a01b0384166137f5565b60008260000182815481106134e9576134e9613fcb565b9060005260206000200154905092915050565b6001600160a01b03821661355c5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610bcc565b6001600160a01b038216600090815260208190526040902054818110156135d05760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610bcc565b6001600160a01b03831660009081526020819052604081208383039055600280548492906135ff908490613db2565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060610b5e84846000856138e8565b60606000613668836002613dc9565b613673906002613d42565b67ffffffffffffffff81111561368b5761368b6140e0565b6040519080825280601f01601f1916602001820160405280156136b5576020820181803683370190505b509050600360fc1b816000815181106136d0576136d0613fcb565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106136ff576136ff613fcb565b60200101906001600160f81b031916908160001a9053506000613723846002613dc9565b61372e906001613d42565b90505b60018111156137a6576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061376257613762613fcb565b1a60f81b82828151811061377857613778613fcb565b60200101906001600160f81b031916908160001a90535060049490941c9361379f816140f6565b9050613731565b508315610af75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610bcc565b600081815260018301602052604081205480156138de576000613819600183613db2565b855490915060009061382d90600190613db2565b905081811461389257600086600001828154811061384d5761384d613fcb565b906000526020600020015490508087600001848154811061387057613870613fcb565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806138a3576138a361410d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a32565b6000915050610a32565b6060824710156139495760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610bcc565b6001600160a01b0385163b6139a05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bcc565b600080866001600160a01b031685876040516139bc9190614123565b60006040518083038185875af1925050503d80600081146139f9576040519150601f19603f3d011682016040523d82523d6000602084013e6139fe565b606091505b509150915061112682828660608315613a18575081610af7565b825115613a285782518084602001fd5b8160405162461bcd60e51b8152600401610bcc9190613adf565b50805460008255906000526020600020908101906111c791905b80821115612a625760008155600101613a5c565b600060208284031215613a8257600080fd5b5035919050565b600060208284031215613a9b57600080fd5b81356001600160e01b031981168114610af757600080fd5b60005b83811015613ace578181015183820152602001613ab6565b8381111561262e5750506000910152565b6020815260008251806020840152613afe816040850160208701613ab3565b601f01601f19169190910160400192915050565b6001600160a01b03811681146111c757600080fd5b60008060408385031215613b3a57600080fd5b8235613b4581613b12565b946020939093013593505050565b60008060408385031215613b6657600080fd5b50508035926020909101359150565b80151581146111c757600080fd5b600060208284031215613b9557600080fd5b8135610af781613b75565b600080600060608486031215613bb557600080fd5b8335613bc081613b12565b92506020840135613bd081613b12565b929592945050506040919091013590565b60008060408385031215613bf457600080fd5b823591506020830135613c0681613b12565b809150509250929050565b600060208284031215613c2357600080fd5b8135610af781613b12565b60008060208385031215613c4157600080fd5b823567ffffffffffffffff80821115613c5957600080fd5b818501915085601f830112613c6d57600080fd5b813581811115613c7c57600080fd5b8660208260051b8501011115613c9157600080fd5b60209290920196919550909350505050565b600080600060608486031215613cb857600080fd5b833592506020840135613cca81613b12565b91506040840135613cda81613b12565b809150509250925092565b60008060408385031215613cf857600080fd5b8235613d0381613b12565b91506020830135613c0681613b12565b600060208284031215613d2557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115613d5557613d55613d2c565b500190565b600181811c90821680613d6e57607f821691505b60208210811415613d8f57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600160ff1b821415613dab57613dab613d2c565b5060000390565b600082821015613dc457613dc4613d2c565b500390565b6000816000190483118215151615613de357613de3613d2c565b500290565b600082613e0557634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215613e1c57600080fd5b815160ff81168114610af757600080fd5b60208082526025908201527f546f74616c20616c6c6f636174696f6e20706f696e747320617265206f766572604082015264203130302560d81b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601590820152741c1b19585cd9481c1c9bdd9a591948185b5bdd5b9d605a1b604082015260600190565b600181815b80851115613f13578160001904821115613ef957613ef9613d2c565b80851615613f0657918102915b93841c9390800290613edd565b509250929050565b600082613f2a57506001610a32565b81613f3757506000610a32565b8160018114613f4d5760028114613f5757613f73565b6001915050610a32565b60ff841115613f6857613f68613d2c565b50506001821b610a32565b5060208310610133831016604e8410600b8410161715613f96575081810a610a32565b613fa08383613ed8565b8060001904821115613fb457613fb4613d2c565b029392505050565b6000610af760ff841683613f1b565b634e487b7160e01b600052603260045260246000fd5b6020808252825482820181905260008481528281209092916040850190845b818110156140255783546001600160a01b031683526001938401939285019201614000565b50909695505050505050565b60006020828403121561404357600080fd5b8151610af781613b12565b60006020828403121561406057600080fd5b8151610af781613b75565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516140a3816017850160208801613ab3565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516140d4816028840160208801613ab3565b01602801949350505050565b634e487b7160e01b600052604160045260246000fd5b60008161410557614105613d2c565b506000190190565b634e487b7160e01b600052603160045260246000fd5b60008251614135818460208701613ab3565b919091019291505056fedf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42b17d0a42cc710456bf9c3efb785dcd0cb93a0ac358113307b5c64b285b516b5ca2646970667358221220ac0e84e2c8909347c36149f14e7eea548ae5bda9f0eb388ccb7ca4fa29fb1bc364736f6c634300080b0033df8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42b17d0a42cc710456bf9c3efb785dcd0cb93a0ac358113307b5c64b285b516b5c0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000003635c9adc5dea00000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000944414920437279707400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005726644414900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000001e71aee6081f62053123140aacc7a06021d7734800000000000000000000000081876677843d00a7d792e1617459ac2e932025760000000000000000000000001a20d7a31e5b3bc5f02c8a146ef6f394502a10c4000000000000000000000000000000000000000000000000000000000000000300000000000000000000000004c710a1e8a738cdf7cad3a52ba77a784c35d8ce000000000000000000000000539ef36c804e4d735d8cab69e8e441c12d4b88e0000000000000000000000000f20e25f2ab644c8ecbfc992a6829478a85a98f2c
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000003635c9adc5dea00000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000944414920437279707400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005726644414900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000001e71aee6081f62053123140aacc7a06021d7734800000000000000000000000081876677843d00a7d792e1617459ac2e932025760000000000000000000000001a20d7a31e5b3bc5f02c8a146ef6f394502a10c4000000000000000000000000000000000000000000000000000000000000000300000000000000000000000004c710a1e8a738cdf7cad3a52ba77a784c35d8ce000000000000000000000000539ef36c804e4d735d8cab69e8e441c12d4b88e0000000000000000000000000f20e25f2ab644c8ecbfc992a6829478a85a98f2c
-----Decoded View---------------
Arg [0] : _asset (address): 0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e
Arg [1] : _name (string): DAI Crypt
Arg [2] : _symbol (string): rfDAI
Arg [3] : _tvlCap (uint256): 1000000000000000000000
Arg [4] : _strategists (address[]): 0x1e71aee6081f62053123140aacc7a06021d77348,0x81876677843d00a7d792e1617459ac2e93202576,0x1a20d7a31e5b3bc5f02c8a146ef6f394502a10c4
Arg [5] : _multisigRoles (address[]): 0x04c710a1e8a738cdf7cad3a52ba77a784c35d8ce,0x539ef36c804e4d735d8cab69e8e441c12d4b88e0,0xf20e25f2ab644c8ecbfc992a6829478a85a98f2c
-----Encoded View---------------
18 Constructor Arguments found :
Arg [0] : 0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [3] : 00000000000000000000000000000000000000000000003635c9adc5dea00000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [7] : 4441492043727970740000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [9] : 7266444149000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [11] : 0000000000000000000000001e71aee6081f62053123140aacc7a06021d77348
Arg [12] : 00000000000000000000000081876677843d00a7d792e1617459ac2e93202576
Arg [13] : 0000000000000000000000001a20d7a31e5b3bc5f02c8a146ef6f394502a10c4
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [15] : 00000000000000000000000004c710a1e8a738cdf7cad3a52ba77a784c35d8ce
Arg [16] : 000000000000000000000000539ef36c804e4d735d8cab69e8e441c12d4b88e0
Arg [17] : 000000000000000000000000f20e25f2ab644c8ecbfc992a6829478a85a98f2c
Deployed ByteCode Sourcemap
836:31020:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27910:148;;;;;;:::i;:::-;;:::i;:::-;;6313:140;;;:::i;:::-;;;345:25:20;;;333:2;318:18;6313:140:0;;;;;;;;634:212:5;;;;;;:::i;:::-;;:::i;:::-;;;837:14:20;;830:22;812:41;;800:2;785:18;634:212:5;672:187:20;2156:98:9;;;:::i;:::-;;;;;;;:::i;8345:262:0:-;;;;;;:::i;:::-;;:::i;4433:197:9:-;;;;;;:::i;:::-;;:::i;13368:308:0:-;;;;;;:::i;:::-;;:::i;25045:2173::-;;;;;;:::i;:::-;;:::i;28819:272::-;;;;;;:::i;:::-;;:::i;3244:106:9:-;3331:12;;3244:106;;21490:1216:0;;;:::i;5192:286:9:-;;;;;;:::i;:::-;;:::i;4391:129:4:-;;;;;;:::i;:::-;4465:7;4491:12;;;:6;:12;;;;;:22;;;;4391:129;28131:110:0;;;:::i;3814:50::-;;-1:-1:-1;;;;;;;;;;;3814:50:0;;4770:145:4;;;;;;:::i;:::-;;:::i;17920:100:0:-;;;:::i;29797:113::-;;;:::i;:::-;;;4092:4:20;4080:17;;;4062:36;;4050:2;4035:18;29797:113:0;3920:184:20;2418:29:0;;;;;;;;;5787:214:4;;;;;;:::i;:::-;;:::i;2535:30:0:-;;;;;;;;-1:-1:-1;;;;;4273:32:20;;;4255:51;;4243:2;4228:18;2535:30:0;4109:203:20;5873:234:9;;;;;;:::i;:::-;;:::i;1482:52:0:-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4856:25:20;;;4912:2;4897:18;;4890:34;;;;4940:18;;;4933:34;;;;4998:2;4983:18;;4976:34;5041:3;5026:19;;5019:35;5085:3;5070:19;;5063:35;4843:3;4828:19;1482:52:0;4569:535:20;1949:21:0;;;;;;8925:228;;;;;;:::i;:::-;;:::i;2728:38::-;;;;;;2848:28;;;;;;2149:29;;;;;;27385:306;;;;;;:::i;:::-;;:::i;2625:34::-;;;;;;1824:48;;1866:6;1824:48;;17361:116;;;;;;:::i;:::-;;:::i;20092:491::-;;;;;;:::i;:::-;;:::i;10111:566::-;;;;;;:::i;:::-;;:::i;2057:28::-;;;;;;3408:125:9;;;;;;:::i;:::-;-1:-1:-1;;;;;3508:18:9;3482:7;3508:18;;;;;;;;;;;;3408:125;3752:56:0;;3787:21;3752:56;;17698:121;;;:::i;30137:309::-;;;;;;:::i;:::-;;:::i;1431:151:5:-;;;;;;:::i;:::-;;:::i;2895:145:4:-;;;;;;:::i;:::-;;:::i;11988:625:0:-;;;;;;:::i;:::-;;:::i;2367:102:9:-;;;:::i;3686:60:0:-;;-1:-1:-1;;;;;;;;;;;3686:60:0;;2027:49:4;;2072:4;2027:49;;6594:427:9;;;;;;:::i;:::-;;:::i;3729:189::-;;;;;;:::i;:::-;;:::i;22884:675:0:-;;;;;;:::i;:::-;;:::i;11425:256::-;;;;;;:::i;:::-;;:::i;14022:293::-;;;;;;:::i;:::-;;:::i;18363:271::-;;;;;;:::i;:::-;;:::i;20711:374::-;;;;;;:::i;:::-;;:::i;2247:25::-;;;;;;10984:136;;;;;;:::i;:::-;;:::i;7719:289::-;;;;;;:::i;:::-;;:::i;1592:32::-;;;;;;:::i;:::-;;:::i;18860:1032::-;;;;;;:::i;:::-;;:::i;1750:140:5:-;;;;;;:::i;:::-;;:::i;12928:125:0:-;;;;;;:::i;:::-;;:::i;1712:58::-;;1762:8;1712:58;;5149:147:4;;;;;;:::i;:::-;;:::i;16938:106:0:-;;;;;;:::i;:::-;;:::i;3976:149:9:-;;;;;;:::i;:::-;;:::i;9684:112:0:-;;;:::i;29236:332::-;;;;;;:::i;:::-;;:::i;9465:117::-;;;;;;:::i;:::-;;:::i;2330:31::-;;;;;;27910:148;27968:19;-1:-1:-1;;;;;;;;;;;27968:12:0;:19::i;:::-;27997:6;:18;;;28030:21;;345:25:20;;;28030:21:0;;333:2:20;318:18;28030:21:0;;;;;;;;27910:148;:::o;6313:140::-;6432:14;;6383:46;;-1:-1:-1;;;6383:46:0;;6423:4;6383:46;;;4255:51:20;6357:7:0;;6432:14;-1:-1:-1;;;;;6398:5:0;6383:31;;;;4228:18:20;;6383:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:63;;;;:::i;:::-;6376:70;;6313:140;:::o;634:212:5:-;719:4;-1:-1:-1;;;;;;742:57:5;;-1:-1:-1;;;742:57:5;;:97;;;803:36;827:11;803:23;:36::i;:::-;735:104;634:212;-1:-1:-1;;634:212:5:o;2156:98:9:-;2210:13;2242:5;2235:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2156:98;:::o;8345:262:0:-;8407:7;8426:20;8449:13;3331:12:9;;;3244:106;8449:13:0;8426:36;-1:-1:-1;8476:17:0;8472:36;;-1:-1:-1;8502:6:0;;8345:262;-1:-1:-1;8345:262:0:o;8472:36::-;8555:45;8573:12;:10;:12::i;:::-;8555:6;;8587:12;8555:17;:45::i;:::-;8548:52;8345:262;-1:-1:-1;;;8345:262:0:o;4433:197:9:-;4516:4;719:10:14;4570:32:9;719:10:14;4586:7:9;4595:6;4570:8;:32::i;:::-;-1:-1:-1;4619:4:9;;4433:197;-1:-1:-1;;;4433:197:9:o;13368:308:0:-;13430:7;13449:20;13472:13;3331:12:9;;;3244:106;13472:13:0;13449:36;;13499:13;3331:12:9;;;3244:106;13499:13:0;13495:32;;-1:-1:-1;13526:1:0;;13368:308;-1:-1:-1;;13368:308:0:o;13495:32::-;13537:17;13557:12;:10;:12::i;:::-;13537:32;-1:-1:-1;13583:14:0;13579:33;;-1:-1:-1;13606:6:0;;13368:308;-1:-1:-1;;13368:308:0:o;13579:33::-;13629:40;:6;13645:12;13659:9;13629:15;:40::i;:::-;13622:47;13368:308;-1:-1:-1;;;;13368:308:0:o;25045:2173::-;25149:10;25110:7;25203:21;;;:10;:21;;;;;25242:19;;25110:7;;25149:10;25234:70;;;;-1:-1:-1;;;25234:70:0;;8197:2:20;25234:70:0;;;8179:21:20;8236:2;8216:18;;;8209:30;8275:34;8255:18;;;8248:62;-1:-1:-1;;;8326:18:20;;;8319:31;8367:19;;25234:70:0;;;;;;;;;25314:12;25340;25377:1;25371:3;:7;25367:194;;;25409:4;25410:3;25409:4;:::i;:::-;25394:20;;25428:28;25440:9;25451:4;25428:11;:28::i;:::-;25367:194;;;25502:3;25487:19;;25546:3;25520:8;:14;;;:30;;;;;;;:::i;:::-;;;;-1:-1:-1;;25367:194:0;25571:16;25590:18;:16;:18::i;:::-;25571:37;;25618:12;25644:14;25688:1;25676:9;:13;25672:437;;;25720:10;25721:9;25720:10;:::i;:::-;25705:26;;25757:25;25766:4;25772:9;25757:8;:25::i;:::-;25745:37;-1:-1:-1;25801:14:0;;25797:164;;25857:9;25835:8;:18;;;:31;;;;;;;:::i;:::-;;;;;;;;25902:9;25884:14;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;25929:17:0;;-1:-1:-1;25937:9:0;25929:17;;:::i;:::-;;;25797:164;25672:437;;;26008:9;25991:27;;26054:6;26032:8;:18;;;:28;;;;;;;:::i;:::-;;;;;;;;26092:6;26074:14;;:24;;;;;;;:::i;:::-;;;;-1:-1:-1;;25672:437:0;26145:9;26119:23;26168:7;;26164:69;;;26191:31;26218:3;26191:31;;:::i;:::-;;;26164:69;26256:15;26247:6;:24;26243:277;;;26287:71;26322:9;26333:24;26342:15;26333:6;:24;:::i;:::-;-1:-1:-1;;;;;26302:5:0;26287:34;;:71;:34;:71::i;:::-;26243:277;;;26388:15;26379:6;:24;26375:145;;;26419:90;26458:9;26477:4;26484:24;26502:6;26484:15;:24;:::i;:::-;-1:-1:-1;;;;;26434:5:0;26419:38;;:90;;:38;:90::i;:::-;26530:30;26590:4;26563:24;:22;:24::i;:::-;:31;;;;:::i;:::-;26530:64;;26633:4;26608:22;:29;26604:151;;;26668:29;26693:4;26668:22;:29;:::i;:::-;26653:12;:44;26604:151;;;26743:1;26728:12;:16;26604:151;26787:15;26765:8;:19;;:37;;;;26825:15;26812:10;:28;;;;26886:9;-1:-1:-1;;;;;26856:210:0;;26909:3;26926:9;26949:8;:14;;;26977:8;:15;;;27006:8;:18;;;27038:8;:17;;;26856:210;;;;;;;;;;4856:25:20;;;4912:2;4897:18;;4890:34;;;;4955:2;4940:18;;4933:34;;;;4998:2;4983:18;;4976:34;5041:3;5026:19;;5019:35;5085:3;5070:19;;5063:35;4843:3;4828:19;;4569:535;26856:210:0;;;;;;;;27081:17;;;;:22;;:43;;-1:-1:-1;27107:17:0;;;;27081:43;27077:113;;;27157:9;-1:-1:-1;;;;;27147:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27140:39;;;;;;;;;;;;;27077:113;-1:-1:-1;27207:4:0;;25045:2173;-1:-1:-1;;;;;;;;;;25045:2173:0:o;28819:272::-;28895:4;28885:14;;;;28881:117;;;28915:22;3787:21;28915:12;:22::i;:::-;28881:117;;;28968:19;-1:-1:-1;;;;;;;;;;;28968:12:0;:19::i;:::-;29007:17;:26;;-1:-1:-1;;29007:26:0;;;;;;;;;;29048:36;;29007:26;29066:17;;;837:14:20;830:22;812:41;;29048:36:0;;800:2:20;785:18;29048:36:0;672:187:20;21490:1216:0;21601:13;;21539:6;;21577:10;;21601:18;;:39;;-1:-1:-1;21623:17:0;;;;21601:39;21597:117;;;-1:-1:-1;;;;;21671:21:0;;;;;;:10;:21;;;;;:31;;;21663:40;;;:::i;:::-;21656:47;;;21490:1216;:::o;21597:117::-;21724:26;1866:6;21787:13;:11;:13::i;:::-;-1:-1:-1;;;;;21754:21:0;;;;;;:10;:21;;;;;:30;;;:46;;;;:::i;:::-;21753:66;;;;:::i;:::-;-1:-1:-1;;;;;21862:21:0;;21829:30;21862:21;;;:10;:21;;;;;:31;;;21724:95;;-1:-1:-1;21908:43:0;;;21904:796;;;21982:43;22007:18;21982:22;:43;:::i;:::-;21974:52;;;:::i;:::-;21967:59;;;;;21490:1216;:::o;21904:796::-;22072:18;22047:22;:43;22043:657;;;22106:26;1866:6;22152:13;:11;:13::i;:::-;22136;;:29;;;;:::i;:::-;22135:49;;;;:::i;:::-;22231:14;;22106:78;;-1:-1:-1;22264:44:0;;;22260:91;;22335:1;22328:8;;;;;;;21490:1216;:::o;22260:91::-;22365:17;22385:43;22406:22;22385:18;:43;:::i;:::-;22365:63;-1:-1:-1;22454:64:0;22365:63;22474:43;22495:22;22474:18;:43;:::i;:::-;22454:8;:64::i;:::-;22564:46;;-1:-1:-1;;;22564:46:0;;22604:4;22564:46;;;4255:51:20;22442:76:0;;-1:-1:-1;22544:67:0;;22442:76;;-1:-1:-1;;;;;22579:5:0;22564:31;;;;4228:18:20;;22564:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;22544:67::-;22532:79;21490:1216;-1:-1:-1;;;;;;;21490:1216:0:o;22043:657::-;22688:1;22681:8;;;;;21490:1216;:::o;5192:286:9:-;5319:4;719:10:14;5375:38:9;5391:4;719:10:14;5406:6:9;5375:15;:38::i;:::-;5423:27;5433:4;5439:2;5443:6;5423:9;:27::i;:::-;-1:-1:-1;5467:4:9;;5192:286;-1:-1:-1;;;;5192:286:9:o;28131:110:0:-;28174:19;-1:-1:-1;;;;;;;;;;;28174:12:0;:19::i;:::-;28203:31;-1:-1:-1;;28203:12:0;:31::i;:::-;28131:110::o;4770:145:4:-;4465:7;4491:12;;;:6;:12;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;4883:25:::1;4894:4;4900:7;4883:10;:25::i;:::-;4770:145:::0;;;:::o;17920:100:0:-;17977:10;3482:7:9;3508:18;;;;;;;;;;;17960:53:0;;17977:10;17960:6;:53::i;:::-;;17920:100::o;29797:113::-;29847:5;29886;-1:-1:-1;;;;;29871:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;5787:214:4:-;-1:-1:-1;;;;;5882:23:4;;719:10:14;5882:23:4;5874:83;;;;-1:-1:-1;;;5874:83:4;;10081:2:20;5874:83:4;;;10063:21:20;10120:2;10100:18;;;10093:30;10159:34;10139:18;;;10132:62;-1:-1:-1;;;10210:18:20;;;10203:45;10265:19;;5874:83:4;9879:411:20;5874:83:4;5968:26;5980:4;5986:7;5968:11;:26::i;:::-;5787:214;;:::o;5873:234:9:-;5961:4;719:10:14;6015:64:9;719:10:14;6031:7:9;6068:10;6040:25;719:10:14;6031:7:9;6040:9;:25::i;:::-;:38;;;;:::i;:::-;6015:8;:64::i;8925:228:0:-;8984:7;9003:20;9026:13;:11;:13::i;:::-;9003:36;;9068:6;;9053:12;:21;9049:60;;;-1:-1:-1;9097:1:0;;8925:228;-1:-1:-1;;8925:228:0:o;9049:60::-;9134:12;9125:6;;:21;;;;:::i;27385:306::-;27461:24;-1:-1:-1;;;;;;;;;;;27461:12:0;:24::i;:::-;1866:6;27503:16;:35;;27495:91;;;;-1:-1:-1;;;27495:91:0;;10497:2:20;27495:91:0;;;10479:21:20;10536:2;10516:18;;;10509:30;10575:34;10555:18;;;10548:62;-1:-1:-1;;;10626:18:20;;;10619:41;10677:19;;27495:91:0;10295:407:20;27495:91:0;27596:15;:34;;;27645:39;;345:25:20;;;27645:39:0;;333:2:20;318:18;27645:39:0;199:177:20;17361:116:0;17421:7;17447:23;17463:6;17447:15;:23::i;20092:491::-;20179:24;-1:-1:-1;;;;;;;;;;;20179:12:0;:24::i;:::-;-1:-1:-1;;;;;20221:20:0;;;;;;:10;:20;;;;;:31;20213:72;;;;-1:-1:-1;;;20213:72:0;;10909:2:20;20213:72:0;;;10891:21:20;10948:2;10928:18;;;10921:30;10987:25;10967:18;;;10960:53;11030:18;;20213:72:0;10707:347:20;20213:72:0;-1:-1:-1;;;;;20312:20:0;;;;;;:10;:20;;;;;:29;;;20295:13;:46;;20312:29;;20295:13;;:46;;20312:29;;20295:46;:::i;:::-;;;;-1:-1:-1;;;;;;;20351:20:0;;;;;;:10;:20;;;;;:29;;:40;;;20401:13;:25;;20383:8;;20351:20;20401:25;;20383:8;;20401:25;:::i;:::-;;;;-1:-1:-1;;20444:13:0;;1866:6;-1:-1:-1;20444:32:0;20436:82;;;;-1:-1:-1;;;20436:82:0;;;;;;;:::i;:::-;20557:8;-1:-1:-1;;;;;20533:43:0;;20567:8;20533:43;;;;345:25:20;;333:2;318:18;;199:177;20533:43:0;;;;;;;;20092:491;;:::o;10111:566::-;10191:14;1744:1:8;2325:7;;:19;;2317:63;;;;-1:-1:-1;;;2317:63:8;;;;;;;:::i;:::-;1744:1;2455:7;:18;10226:17:0::1;::::0;::::1;;10225:18;10217:71;;;::::0;-1:-1:-1;;;10217:71:0;;12027:2:20;10217:71:0::1;::::0;::::1;12009:21:20::0;12066:2;12046:18;;;12039:30;12105:34;12085:18;;;12078:62;-1:-1:-1;;;12156:18:20;;;12149:38;12204:19;;10217:71:0::1;11825:404:20::0;10217:71:0::1;10306:11:::0;10298:45:::1;;;;-1:-1:-1::0;;;10298:45:0::1;;;;;;;:::i;:::-;10353:13;10369;:11;:13::i;:::-;10418:6;::::0;10353:29;;-1:-1:-1;10400:14:0::1;10408:6:::0;10353:29;10400:14:::1;:::i;:::-;:24;;10392:51;;;::::0;-1:-1:-1;;;10392:51:0;;12786:2:20;10392:51:0::1;::::0;::::1;12768:21:20::0;12825:2;12805:18;;;12798:30;-1:-1:-1;;;12844:18:20;;;12837:44;12898:18;;10392:51:0::1;12584:338:20::0;10392:51:0::1;10462:22;10477:6;10462:14;:22::i;:::-;10453:31:::0;-1:-1:-1;10495:73:0::1;-1:-1:-1::0;;;;;10510:5:0::1;10495:38;10534:10;10554:4;10561:6:::0;10495:38:::1;:73::i;:::-;10587:23;10593:8;10603:6;10587:5;:23::i;:::-;10625:45;::::0;;13101:25:20;;;13157:2;13142:18;;13135:34;;;-1:-1:-1;;;;;10625:45:0;::::1;::::0;10633:10:::1;::::0;10625:45:::1;::::0;13074:18:20;10625:45:0::1;;;;;;;-1:-1:-1::0;1701:1:8;2628:7;:22;10111:566:0;;-1:-1:-1;;10111:566:0:o;17698:121::-;17753:7;17779:33;17801:10;:8;:10::i;:::-;17795:16;;:2;:16;:::i;30137:309::-;30213:24;-1:-1:-1;;;;;;;;;;;30213:12:0;:24::i;:::-;1762:8;30255:11;:38;;30247:87;;;;-1:-1:-1;;;30247:87:0;;14765:2:20;30247:87:0;;;14747:21:20;14804:2;14784:18;;;14777:30;14843:34;14823:18;;;14816:62;-1:-1:-1;;;14894:18:20;;;14887:34;14938:19;;30247:87:0;14563:400:20;30247:87:0;30344:23;:37;;;30396:43;;345:25:20;;;30396:43:0;;333:2:20;318:18;30396:43:0;199:177:20;1431:151:5;1521:7;1547:18;;;:12;:18;;;;;:28;;1569:5;1547:21;:28::i;2895:145:4:-;2981:4;3004:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;3004:29:4;;;;;;;;;;;;;;;2895:145::o;11988:625:0:-;12067:7;1744:1:8;2325:7;;:19;;2317:63;;;;-1:-1:-1;;;2317:63:8;;;;;;;:::i;:::-;1744:1;2455:7;:18;12095:17:0::1;::::0;::::1;;12094:18;12086:68;;;::::0;-1:-1:-1;;;12086:68:0;;15170:2:20;12086:68:0::1;::::0;::::1;15152:21:20::0;15209:2;15189:18;;;15182:30;15248:34;15228:18;;;15221:62;-1:-1:-1;;;15299:18:20;;;15292:35;15344:19;;12086:68:0::1;14968:401:20::0;12086:68:0::1;12172:11:::0;12164:45:::1;;;;-1:-1:-1::0;;;12164:45:0::1;;;;;;;:::i;:::-;12219:14;12236:19;12248:6;12236:11;:19::i;:::-;12219:36;;12265:13;12281;:11;:13::i;:::-;12330:6;::::0;12265:29;;-1:-1:-1;12312:14:0::1;12320:6:::0;12265:29;12312:14:::1;:::i;:::-;:24;;12304:51;;;::::0;-1:-1:-1;;;12304:51:0;;12786:2:20;12304:51:0::1;::::0;::::1;12768:21:20::0;12825:2;12805:18;;;12798:30;-1:-1:-1;;;12844:18:20;;;12837:44;12898:18;;12304:51:0::1;12584:338:20::0;12304:51:0::1;12370:12;:10;:12::i;:::-;12366:38;;12398:6;12389:15;;12366:38;12415:73;-1:-1:-1::0;;;;;12430:5:0::1;12415:38;12454:10;12474:4;12481:6:::0;12415:38:::1;:73::i;:::-;12499:23;12505:8;12515:6;12499:5;:23::i;:::-;12537:45;::::0;;13101:25:20;;;13157:2;13142:18;;13135:34;;;-1:-1:-1;;;;;12537:45:0;::::1;::::0;12545:10:::1;::::0;12537:45:::1;::::0;13074:18:20;12537:45:0::1;;;;;;;-1:-1:-1::0;1701:1:8;2628:7;:22;12600:6:0;11988:625;-1:-1:-1;;;11988:625:0:o;2367:102:9:-;2423:13;2455:7;2448:14;;;;;:::i;6594:427::-;6687:4;719:10:14;6687:4:9;6768:25;719:10:14;6785:7:9;6768:9;:25::i;:::-;6741:52;;6831:15;6811:16;:35;;6803:85;;;;-1:-1:-1;;;6803:85:9;;15576:2:20;6803:85:9;;;15558:21:20;15615:2;15595:18;;;15588:30;15654:34;15634:18;;;15627:62;-1:-1:-1;;;15705:18:20;;;15698:35;15750:19;;6803:85:9;15374:401:20;6803:85:9;6922:60;6931:5;6938:7;6966:15;6947:16;:34;6922:8;:60::i;3729:189::-;3808:4;719:10:14;3862:28:9;719:10:14;3879:2:9;3883:6;3862:9;:28::i;22884:675:0:-;22968:24;-1:-1:-1;;;;;;;;;;;22968:12:0;:24::i;:::-;23024:16;23065;23057:65;;;;-1:-1:-1;;;23057:65:0;;15982:2:20;23057:65:0;;;15964:21:20;16021:2;16001:18;;;15994:30;16060:34;16040:18;;;16033:62;-1:-1:-1;;;16111:18:20;;;16104:34;16155:19;;23057:65:0;15780:400:20;23057:65:0;23133:22;23140:15;;23133:22;:::i;:::-;23170:9;23165:335;23189:11;23185:1;:15;23165:335;;;23238:16;23257;;23274:1;23257:19;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;23322:20:0;;23290:29;23322:20;;;:10;:20;;;;;23364:17;;23238:38;;-1:-1:-1;23322:20:0;23356:89;;;;-1:-1:-1;;;23356:89:0;;16519:2:20;23356:89:0;;;16501:21:20;16558:2;16538:18;;;16531:30;16597:34;16577:18;;;16570:62;-1:-1:-1;;;16648:18:20;;;16641:52;16710:19;;23356:89:0;16317:418:20;23356:89:0;-1:-1:-1;23459:15:0;:30;;;;;;;;-1:-1:-1;23459:30:0;;;;;;;;-1:-1:-1;;;;;;23459:30:0;-1:-1:-1;;;;;23459:30:0;;;;;;;;;;;31832:5;23165:335;;;;23514:38;23536:15;23514:38;;;;;;:::i;:::-;;;;;;;;22958:601;22884:675;;:::o;11425:256::-;11483:7;11502:20;11525:13;3331:12:9;;;3244:106;11525:13:0;11502:36;-1:-1:-1;11552:17:0;11548:36;;-1:-1:-1;11578:6:0;;11425:256;-1:-1:-1;11425:256:0:o;11548:36::-;11631:43;11647:12;:10;:12::i;:::-;11631:6;;11661:12;11631:15;:43::i;14022:293::-;14120:14;1744:1:8;2325:7;;:19;;2317:63;;;;-1:-1:-1;;;2317:63:8;;;;;;;:::i;:::-;1744:1;2455:7;:18;14154:11:0;14146:45:::1;;;;-1:-1:-1::0;;;14146:45:0::1;;;;;;;:::i;:::-;14210:23;14226:6;14210:15;:23::i;:::-;14201:32;;14243:42;14253:6;14261;14269:8;14279:5;14243:9;:42::i;:::-;;1701:1:8::0;2628:7;:22;14022:293:0;;-1:-1:-1;;;14022:293:0:o;18363:271::-;18457:14;1744:1:8;2325:7;;:19;;2317:63;;;;-1:-1:-1;;;2317:63:8;;;;;;;:::i;:::-;1744:1;2455:7;:18;18491:11:0;18483:45:::1;;;;-1:-1:-1::0;;;18483:45:0::1;;;;;;;:::i;:::-;18547:21;18561:6;18547:13;:21::i;:::-;18538:30;;18585:42;18595:6;18603;18611:8;18621:5;18585:9;:42::i;:::-;1701:1:8::0;2628:7;:22;18578:49:0;18363:271;-1:-1:-1;;;;18363:271:0:o;20711:374::-;20778:10;-1:-1:-1;;;;;20778:22:0;;;20772:78;;20817:22;3787:21;20817:12;:22::i;:::-;-1:-1:-1;;;;;20872:20:0;;;;;;:10;:20;;;;;:29;;;20868:71;;20711:374;:::o;20868:71::-;-1:-1:-1;;;;;20966:20:0;;;;;;:10;:20;;;;;:29;;;20949:13;:46;;20966:29;;20949:13;;:46;;20966:29;;20949:46;:::i;:::-;;;;-1:-1:-1;;;;;;;21005:20:0;;21037:1;21005:20;;;:10;:20;;;;;;:29;;:33;;;21053:25;;;21037:1;21053:25;20711:374;:::o;10984:136::-;11048:7;11074:39;11090:22;11109:1;11090:10;:22::i;7719:289::-;7781:7;7800:20;7823:13;3331:12:9;;;3244:106;7823:13:0;7800:36;;7846:17;7866:12;:10;:12::i;:::-;7846:32;-1:-1:-1;7892:14:0;;;:35;;-1:-1:-1;7910:17:0;;7892:35;7888:54;;;-1:-1:-1;7936:6:0;;7719:289;-1:-1:-1;;7719:289:0:o;7888:54::-;7959:42;:6;7977:12;7991:9;7959:17;:42::i;1592:32::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1592:32:0;;-1:-1:-1;1592:32:0;:::o;18860:1032::-;18936:32;2072:4:4;18936:12:0;:32::i;:::-;18987:17;;;;18986:18;18978:78;;;;-1:-1:-1;;;18978:78:0;;17628:2:20;18978:78:0;;;17610:21:20;17667:2;17647:18;;;17640:30;17706:34;17686:18;;;17679:62;-1:-1:-1;;;17757:18:20;;;17750:45;17812:19;;18978:78:0;17426:411:20;18978:78:0;-1:-1:-1;;;;;19074:22:0;;19066:62;;;;-1:-1:-1;;;19066:62:0;;18044:2:20;19066:62:0;;;18026:21:20;18083:2;18063:18;;;18056:30;18122:29;18102:18;;;18095:57;18169:18;;19066:62:0;17842:351:20;19066:62:0;-1:-1:-1;;;;;19146:20:0;;;;;;:10;:20;;;;;:31;:36;19138:83;;;;-1:-1:-1;;;19138:83:0;;18400:2:20;19138:83:0;;;18382:21:20;18439:2;18419:18;;;18412:30;18478:34;18458:18;;;18451:62;-1:-1:-1;;;18529:18:20;;;18522:32;18571:19;;19138:83:0;18198:398:20;19138:83:0;19266:8;-1:-1:-1;;;;;19256:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;19239:44:0;19247:4;-1:-1:-1;;;;;19239:44:0;;19231:89;;;;-1:-1:-1;;;19231:89:0;;19059:2:20;19231:89:0;;;19041:21:20;;;19078:18;;;19071:30;19137:34;19117:18;;;19110:62;19189:18;;19231:89:0;18857:356:20;19231:89:0;19357:8;-1:-1:-1;;;;;19347:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;19338:35:0;:5;-1:-1:-1;;;;;19338:35:0;;19330:83;;;;-1:-1:-1;;;19330:83:0;;19420:2:20;19330:83:0;;;19402:21:20;19459:2;19439:18;;;19432:30;19498:34;19478:18;;;19471:62;-1:-1:-1;;;19549:18:20;;;19542:33;19592:19;;19330:83:0;19218:399:20;19330:83:0;1866:6;19442:13;;19431:8;:24;;;;:::i;:::-;:43;;19423:93;;;;-1:-1:-1;;;19423:93:0;;;;;;;:::i;:::-;19550:211;;;;;;;;19591:15;19550:211;;;;;;;;;;-1:-1:-1;19550:211:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19527:20:0;;;;:10;:20;;;;;;:234;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19772:13;:25;;19630:8;;-1:-1:-1;19772:25:0;;19630:8;;19772:25;:::i;:::-;;;;-1:-1:-1;;19807:15:0;:30;;;;;;;-1:-1:-1;19807:30:0;;;;;;;;-1:-1:-1;;;;;;19807:30:0;-1:-1:-1;;;;;19807:30:0;;;;;;;;19852:33;;345:25:20;;;19852:33:0;;333:2:20;318:18;19852:33:0;199:177:20;1750:140:5;1830:7;1856:18;;;:12;:18;;;;;:27;;:25;:27::i;12928:125:0:-;-1:-1:-1;;;;;3508:18:9;;12987:7:0;3508:18:9;;;;;;;;;;;13013:33:0;;8345:262;:::i;5149:147:4:-;4465:7;4491:12;;;:6;:12;;;;;:22;;;2505:16;2516:4;2505:10;:16::i;:::-;5263:26:::1;5275:4;5281:7;5263:11;:26::i;16938:106:0:-:0;-1:-1:-1;;;;;3508:18:9;;16995:7:0;3508:18:9;;;;;;;;;;;17021:16:0;3408:125:9;3976:149;-1:-1:-1;;;;;4091:18:9;;;4065:7;4091:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3976:149::o;9684:112:0:-;9733:43;;-1:-1:-1;;;9733:43:0;;9765:10;9733:43;;;4255:51:20;9725:64:0;;9748:5;-1:-1:-1;;;;;9733:31:0;;;;4228:18:20;;9733:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9778:10;9725:7;:64::i;29236:332::-;29300:24;-1:-1:-1;;;;;;;;;;;29300:12:0;:24::i;:::-;29351:5;-1:-1:-1;;;;;29342:14:0;:5;-1:-1:-1;;;;;29342:14:0;;;29334:33;;;;-1:-1:-1;;;29334:33:0;;19824:2:20;29334:33:0;;;19806:21:20;19863:1;19843:18;;;19836:29;-1:-1:-1;;;19881:18:20;;;19874:36;19927:18;;29334:33:0;19622:329:20;29334:33:0;29395:46;;-1:-1:-1;;;29395:46:0;;29435:4;29395:46;;;4255:51:20;29378:14:0;;-1:-1:-1;;;;;29395:31:0;;;;;4228:18:20;;29395:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29378:63;-1:-1:-1;29451:54:0;-1:-1:-1;;;;;29451:34:0;;29486:10;29378:63;29451:34;:54::i;:::-;29520:41;;;-1:-1:-1;;;;;20148:32:20;;20130:51;;20212:2;20197:18;;20190:34;;;29520:41:0;;20103:18:20;29520:41:0;;;;;;;29290:278;29236:332;:::o;9465:117::-;9526:7;9552:23;9568:6;9552:15;:23::i;7244:233:4:-;7327:22;7335:4;7341:7;7327;:22::i;:::-;7322:149;;7365:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7365:29:4;;;;;;;;;:36;;-1:-1:-1;;7365:36:4;7397:4;7365:36;;;7447:12;719:10:14;;640:96;7447:12:4;-1:-1:-1;;;;;7420:40:4;7438:7;-1:-1:-1;;;;;7420:40:4;7432:4;7420:40;;;;;;;;;;7244:233;;:::o;7627:150:19:-;7697:4;7720:50;7725:3;-1:-1:-1;;;;;7745:23:19;;7720:4;:50::i;30860:673:0:-;30939:15;:22;30920:16;;31007:260;31031:8;31027:1;:12;31007:260;;;31089:15;31105:1;31089:18;;;;;;;;:::i;:::-;;;;;;;;;31081:4;:26;31077:180;;;31148:1;31127:22;;31167:5;;31077:180;31202:12;31213:1;31202:8;:12;:::i;:::-;31197:1;:17;31193:64;;;31234:8;;;31193:64;31836:1;31832:5;31007:260;;;;31282:9;31277:250;31302:18;31297:1;:23;31277:250;;31362:39;31370:15;31386:1;31370:18;;;;;;;;:::i;:::-;;;;;;;;;31390:10;31362:7;:39::i;:::-;31358:159;;;31421:5;;31358:159;31456:18;31451:1;:23;31447:70;;;31494:8;;;31447:70;31836:1;31832:5;31277:250;;;;30910:623;;30860:673;:::o;2606:202:4:-;2691:4;-1:-1:-1;;;;;;2714:47:4;;-1:-1:-1;;;2714:47:4;;:87;;-1:-1:-1;;;;;;;;;;937:40:16;;;2765:36:4;829:155:16;6689:118:0;6734:7;6776:24;:22;:24::i;:::-;6760:13;:11;:13::i;:::-;:40;;;;:::i;1504:535:3:-;1710:9;;;1841:19;;1834:27;1866:9;;1880;;;1877:16;;1863:31;1830:65;1820:121;;1925:1;1922;1915:12;1820:121;2004:19;;1504:535;-1:-1:-1;;1504:535:3:o;10119:370:9:-;-1:-1:-1;;;;;10250:19:9;;10242:68;;;;-1:-1:-1;;;10242:68:9;;20437:2:20;10242:68:9;;;20419:21:20;20476:2;20456:18;;;20449:30;20515:34;20495:18;;;20488:62;-1:-1:-1;;;20566:18:20;;;20559:34;20610:19;;10242:68:9;20235:400:20;10242:68:9;-1:-1:-1;;;;;10328:21:9;;10320:68;;;;-1:-1:-1;;;10320:68:9;;20842:2:20;10320:68:9;;;20824:21:20;20881:2;20861:18;;;20854:30;20920:34;20900:18;;;20893:62;-1:-1:-1;;;20971:18:20;;;20964:32;21013:19;;10320:68:9;20640:398:20;10320:68:9;-1:-1:-1;;;;;10399:18:9;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;10450:32;;345:25:20;;;10450:32:9;;318:18:20;10450:32:9;;;;;;;10119:370;;;:::o;2045:752:3:-;2249:9;;;2380:19;;2373:27;2405:9;;2419;;;2416:16;;2402:31;2369:65;2359:121;;2464:1;2461;2454:12;2359:121;2778:1;2764:11;2760:1;2757;2753:9;2749:27;2745:35;2740:1;2733:9;2726:17;2722:59;2717:64;;2045:752;;;;;:::o;23746:952:0:-;-1:-1:-1;;;;;23855:20:0;;23818:34;23855:20;;;:10;:20;;;;;23985:21;;;;24024:18;;;;24016:87;;;;-1:-1:-1;;;24016:87:0;;21245:2:20;24016:87:0;;;21227:21:20;21284:2;21264:18;;;21257:30;21323:34;21303:18;;;21296:62;21394:26;21374:18;;;21367:54;21438:19;;24016:87:0;21043:420:20;24016:87:0;24118:13;;:18;24114:405;;24212:17;24232:71;24266:14;;24249:13;;24242:4;:20;;;;:::i;:::-;24241:39;;;;:::i;:::-;24282:11;:20;;;24232:8;:71::i;:::-;24212:91;-1:-1:-1;24383:14:0;;24379:130;;24441:9;24417:11;:20;;;:33;;;;;;;:::i;:::-;;;;;;;;24485:9;24468:13;;:26;;;;;;;:::i;:::-;;;;-1:-1:-1;;24379:130:0;24138:381;24114:405;24616:4;24594:11;:18;;;:26;;;;;;;:::i;:::-;;;;;;;;24655:4;24630:11;:21;;;:29;;;;;;;:::i;:::-;;;;;;;;24687:4;24669:14;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;23746:952:0:o;461:104:18:-;519:7;549:1;545;:5;:13;;557:1;545:13;;;-1:-1:-1;553:1:18;;461:104;-1:-1:-1;461:104:18:o;701:205:12:-;840:58;;-1:-1:-1;;;;;20148:32:20;;840:58:12;;;20130:51:20;20197:18;;;20190:34;;;813:86:12;;833:5;;-1:-1:-1;;;863:23:12;20103:18:20;;840:58:12;;;;-1:-1:-1;;840:58:12;;;;;;;;;;;;;;-1:-1:-1;;;;;840:58:12;-1:-1:-1;;;;;;840:58:12;;;;;;;;;;813:19;:86::i;912:241::-;1077:68;;-1:-1:-1;;;;;21726:15:20;;;1077:68:12;;;21708:34:20;21778:15;;21758:18;;;21751:43;21810:18;;;21803:34;;;1050:96:12;;1070:5;;-1:-1:-1;;;1100:27:12;21643:18:20;;1077:68:12;21468:375:20;6952:430:0;7009:7;7028:24;7088:23;;7074:10;;7056:15;:28;;;;:::i;:::-;7055:56;;;;:::i;:::-;7028:83;;1762:8;7125:16;:42;7122:254;;;1762:8;7258:12;;7223:16;:47;;;;:::i;:::-;:89;;;;:::i;:::-;7190:12;;:136;;;;:::i;7122:254::-;7364:1;7357:8;;;6952:430;:::o;7122:254::-;7018:364;6952:430;:::o;10770:441:9:-;10900:24;10927:25;10937:5;10944:7;10927:9;:25::i;:::-;10900:52;;-1:-1:-1;;10966:16:9;:37;10962:243;;11047:6;11027:16;:26;;11019:68;;;;-1:-1:-1;;;11019:68:9;;22050:2:20;11019:68:9;;;22032:21:20;22089:2;22069:18;;;22062:30;22128:31;22108:18;;;22101:59;22177:18;;11019:68:9;21848:353:20;11019:68:9;11129:51;11138:5;11145:7;11173:6;11154:16;:25;11129:8;:51::i;7484:651::-;-1:-1:-1;;;;;7610:18:9;;7602:68;;;;-1:-1:-1;;;7602:68:9;;22408:2:20;7602:68:9;;;22390:21:20;22447:2;22427:18;;;22420:30;22486:34;22466:18;;;22459:62;-1:-1:-1;;;22537:18:20;;;22530:35;22582:19;;7602:68:9;22206:401:20;7602:68:9;-1:-1:-1;;;;;7688:16:9;;7680:64;;;;-1:-1:-1;;;7680:64:9;;22814:2:20;7680:64:9;;;22796:21:20;22853:2;22833:18;;;22826:30;22892:34;22872:18;;;22865:62;-1:-1:-1;;;22943:18:20;;;22936:33;22986:19;;7680:64:9;22612:399:20;7680:64:9;-1:-1:-1;;;;;7826:15:9;;7804:19;7826:15;;;;;;;;;;;7859:21;;;;7851:72;;;;-1:-1:-1;;;7851:72:9;;23218:2:20;7851:72:9;;;23200:21:20;23257:2;23237:18;;;23230:30;23296:34;23276:18;;;23269:62;-1:-1:-1;;;23347:18:20;;;23340:36;23393:19;;7851:72:9;23016:402:20;7851:72:9;-1:-1:-1;;;;;7957:15:9;;;:9;:15;;;;;;;;;;;7975:20;;;7957:38;;8015:13;;;;;;;;:23;;7989:6;;7957:9;8015:23;;7989:6;;8015:23;:::i;:::-;;;;;;;;8069:2;-1:-1:-1;;;;;8054:26:9;8063:4;-1:-1:-1;;;;;8054:26:9;;8073:6;8054:26;;;;345:25:20;;333:2;318:18;;199:177;8054:26:9;;;;;;;;8091:37;4770:145:4;3334:103;3400:30;3411:4;719:10:14;3400::4;:30::i;1978:166:5:-;2065:31;2082:4;2088:7;2065:16;:31::i;:::-;2106:18;;;;:12;:18;;;;;:31;;2129:7;2106:22;:31::i;2233:171::-;2321:32;2339:4;2345:7;2321:17;:32::i;:::-;2363:18;;;;:12;:18;;;;;:34;;2389:7;2363:25;:34::i;8411:389:9:-;-1:-1:-1;;;;;8494:21:9;;8486:65;;;;-1:-1:-1;;;8486:65:9;;23625:2:20;8486:65:9;;;23607:21:20;23664:2;23644:18;;;23637:30;23703:33;23683:18;;;23676:61;23754:18;;8486:65:9;23423:355:20;8486:65:9;8638:6;8622:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;8654:18:9;;:9;:18;;;;;;;;;;:28;;8676:6;;8654:9;:28;;8676:6;;8654:28;:::i;:::-;;;;-1:-1:-1;;8697:37:9;;345:25:20;;;-1:-1:-1;;;;;8697:37:9;;;8714:1;;8697:37;;333:2:20;318:18;8697:37:9;;;;;;;5787:214:4;;:::o;8885:156:19:-;8959:7;9009:22;9013:3;9025:5;9009:3;:22::i;14701:1965:0:-;14803:7;14822:20;14828:5;14835:6;14822:5;:20::i;:::-;14866:46;;-1:-1:-1;;;14866:46:0;;14906:4;14866:46;;;4255:51:20;14881:5:0;-1:-1:-1;;;;;14866:31:0;;;;4228:18:20;;14866:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14857:6;:55;14853:1653;;;14985:15;:22;14928:17;;;;15072:1104;15096:11;15092:1;:15;15072:1104;;;15164:46;;-1:-1:-1;;;15164:46:0;;15204:4;15164:46;;;4255:51:20;15179:5:0;-1:-1:-1;;;;;15164:31:0;;;;4228:18:20;;15164:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15149:61;;15242:12;15232:6;:22;15228:74;;15278:5;;15228:74;15320:17;15340:15;15356:1;15340:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;15340:18:0;15398:21;;;:10;:21;;;;;;;:31;;;15340:18;;-1:-1:-1;15451:16:0;15447:71;;15491:8;;;;15447:71;15536:17;15556:21;15565:12;15556:6;:21;:::i;:::-;15536:41;;15595:12;15620:9;-1:-1:-1;;;;;15610:29:0;;15640:32;15649:9;15660:11;15640:8;:32::i;:::-;15610:63;;;;;;;;;;;;;345:25:20;;333:2;318:18;;199:177;15610:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;15717:46;;-1:-1:-1;;;15717:46:0;;15757:4;15717:46;;;4255:51:20;15595:78:0;;-1:-1:-1;15691:23:0;;15766:12;;-1:-1:-1;;;;;15732:5:0;15717:31;;;;4228:18:20;;15717:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:61;;;;:::i;:::-;15691:87;-1:-1:-1;15887:9:0;;15883:159;;15920:14;15930:4;15920:14;;:::i;:::-;;-1:-1:-1;15956:17:0;15969:4;15956:17;;:::i;:::-;;;15995:28;16007:9;16018:4;15995:11;:28::i;:::-;-1:-1:-1;;;;;16060:21:0;;;;;;:10;:21;;;;;:31;;:50;;16095:15;;16060:21;:50;;16095:15;;16060:50;:::i;:::-;;;;;;;;16146:15;16128:14;;:33;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;15072:1104:0;31836:1;31832:5;15072:1104;;;-1:-1:-1;16205:46:0;;-1:-1:-1;;;16205:46:0;;16245:4;16205:46;;;4255:51:20;16220:5:0;-1:-1:-1;;;;;16205:31:0;;;;4228:18:20;;16205:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16190:61;;16278:12;16269:6;:21;16265:81;;;16319:12;16310:21;;16265:81;16405:15;;1866:6;;16383:18;16392:9;16383:6;:18;:::i;:::-;16382:38;;;;:::i;:::-;16381:58;;;;:::i;:::-;16368:9;:71;;16360:135;;;;-1:-1:-1;;;16360:135:0;;23985:2:20;16360:135:0;;;23967:21:20;24024:2;24004:18;;;23997:30;24063:34;24043:18;;;24036:62;-1:-1:-1;;;24114:18:20;;;24107:49;24173:19;;16360:135:0;23783:415:20;16360:135:0;14914:1592;;;14853:1653;16516:52;-1:-1:-1;;;;;16531:5:0;16516:34;16551:8;16561:6;16516:34;:52::i;:::-;16583:53;;;13101:25:20;;;13157:2;13142:18;;13135:34;;;-1:-1:-1;;;;;16583:53:0;;;;;;;;16592:10;;16583:53;;13074:18:20;16583:53:0;;;;;;;-1:-1:-1;16653:6:0;;14701:1965;-1:-1:-1;;;14701:1965:0:o;8428:115:19:-;8491:7;8517:19;8525:3;4043:18;;3961:107;1712:404;1775:4;3849:19;;;:12;;;:19;;;;;;1791:319;;-1:-1:-1;1833:23:19;;;;;;;;:11;:23;;;;;;;;;;;;;2013:18;;1991:19;;;:12;;;:19;;;;;;:40;;;;2045:11;;1791:319;-1:-1:-1;2094:5:19;2087:12;;3207:706:12;3626:23;3652:69;3680:4;3652:69;;;;;;;;;;;;;;;;;3660:5;-1:-1:-1;;;;;3652:27:12;;;:69;;;;;:::i;:::-;3735:17;;3626:95;;-1:-1:-1;3735:21:12;3731:176;;3830:10;3819:30;;;;;;;;;;;;:::i;:::-;3811:85;;;;-1:-1:-1;;;3811:85:12;;24655:2:20;3811:85:12;;;24637:21:20;24694:2;24674:18;;;24667:30;24733:34;24713:18;;;24706:62;-1:-1:-1;;;24784:18:20;;;24777:40;24834:19;;3811:85:12;24453:406:20;3718:492:4;3806:22;3814:4;3820:7;3806;:22::i;:::-;3801:403;;3989:41;4017:7;-1:-1:-1;;;;;3989:41:4;4027:2;3989:19;:41::i;:::-;4101:38;4129:4;4136:2;4101:19;:38::i;:::-;3896:265;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3896:265:4;;;;;;;;;;-1:-1:-1;;;3844:349:4;;;;;;;:::i;7602:234::-;7685:22;7693:4;7699:7;7685;:22::i;:::-;7681:149;;;7755:5;7723:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;7723:29:4;;;;;;;;;;:37;;-1:-1:-1;;7723:37:4;;;7779:40;719:10:14;;7723:12:4;;7779:40;;7755:5;7779:40;7602:234;;:::o;7945:156:19:-;8018:4;8041:53;8049:3;-1:-1:-1;;;;;8069:23:19;;8041:7;:53::i;4410:118::-;4477:7;4503:3;:11;;4515:5;4503:18;;;;;;;;:::i;:::-;;;;;;;;;4496:25;;4410:118;;;;:::o;9120:576:9:-;-1:-1:-1;;;;;9203:21:9;;9195:67;;;;-1:-1:-1;;;9195:67:9;;25857:2:20;9195:67:9;;;25839:21:20;25896:2;25876:18;;;25869:30;25935:34;25915:18;;;25908:62;-1:-1:-1;;;25986:18:20;;;25979:31;26027:19;;9195:67:9;25655:397:20;9195:67:9;-1:-1:-1;;;;;9358:18:9;;9333:22;9358:18;;;;;;;;;;;9394:24;;;;9386:71;;;;-1:-1:-1;;;9386:71:9;;26259:2:20;9386:71:9;;;26241:21:20;26298:2;26278:18;;;26271:30;26337:34;26317:18;;;26310:62;-1:-1:-1;;;26388:18:20;;;26381:32;26430:19;;9386:71:9;26057:398:20;9386:71:9;-1:-1:-1;;;;;9491:18:9;;:9;:18;;;;;;;;;;9512:23;;;9491:44;;9555:12;:22;;9529:6;;9491:9;9555:22;;9529:6;;9555:22;:::i;:::-;;;;-1:-1:-1;;9593:37:9;;345:25:20;;;9619:1:9;;-1:-1:-1;;;;;9593:37:9;;;;;333:2:20;318:18;9593:37:9;;;;;;;4770:145:4;;;:::o;3861:223:13:-;3994:12;4025:52;4047:6;4055:4;4061:1;4064:12;4025:21;:52::i;1588:441:15:-;1663:13;1688:19;1720:10;1724:6;1720:1;:10;:::i;:::-;:14;;1733:1;1720:14;:::i;:::-;1710:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1710:25:15;;1688:47;;-1:-1:-1;;;1745:6:15;1752:1;1745:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1745:15:15;;;;;;;;;-1:-1:-1;;;1770:6:15;1777:1;1770:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;1770:15:15;;;;;;;;-1:-1:-1;1800:9:15;1812:10;1816:6;1812:1;:10;:::i;:::-;:14;;1825:1;1812:14;:::i;:::-;1800:26;;1795:132;1832:1;1828;:5;1795:132;;;-1:-1:-1;;;1879:5:15;1887:3;1879:11;1866:25;;;;;;;:::i;:::-;;;;1854:6;1861:1;1854:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;1854:37:15;;;;;;;;-1:-1:-1;1915:1:15;1905:11;;;;;1835:3;;;:::i;:::-;;;1795:132;;;-1:-1:-1;1944:10:15;;1936:55;;;;-1:-1:-1;;;1936:55:15;;26935:2:20;1936:55:15;;;26917:21:20;;;26954:18;;;26947:30;27013:34;26993:18;;;26986:62;27065:18;;1936:55:15;26733:356:20;2284:1388:19;2350:4;2487:19;;;:12;;;:19;;;;;;2521:15;;2517:1149;;2890:21;2914:14;2927:1;2914:10;:14;:::i;:::-;2962:18;;2890:38;;-1:-1:-1;2942:17:19;;2962:22;;2983:1;;2962:22;:::i;:::-;2942:42;;3016:13;3003:9;:26;2999:398;;3049:17;3069:3;:11;;3081:9;3069:22;;;;;;;;:::i;:::-;;;;;;;;;3049:42;;3220:9;3191:3;:11;;3203:13;3191:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;3303:23;;;:12;;;:23;;;;;:36;;;2999:398;3475:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;3567:3;:12;;:19;3580:5;3567:19;;;;;;;;;;;3560:26;;;3608:4;3601:11;;;;;;;2517:1149;3650:5;3643:12;;;;;4948:499:13;5113:12;5170:5;5145:21;:30;;5137:81;;;;-1:-1:-1;;;5137:81:13;;27428:2:20;5137:81:13;;;27410:21:20;27467:2;27447:18;;;27440:30;27506:34;27486:18;;;27479:62;-1:-1:-1;;;27557:18:20;;;27550:36;27603:19;;5137:81:13;27226:402:20;5137:81:13;-1:-1:-1;;;;;1465:19:13;;;5228:60;;;;-1:-1:-1;;;5228:60:13;;27835:2:20;5228:60:13;;;27817:21:20;27874:2;27854:18;;;27847:30;27913:31;27893:18;;;27886:59;27962:18;;5228:60:13;27633:353:20;5228:60:13;5300:12;5314:23;5341:6;-1:-1:-1;;;;;5341:11:13;5360:5;5367:4;5341:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5299:73;;;;5389:51;5406:7;5415:10;5427:12;7707;7735:7;7731:516;;;-1:-1:-1;7765:10:13;7758:17;;7731:516;7876:17;;:21;7872:365;;8070:10;8064:17;8130:15;8117:10;8113:2;8109:19;8102:44;7872:365;8209:12;8202:20;;-1:-1:-1;;;8202:20:13;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:180:20;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:20;;14:180;-1:-1:-1;14:180:20:o;381:286::-;439:6;492:2;480:9;471:7;467:23;463:32;460:52;;;508:1;505;498:12;460:52;534:23;;-1:-1:-1;;;;;;586:32:20;;576:43;;566:71;;633:1;630;623:12;864:258;936:1;946:113;960:6;957:1;954:13;946:113;;;1036:11;;;1030:18;1017:11;;;1010:39;982:2;975:10;946:113;;;1077:6;1074:1;1071:13;1068:48;;;-1:-1:-1;;1112:1:20;1094:16;;1087:27;864:258::o;1127:383::-;1276:2;1265:9;1258:21;1239:4;1308:6;1302:13;1351:6;1346:2;1335:9;1331:18;1324:34;1367:66;1426:6;1421:2;1410:9;1406:18;1401:2;1393:6;1389:15;1367:66;:::i;:::-;1494:2;1473:15;-1:-1:-1;;1469:29:20;1454:45;;;;1501:2;1450:54;;1127:383;-1:-1:-1;;1127:383:20:o;1515:131::-;-1:-1:-1;;;;;1590:31:20;;1580:42;;1570:70;;1636:1;1633;1626:12;1651:315;1719:6;1727;1780:2;1768:9;1759:7;1755:23;1751:32;1748:52;;;1796:1;1793;1786:12;1748:52;1835:9;1822:23;1854:31;1879:5;1854:31;:::i;:::-;1904:5;1956:2;1941:18;;;;1928:32;;-1:-1:-1;;;1651:315:20:o;1971:247::-;2038:6;2046;2099:2;2087:9;2078:7;2074:23;2070:32;2067:52;;;2115:1;2112;2105:12;2067:52;-1:-1:-1;;2138:23:20;;;2208:2;2193:18;;;2180:32;;-1:-1:-1;1971:247:20:o;2223:118::-;2309:5;2302:13;2295:21;2288:5;2285:32;2275:60;;2331:1;2328;2321:12;2346:241;2402:6;2455:2;2443:9;2434:7;2430:23;2426:32;2423:52;;;2471:1;2468;2461:12;2423:52;2510:9;2497:23;2529:28;2551:5;2529:28;:::i;2772:456::-;2849:6;2857;2865;2918:2;2906:9;2897:7;2893:23;2889:32;2886:52;;;2934:1;2931;2924:12;2886:52;2973:9;2960:23;2992:31;3017:5;2992:31;:::i;:::-;3042:5;-1:-1:-1;3099:2:20;3084:18;;3071:32;3112:33;3071:32;3112:33;:::i;:::-;2772:456;;3164:7;;-1:-1:-1;;;3218:2:20;3203:18;;;;3190:32;;2772:456::o;3600:315::-;3668:6;3676;3729:2;3717:9;3708:7;3704:23;3700:32;3697:52;;;3745:1;3742;3735:12;3697:52;3781:9;3768:23;3758:33;;3841:2;3830:9;3826:18;3813:32;3854:31;3879:5;3854:31;:::i;:::-;3904:5;3894:15;;;3600:315;;;;;:::o;4317:247::-;4376:6;4429:2;4417:9;4408:7;4404:23;4400:32;4397:52;;;4445:1;4442;4435:12;4397:52;4484:9;4471:23;4503:31;4528:5;4503:31;:::i;5682:615::-;5768:6;5776;5829:2;5817:9;5808:7;5804:23;5800:32;5797:52;;;5845:1;5842;5835:12;5797:52;5885:9;5872:23;5914:18;5955:2;5947:6;5944:14;5941:34;;;5971:1;5968;5961:12;5941:34;6009:6;5998:9;5994:22;5984:32;;6054:7;6047:4;6043:2;6039:13;6035:27;6025:55;;6076:1;6073;6066:12;6025:55;6116:2;6103:16;6142:2;6134:6;6131:14;6128:34;;;6158:1;6155;6148:12;6128:34;6211:7;6206:2;6196:6;6193:1;6189:14;6185:2;6181:23;6177:32;6174:45;6171:65;;;6232:1;6229;6222:12;6171:65;6263:2;6255:11;;;;;6285:6;;-1:-1:-1;5682:615:20;;-1:-1:-1;;;;5682:615:20:o;6302:456::-;6379:6;6387;6395;6448:2;6436:9;6427:7;6423:23;6419:32;6416:52;;;6464:1;6461;6454:12;6416:52;6500:9;6487:23;6477:33;;6560:2;6549:9;6545:18;6532:32;6573:31;6598:5;6573:31;:::i;:::-;6623:5;-1:-1:-1;6680:2:20;6665:18;;6652:32;6693:33;6652:32;6693:33;:::i;:::-;6745:7;6735:17;;;6302:456;;;;;:::o;6763:388::-;6831:6;6839;6892:2;6880:9;6871:7;6867:23;6863:32;6860:52;;;6908:1;6905;6898:12;6860:52;6947:9;6934:23;6966:31;6991:5;6966:31;:::i;:::-;7016:5;-1:-1:-1;7073:2:20;7058:18;;7045:32;7086:33;7045:32;7086:33;:::i;7156:184::-;7226:6;7279:2;7267:9;7258:7;7254:23;7250:32;7247:52;;;7295:1;7292;7285:12;7247:52;-1:-1:-1;7318:16:20;;7156:184;-1:-1:-1;7156:184:20:o;7345:127::-;7406:10;7401:3;7397:20;7394:1;7387:31;7437:4;7434:1;7427:15;7461:4;7458:1;7451:15;7477:128;7517:3;7548:1;7544:6;7541:1;7538:13;7535:39;;;7554:18;;:::i;:::-;-1:-1:-1;7590:9:20;;7477:128::o;7610:380::-;7689:1;7685:12;;;;7732;;;7753:61;;7807:4;7799:6;7795:17;7785:27;;7753:61;7860:2;7852:6;7849:14;7829:18;7826:38;7823:161;;;7906:10;7901:3;7897:20;7894:1;7887:31;7941:4;7938:1;7931:15;7969:4;7966:1;7959:15;7823:161;;7610:380;;;:::o;8397:136::-;8432:3;-1:-1:-1;;;8453:22:20;;8450:48;;;8478:18;;:::i;:::-;-1:-1:-1;8518:1:20;8514:13;;8397:136::o;8538:125::-;8578:4;8606:1;8603;8600:8;8597:34;;;8611:18;;:::i;:::-;-1:-1:-1;8648:9:20;;8538:125::o;9206:168::-;9246:7;9312:1;9308;9304:6;9300:14;9297:1;9294:21;9289:1;9282:9;9275:17;9271:45;9268:71;;;9319:18;;:::i;:::-;-1:-1:-1;9359:9:20;;9206:168::o;9379:217::-;9419:1;9445;9435:132;;9489:10;9484:3;9480:20;9477:1;9470:31;9524:4;9521:1;9514:15;9552:4;9549:1;9542:15;9435:132;-1:-1:-1;9581:9:20;;9379:217::o;9601:273::-;9669:6;9722:2;9710:9;9701:7;9697:23;9693:32;9690:52;;;9738:1;9735;9728:12;9690:52;9770:9;9764:16;9820:4;9813:5;9809:16;9802:5;9799:27;9789:55;;9840:1;9837;9830:12;11059:401;11261:2;11243:21;;;11300:2;11280:18;;;11273:30;11339:34;11334:2;11319:18;;11312:62;-1:-1:-1;;;11405:2:20;11390:18;;11383:35;11450:3;11435:19;;11059:401::o;11465:355::-;11667:2;11649:21;;;11706:2;11686:18;;;11679:30;11745:33;11740:2;11725:18;;11718:61;11811:2;11796:18;;11465:355::o;12234:345::-;12436:2;12418:21;;;12475:2;12455:18;;;12448:30;-1:-1:-1;;;12509:2:20;12494:18;;12487:51;12570:2;12555:18;;12234:345::o;13180:422::-;13269:1;13312:5;13269:1;13326:270;13347:7;13337:8;13334:21;13326:270;;;13406:4;13402:1;13398:6;13394:17;13388:4;13385:27;13382:53;;;13415:18;;:::i;:::-;13465:7;13455:8;13451:22;13448:55;;;13485:16;;;;13448:55;13564:22;;;;13524:15;;;;13326:270;;;13330:3;13180:422;;;;;:::o;13607:806::-;13656:5;13686:8;13676:80;;-1:-1:-1;13727:1:20;13741:5;;13676:80;13775:4;13765:76;;-1:-1:-1;13812:1:20;13826:5;;13765:76;13857:4;13875:1;13870:59;;;;13943:1;13938:130;;;;13850:218;;13870:59;13900:1;13891:10;;13914:5;;;13938:130;13975:3;13965:8;13962:17;13959:43;;;13982:18;;:::i;:::-;-1:-1:-1;;14038:1:20;14024:16;;14053:5;;13850:218;;14152:2;14142:8;14139:16;14133:3;14127:4;14124:13;14120:36;14114:2;14104:8;14101:16;14096:2;14090:4;14087:12;14083:35;14080:77;14077:159;;;-1:-1:-1;14189:19:20;;;14221:5;;14077:159;14268:34;14293:8;14287:4;14268:34;:::i;:::-;14338:6;14334:1;14330:6;14326:19;14317:7;14314:32;14311:58;;;14349:18;;:::i;:::-;14387:20;;13607:806;-1:-1:-1;;;13607:806:20:o;14418:140::-;14476:5;14505:47;14546:4;14536:8;14532:19;14526:4;14505:47;:::i;16185:127::-;16246:10;16241:3;16237:20;16234:1;16227:31;16277:4;16274:1;16267:15;16301:4;16298:1;16291:15;16740:681;16908:2;16960:21;;;17030:13;;16933:18;;;17052:22;;;16879:4;17117:17;;;17157:16;;;16879:4;;16908:2;17105;17090:18;;;16879:4;17201:194;17215:6;17212:1;17209:13;17201:194;;;17280:13;;-1:-1:-1;;;;;17276:39:20;17264:52;;17312:1;17371:14;;;;17336:12;;;;17230:9;17201:194;;;-1:-1:-1;17412:3:20;;16740:681;-1:-1:-1;;;;;;16740:681:20:o;18601:251::-;18671:6;18724:2;18712:9;18703:7;18699:23;18695:32;18692:52;;;18740:1;18737;18730:12;18692:52;18772:9;18766:16;18791:31;18816:5;18791:31;:::i;24203:245::-;24270:6;24323:2;24311:9;24302:7;24298:23;24294:32;24291:52;;;24339:1;24336;24329:12;24291:52;24371:9;24365:16;24390:28;24412:5;24390:28;:::i;24864:786::-;25275:25;25270:3;25263:38;25245:3;25330:6;25324:13;25346:62;25401:6;25396:2;25391:3;25387:12;25380:4;25372:6;25368:17;25346:62;:::i;:::-;-1:-1:-1;;;25467:2:20;25427:16;;;25459:11;;;25452:40;25517:13;;25539:63;25517:13;25588:2;25580:11;;25573:4;25561:17;;25539:63;:::i;:::-;25622:17;25641:2;25618:26;;24864:786;-1:-1:-1;;;;24864:786:20:o;26460:127::-;26521:10;26516:3;26512:20;26509:1;26502:31;26552:4;26549:1;26542:15;26576:4;26573:1;26566:15;26592:136;26631:3;26659:5;26649:39;;26668:18;;:::i;:::-;-1:-1:-1;;;26704:18:20;;26592:136::o;27094:127::-;27155:10;27150:3;27146:20;27143:1;27136:31;27186:4;27183:1;27176:15;27210:4;27207:1;27200:15;27991:274;28120:3;28158:6;28152:13;28174:53;28220:6;28215:3;28208:4;28200:6;28196:17;28174:53;:::i;:::-;28243:16;;;;;27991:274;-1:-1:-1;;27991:274:20:o
Swarm Source
ipfs://ac0e84e2c8909347c36149f14e7eea548ae5bda9f0eb388ccb7ca4fa29fb1bc3
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Validator ID :
0 FTM
Amount Staked
0
Amount Delegated
0
Staking Total
0
Staking Start Epoch
0
Staking Start Time
0
Proof of Importance
0
Origination Score
0
Validation Score
0
Active
0
Online
0
Downtime
0 s
Address | Amount | claimed Rewards | Created On Epoch | Created On |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.