Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60a06040 | 12042724 | 1272 days ago | IN | 0 ETH | 0.95487935 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MusdV3
Compiler Version
v0.8.0+commit.c7dfd78e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-03-15 */ // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.0; pragma abicoder v2; interface MassetStructs { struct BassetPersonal { // Address of the bAsset address addr; // Address of the bAsset address integrator; // An ERC20 can charge transfer fee, for example USDT, DGX tokens. bool hasTxFee; // takes a byte in storage // Status of the bAsset BassetStatus status; } struct BassetData { // 1 Basset * ratio / ratioScale == x Masset (relative value) // If ratio == 10e8 then 1 bAsset = 10 mAssets // A ratio is divised as 10^(18-tokenDecimals) * measurementMultiple(relative value of 1 base unit) uint128 ratio; // Amount of the Basset that is held in Collateral uint128 vaultBalance; } // Status of the Basset - has it broken its peg? enum BassetStatus { Default, Normal, BrokenBelowPeg, BrokenAbovePeg, Blacklisted, Liquidating, Liquidated, Failed } struct BasketState { bool undergoingRecol; bool failed; } struct InvariantConfig { uint256 a; WeightLimits limits; } struct WeightLimits { uint128 min; uint128 max; } struct AmpData { uint64 initialA; uint64 targetA; uint64 rampStartTime; uint64 rampEndTime; } } abstract contract IInvariantValidator is MassetStructs { // Mint function computeMint( BassetData[] calldata _bAssets, uint8 _i, uint256 _rawInput, InvariantConfig memory _config ) external view virtual returns (uint256); function computeMintMulti( BassetData[] calldata _bAssets, uint8[] calldata _indices, uint256[] calldata _rawInputs, InvariantConfig memory _config ) external view virtual returns (uint256); // Swap function computeSwap( BassetData[] calldata _bAssets, uint8 _i, uint8 _o, uint256 _rawInput, uint256 _feeRate, InvariantConfig memory _config ) external view virtual returns (uint256, uint256); // Redeem function computeRedeem( BassetData[] calldata _bAssets, uint8 _i, uint256 _mAssetQuantity, InvariantConfig memory _config ) external view virtual returns (uint256); function computeRedeemExact( BassetData[] calldata _bAssets, uint8[] calldata _indices, uint256[] calldata _rawOutputs, InvariantConfig memory _config ) external view virtual returns (uint256); } contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. // constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return payable(msg.sender); } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } contract ERC205 is Context, IERC20 { mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @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: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, 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}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), 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}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - 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) { _approve(_msgSender(), spender, _allowances[_msgSender()][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) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is 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: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, 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: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply += amount; _balances[account] += amount; emit Transfer(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"); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(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); } } abstract contract InitializableERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. * @notice To avoid variable shadowing appended `Arg` after arguments name. */ function _initialize( string memory nameArg, string memory symbolArg, uint8 decimalsArg ) internal { _name = nameArg; _symbol = symbolArg; _decimals = decimalsArg; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view 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. * * 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 returns (uint8) { return _decimals; } } abstract contract InitializableToken is ERC205, InitializableERC20Detailed { /** * @dev Initialization function for implementing contract * @notice To avoid variable shadowing appended `Arg` after arguments name. */ function _initialize(string memory _nameArg, string memory _symbolArg) internal { InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18); } } contract ModuleKeys { // Governance // =========== // keccak256("Governance"); bytes32 internal constant KEY_GOVERNANCE = 0x9409903de1e6fd852dfc61c9dacb48196c48535b60e25abf92acc92dd689078d; //keccak256("Staking"); bytes32 internal constant KEY_STAKING = 0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034; //keccak256("ProxyAdmin"); bytes32 internal constant KEY_PROXY_ADMIN = 0x96ed0203eb7e975a4cbcaa23951943fa35c5d8288117d50c12b3d48b0fab48d1; // mStable // ======= // keccak256("OracleHub"); bytes32 internal constant KEY_ORACLE_HUB = 0x8ae3a082c61a7379e2280f3356a5131507d9829d222d853bfa7c9fe1200dd040; // keccak256("Manager"); bytes32 internal constant KEY_MANAGER = 0x6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f; //keccak256("Recollateraliser"); bytes32 internal constant KEY_RECOLLATERALISER = 0x39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f; //keccak256("MetaToken"); bytes32 internal constant KEY_META_TOKEN = 0xea7469b14936af748ee93c53b2fe510b9928edbdccac3963321efca7eb1a57a2; // keccak256("SavingsManager"); bytes32 internal constant KEY_SAVINGS_MANAGER = 0x12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf1; // keccak256("Liquidator"); bytes32 internal constant KEY_LIQUIDATOR = 0x1e9cb14d7560734a61fa5ff9273953e971ff3cd9283c03d8346e3264617933d4; } interface INexus { function governor() external view returns (address); function getModule(bytes32 key) external view returns (address); function proposeModule(bytes32 _key, address _addr) external; function cancelProposedModule(bytes32 _key) external; function acceptProposedModule(bytes32 _key) external; function acceptProposedModules(bytes32[] calldata _keys) external; function requestLockModule(bytes32 _key) external; function cancelLockModule(bytes32 _key) external; function lockModule(bytes32 _key) external; } abstract contract ImmutableModule is ModuleKeys { INexus public immutable nexus; /** * @dev Initialization function for upgradable proxy contracts * @param _nexus Nexus contract address */ constructor(address _nexus) { require(_nexus != address(0), "Nexus address is zero"); nexus = INexus(_nexus); } /** * @dev Modifier to allow function calls only from the Governor. */ modifier onlyGovernor() { _onlyGovernor(); _; } function _onlyGovernor() internal view { require(msg.sender == _governor(), "Only governor can execute"); } /** * @dev Modifier to allow function calls only from the Governance. * Governance is either Governor address or Governance address. */ modifier onlyGovernance() { require( msg.sender == _governor() || msg.sender == _governance(), "Only governance can execute" ); _; } /** * @dev Modifier to allow function calls only from the ProxyAdmin. */ modifier onlyProxyAdmin() { require(msg.sender == _proxyAdmin(), "Only ProxyAdmin can execute"); _; } /** * @dev Modifier to allow function calls only from the Manager. */ modifier onlyManager() { require(msg.sender == _manager(), "Only manager can execute"); _; } /** * @dev Returns Governor address from the Nexus * @return Address of Governor Contract */ function _governor() internal view returns (address) { return nexus.governor(); } /** * @dev Returns Governance Module address from the Nexus * @return Address of the Governance (Phase 2) */ function _governance() internal view returns (address) { return nexus.getModule(KEY_GOVERNANCE); } /** * @dev Return Staking Module address from the Nexus * @return Address of the Staking Module contract */ function _staking() internal view returns (address) { return nexus.getModule(KEY_STAKING); } /** * @dev Return ProxyAdmin Module address from the Nexus * @return Address of the ProxyAdmin Module contract */ function _proxyAdmin() internal view returns (address) { return nexus.getModule(KEY_PROXY_ADMIN); } /** * @dev Return MetaToken Module address from the Nexus * @return Address of the MetaToken Module contract */ function _metaToken() internal view returns (address) { return nexus.getModule(KEY_META_TOKEN); } /** * @dev Return OracleHub Module address from the Nexus * @return Address of the OracleHub Module contract */ function _oracleHub() internal view returns (address) { return nexus.getModule(KEY_ORACLE_HUB); } /** * @dev Return Manager Module address from the Nexus * @return Address of the Manager Module contract */ function _manager() internal view returns (address) { return nexus.getModule(KEY_MANAGER); } /** * @dev Return SavingsManager Module address from the Nexus * @return Address of the SavingsManager Module contract */ function _savingsManager() internal view returns (address) { return nexus.getModule(KEY_SAVINGS_MANAGER); } /** * @dev Return Recollateraliser Module address from the Nexus * @return Address of the Recollateraliser Module contract (Phase 2) */ function _recollateraliser() internal view returns (address) { return nexus.getModule(KEY_RECOLLATERALISER); } } contract InitializableReentrancyGuard { bool private _notEntered; function _initializeReentrancyGuard() internal { // Storing an initial 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 percetange 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. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } } abstract contract IMasset is MassetStructs { // Mint function mint( address _input, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external virtual returns (uint256 mintOutput); function mintMulti( address[] calldata _inputs, uint256[] calldata _inputQuantities, uint256 _minOutputQuantity, address _recipient ) external virtual returns (uint256 mintOutput); function getMintOutput(address _input, uint256 _inputQuantity) external view virtual returns (uint256 mintOutput); function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities) external view virtual returns (uint256 mintOutput); // Swaps function swap( address _input, address _output, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external virtual returns (uint256 swapOutput); function getSwapOutput( address _input, address _output, uint256 _inputQuantity ) external view virtual returns (uint256 swapOutput); // Redemption function redeem( address _output, uint256 _mAssetQuantity, uint256 _minOutputQuantity, address _recipient ) external virtual returns (uint256 outputQuantity); function redeemMasset( uint256 _mAssetQuantity, uint256[] calldata _minOutputQuantities, address _recipient ) external virtual returns (uint256[] memory outputQuantities); function redeemExactBassets( address[] calldata _outputs, uint256[] calldata _outputQuantities, uint256 _maxMassetQuantity, address _recipient ) external virtual returns (uint256 mAssetRedeemed); function getRedeemOutput(address _output, uint256 _mAssetQuantity) external view virtual returns (uint256 bAssetOutput); function getRedeemExactBassetsOutput( address[] calldata _outputs, uint256[] calldata _outputQuantities ) external view virtual returns (uint256 mAssetAmount); // Views function getBasket() external view virtual returns (bool, bool); function getBasset(address _token) external view virtual returns (BassetPersonal memory personal, BassetData memory data); function getBassets() external view virtual returns (BassetPersonal[] memory personal, BassetData[] memory data); function bAssetIndexes(address) external view virtual returns (uint8); // SavingsManager function collectInterest() external virtual returns (uint256 swapFeesGained, uint256 newSupply); function collectPlatformInterest() external virtual returns (uint256 mintAmount, uint256 newSupply); // Admin function setCacheSize(uint256 _cacheSize) external virtual; function upgradeForgeValidator(address _newForgeValidator) external virtual; function setFees(uint256 _swapFee, uint256 _redemptionFee) external virtual; function setTransferFeesFlag(address _bAsset, bool _flag) external virtual; function migrateBassets(address[] calldata _bAssets, address _newIntegration) external virtual; } abstract contract Deprecated_BasketManager is MassetStructs {} library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { require(value < 2**255, "SafeCast: value doesn't fit in an int256"); return int256(value); } } library StableMath { /** * @dev Scaling unit for use in specific calculations, * where 1 * 10**18, or 1e18 represents a unit '1' */ uint256 private constant FULL_SCALE = 1e18; /** * @dev Token Ratios are used when converting between units of bAsset, mAsset and MTA * Reasoning: Takes into account token decimals, and difference in base unit (i.e. grams to Troy oz for gold) * bAsset ratio unit for use in exact calculations, * where (1 bAsset unit * bAsset.ratio) / ratioScale == x mAsset unit */ uint256 private constant RATIO_SCALE = 1e8; /** * @dev Provides an interface to the scaling unit * @return Scaling unit (1e18 or 1 * 10**18) */ function getFullScale() internal pure returns (uint256) { return FULL_SCALE; } /** * @dev Provides an interface to the ratio unit * @return Ratio scale unit (1e8 or 1 * 10**8) */ function getRatioScale() internal pure returns (uint256) { return RATIO_SCALE; } /** * @dev Scales a given integer to the power of the full scale. * @param x Simple uint256 to scale * @return Scaled value a to an exact number */ function scaleInteger(uint256 x) internal pure returns (uint256) { return x * FULL_SCALE; } /*************************************** PRECISE ARITHMETIC ****************************************/ /** * @dev Multiplies two precise units, and then truncates by the full scale * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) { return mulTruncateScale(x, y, FULL_SCALE); } /** * @dev Multiplies two precise units, and then truncates by the given scale. For example, * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18 * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @param scale Scale unit * @return Result after multiplying the two inputs and then dividing by the shared * scale unit */ function mulTruncateScale( uint256 x, uint256 y, uint256 scale ) internal pure returns (uint256) { // e.g. assume scale = fullScale // z = 10e18 * 9e17 = 9e36 // return 9e38 / 1e18 = 9e18 return (x * y) / scale; } /** * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result * @param x Left hand input to multiplication * @param y Right hand input to multiplication * @return Result after multiplying the two inputs and then dividing by the shared * scale unit, rounded up to the closest base unit. */ function mulTruncateCeil(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e17 * 17268172638 = 138145381104e17 uint256 scaled = x * y; // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17 uint256 ceil = scaled + FULL_SCALE - 1; // e.g. 13814538111.399...e18 / 1e18 = 13814538111 return ceil / FULL_SCALE; } /** * @dev Precisely divides two units, by first scaling the left hand operand. Useful * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17) * @param x Left hand input to division * @param y Right hand input to division * @return Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divPrecisely(uint256 x, uint256 y) internal pure returns (uint256) { // e.g. 8e18 * 1e18 = 8e36 // e.g. 8e36 / 10e18 = 8e17 return (x * FULL_SCALE) / y; } /*************************************** RATIO FUNCS ****************************************/ /** * @dev Multiplies and truncates a token ratio, essentially flooring the result * i.e. How much mAsset is this bAsset worth? * @param x Left hand operand to multiplication (i.e Exact quantity) * @param ratio bAsset ratio * @return c Result after multiplying the two inputs and then dividing by the ratio scale */ function mulRatioTruncate(uint256 x, uint256 ratio) internal pure returns (uint256 c) { return mulTruncateScale(x, ratio, RATIO_SCALE); } /** * @dev Multiplies and truncates a token ratio, rounding up the result * i.e. How much mAsset is this bAsset worth? * @param x Left hand input to multiplication (i.e Exact quantity) * @param ratio bAsset ratio * @return Result after multiplying the two inputs and then dividing by the shared * ratio scale, rounded up to the closest base unit. */ function mulRatioTruncateCeil(uint256 x, uint256 ratio) internal pure returns (uint256) { // e.g. How much mAsset should I burn for this bAsset (x)? // 1e18 * 1e8 = 1e26 uint256 scaled = x * ratio; // 1e26 + 9.99e7 = 100..00.999e8 uint256 ceil = scaled + RATIO_SCALE - 1; // return 100..00.999e8 / 1e8 = 1e18 return ceil / RATIO_SCALE; } /** * @dev Precisely divides two ratioed units, by first scaling the left hand operand * i.e. How much bAsset is this mAsset worth? * @param x Left hand operand in division * @param ratio bAsset ratio * @return c Result after multiplying the left operand by the scale, and * executing the division on the right hand input. */ function divRatioPrecisely(uint256 x, uint256 ratio) internal pure returns (uint256 c) { // e.g. 1e14 * 1e8 = 1e22 // return 1e22 / 1e12 = 1e10 return (x * RATIO_SCALE) / ratio; } /*************************************** HELPERS ****************************************/ /** * @dev Calculates minimum of two numbers * @param x Left hand input * @param y Right hand input * @return Minimum of the two inputs */ function min(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? y : x; } /** * @dev Calculated maximum of two numbers * @param x Left hand input * @param y Right hand input * @return Maximum of the two inputs */ function max(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? x : y; } /** * @dev Clamps a value to an upper bound * @param x Left hand input * @param upperBound Maximum possible value to return * @return Input x clamped to a maximum value, upperBound */ function clamp(uint256 x, uint256 upperBound) internal pure returns (uint256) { return x > upperBound ? upperBound : x; } } interface IPlatformIntegration { /** * @dev Deposit the given bAsset to Lending platform * @param _bAsset bAsset address * @param _amount Amount to deposit */ function deposit( address _bAsset, uint256 _amount, bool isTokenFeeCharged ) external returns (uint256 quantityDeposited); /** * @dev Withdraw given bAsset from Lending platform */ function withdraw( address _receiver, address _bAsset, uint256 _amount, bool _hasTxFee ) external; /** * @dev Withdraw given bAsset from Lending platform */ function withdraw( address _receiver, address _bAsset, uint256 _amount, uint256 _totalAmount, bool _hasTxFee ) external; /** * @dev Withdraw given bAsset from the cache */ function withdrawRaw( address _receiver, address _bAsset, uint256 _amount ) external; /** * @dev Returns the current balance of the given bAsset */ function checkBalance(address _bAsset) external returns (uint256 balance); /** * @dev Returns the pToken */ function bAssetToPToken(address _bAsset) external returns (address pToken); } interface IBasicToken { function decimals() external view returns (uint8); } /** * @dev Interface of the ERC20 standard as defined in the EIP. */ /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } 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' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + 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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } library MassetHelpers { using SafeERC20 for IERC20; function transferReturnBalance( address _sender, address _recipient, address _bAsset, uint256 _qty ) internal returns (uint256 receivedQty, uint256 recipientBalance) { uint256 balBefore = IERC20(_bAsset).balanceOf(_recipient); IERC20(_bAsset).safeTransferFrom(_sender, _recipient, _qty); recipientBalance = IERC20(_bAsset).balanceOf(_recipient); receivedQty = recipientBalance - balBefore; } function safeInfiniteApprove(address _asset, address _spender) internal { IERC20(_asset).safeApprove(_spender, 0); IERC20(_asset).safeApprove(_spender, 2**256 - 1); } } library Manager { using SafeERC20 for IERC20; using StableMath for uint256; event BassetsMigrated(address[] bAssets, address newIntegrator); event TransferFeeEnabled(address indexed bAsset, bool enabled); event BassetAdded(address indexed bAsset, address integrator); event BassetStatusChanged(address indexed bAsset, MassetStructs.BassetStatus status); event BasketStatusChanged(); event StartRampA(uint256 currentA, uint256 targetA, uint256 startTime, uint256 rampEndTime); event StopRampA(uint256 currentA, uint256 time); uint256 private constant MIN_RAMP_TIME = 1 days; uint256 private constant MAX_A = 1e6; /** * @notice Adds a bAsset to the given personal, data and mapping, provided it is valid * @param _bAssetPersonal Basset data storage array * @param _bAssetData Basset data storage array * @param _bAssetIndexes Mapping of bAsset address to their index * @param _maxBassets Max size of the basket * @param _bAsset Address of the ERC20 token to add to the Basket * @param _integration Address of the Platform Integration * @param _mm Base 1e8 var to determine measurement ratio * @param _hasTxFee Are transfer fees charged on this bAsset (e.g. USDT) */ function addBasset( MassetStructs.BassetPersonal[] storage _bAssetPersonal, MassetStructs.BassetData[] storage _bAssetData, mapping(address => uint8) storage _bAssetIndexes, uint8 _maxBassets, address _bAsset, address _integration, uint256 _mm, bool _hasTxFee ) external { require(_bAsset != address(0), "bAsset address must be valid"); uint8 bAssetCount = uint8(_bAssetPersonal.length); require(bAssetCount < _maxBassets, "Max bAssets in Basket"); uint8 idx = _bAssetIndexes[_bAsset]; require( bAssetCount == 0 || _bAssetPersonal[idx].addr != _bAsset, "bAsset already exists in Basket" ); // Should fail if bAsset is not added to integration // Programmatic enforcement of bAsset validity should service through decentralised feed if (_integration != address(0)) { IPlatformIntegration(_integration).checkBalance(_bAsset); } uint256 bAssetDecimals = IBasicToken(_bAsset).decimals(); require( bAssetDecimals >= 4 && bAssetDecimals <= 18, "Token must have sufficient decimal places" ); uint256 delta = uint256(18) - bAssetDecimals; uint256 ratio = _mm * (10**delta); _bAssetIndexes[_bAsset] = bAssetCount; _bAssetPersonal.push( MassetStructs.BassetPersonal({ addr: _bAsset, integrator: _integration, hasTxFee: _hasTxFee, status: MassetStructs.BassetStatus.Normal }) ); _bAssetData.push( MassetStructs.BassetData({ ratio: SafeCast.toUint128(ratio), vaultBalance: 0 }) ); emit BassetAdded(_bAsset, _integration); } /** * @dev Collects the interest generated from the Basket, minting a relative * amount of mAsset and sending it over to the SavingsManager. * @param _bAssetPersonal Basset personal storage array * @param _bAssetData Basset data storage array * @param _forgeValidator Link to the current InvariantValidator * @return mintAmount Lending market interest collected * @return rawGains Raw increases in vault Balance */ function collectPlatformInterest( MassetStructs.BassetPersonal[] memory _bAssetPersonal, MassetStructs.BassetData[] storage _bAssetData, IInvariantValidator _forgeValidator, MassetStructs.InvariantConfig memory _config ) external returns (uint256 mintAmount, uint256[] memory rawGains) { // Get basket details MassetStructs.BassetData[] memory bAssetData_ = _bAssetData; uint256 count = bAssetData_.length; uint8[] memory indices = new uint8[](count); rawGains = new uint256[](count); // 1. Calculate rawGains in each bAsset, in comparison to current vault balance for (uint256 i = 0; i < count; i++) { indices[i] = uint8(i); MassetStructs.BassetPersonal memory bPersonal = _bAssetPersonal[i]; MassetStructs.BassetData memory bData = bAssetData_[i]; // If there is no integration, then nothing can have accrued if (bPersonal.integrator == address(0)) continue; uint256 lending = IPlatformIntegration(bPersonal.integrator).checkBalance(bPersonal.addr); uint256 cache = 0; if (!bPersonal.hasTxFee) { cache = IERC20(bPersonal.addr).balanceOf(bPersonal.integrator); } uint256 balance = lending + cache; uint256 oldVaultBalance = bData.vaultBalance; if ( balance > oldVaultBalance && bPersonal.status == MassetStructs.BassetStatus.Normal ) { _bAssetData[i].vaultBalance = SafeCast.toUint128(balance); uint256 interestDelta = balance - oldVaultBalance; rawGains[i] = interestDelta; } else { rawGains[i] = 0; } } mintAmount = _forgeValidator.computeMintMulti(bAssetData_, indices, rawGains, _config); } /** * @dev Update transfer fee flag for a given bAsset, should it change its fee practice * @param _bAssetPersonal Basset data storage array * @param _bAssetIndexes Mapping of bAsset address to their index * @param _bAsset bAsset address * @param _flag Charge transfer fee when its set to 'true', otherwise 'false' */ function setTransferFeesFlag( MassetStructs.BassetPersonal[] storage _bAssetPersonal, mapping(address => uint8) storage _bAssetIndexes, address _bAsset, bool _flag ) external { uint256 index = _getAssetIndex(_bAssetPersonal, _bAssetIndexes, _bAsset); _bAssetPersonal[index].hasTxFee = _flag; if (_flag) { // if token has tx fees, it can no longer operate with a cache address integration = _bAssetPersonal[index].integrator; if (integration != address(0)) { uint256 bal = IERC20(_bAsset).balanceOf(integration); if (bal > 0) { IPlatformIntegration(integration).deposit(_bAsset, bal, true); } } } emit TransferFeeEnabled(_bAsset, _flag); } /** * @dev Transfers all collateral from one lending market to another - used initially * to handle the migration between Aave V1 and Aave V2. Note - only supports non * tx fee enabled assets. Supports going from no integration to integration, but * not the other way around. * @param _bAssetPersonal Basset data storage array * @param _bAssetIndexes Mapping of bAsset address to their index * @param _bAssets Array of basket assets to migrate * @param _newIntegration Address of the new platform integration */ function migrateBassets( MassetStructs.BassetPersonal[] storage _bAssetPersonal, mapping(address => uint8) storage _bAssetIndexes, address[] calldata _bAssets, address _newIntegration ) external { uint256 len = _bAssets.length; require(len > 0, "Must migrate some bAssets"); for (uint256 i = 0; i < len; i++) { // 1. Check that the bAsset is in the basket address bAsset = _bAssets[i]; uint256 index = _getAssetIndex(_bAssetPersonal, _bAssetIndexes, bAsset); require(!_bAssetPersonal[index].hasTxFee, "A bAsset has a transfer fee"); // 2. Withdraw everything from the old platform integration address oldAddress = _bAssetPersonal[index].integrator; require(oldAddress != _newIntegration, "Must transfer to new integrator"); (uint256 cache, uint256 lendingBal) = (0, 0); if (oldAddress == address(0)) { cache = IERC20(bAsset).balanceOf(address(this)); } else { IPlatformIntegration oldIntegration = IPlatformIntegration(oldAddress); cache = IERC20(bAsset).balanceOf(address(oldIntegration)); // 2.1. Withdraw from the lending market lendingBal = oldIntegration.checkBalance(bAsset); if (lendingBal > 0) { oldIntegration.withdraw(address(this), bAsset, lendingBal, false); } // 2.2. Withdraw from the cache, if any if (cache > 0) { oldIntegration.withdrawRaw(address(this), bAsset, cache); } } uint256 sum = lendingBal + cache; // 3. Update the integration address for this bAsset _bAssetPersonal[index].integrator = _newIntegration; // 4. Deposit everything into the new // This should fail if we did not receive the full amount from the platform withdrawal // 4.1. Deposit all bAsset IERC20(bAsset).safeTransfer(_newIntegration, sum); IPlatformIntegration newIntegration = IPlatformIntegration(_newIntegration); if (lendingBal > 0) { newIntegration.deposit(bAsset, lendingBal, false); } // 4.2. Check balances uint256 newLendingBal = newIntegration.checkBalance(bAsset); uint256 newCache = IERC20(bAsset).balanceOf(address(newIntegration)); uint256 upperMargin = 10001e14; uint256 lowerMargin = 9999e14; require( newLendingBal >= lendingBal.mulTruncate(lowerMargin) && newLendingBal <= lendingBal.mulTruncate(upperMargin), "Must transfer full amount" ); require( newCache >= cache.mulTruncate(lowerMargin) && newCache <= cache.mulTruncate(upperMargin), "Must transfer full amount" ); } emit BassetsMigrated(_bAssets, _newIntegration); } /** * @dev Executes the Auto Redistribution event by isolating the bAsset from the Basket * @param _basket Struct containing core basket info * @param _bAssetPersonal Basset data storage array * @param _bAsset Address of the ERC20 token to isolate * @param _belowPeg Bool to describe whether the bAsset deviated below peg (t) * or above (f) */ function handlePegLoss( MassetStructs.BasketState storage _basket, MassetStructs.BassetPersonal[] storage _bAssetPersonal, mapping(address => uint8) storage _bAssetIndexes, address _bAsset, bool _belowPeg ) external { require(!_basket.failed, "Basket must be alive"); uint256 i = _getAssetIndex(_bAssetPersonal, _bAssetIndexes, _bAsset); MassetStructs.BassetStatus newStatus = _belowPeg ? MassetStructs.BassetStatus.BrokenBelowPeg : MassetStructs.BassetStatus.BrokenAbovePeg; _bAssetPersonal[i].status = newStatus; _basket.undergoingRecol = true; emit BassetStatusChanged(_bAsset, newStatus); } /** * @dev Negates the isolation of a given bAsset * @param _basket Struct containing core basket info * @param _bAssetPersonal Basset data storage array * @param _bAssetIndexes Mapping of bAsset address to their index * @param _bAsset Address of the bAsset */ function negateIsolation( MassetStructs.BasketState storage _basket, MassetStructs.BassetPersonal[] storage _bAssetPersonal, mapping(address => uint8) storage _bAssetIndexes, address _bAsset ) external { uint256 i = _getAssetIndex(_bAssetPersonal, _bAssetIndexes, _bAsset); _bAssetPersonal[i].status = MassetStructs.BassetStatus.Normal; bool undergoingRecol = false; for (uint256 j = 0; j < _bAssetPersonal.length; j++) { if (_bAssetPersonal[j].status != MassetStructs.BassetStatus.Normal) { undergoingRecol = true; break; } } _basket.undergoingRecol = undergoingRecol; emit BassetStatusChanged(_bAsset, MassetStructs.BassetStatus.Normal); } /** * @dev Starts changing of the amplification var A * @param _targetA Target A value * @param _rampEndTime Time at which A will arrive at _targetA */ function startRampA( MassetStructs.AmpData storage _ampData, uint256 _targetA, uint256 _rampEndTime, uint256 _currentA, uint256 _precision ) external { require( block.timestamp >= (_ampData.rampStartTime + MIN_RAMP_TIME), "Sufficient period of previous ramp has not elapsed" ); require(_rampEndTime >= (block.timestamp + MIN_RAMP_TIME), "Ramp time too short"); require(_targetA > 0 && _targetA < MAX_A, "A target out of bounds"); uint256 preciseTargetA = _targetA * _precision; if (preciseTargetA > _currentA) { require(preciseTargetA <= _currentA * 10, "A target increase too big"); } else { require(preciseTargetA >= _currentA / 10, "A target decrease too big"); } _ampData.initialA = SafeCast.toUint64(_currentA); _ampData.targetA = SafeCast.toUint64(preciseTargetA); _ampData.rampStartTime = SafeCast.toUint64(block.timestamp); _ampData.rampEndTime = SafeCast.toUint64(_rampEndTime); emit StartRampA(_currentA, preciseTargetA, block.timestamp, _rampEndTime); } /** * @dev Stops the changing of the amplification var A, setting * it to whatever the current value is. */ function stopRampA(MassetStructs.AmpData storage _ampData, uint256 _currentA) external { require(block.timestamp < _ampData.rampEndTime, "Amplification not changing"); _ampData.initialA = SafeCast.toUint64(_currentA); _ampData.targetA = SafeCast.toUint64(_currentA); _ampData.rampStartTime = SafeCast.toUint64(block.timestamp); _ampData.rampEndTime = SafeCast.toUint64(block.timestamp); emit StopRampA(_currentA, block.timestamp); } /** * @dev Gets a bAsset index from storage * @param _asset Address of the asset * @return idx Index of the asset */ function _getAssetIndex( MassetStructs.BassetPersonal[] storage _bAssetPersonal, mapping(address => uint8) storage _bAssetIndexes, address _asset ) internal view returns (uint8 idx) { idx = _bAssetIndexes[_asset]; require(_bAssetPersonal[idx].addr == _asset, "Invalid asset input"); } /*************************************** FORGING ****************************************/ /** * @dev Deposits a given asset to the system. If there is sufficient room for the asset * in the cache, then just transfer, otherwise reset the cache to the desired mid level by * depositing the delta in the platform */ function depositTokens( MassetStructs.BassetPersonal memory _bAsset, uint256 _bAssetRatio, uint256 _quantity, uint256 _maxCache ) external returns (uint256 quantityDeposited) { // 0. If integration is 0, short circuit if (_bAsset.integrator == address(0)) { (uint256 received, ) = MassetHelpers.transferReturnBalance( msg.sender, address(this), _bAsset.addr, _quantity ); return received; } // 1 - Send all to PI, using the opportunity to get the cache balance and net amount transferred uint256 cacheBal; (quantityDeposited, cacheBal) = MassetHelpers.transferReturnBalance( msg.sender, _bAsset.integrator, _bAsset.addr, _quantity ); // 2 - Deposit X if necessary // 2.1 - Deposit if xfer fees if (_bAsset.hasTxFee) { uint256 deposited = IPlatformIntegration(_bAsset.integrator).deposit( _bAsset.addr, quantityDeposited, true ); return StableMath.min(deposited, quantityDeposited); } // 2.2 - Else Deposit X if Cache > % // This check is in place to ensure that any token with a txFee is rejected require(quantityDeposited == _quantity, "Asset not fully transferred"); uint256 relativeMaxCache = _maxCache.divRatioPrecisely(_bAssetRatio); if (cacheBal > relativeMaxCache) { uint256 delta = cacheBal - (relativeMaxCache / 2); IPlatformIntegration(_bAsset.integrator).deposit(_bAsset.addr, delta, false); } } /** * @dev Withdraws a given asset from its platformIntegration. If there is sufficient liquidity * in the cache, then withdraw from there, otherwise withdraw from the lending market and reset the * cache to the mid level. */ function withdrawTokens( uint256 _quantity, MassetStructs.BassetPersonal memory _personal, MassetStructs.BassetData memory _data, address _recipient, uint256 _maxCache ) external { if (_quantity == 0) return; // 1.0 If there is no integrator, send from here if (_personal.integrator == address(0)) { IERC20(_personal.addr).safeTransfer(_recipient, _quantity); } // 1.1 If txFee then short circuit - there is no cache else if (_personal.hasTxFee) { IPlatformIntegration(_personal.integrator).withdraw( _recipient, _personal.addr, _quantity, _quantity, true ); } // 1.2. Else, withdraw from either cache or main vault else { uint256 cacheBal = IERC20(_personal.addr).balanceOf(_personal.integrator); // 2.1 - If balance b in cache, simply withdraw if (cacheBal >= _quantity) { IPlatformIntegration(_personal.integrator).withdrawRaw( _recipient, _personal.addr, _quantity ); } // 2.2 - Else reset the cache to X, or as far as possible // - Withdraw X+b from platform // - Send b to user else { uint256 relativeMidCache = _maxCache.divRatioPrecisely(_data.ratio) / 2; uint256 totalWithdrawal = StableMath.min( relativeMidCache + _quantity - cacheBal, _data.vaultBalance - SafeCast.toUint128(cacheBal) ); IPlatformIntegration(_personal.integrator).withdraw( _recipient, _personal.addr, _quantity, totalWithdrawal, false ); } } } } struct Basket { Basset[] bassets; uint8 maxBassets; bool undergoingRecol; bool failed; uint256 collateralisationRatio; } interface IBasketManager { function getBassetIntegrator(address _bAsset) external view returns (address integrator); function getBasket() external view returns (Basket memory b); } struct Basset { address addr; BassetStatus status; bool isTransferFeeCharged; uint256 ratio; uint256 maxWeight; uint256 vaultBalance; } library Migrator { function upgrade( IBasketManager basketManager, MassetStructs.BassetPersonal[] storage bAssetPersonal, MassetStructs.BassetData[] storage bAssetData, mapping(address => uint8) storage bAssetIndexes ) external { Basket memory importedBasket = basketManager.getBasket(); uint256 len = importedBasket.bassets.length; uint256[] memory scaledVaultBalances = new uint[](len); uint256 maxScaledVaultBalance; for (uint8 i = 0; i < len; i++) { Basset memory bAsset = importedBasket.bassets[i]; address bAssetAddress = bAsset.addr; bAssetIndexes[bAssetAddress] = i; address integratorAddress = basketManager.getBassetIntegrator(bAssetAddress); bAssetPersonal.push( MassetStructs.BassetPersonal({ addr: bAssetAddress, integrator: integratorAddress, hasTxFee: false, status: MassetStructs.BassetStatus.Normal }) ); uint128 ratio = SafeCast.toUint128(bAsset.ratio); uint128 vaultBalance = SafeCast.toUint128(bAsset.vaultBalance); bAssetData.push( MassetStructs.BassetData({ ratio: ratio, vaultBalance: vaultBalance }) ); // caclulate scaled vault bAsset balance and totoal vault balance uint128 scaledVaultBalance = (vaultBalance * ratio) / 1e8; scaledVaultBalances[i] = scaledVaultBalance; maxScaledVaultBalance += scaledVaultBalance; } // Check each bAsset is under 25.01% weight uint256 maxWeight = 2501; if(len == 3){ maxWeight = 3334; } else if (len != 4){ revert("Invalid length"); } maxScaledVaultBalance = maxScaledVaultBalance * 2501 / 10000; for (uint8 i = 0; i < len; i++) { require(scaledVaultBalances[i] < maxScaledVaultBalance, "imbalanced"); } } } /** * @notice Is the Masset V2.0 structs used in the upgrade of mUSD from V2.0 to V3.0. * @author mStable * @dev VERSION: 2.0 * DATE: 2021-02-23 */ /** @dev Stores high level basket info */ /** @dev Stores bAsset info. The struct takes 5 storage slots per Basset */ /** @dev Status of the Basset - has it broken its peg? */ enum BassetStatus { Default, Normal, BrokenBelowPeg, BrokenAbovePeg, Blacklisted, Liquidating, Liquidated, Failed } /** @dev Internal details on Basset */ struct BassetDetails { Basset bAsset; address integrator; uint8 index; } contract InitializableModuleKeysV2 { // Governance // Phases bytes32 private KEY_GOVERNANCE_DEPRICATED; // 2.x bytes32 private KEY_STAKING_DEPRICATED; // 1.2 bytes32 private KEY_PROXY_ADMIN_DEPRICATED; // 1.0 // mStable bytes32 private KEY_ORACLE_HUB_DEPRICATED; // 1.2 bytes32 private KEY_MANAGER_DEPRICATED; // 1.2 bytes32 private KEY_RECOLLATERALISER_DEPRICATED; // 2.x bytes32 private KEY_META_TOKEN_DEPRICATED; // 1.1 bytes32 private KEY_SAVINGS_MANAGER_DEPRICATED; // 1.0 } contract InitializableModuleV2 is InitializableModuleKeysV2 { address private nexus_depricated; } // External // Internal // Libs // Legacy /** * @title Masset used to migrate mUSD from V2.0 to V3.0 * @author mStable * @notice An incentivised constant sum market maker with hard limits at max region. This supports * low slippage swaps and applies penalties towards min and max regions. AMM produces a * stablecoin (mAsset) and redirects lending market interest and swap fees to the savings * contract, producing a second yield bearing asset. * @dev VERSION: 3.0 * DATE: 2021-01-22 */ contract MusdV3 is IMasset, Initializable, InitializableToken, InitializableModuleV2, InitializableReentrancyGuard, ImmutableModule { using StableMath for uint256; // Forging Events event Minted( address indexed minter, address recipient, uint256 mAssetQuantity, address input, uint256 inputQuantity ); event MintedMulti( address indexed minter, address recipient, uint256 mAssetQuantity, address[] inputs, uint256[] inputQuantities ); event Swapped( address indexed swapper, address input, address output, uint256 outputAmount, uint256 scaledFee, address recipient ); event Redeemed( address indexed redeemer, address recipient, uint256 mAssetQuantity, address output, uint256 outputQuantity, uint256 scaledFee ); event RedeemedMulti( address indexed redeemer, address recipient, uint256 mAssetQuantity, address[] outputs, uint256[] outputQuantity, uint256 scaledFee ); // State Events event CacheSizeChanged(uint256 cacheSize); event FeesChanged(uint256 swapFee, uint256 redemptionFee); event WeightLimitsChanged(uint128 min, uint128 max); event ForgeValidatorChanged(address forgeValidator); // Release 1.0 VARS IInvariantValidator public forgeValidator; bool private forgeValidatorLocked; // Deprecated - maintain for storage layout in mUSD address private deprecated_basketManager; // Basic redemption fee information uint256 public swapFee; uint256 private MAX_FEE; // Release 1.1 VARS uint256 public redemptionFee; // Release 2.0 VARS uint256 public cacheSize; uint256 public surplus; // Release 3.0 VARS // Struct holding Basket details BassetPersonal[] public bAssetPersonal; BassetData[] public bAssetData; mapping(address => uint8) public override bAssetIndexes; uint8 public maxBassets; BasketState public basket; // Amplification Data uint256 private constant A_PRECISION = 100; AmpData public ampData; WeightLimits public weightLimits; /** * @dev Constructor to set immutable bytecode * @param _nexus Nexus address */ constructor(address _nexus) ImmutableModule(_nexus) {} /** * @dev Upgrades mUSD from v2.0 to v3.0. * This function should be called via Proxy just after the proxy has been updated. * @param _forgeValidator Address of the AMM implementation * @param _config Configutation for the invariant validator including the * amplification coefficient (A) and weight limits */ function upgrade( address _forgeValidator, InvariantConfig memory _config ) public { // prevent upgrade being run again by checking the old basket manager require(deprecated_basketManager != address(0), "already upgraded"); // Read the Basket Manager details from the mUSD proxy's storage into memory IBasketManager basketManager = IBasketManager(deprecated_basketManager); // Update the storage of the Basket Manager in the mUSD Proxy deprecated_basketManager = address(0); // Set the state to be undergoingRecol in order to pause after upgrade basket.undergoingRecol = true; forgeValidator = IInvariantValidator(_forgeValidator); Migrator.upgrade(basketManager, bAssetPersonal, bAssetData, bAssetIndexes); // Set new V3.0 storage variables maxBassets = 10; uint64 startA = SafeCast.toUint64(_config.a * A_PRECISION); ampData = AmpData(startA, startA, 0, 0); weightLimits = _config.limits; } /** * @dev Verifies that the caller is the Savings Manager contract */ modifier onlySavingsManager() { _isSavingsManager(); _; } // Internal fn for modifier to reduce deployment size function _isSavingsManager() internal view { require(_savingsManager() == msg.sender, "Must be savings manager"); } /** * @dev Requires the overall basket composition to be healthy */ modifier whenHealthy() { _isHealthy(); _; } // Internal fn for modifier to reduce deployment size function _isHealthy() internal view { BasketState memory basket_ = basket; require(!basket_.undergoingRecol && !basket_.failed, "Unhealthy"); } /** * @dev Requires the basket not to be undergoing recollateralisation */ modifier whenNoRecol() { _noRecol(); _; } // Internal fn for modifier to reduce deployment size function _noRecol() internal view { BasketState memory basket_ = basket; require(!basket_.undergoingRecol, "In recol"); } /*************************************** MINTING (PUBLIC) ****************************************/ /** * @dev Mint a single bAsset, at a 1:1 ratio with the bAsset. This contract * must have approval to spend the senders bAsset * @param _input Address of the bAsset to deposit for the minted mAsset. * @param _inputQuantity Quantity in bAsset units * @param _minOutputQuantity Minimum mAsset quanity to be minted. This protects against slippage. * @param _recipient Receipient of the newly minted mAsset tokens * @return mintOutput Quantity of newly minted mAssets for the deposited bAsset. */ function mint( address _input, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenHealthy returns (uint256 mintOutput) { mintOutput = _mintTo(_input, _inputQuantity, _minOutputQuantity, _recipient); } /** * @dev Mint with multiple bAssets, at a 1:1 ratio to mAsset. This contract * must have approval to spend the senders bAssets * @param _inputs Non-duplicate address array of bASset addresses to deposit for the minted mAsset tokens. * @param _inputQuantities Quantity of each bAsset to deposit for the minted mAsset. * Order of array should mirror the above bAsset addresses. * @param _minOutputQuantity Minimum mAsset quanity to be minted. This protects against slippage. * @param _recipient Address to receive the newly minted mAsset tokens * @return mintOutput Quantity of newly minted mAssets for the deposited bAssets. */ function mintMulti( address[] calldata _inputs, uint256[] calldata _inputQuantities, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenHealthy returns (uint256 mintOutput) { mintOutput = _mintMulti(_inputs, _inputQuantities, _minOutputQuantity, _recipient); } /** * @dev Get the projected output of a given mint * @param _input Address of the bAsset to deposit for the minted mAsset * @param _inputQuantity Quantity in bAsset units * @return mintOutput Estimated mint output in mAsset terms */ function getMintOutput(address _input, uint256 _inputQuantity) external view override returns (uint256 mintOutput) { require(_inputQuantity > 0, "Qty==0"); (uint8 idx, ) = _getAsset(_input); mintOutput = forgeValidator.computeMint(bAssetData, idx, _inputQuantity, _getConfig()); } /** * @dev Get the projected output of a given mint * @param _inputs Non-duplicate address array of addresses to bAssets to deposit for the minted mAsset tokens. * @param _inputQuantities Quantity of each bAsset to deposit for the minted mAsset. * @return mintOutput Estimated mint output in mAsset terms */ function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities) external view override returns (uint256 mintOutput) { uint256 len = _inputQuantities.length; require(len > 0 && len == _inputs.length, "Input array mismatch"); (uint8[] memory indexes, ) = _getBassets(_inputs); return forgeValidator.computeMintMulti(bAssetData, indexes, _inputQuantities, _getConfig()); } /*************************************** MINTING (INTERNAL) ****************************************/ /** @dev Mint Single */ function _mintTo( address _input, uint256 _inputQuantity, uint256 _minMassetQuantity, address _recipient ) internal returns (uint256 mAssetMinted) { require(_recipient != address(0), "Invalid recipient"); require(_inputQuantity > 0, "Qty==0"); BassetData[] memory allBassets = bAssetData; (uint8 bAssetIndex, BassetPersonal memory personal) = _getAsset(_input); Cache memory cache = _getCacheDetails(); // Transfer collateral to the platform integration address and call deposit uint256 quantityDeposited = Manager.depositTokens( personal, allBassets[bAssetIndex].ratio, _inputQuantity, cache.maxCache ); // Validation should be after token transfer, as bAssetQty is unknown before mAssetMinted = forgeValidator.computeMint( allBassets, bAssetIndex, quantityDeposited, _getConfig() ); require(mAssetMinted >= _minMassetQuantity, "Mint quantity < min qty"); // Log the Vault increase - can only be done when basket is healthy bAssetData[bAssetIndex].vaultBalance = allBassets[bAssetIndex].vaultBalance + SafeCast.toUint128(quantityDeposited); // Mint the Masset _mint(_recipient, mAssetMinted); emit Minted(msg.sender, _recipient, mAssetMinted, _input, quantityDeposited); } /** @dev Mint Multi */ function _mintMulti( address[] memory _inputs, uint256[] memory _inputQuantities, uint256 _minMassetQuantity, address _recipient ) internal returns (uint256 mAssetMinted) { require(_recipient != address(0), "Invalid recipient"); uint256 len = _inputQuantities.length; require(len > 0 && len == _inputs.length, "Input array mismatch"); // Load bAssets from storage into memory (uint8[] memory indexes, BassetPersonal[] memory personals) = _getBassets(_inputs); BassetData[] memory allBassets = bAssetData; Cache memory cache = _getCacheDetails(); uint256[] memory quantitiesDeposited = new uint256[](len); // Transfer the Bassets to the integrator, update storage and calc MassetQ for (uint256 i = 0; i < len; i++) { uint256 bAssetQuantity = _inputQuantities[i]; if (bAssetQuantity > 0) { uint8 idx = indexes[i]; BassetData memory data = allBassets[idx]; BassetPersonal memory personal = personals[i]; uint256 quantityDeposited = Manager.depositTokens(personal, data.ratio, bAssetQuantity, cache.maxCache); quantitiesDeposited[i] = quantityDeposited; bAssetData[idx].vaultBalance = data.vaultBalance + SafeCast.toUint128(quantityDeposited); } } // Validate the proposed mint, after token transfer mAssetMinted = forgeValidator.computeMintMulti( allBassets, indexes, quantitiesDeposited, _getConfig() ); require(mAssetMinted >= _minMassetQuantity, "Mint quantity < min qty"); require(mAssetMinted > 0, "Zero mAsset quantity"); // Mint the Masset _mint(_recipient, mAssetMinted); emit MintedMulti(msg.sender, _recipient, mAssetMinted, _inputs, _inputQuantities); } /*************************************** SWAP (PUBLIC) ****************************************/ /** * @dev Swaps one bAsset for another bAsset using the bAsset addresses. * bAsset <> bAsset swaps will incur a small fee (swapFee()). * @param _input Address of bAsset to deposit * @param _output Address of bAsset to receive * @param _inputQuantity Units of input bAsset to swap * @param _minOutputQuantity Minimum quantity of the swap output asset. This protects against slippage * @param _recipient Address to transfer output asset to * @return swapOutput Quantity of output asset returned from swap */ function swap( address _input, address _output, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenHealthy returns (uint256 swapOutput) { swapOutput = _swap(_input, _output, _inputQuantity, _minOutputQuantity, _recipient); } /** * @dev Determines both if a trade is valid, and the expected fee or output. * Swap is valid if it does not result in the input asset exceeding its maximum weight. * @param _input Address of bAsset to deposit * @param _output Address of bAsset to receive * @param _inputQuantity Units of input bAsset to swap * @return swapOutput Quantity of output asset returned from swap */ function getSwapOutput( address _input, address _output, uint256 _inputQuantity ) external view override returns (uint256 swapOutput) { require(_input != _output, "Invalid pair"); require(_inputQuantity > 0, "Invalid swap quantity"); // 1. Load the bAssets from storage into memory BassetData[] memory allBassets = bAssetData; (uint8 inputIdx, ) = _getAsset(_input); (uint8 outputIdx, ) = _getAsset(_output); // 2. If a bAsset swap, calculate the validity, output and fee (swapOutput, ) = forgeValidator.computeSwap( allBassets, inputIdx, outputIdx, _inputQuantity, swapFee, _getConfig() ); } /*************************************** SWAP (INTERNAL) ****************************************/ /** @dev Swap single */ function _swap( address _input, address _output, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) internal returns (uint256 swapOutput) { require(_recipient != address(0), "Invalid recipient"); require(_input != _output, "Invalid pair"); require(_inputQuantity > 0, "Invalid swap quantity"); // 1. Load the bAssets from storage into memory BassetData[] memory allBassets = bAssetData; (uint8 inputIdx, BassetPersonal memory inputPersonal) = _getAsset(_input); (uint8 outputIdx, BassetPersonal memory outputPersonal) = _getAsset(_output); // 2. Load cache Cache memory cache = _getCacheDetails(); // 3. Deposit the input tokens uint256 quantityDeposited = Manager.depositTokens( inputPersonal, allBassets[inputIdx].ratio, _inputQuantity, cache.maxCache ); // 3.1. Update the input balance bAssetData[inputIdx].vaultBalance = allBassets[inputIdx].vaultBalance + SafeCast.toUint128(quantityDeposited); // 3. Validate the swap uint256 scaledFee; (swapOutput, scaledFee) = forgeValidator.computeSwap( allBassets, inputIdx, outputIdx, quantityDeposited, swapFee, _getConfig() ); require(swapOutput >= _minOutputQuantity, "Output qty < minimum qty"); require(swapOutput > 0, "Zero output quantity"); //4. Settle the swap //4.1. Decrease output bal Manager.withdrawTokens( swapOutput, outputPersonal, allBassets[outputIdx], _recipient, cache.maxCache ); bAssetData[outputIdx].vaultBalance = allBassets[outputIdx].vaultBalance - SafeCast.toUint128(swapOutput); // Save new surplus to storage surplus = cache.surplus + scaledFee; emit Swapped( msg.sender, inputPersonal.addr, outputPersonal.addr, swapOutput, scaledFee, _recipient ); } /*************************************** REDEMPTION (PUBLIC) ****************************************/ /** * @notice Redeems a specified quantity of mAsset in return for a bAsset specified by bAsset address. * The bAsset is sent to the specified recipient. * The bAsset quantity is relative to current vault balance levels and desired mAsset quantity. * The quantity of mAsset is burnt as payment. * A minimum quantity of bAsset is specified to protect against price slippage between the mAsset and bAsset. * @param _output Address of the bAsset to receive * @param _mAssetQuantity Quantity of mAsset to redeem * @param _minOutputQuantity Minimum bAsset quantity to receive for the burnt mAssets. This protects against slippage. * @param _recipient Address to transfer the withdrawn bAssets to. * @return outputQuantity Quanity of bAsset units received for the burnt mAssets */ function redeem( address _output, uint256 _mAssetQuantity, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenNoRecol returns (uint256 outputQuantity) { outputQuantity = _redeem(_output, _mAssetQuantity, _minOutputQuantity, _recipient); } /** * @dev Credits a recipient with a proportionate amount of bAssets, relative to current vault * balance levels and desired mAsset quantity. Burns the mAsset as payment. * @param _mAssetQuantity Quantity of mAsset to redeem * @param _minOutputQuantities Min units of output to receive * @param _recipient Address to credit the withdrawn bAssets */ function redeemMasset( uint256 _mAssetQuantity, uint256[] calldata _minOutputQuantities, address _recipient ) external override nonReentrant whenNoRecol returns (uint256[] memory outputQuantities) { outputQuantities = _redeemMasset(_mAssetQuantity, _minOutputQuantities, _recipient); } /** * @dev Credits a recipient with a certain quantity of selected bAssets, in exchange for burning the * relative Masset quantity from the sender. Sender also incurs a small fee on the outgoing asset. * @param _outputs Addresses of the bAssets to receive * @param _outputQuantities Units of the bAssets to redeem * @param _maxMassetQuantity Maximum mAsset quantity to burn for the received bAssets. This protects against slippage. * @param _recipient Address to receive the withdrawn bAssets * @return mAssetQuantity Quantity of mAsset units burned plus the swap fee to pay for the redeemed bAssets */ function redeemExactBassets( address[] calldata _outputs, uint256[] calldata _outputQuantities, uint256 _maxMassetQuantity, address _recipient ) external override nonReentrant whenNoRecol returns (uint256 mAssetQuantity) { mAssetQuantity = _redeemExactBassets( _outputs, _outputQuantities, _maxMassetQuantity, _recipient ); } /** * @notice Gets the estimated output from a given redeem * @param _output Address of the bAsset to receive * @param _mAssetQuantity Quantity of mAsset to redeem * @return bAssetOutput Estimated quantity of bAsset units received for the burnt mAssets */ function getRedeemOutput(address _output, uint256 _mAssetQuantity) external view override returns (uint256 bAssetOutput) { require(_mAssetQuantity > 0, "Qty==0"); (uint8 idx, ) = _getAsset(_output); uint256 scaledFee = _mAssetQuantity.mulTruncate(swapFee); bAssetOutput = forgeValidator.computeRedeem( bAssetData, idx, _mAssetQuantity - scaledFee, _getConfig() ); } /** * @notice Gets the estimated output from a given redeem * @param _outputs Addresses of the bAsset to receive * @param _outputQuantities Quantities of bAsset to redeem * @return mAssetQuantity Estimated quantity of mAsset units needed to burn to receive output */ function getRedeemExactBassetsOutput( address[] calldata _outputs, uint256[] calldata _outputQuantities ) external view override returns (uint256 mAssetQuantity) { uint256 len = _outputQuantities.length; require(len > 0 && len == _outputs.length, "Invalid array input"); (uint8[] memory indexes, ) = _getBassets(_outputs); // calculate the value of mAssets need to cover the value of bAssets being redeemed uint256 mAssetRedeemed = forgeValidator.computeRedeemExact(bAssetData, indexes, _outputQuantities, _getConfig()); mAssetQuantity = mAssetRedeemed.divPrecisely(1e18 - swapFee) + 1; } /*************************************** REDEMPTION (INTERNAL) ****************************************/ /** * @dev Redeem mAsset for a single bAsset */ function _redeem( address _output, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) internal returns (uint256 bAssetQuantity) { require(_recipient != address(0), "Invalid recipient"); require(_inputQuantity > 0, "Qty==0"); // Load the bAsset data from storage into memory BassetData[] memory allBassets = bAssetData; (uint8 bAssetIndex, BassetPersonal memory personal) = _getAsset(_output); // Calculate redemption quantities uint256 scaledFee = _inputQuantity.mulTruncate(swapFee); bAssetQuantity = forgeValidator.computeRedeem( allBassets, bAssetIndex, _inputQuantity - scaledFee, _getConfig() ); require(bAssetQuantity >= _minOutputQuantity, "bAsset qty < min qty"); require(bAssetQuantity > 0, "Output == 0"); // Apply fees, burn mAsset and return bAsset to recipient // 1.0. Burn the full amount of Masset _burn(msg.sender, _inputQuantity); surplus += scaledFee; Cache memory cache = _getCacheDetails(); // 2.0. Transfer the Bassets to the recipient Manager.withdrawTokens( bAssetQuantity, personal, allBassets[bAssetIndex], _recipient, cache.maxCache ); // 3.0. Set vault balance bAssetData[bAssetIndex].vaultBalance = allBassets[bAssetIndex].vaultBalance - SafeCast.toUint128(bAssetQuantity); emit Redeemed( msg.sender, _recipient, _inputQuantity, personal.addr, bAssetQuantity, scaledFee ); } /** * @dev Redeem mAsset for proportional amount of bAssets */ function _redeemMasset( uint256 _inputQuantity, uint256[] calldata _minOutputQuantities, address _recipient ) internal returns (uint256[] memory outputQuantities) { require(_recipient != address(0), "Invalid recipient"); require(_inputQuantity > 0, "Qty==0"); // Calculate mAsset redemption quantities uint256 scaledFee = _inputQuantity.mulTruncate(redemptionFee); uint256 mAssetRedemptionAmount = _inputQuantity - scaledFee; // Burn mAsset quantity _burn(msg.sender, _inputQuantity); surplus += scaledFee; // Calc cache and total mAsset circulating Cache memory cache = _getCacheDetails(); // Total mAsset = (totalSupply + _inputQuantity - scaledFee) + surplus uint256 totalMasset = cache.vaultBalanceSum + mAssetRedemptionAmount; // Load the bAsset data from storage into memory BassetData[] memory allBassets = bAssetData; uint256 len = allBassets.length; address[] memory outputs = new address[](len); outputQuantities = new uint256[](len); for (uint256 i = 0; i < len; i++) { // Get amount out, proportionate to redemption quantity // Use `cache.sum` here as the total mAsset supply is actually totalSupply + surplus uint256 amountOut = (allBassets[i].vaultBalance * mAssetRedemptionAmount) / totalMasset; require(amountOut > 1, "Output == 0"); amountOut -= 1; require(amountOut >= _minOutputQuantities[i], "bAsset qty < min qty"); // Set output in array (outputQuantities[i], outputs[i]) = (amountOut, bAssetPersonal[i].addr); // Transfer the bAsset to the recipient Manager.withdrawTokens( amountOut, bAssetPersonal[i], allBassets[i], _recipient, cache.maxCache ); // reduce vaultBalance bAssetData[i].vaultBalance = allBassets[i].vaultBalance - SafeCast.toUint128(amountOut); } emit RedeemedMulti( msg.sender, _recipient, _inputQuantity, outputs, outputQuantities, scaledFee ); } /** @dev Redeem mAsset for one or more bAssets */ function _redeemExactBassets( address[] memory _outputs, uint256[] memory _outputQuantities, uint256 _maxMassetQuantity, address _recipient ) internal returns (uint256 mAssetQuantity) { require(_recipient != address(0), "Invalid recipient"); uint256 len = _outputQuantities.length; require(len > 0 && len == _outputs.length, "Invalid array input"); require(_maxMassetQuantity > 0, "Qty==0"); (uint8[] memory indexes, BassetPersonal[] memory personal) = _getBassets(_outputs); // Load bAsset data from storage to memory BassetData[] memory allBassets = bAssetData; // Validate redemption uint256 mAssetRequired = forgeValidator.computeRedeemExact(allBassets, indexes, _outputQuantities, _getConfig()); mAssetQuantity = mAssetRequired.divPrecisely(1e18 - swapFee); uint256 fee = mAssetQuantity - mAssetRequired; require(mAssetQuantity > 0, "Must redeem some mAssets"); mAssetQuantity += 1; require(mAssetQuantity <= _maxMassetQuantity, "Redeem mAsset qty > max quantity"); // Apply fees, burn mAsset and return bAsset to recipient // 1.0. Burn the full amount of Masset _burn(msg.sender, mAssetQuantity); surplus += fee; Cache memory cache = _getCacheDetails(); // 2.0. Transfer the Bassets to the recipient and count fees for (uint256 i = 0; i < len; i++) { uint8 idx = indexes[i]; Manager.withdrawTokens( _outputQuantities[i], personal[i], allBassets[idx], _recipient, cache.maxCache ); bAssetData[idx].vaultBalance = allBassets[idx].vaultBalance - SafeCast.toUint128(_outputQuantities[i]); } emit RedeemedMulti( msg.sender, _recipient, mAssetQuantity, _outputs, _outputQuantities, fee ); } /*************************************** GETTERS ****************************************/ /** * @dev Get basket details for `Masset_MassetStructs.Basket` * @return b Basket struct */ function getBasket() external view override returns (bool, bool) { return (basket.undergoingRecol, basket.failed); } /** * @dev Get data for a all bAssets in basket * @return personal Struct[] with full bAsset data * @return data Number of bAssets in the Basket */ function getBassets() external view override returns (BassetPersonal[] memory personal, BassetData[] memory data) { return (bAssetPersonal, bAssetData); } /** * @dev Get data for a specific bAsset, if it exists * @param _bAsset Address of bAsset * @return personal Struct with full bAsset data * @return data Struct with full bAsset data */ function getBasset(address _bAsset) external view override returns (BassetPersonal memory personal, BassetData memory data) { uint8 idx = bAssetIndexes[_bAsset]; personal = bAssetPersonal[idx]; require(personal.addr == _bAsset, "Invalid asset"); data = bAssetData[idx]; } /** * @dev Gets all config needed for general InvariantValidator calls */ function getConfig() external view returns (InvariantConfig memory config) { return _getConfig(); } /*************************************** GETTERS - INTERNAL ****************************************/ /** * vaultBalanceSum = totalSupply + 'surplus' * maxCache = vaultBalanceSum * (cacheSize / 1e18) * surplus is simply surplus, to reduce SLOADs */ struct Cache { uint256 vaultBalanceSum; uint256 maxCache; uint256 surplus; } /** * @dev Gets the supply and cache details for the mAsset, taking into account the surplus * @return Cache containing (tracked) sum of vault balances, ideal cache size and surplus */ function _getCacheDetails() internal view returns (Cache memory) { // read surplus from storage into memory uint256 _surplus = surplus; uint256 sum = totalSupply() + _surplus; return Cache(sum, sum.mulTruncate(cacheSize), _surplus); } /** * @dev Gets a bAsset from storage * @param _asset Address of the asset * @return idx Index of the asset * @return personal Personal details for the asset */ function _getAsset(address _asset) internal view returns (uint8 idx, BassetPersonal memory personal) { idx = bAssetIndexes[_asset]; personal = bAssetPersonal[idx]; require(personal.addr == _asset, "Invalid asset"); } /** * @dev Gets a an array of bAssets from storage and protects against duplicates * @param _bAssets Addresses of the assets * @return indexes Indexes of the assets * @return personal Personal details for the assets */ function _getBassets(address[] memory _bAssets) internal view returns (uint8[] memory indexes, BassetPersonal[] memory personal) { uint256 len = _bAssets.length; indexes = new uint8[](len); personal = new BassetPersonal[](len); for (uint256 i = 0; i < len; i++) { (indexes[i], personal[i]) = _getAsset(_bAssets[i]); for (uint256 j = i + 1; j < len; j++) { require(_bAssets[i] != _bAssets[j], "Duplicate asset"); } } } /** * @dev Gets all config needed for general InvariantValidator calls */ function _getConfig() internal view returns (InvariantConfig memory) { return InvariantConfig(_getA(), weightLimits); } /** * @dev Gets current amplification var A */ function _getA() internal view returns (uint256) { AmpData memory ampData_ = ampData; uint64 endA = ampData_.targetA; uint64 endTime = ampData_.rampEndTime; // If still changing, work out based on current timestmap if (block.timestamp < endTime) { uint64 startA = ampData_.initialA; uint64 startTime = ampData_.rampStartTime; (uint256 elapsed, uint256 total) = (block.timestamp - startTime, endTime - startTime); if (endA > startA) { return startA + (((endA - startA) * elapsed) / total); } else { return startA - (((startA - endA) * elapsed) / total); } } // Else return final value else { return endA; } } /*************************************** YIELD ****************************************/ /** * @dev Converts recently accrued swap and redeem fees into mAsset * @return mintAmount mAsset units generated from swap and redeem fees * @return newSupply mAsset total supply after mint */ function collectInterest() external override onlySavingsManager returns (uint256 mintAmount, uint256 newSupply) { // Set the surplus variable to 1 to optimise for SSTORE costs. // If setting to 0 here, it would save 5k per savings deposit, but cost 20k for the // first surplus call (a SWAP or REDEEM). uint256 surplusFees = surplus; if (surplusFees > 1) { mintAmount = surplusFees - 1; surplus = 1; // mint new mAsset to savings manager _mint(msg.sender, mintAmount); emit MintedMulti( address(this), msg.sender, mintAmount, new address[](0), new uint256[](0) ); } newSupply = totalSupply(); } /** * @dev Collects the interest generated from the Basket, minting a relative * amount of mAsset and sends it over to the SavingsManager. * @return mintAmount mAsset units generated from interest collected from lending markets * @return newSupply mAsset total supply after mint */ function collectPlatformInterest() external override onlySavingsManager whenHealthy nonReentrant returns (uint256 mintAmount, uint256 newSupply) { uint256[] memory gains; (mintAmount, gains) = Manager.collectPlatformInterest( bAssetPersonal, bAssetData, forgeValidator, _getConfig() ); require(mintAmount > 0, "Must collect something"); _mint(msg.sender, mintAmount); emit MintedMulti(address(this), msg.sender, mintAmount, new address[](0), gains); newSupply = totalSupply(); } /*************************************** STATE ****************************************/ /** * @dev Sets the MAX cache size for each bAsset. The cache will actually revolve around * _cacheSize * totalSupply / 2 under normal circumstances. * @param _cacheSize Maximum percent of total mAsset supply to hold for each bAsset */ function setCacheSize(uint256 _cacheSize) external override onlyGovernor { require(_cacheSize <= 2e17, "Must be <= 20%"); cacheSize = _cacheSize; emit CacheSizeChanged(_cacheSize); } /** * @dev Upgrades the version of ForgeValidator protocol. Governor can do this * only while ForgeValidator is unlocked. * @param _newForgeValidator Address of the new ForgeValidator */ function upgradeForgeValidator(address _newForgeValidator) external override onlyGovernor { require(!forgeValidatorLocked, "ForgeVal locked"); require(_newForgeValidator != address(0), "Null address"); forgeValidator = IInvariantValidator(_newForgeValidator); emit ForgeValidatorChanged(_newForgeValidator); } /** * @dev Set the ecosystem fee for sewapping bAssets or redeeming specific bAssets * @param _swapFee Fee calculated in (%/100 * 1e18) */ function setFees(uint256 _swapFee, uint256 _redemptionFee) external override onlyGovernor { require(_swapFee <= MAX_FEE, "Swap rate oob"); require(_redemptionFee <= MAX_FEE, "Redemption rate oob"); swapFee = _swapFee; redemptionFee = _redemptionFee; emit FeesChanged(_swapFee, _redemptionFee); } /** * @dev Set the maximum weight for a given bAsset * @param _min Weight where 100% = 1e18 * @param _max Weight where 100% = 1e18 */ function setWeightLimits(uint128 _min, uint128 _max) external onlyGovernor { require(_min <= 1e18 / (bAssetData.length * 2), "Min weight oob"); require(_max >= 1e18 / (bAssetData.length - 1), "Max weight oob"); weightLimits = WeightLimits(_min, _max); emit WeightLimitsChanged(_min, _max); } /** * @dev Update transfer fee flag for a given bAsset, should it change its fee practice * @param _bAsset bAsset address * @param _flag Charge transfer fee when its set to 'true', otherwise 'false' */ function setTransferFeesFlag(address _bAsset, bool _flag) external override onlyGovernor { Manager.setTransferFeesFlag(bAssetPersonal, bAssetIndexes, _bAsset, _flag); } /** * @dev Transfers all collateral from one lending market to another - used initially * to handle the migration between Aave V1 and Aave V2. Note - only supports non * tx fee enabled assets. Supports going from no integration to integration, but * not the other way around. * @param _bAssets Array of basket assets to migrate * @param _newIntegration Address of the new platform integration */ function migrateBassets(address[] calldata _bAssets, address _newIntegration) external override onlyGovernor { Manager.migrateBassets(bAssetPersonal, bAssetIndexes, _bAssets, _newIntegration); } /** * @dev Executes the Auto Redistribution event by isolating the bAsset from the Basket * @param _bAsset Address of the ERC20 token to isolate * @param _belowPeg Bool to describe whether the bAsset deviated below peg (t) * or above (f) */ function handlePegLoss(address _bAsset, bool _belowPeg) external onlyGovernor { Manager.handlePegLoss(basket, bAssetPersonal, bAssetIndexes, _bAsset, _belowPeg); } /** * @dev Negates the isolation of a given bAsset * @param _bAsset Address of the bAsset */ function negateIsolation(address _bAsset) external onlyGovernor { Manager.negateIsolation(basket, bAssetPersonal, bAssetIndexes, _bAsset); } /** * @dev Starts changing of the amplification var A * @param _targetA Target A value * @param _rampEndTime Time at which A will arrive at _targetA */ function startRampA(uint256 _targetA, uint256 _rampEndTime) external onlyGovernor { Manager.startRampA(ampData, _targetA, _rampEndTime, _getA(), A_PRECISION); } /** * @dev Stops the changing of the amplification var A, setting * it to whatever the current value is. */ function stopRampA() external onlyGovernor { Manager.stopRampA(ampData, _getA()); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_nexus","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":false,"internalType":"uint256","name":"cacheSize","type":"uint256"}],"name":"CacheSizeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionFee","type":"uint256"}],"name":"FeesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"forgeValidator","type":"address"}],"name":"ForgeValidatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"mAssetQuantity","type":"uint256"},{"indexed":false,"internalType":"address","name":"input","type":"address"},{"indexed":false,"internalType":"uint256","name":"inputQuantity","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"mAssetQuantity","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"inputs","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"inputQuantities","type":"uint256[]"}],"name":"MintedMulti","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"mAssetQuantity","type":"uint256"},{"indexed":false,"internalType":"address","name":"output","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputQuantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledFee","type":"uint256"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"mAssetQuantity","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"outputs","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"outputQuantity","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"scaledFee","type":"uint256"}],"name":"RedeemedMulti","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"swapper","type":"address"},{"indexed":false,"internalType":"address","name":"input","type":"address"},{"indexed":false,"internalType":"address","name":"output","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"Swapped","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":"uint128","name":"min","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"max","type":"uint128"}],"name":"WeightLimitsChanged","type":"event"},{"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":[],"name":"ampData","outputs":[{"internalType":"uint64","name":"initialA","type":"uint64"},{"internalType":"uint64","name":"targetA","type":"uint64"},{"internalType":"uint64","name":"rampStartTime","type":"uint64"},{"internalType":"uint64","name":"rampEndTime","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bAssetData","outputs":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bAssetIndexes","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bAssetPersonal","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"bool","name":"hasTxFee","type":"bool"},{"internalType":"enum MassetStructs.BassetStatus","name":"status","type":"uint8"}],"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":"basket","outputs":[{"internalType":"bool","name":"undergoingRecol","type":"bool"},{"internalType":"bool","name":"failed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cacheSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectInterest","outputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"newSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectPlatformInterest","outputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"uint256","name":"newSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"forgeValidator","outputs":[{"internalType":"contract IInvariantValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBasket","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bAsset","type":"address"}],"name":"getBasset","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"bool","name":"hasTxFee","type":"bool"},{"internalType":"enum MassetStructs.BassetStatus","name":"status","type":"uint8"}],"internalType":"struct MassetStructs.BassetPersonal","name":"personal","type":"tuple"},{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct MassetStructs.BassetData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBassets","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"bool","name":"hasTxFee","type":"bool"},{"internalType":"enum MassetStructs.BassetStatus","name":"status","type":"uint8"}],"internalType":"struct MassetStructs.BassetPersonal[]","name":"personal","type":"tuple[]"},{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct MassetStructs.BassetData[]","name":"data","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct MassetStructs.WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct MassetStructs.InvariantConfig","name":"config","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_inputs","type":"address[]"},{"internalType":"uint256[]","name":"_inputQuantities","type":"uint256[]"}],"name":"getMintMultiOutput","outputs":[{"internalType":"uint256","name":"mintOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_input","type":"address"},{"internalType":"uint256","name":"_inputQuantity","type":"uint256"}],"name":"getMintOutput","outputs":[{"internalType":"uint256","name":"mintOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_outputs","type":"address[]"},{"internalType":"uint256[]","name":"_outputQuantities","type":"uint256[]"}],"name":"getRedeemExactBassetsOutput","outputs":[{"internalType":"uint256","name":"mAssetQuantity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_mAssetQuantity","type":"uint256"}],"name":"getRedeemOutput","outputs":[{"internalType":"uint256","name":"bAssetOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_input","type":"address"},{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_inputQuantity","type":"uint256"}],"name":"getSwapOutput","outputs":[{"internalType":"uint256","name":"swapOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bAsset","type":"address"},{"internalType":"bool","name":"_belowPeg","type":"bool"}],"name":"handlePegLoss","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":"maxBassets","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bAssets","type":"address[]"},{"internalType":"address","name":"_newIntegration","type":"address"}],"name":"migrateBassets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_input","type":"address"},{"internalType":"uint256","name":"_inputQuantity","type":"uint256"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"mintOutput","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_inputs","type":"address[]"},{"internalType":"uint256[]","name":"_inputQuantities","type":"uint256[]"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"mintMulti","outputs":[{"internalType":"uint256","name":"mintOutput","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bAsset","type":"address"}],"name":"negateIsolation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nexus","outputs":[{"internalType":"contract INexus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_mAssetQuantity","type":"uint256"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"outputQuantity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_outputs","type":"address[]"},{"internalType":"uint256[]","name":"_outputQuantities","type":"uint256[]"},{"internalType":"uint256","name":"_maxMassetQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"redeemExactBassets","outputs":[{"internalType":"uint256","name":"mAssetQuantity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mAssetQuantity","type":"uint256"},{"internalType":"uint256[]","name":"_minOutputQuantities","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"redeemMasset","outputs":[{"internalType":"uint256[]","name":"outputQuantities","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cacheSize","type":"uint256"}],"name":"setCacheSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_swapFee","type":"uint256"},{"internalType":"uint256","name":"_redemptionFee","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bAsset","type":"address"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"setTransferFeesFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_min","type":"uint128"},{"internalType":"uint128","name":"_max","type":"uint128"}],"name":"setWeightLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetA","type":"uint256"},{"internalType":"uint256","name":"_rampEndTime","type":"uint256"}],"name":"startRampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopRampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"surplus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_input","type":"address"},{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_inputQuantity","type":"uint256"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"swap","outputs":[{"internalType":"uint256","name":"swapOutput","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forgeValidator","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct MassetStructs.WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct MassetStructs.InvariantConfig","name":"_config","type":"tuple"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newForgeValidator","type":"address"}],"name":"upgradeForgeValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weightLimits","outputs":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162005d6838038062005d6883398101604081905262000034916200007e565b806001600160a01b038116620000675760405162461bcd60e51b81526004016200005e90620000ae565b60405180910390fd5b60601b6001600160601b03191660805250620000e5565b60006020828403121562000090578081fd5b81516001600160a01b0381168114620000a7578182fd5b9392505050565b60208082526015908201527f4e657875732061646472657373206973207a65726f0000000000000000000000604082015260600190565b60805160601c615c5662000112600039600081816119f90152818161415201526141fb0152615c566000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c80636d5d6eb11161019d578063aa5d27e9116100e9578063cd6ef2b0116100a2578063dd62ed3e1161007c578063dd62ed3e1461069c578063e5555b8f146106af578063edc832b3146106c2578063f74bfe8e146106ca5761030c565b8063cd6ef2b01461066b578063d5bcb9b514610681578063d7d52266146106945761030c565b8063aa5d27e9146105f5578063ab06346c14610608578063af290bd414610628578063bdfbe29c1461063b578063c3f909d41461064e578063c4db7fa0146106635761030c565b8063905e891411610156578063a1c2515111610130578063a1c25151146105a7578063a3f5c1d2146105ba578063a457c2d7146105cf578063a9059cbb146105e25761030c565b8063905e89141461057957806395d89b411461058c578063969642b9146105945761030c565b80636d5d6eb1146105125780636fb3e89c1461052557806370a082311461053857806372ea90761461054b57806378aa987e1461055e5780637e8901ea146105715761030c565b806326bbe60a1161025c57806343bcfab61161021557806354cf2aeb116101ef57806354cf2aeb146104e2578063598362f0146104ea578063674a64e0146105025780636c36581c1461050a5761030c565b806343bcfab6146104b457806344e3fa3c146104c7578063458f5815146104da5761030c565b806326bbe60a1461042f5780632a2fab22146104425780632f91a72414610458578063313ce5671461047857806339509351146104805780633e37bcbc146104935761030c565b806313888565116102c95780631820783d116102a35780631820783d146103dd5780631d3ce398146103f0578063213c501a1461040657806323b872dd1461041c5761030c565b806313888565146103ba57806317036826146103c257806318160ddd146103d55761030c565b80630357359c1461031157806304de5a731461033d57806306fdde031461035d578063095ea7b3146103725780630b78f9c014610392578063119849cf146103a7575b600080fd5b61032461031f366004614896565b6106dd565b6040516103349493929190614c0e565b60405180910390f35b61035061034b366004614774565b61072d565b604051610334919061501d565b61036561086f565b604051610334919061504c565b6103856103803660046146ac565b610902565b6040516103349190615000565b6103a56103a03660046149c9565b610920565b005b6103506103b53660046146ac565b6109b4565b610350610a78565b6103a56103d03660046145ed565b610a7e565b610350610c1d565b6103a56103eb366004614896565b610c23565b6103f8610c93565b604051610334929190614e8b565b61040e610df0565b6040516103349291906159d8565b61038561042a36600461451e565b610e0a565b6103a561043d3660046144ae565b610ea3565b61044a610f46565b6040516103349291906158fa565b61046b6104663660046144ae565b610ffd565b6040516103349190615a71565b61046b611012565b61038561048e3660046146ac565b61101b565b6104a66104a13660046144ae565b61106a565b60405161033492919061597d565b6103506104c23660046146d7565b6111f5565b6103a56104d53660046149c9565b61125e565b6103506112e2565b6103506112e8565b6104f26112ee565b6040516103349493929190615a46565b61035061131c565b61046b611322565b61040e610520366004614896565b61132b565b6103a5610533366004614720565b611360565b6103506105463660046144ae565b6113de565b61035061055936600461451e565b6113fd565b61035061056c3660046146ac565b611583565b61044a61166a565b6103a56105873660046145bc565b611816565b610365611860565b6103a56105a23660046144ae565b61186f565b6103a56105b5366004614864565b6118ea565b6105c26119f7565b6040516103349190614bfa565b6103856105dd3660046146ac565b611a1b565b6103856105f03660046146ac565b611a96565b6103506106033660046147dc565b611aaa565b61061b6106163660046148c6565b611b7a565b6040516103349190614fed565b6103506106363660046147dc565b611bc7565b6103a56106493660046145bc565b611c79565b610656611cc0565b60405161033491906159ca565b6103a5611cd5565b610673611d50565b60405161033492919061500b565b61035061068f36600461455e565b611d63565b6105c2611dce565b6103506106aa3660046144e6565b611ddd565b6103506106bd366004614774565b611e08565b610673611f10565b6103506106d83660046146d7565b611f22565b604981815481106106ed57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b90041684565b600081801580159061073e57508085145b6107635760405162461bcd60e51b815260040161075a90615467565b60405180910390fd5b60006107a1878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f6f92505050565b506042549091506000906001600160a01b031663d176d694604a8489896107c6612185565b6040518663ffffffff1660e01b81526004016107e6959493929190614e0a565b60206040518083038186803b1580156107fe57600080fd5b505afa158015610812573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083691906148ae565b9050610858604454670de0b6b3a76400006108519190615b52565b82906121d7565b610863906001615ad3565b98975050505050505050565b60606036805461087e90615b89565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90615b89565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b505050505090505b90565b600061091661090f6121f6565b84846121fa565b5060015b92915050565b6109286122ae565b60455482111561094a5760405162461bcd60e51b815260040161075a9061519e565b60455481111561096c5760405162461bcd60e51b815260040161075a90615403565b604482905560468190556040517f64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068906109a890849084906158fa565b60405180910390a15050565b60008082116109d55760405162461bcd60e51b815260040161075a9061578d565b60006109e0846122e8565b506042549091506001600160a01b0316637910213b604a8386610a01612185565b6040518563ffffffff1660e01b8152600401610a209493929190614e78565b60206040518083038186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7091906148ae565b949350505050565b60485481565b6043546001600160a01b0316610aa65760405162461bcd60e51b815260040161075a9061510b565b604380546001600160a01b0319808216909255604d805460ff19166001179055604280546001600160a01b0386811691909416179055604051637fe405b760e01b815291169073da681d409319b1f4122b1402c8b5cd4baedf900190637fe405b790610b1f908490604990604a90604b90600401615026565b60006040518083038186803b158015610b3757600080fd5b505af4158015610b4b573d6000803e3d6000fd5b5050604c805460ff1916600a17905550508151600090610b7690610b7190606490615b0b565b612412565b604080516080810182526001600160401b039290921680835260208084018290526000928401839052606090930191909152604e805467ffffffffffffffff191682176fffffffffffffffff00000000000000001916600160401b909202919091176001600160801b03908116909155938101518051604f805492909301516001600160801b0319909216908616178516600160801b919095160293909317909255505050565b60355490565b610c2b6122ae565b6702c68af0bb140000811115610c535760405162461bcd60e51b815260040161075a9061550f565b60478190556040517f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe790610c8890839061501d565b60405180910390a150565b6060806049604a81805480602002602001604051908101604052809291908181526020016000905b82821015610d72576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610d4057634e487b7160e01b600052602160045260246000fd5b6007811115610d5f57634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610cbb565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610de257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610d99565b505050509050915091509091565b604f546001600160801b0380821691600160801b90041682565b6000610e1784848461243b565b6001600160a01b038416600090815260346020526040812081610e386121f6565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905082811015610e7b5760405162461bcd60e51b815260040161075a906155a2565b610e9685610e876121f6565b610e918685615b52565b6121fa565b60019150505b9392505050565b610eab6122ae565b604254600160a01b900460ff1615610ed55760405162461bcd60e51b815260040161075a9061509f565b6001600160a01b038116610efb5760405162461bcd60e51b815260040161075a9061536f565b604280546001600160a01b0319166001600160a01b0383161790556040517f2e137a82d7f7fe8a4c453313f3d08557c162ad9d78219a2e937e318b41e12f7a90610c88908390614bfa565b600080610f51612558565b6048546001811115610fee57610f68600182615b52565b60016048559250610f793384612587565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015610fc8578160200160208202803683370190505b5060408051600081526020810191829052610fe594939291614cc9565b60405180910390a25b610ff6610c1d565b9150509091565b604b6020526000908152604090205460ff1681565b60385460ff1690565b60006109166110286121f6565b8484603460006110366121f6565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610e919190615ad3565b6110726143d5565b61107a6143fd565b6001600160a01b0383166000908152604b60205260409020546049805460ff90921691829081106110bb57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561113957634e487b7160e01b600052602160045260246000fd5b600781111561115857634e487b7160e01b600052602160045260246000fd5b815250509250836001600160a01b031683600001516001600160a01b0316146111935760405162461bcd60e51b815260040161075a90615135565b604a8160ff16815481106111b757634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b604154600090600160a01b900460ff166112215760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b1916905561123661263b565b6112428585858561267f565b6041805460ff60a01b1916600160a01b17905595945050505050565b6112666122ae565b731e91f826fa8aa4fa4d3f595898af3a64dd18884863e2a5f044604e848461128c6129e1565b60646040518663ffffffff1660e01b81526004016112ae959493929190615908565b60006040518083038186803b1580156112c657600080fd5b505af41580156112da573d6000803e3d6000fd5b505050505050565b60465481565b60445481565b604e546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b60475481565b604c5460ff1681565b604a818154811061133b57600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6113686122ae565b60405163a5bee44b60e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063a5bee44b906113a990604990604b90889088908890600401614f78565b60006040518083038186803b1580156113c157600080fd5b505af41580156113d5573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152603360205260409020545b919050565b6000826001600160a01b0316846001600160a01b031614156114315760405162461bcd60e51b815260040161075a906151c5565b600082116114515760405162461bcd60e51b815260040161075a90615615565b6000604a805480602002602001604051908101604052809291908181526020016000905b828210156114be57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611475565b50505050905060006114cf866122e8565b50905060006114dd866122e8565b506042546044549192506001600160a01b031690630e3c01d3908590859085908a90611507612185565b6040518763ffffffff1660e01b815260040161152896959493929190614dc8565b604080518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157791906149ea565b50979650505050505050565b60008082116115a45760405162461bcd60e51b815260040161075a9061578d565b60006115af846122e8565b50905060006115c960445485612b1e90919063ffffffff16565b6042549091506001600160a01b03166350494dc0604a846115ea8589615b52565b6115f2612185565b6040518563ffffffff1660e01b81526004016116119493929190614e78565b60206040518083038186803b15801561162957600080fd5b505afa15801561163d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166191906148ae565b95945050505050565b600080611675612558565b61167d612b33565b604154600160a01b900460ff166116a65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055604254606090731e91f826fa8aa4fa4d3f595898af3a64dd18884890638b8029b490604990604a906001600160a01b03166116ec612185565b6040518563ffffffff1660e01b815260040161170b9493929190614ee2565b60006040518083038186803b15801561172357600080fd5b505af4158015611737573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261175f9190810190614917565b9093509050826117815760405162461bcd60e51b815260040161075a906154df565b61178b3384612587565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc338560006040519080825280602002602001820160405280156117da578160200160208202803683370190505b50856040516117ec9493929190614cc9565b60405180910390a26117fc610c1d565b6041805460ff60a01b1916600160a01b1790559293915050565b61181e6122ae565b60405163ee60ee2b60e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063ee60ee2b906112ae90604d90604990604b908890889060040161594f565b60606037805461087e90615b89565b6118776122ae565b604051634c1e9da160e11b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063983d3b42906118b790604d90604990604b90879060040161592b565b60006040518083038186803b1580156118cf57600080fd5b505af41580156118e3573d6000803e3d6000fd5b5050505050565b6118f26122ae565b604a54611900906002615b0b565b61191290670de0b6b3a7640000615aeb565b826001600160801b0316111561193a5760405162461bcd60e51b815260040161075a90615721565b604a5461194990600190615b52565b61195b90670de0b6b3a7640000615aeb565b816001600160801b031610156119835760405162461bcd60e51b815260040161075a90615494565b6040805180820182526001600160801b038481168083528482166020909301839052604f80546001600160801b031916909117909116600160801b909202919091179055517f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136906109a890849084906159d8565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060346000611a2a6121f6565b6001600160a01b0390811682526020808301939093526040918201600090812091881681529252902054905082811015611a765760405162461bcd60e51b815260040161075a9061587e565b611a8c611a816121f6565b85610e918685615b52565b5060019392505050565b6000610916611aa36121f6565b848461243b565b604154600090600160a01b900460ff16611ad65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611aeb61263b565b611b5c87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250879150612b849050565b6041805460ff60a01b1916600160a01b179055979650505050505050565b604154606090600160a01b900460ff16611ba65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611bbb61263b565b61124285858585612ff4565b604154600090600160a01b900460ff16611bf35760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611c08612b33565b611b5c87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506134df9050565b611c816122ae565b604051638d18aef960e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd18884890638d18aef9906112ae90604990604b9087908790600401614f52565b611cc8614414565b611cd0612185565b905090565b611cdd6122ae565b731e91f826fa8aa4fa4d3f595898af3a64dd1888486318068e40604e611d016129e1565b6040518363ffffffff1660e01b8152600401611d1e9291906158fa565b60006040518083038186803b158015611d3657600080fd5b505af4158015611d4a573d6000803e3d6000fd5b50505050565b604d5460ff808216916101009004169091565b604154600090600160a01b900460ff16611d8f5760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611da4612b33565b611db1868686868661394b565b6041805460ff60a01b1916600160a01b1790559695505050505050565b6042546001600160a01b031681565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000818015801590611e1957508085145b611e355760405162461bcd60e51b815260040161075a906152fa565b6000611e73878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f6f92505050565b506042549091506001600160a01b031663b7ecbf72604a838888611e95612185565b6040518663ffffffff1660e01b8152600401611eb5959493929190614e0a565b60206040518083038186803b158015611ecd57600080fd5b505afa158015611ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0591906148ae565b979650505050505050565b604d5460ff8082169161010090041682565b604154600090600160a01b900460ff16611f4e5760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611f63612b33565b61124285858585613e31565b80516060908190806001600160401b03811115611f9c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611fc5578160200160208202803683370190505b509250806001600160401b03811115611fee57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561202757816020015b6120146143d5565b81526020019060019003908161200c5790505b50915060005b8181101561217e5761206585828151811061205857634e487b7160e01b600052603260045260246000fd5b60200260200101516122e8565b85838151811061208557634e487b7160e01b600052603260045260246000fd5b602002602001018584815181106120ac57634e487b7160e01b600052603260045260246000fd5b602090810291909101019190915260ff909116905260006120ce826001615ad3565b90505b8281101561216b578581815181106120f957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061212a57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156121595760405162461bcd60e51b815260040161075a906156b3565b8061216381615bc4565b9150506120d1565b508061217681615bc4565b91505061202d565b5050915091565b61218d614414565b60405180604001604052806121a06129e1565b815260408051808201909152604f546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b6000816121ec670de0b6b3a764000085615b0b565b610e9c9190615aeb565b3390565b6001600160a01b0383166122205760405162461bcd60e51b815260040161075a90615749565b6001600160a01b0382166122465760405162461bcd60e51b815260040161075a906151eb565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906122a190859061501d565b60405180910390a3505050565b6122b661414e565b6001600160a01b0316336001600160a01b0316146122e65760405162461bcd60e51b815260040161075a90615430565b565b60006122f26143d5565b6001600160a01b0383166000908152604b60205260409020546049805460ff9092169350908390811061233557634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156123b357634e487b7160e01b600052602160045260246000fd5b60078111156123d257634e487b7160e01b600052602160045260246000fd5b815250509050826001600160a01b031681600001516001600160a01b03161461240d5760405162461bcd60e51b815260040161075a90615135565b915091565b6000600160401b82106124375760405162461bcd60e51b815260040161075a9061555c565b5090565b6001600160a01b0383166124615760405162461bcd60e51b815260040161075a906156dc565b6001600160a01b0382166124875760405162461bcd60e51b815260040161075a906150c8565b6001600160a01b038316600090815260336020526040902054818110156124c05760405162461bcd60e51b815260040161075a906152b4565b6124ca8282615b52565b6001600160a01b038086166000908152603360205260408082209390935590851681529081208054849290612500908490615ad3565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161254a919061501d565b60405180910390a350505050565b336125616141e1565b6001600160a01b0316146122e65760405162461bcd60e51b815260040161075a906153cc565b6001600160a01b0382166125ad5760405162461bcd60e51b815260040161075a906158c3565b80603560008282546125bf9190615ad3565b90915550506001600160a01b038216600090815260336020526040812080548392906125ec908490615ad3565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061262f90859061501d565b60405180910390a35050565b60408051808201909152604d5460ff8082161580158452610100909204161515602083015261267c5760405162461bcd60e51b815260040161075a90615264565b50565b60006001600160a01b0382166126a75760405162461bcd60e51b815260040161075a906155ea565b600084116126c75760405162461bcd60e51b815260040161075a9061578d565b6000604a805480602002602001604051908101604052809291908181526020016000905b8282101561273457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016126eb565b505050509050600080612746886122e8565b91509150600061276160445489612b1e90919063ffffffff16565b6042549091506001600160a01b03166350494dc08585612781858d615b52565b612789612185565b6040518563ffffffff1660e01b81526004016127a89493929190614d97565b60206040518083038186803b1580156127c057600080fd5b505afa1580156127d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f891906148ae565b94508685101561281a5760405162461bcd60e51b815260040161075a90615286565b6000851161283a5760405162461bcd60e51b815260040161075a90615537565b6128443389614268565b80604860008282546128569190615ad3565b9091555060009050612866614342565b9050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548785888860ff16815181106128a757634e487b7160e01b600052603260045260246000fd5b60200260200101518b86602001516040518663ffffffff1660e01b81526004016128d59594939291906159f2565b60006040518083038186803b1580156128ed57600080fd5b505af4158015612901573d6000803e3d6000fd5b5050505061290e86614399565b858560ff168151811061293157634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516129479190615b2a565b604a8560ff168154811061296b57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055825160405133917f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad8916129cc918b918e91908c908990614c95565b60405180910390a25050505050949350505050565b60408051608081018252604e546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b90910416606082018190526000929042811115612b0b5782516040840151600080612a546001600160401b03841642615b52565b612a5e8487615b69565b6001600160401b031691509150836001600160401b0316866001600160401b03161115612acf578082612a918689615b69565b6001600160401b0316612aa49190615b0b565b612aae9190615aeb565b612ac1906001600160401b038616615ad3565b9750505050505050506108ff565b8082612adb8887615b69565b6001600160401b0316612aee9190615b0b565b612af89190615aeb565b612ac1906001600160401b038616615b52565b506001600160401b031691506108ff9050565b6000610e9c8383670de0b6b3a76400006143be565b60408051808201909152604d5460ff8082161580158085526101009093049091161515602084015290612b6857508060200151155b61267c5760405162461bcd60e51b815260040161075a906154bc565b60006001600160a01b038216612bac5760405162461bcd60e51b815260040161075a906155ea565b83518015801590612bbd5750855181145b612bd95760405162461bcd60e51b815260040161075a90615467565b60008411612bf95760405162461bcd60e51b815260040161075a9061578d565b600080612c0588611f6f565b915091506000604a805480602002602001604051908101604052809291908181526020016000905b82821015612c7657600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612c2d565b50506042549293506000926001600160a01b0316915063d176d694905083868c612c9e612185565b6040518563ffffffff1660e01b8152600401612cbd9493929190614d4e565b60206040518083038186803b158015612cd557600080fd5b505afa158015612ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0d91906148ae565b9050612d28604454670de0b6b3a76400006108519190615b52565b95506000612d368288615b52565b905060008711612d585760405162461bcd60e51b815260040161075a90615812565b612d63600188615ad3565b965088871115612d855760405162461bcd60e51b815260040161075a90615849565b612d8f3388614268565b8060486000828254612da19190615ad3565b9091555060009050612db1614342565b905060005b87811015612f9b576000878281518110612de057634e487b7160e01b600052603260045260246000fd5b60200260200101519050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548e8481518110612e2457634e487b7160e01b600052603260045260246000fd5b6020026020010151898581518110612e4c57634e487b7160e01b600052603260045260246000fd5b6020026020010151898560ff1681518110612e7757634e487b7160e01b600052603260045260246000fd5b60200260200101518f88602001516040518663ffffffff1660e01b8152600401612ea59594939291906159f2565b60006040518083038186803b158015612ebd57600080fd5b505af4158015612ed1573d6000803e3d6000fd5b50505050612f058d8381518110612ef857634e487b7160e01b600052603260045260246000fd5b6020026020010151614399565b868260ff1681518110612f2857634e487b7160e01b600052603260045260246000fd5b602002602001015160200151612f3e9190615b2a565b604a8260ff1681548110612f6257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080612f9381615bc4565b915050612db6565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8a8f8f87604051612fdd959493929190614d02565b60405180910390a250505050505050949350505050565b60606001600160a01b03821661301c5760405162461bcd60e51b815260040161075a906155ea565b6000851161303c5760405162461bcd60e51b815260040161075a9061578d565b600061305360465487612b1e90919063ffffffff16565b905060006130618288615b52565b905061306d3388614268565b816048600082825461307f9190615ad3565b909155506000905061308f614342565b905060008282600001516130a39190615ad3565b90506000604a805480602002602001604051908101604052809291908181526020016000905b8282101561311257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016130c9565b5050505090506000815190506000816001600160401b0381111561314657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561316f578160200160208202803683370190505b509050816001600160401b0381111561319857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156131c1578160200160208202803683370190505b50975060005b8281101561349d57600085888684815181106131f357634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b03166132129190615b0b565b61321c9190615aeb565b90506001811161323e5760405162461bcd60e51b815260040161075a90615537565b613249600182615b52565b90508c8c8381811061326b57634e487b7160e01b600052603260045260246000fd5b905060200201358110156132915760405162461bcd60e51b815260040161075a90615286565b80604983815481106132b357634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201548b516001600160a01b03909116908c90859081106132f257634e487b7160e01b600052603260045260246000fd5b6020026020010185858151811061331957634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b0316815250828152505050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a54826049858154811061337857634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202018886815181106133a657634e487b7160e01b600052603260045260246000fd5b60200260200101518f8c602001516040518663ffffffff1660e01b81526004016133d4959493929190615a31565b60006040518083038186803b1580156133ec57600080fd5b505af4158015613400573d6000803e3d6000fd5b5050505061340d81614399565b85838151811061342d57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516134439190615b2a565b604a838154811061346457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055508061349581615bc4565b9150506131c7565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8e848c8c604051612fdd959493929190614d02565b60006001600160a01b0382166135075760405162461bcd60e51b815260040161075a906155ea565b835180158015906135185750855181145b6135345760405162461bcd60e51b815260040161075a906152fa565b60008061354088611f6f565b915091506000604a805480602002602001604051908101604052809291908181526020016000905b828210156135b157600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613568565b50505050905060006135c1614342565b90506000856001600160401b038111156135eb57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613614578160200160208202803683370190505b50905060005b8681101561381e5760008b828151811061364457634e487b7160e01b600052603260045260246000fd5b60200260200101519050600081111561380b57600087838151811061367957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000868260ff16815181106136a857634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008885815181106136d457634e487b7160e01b600052603260045260246000fd5b602002602001015190506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d3913838560000151888c602001516040518563ffffffff1660e01b81526004016137259493929190615998565b60206040518083038186803b15801561373d57600080fd5b505af4158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906148ae565b90508087878151811061379857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506137ad81614399565b83602001516137bc9190615aa8565b604a8560ff16815481106137e057634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055505050505b508061381681615bc4565b91505061361a565b506042546001600160a01b031663b7ecbf7284878461383b612185565b6040518563ffffffff1660e01b815260040161385a9493929190614d4e565b60206040518083038186803b15801561387257600080fd5b505afa158015613886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138aa91906148ae565b9650888710156138cc5760405162461bcd60e51b815260040161075a9061522d565b600087116138ec5760405162461bcd60e51b815260040161075a90615644565b6138f68888612587565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc89898e8e6040516139359493929190614cc9565b60405180910390a2505050505050949350505050565b60006001600160a01b0382166139735760405162461bcd60e51b815260040161075a906155ea565b846001600160a01b0316866001600160a01b031614156139a55760405162461bcd60e51b815260040161075a906151c5565b600084116139c55760405162461bcd60e51b815260040161075a90615615565b6000604a805480602002602001604051908101604052809291908181526020016000905b82821015613a3257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016139e9565b505050509050600080613a44896122e8565b91509150600080613a548a6122e8565b915091506000613a62614342565b90506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d391386898960ff1681518110613aa457634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518e86602001516040518563ffffffff1660e01b8152600401613ad59493929190615998565b60206040518083038186803b158015613aed57600080fd5b505af4158015613b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2591906148ae565b9050613b3081614399565b878760ff1681518110613b5357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613b699190615aa8565b604a8760ff1681548110613b8d57634e487b7160e01b600052603260045260246000fd5b6000918252602082200180546001600160801b03938416600160801b029316929092179091556042546044546001600160a01b0390911690630e3c01d3908a908a9089908790613bdb612185565b6040518763ffffffff1660e01b8152600401613bfc96959493929190614dc8565b604080518083038186803b158015613c1357600080fd5b505afa158015613c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c4b91906149ea565b90995090508a891015613c705760405162461bcd60e51b815260040161075a90615395565b60008911613c905760405162461bcd60e51b815260040161075a906157e4565b731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548a868b8960ff1681518110613ccf57634e487b7160e01b600052603260045260246000fd5b60200260200101518e88602001516040518663ffffffff1660e01b8152600401613cfd9594939291906159f2565b60006040518083038186803b158015613d1557600080fd5b505af4158015613d29573d6000803e3d6000fd5b50505050613d3689614399565b888660ff1681518110613d5957634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613d6f9190615b2a565b604a8660ff1681548110613d9357634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790556040830151613dc9908290615ad3565b604881905550336001600160a01b03167f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d876000015186600001518c858f604051613e18959493929190614c3b565b60405180910390a2505050505050505095945050505050565b60006001600160a01b038216613e595760405162461bcd60e51b815260040161075a906155ea565b60008411613e795760405162461bcd60e51b815260040161075a9061578d565b6000604a805480602002602001604051908101604052809291908181526020016000905b82821015613ee657600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613e9d565b505050509050600080613ef8886122e8565b915091506000613f06614342565b90506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d391384878760ff1681518110613f4857634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518c86602001516040518563ffffffff1660e01b8152600401613f799493929190615998565b60206040518083038186803b158015613f9157600080fd5b505af4158015613fa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fc991906148ae565b6042549091506001600160a01b0316637910213b868684613fe8612185565b6040518563ffffffff1660e01b81526004016140079493929190614d97565b60206040518083038186803b15801561401f57600080fd5b505afa158015614033573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061405791906148ae565b9550878610156140795760405162461bcd60e51b815260040161075a9061522d565b61408281614399565b858560ff16815181106140a557634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516140bb9190615aa8565b604a8560ff16815481106140df57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905561410f8787612587565b336001600160a01b03167f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c788888d856040516129cc9493929190614c6b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156141a957600080fd5b505afa1580156141bd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd091906144ca565b6040516385acd64160e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385acd64190614250907f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf19060040161501d565b60206040518083038186803b1580156141a957600080fd5b6001600160a01b03821661428e5760405162461bcd60e51b815260040161075a90615672565b6001600160a01b038216600090815260336020526040902054818110156142c75760405162461bcd60e51b815260040161075a9061515c565b6142d18282615b52565b6001600160a01b038416600090815260336020526040812091909155603580548492906142ff908490615b52565b90915550506040516000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906122a190869061501d565b61434a61442e565b604854600081614358610c1d565b6143629190615ad3565b9050604051806060016040528082815260200161438a60475484612b1e90919063ffffffff16565b81526020019290925250905090565b6000600160801b82106124375760405162461bcd60e51b815260040161075a90615328565b6000816143cb8486615b0b565b610a709190615aeb565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604080518082019091526000808252602082015290565b6040518060400160405280600081526020016143f86143fd565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f840112614460578081fd5b5081356001600160401b03811115614476578182fd5b602083019150836020808302850101111561449057600080fd5b9250929050565b80356001600160801b03811681146113f857600080fd5b6000602082840312156144bf578081fd5b8135610e9c81615c0b565b6000602082840312156144db578081fd5b8151610e9c81615c0b565b600080604083850312156144f8578081fd5b823561450381615c0b565b9150602083013561451381615c0b565b809150509250929050565b600080600060608486031215614532578081fd5b833561453d81615c0b565b9250602084013561454d81615c0b565b929592945050506040919091013590565b600080600080600060a08688031215614575578081fd5b853561458081615c0b565b9450602086013561459081615c0b565b9350604086013592506060860135915060808601356145ae81615c0b565b809150509295509295909350565b600080604083850312156145ce578182fd5b82356145d981615c0b565b915060208301358015158114614513578182fd5b6000808284036080811215614600578283fd5b833561460b81615c0b565b92506060601f198201121561461e578182fd5b604080518181016001600160401b03828210818311171561464157614641615bf5565b8184526020880135835283603f198601121561465b578586fd5b835194508385019150848210818311171561467857614678615bf5565b508252614686868301614497565b835261469460608701614497565b60208401528260208201528093505050509250929050565b600080604083850312156146be578182fd5b82356146c981615c0b565b946020939093013593505050565b600080600080608085870312156146ec578384fd5b84356146f781615c0b565b93506020850135925060408501359150606085013561471581615c0b565b939692955090935050565b600080600060408486031215614734578283fd5b83356001600160401b03811115614749578384fd5b6147558682870161444f565b909450925050602084013561476981615c0b565b809150509250925092565b60008060008060408587031215614789578182fd5b84356001600160401b038082111561479f578384fd5b6147ab8883890161444f565b909650945060208701359150808211156147c3578384fd5b506147d08782880161444f565b95989497509550505050565b600080600080600080608087890312156147f4578384fd5b86356001600160401b038082111561480a578586fd5b6148168a838b0161444f565b9098509650602089013591508082111561482e578586fd5b5061483b89828a0161444f565b90955093505060408701359150606087013561485681615c0b565b809150509295509295509295565b60008060408385031215614876578182fd5b61487f83614497565b915061488d60208401614497565b90509250929050565b6000602082840312156148a7578081fd5b5035919050565b6000602082840312156148bf578081fd5b5051919050565b600080600080606085870312156148db578182fd5b8435935060208501356001600160401b038111156148f7578283fd5b6149038782880161444f565b909450925050604085013561471581615c0b565b60008060408385031215614929578182fd5b825191506020808401516001600160401b0380821115614947578384fd5b818601915086601f83011261495a578384fd5b81518181111561496c5761496c615bf5565b838102915061497c848301615a7f565b8181528481019084860184860187018b1015614996578788fd5b8795505b838610156149b857805183526001959095019491860191860161499a565b508096505050505050509250929050565b600080604083850312156149db578182fd5b50508035926020909101359150565b600080604083850312156149fc578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b83811015614a455781516001600160a01b031687529582019590820190600101614a20565b509495945050505050565b6000815180845260208085019450808401835b83811015614a4557614a76878351614b51565b6040969096019590820190600101614a63565b6000815480845260208085019450838352808320835b83811015614a455781546001600160801b038116885260801c8388015260409096019560019182019101614a9f565b6000815180845260208085019450808401835b83811015614a4557815187529582019590820190600101614ae1565b6000815180845260208085019450808401835b83811015614a4557815160ff1687529582019590820190600101614b10565b60088110614b4d57634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160801b03908116835260209182015116910152565b60018060a01b03808251168352806020830151166020840152506040810151151560408301526060810151614ba46060840182614b2f565b505050565b60018060a01b038082541683526001820154818116602085015260ff8160a01c1615156040850152611d4a6060850160ff8360a81c16614b2f565b805182526020810151614ba46020840182614b51565b6001600160a01b0391909116815260200190565b6001600160a01b038581168252841660208201528215156040820152608081016116616060830184614b2f565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b03958616815260208101949094529190931660408301526060820192909252608081019190915260a00190565b600060018060a01b038616825284602083015260806040830152614cf06080830185614a0d565b8281036060840152611f058185614ace565b600060018060a01b038716825285602083015260a06040830152614d2960a0830186614a0d565b8281036060840152614d3b8186614ace565b9150508260808301529695505050505050565b600060c08252614d6160c0830187614a50565b8281036020840152614d738187614afd565b90508281036040840152614d878186614ace565b9150506116616060830184614be4565b600060c08252614daa60c0830187614a50565b905060ff851660208301528360408301526116616060830184614be4565b6000610100808352614ddc8184018a614a50565b91505060ff8716602083015260ff86166040830152846060830152836080830152611f0560a0830184614be4565b600060c08252614e1d60c0830188614a89565b8281036020840152614e2f8188614afd565b838103604085015285815290506001600160fb1b03851115614e4f578182fd5b602085028087602084013701602001908152614e6e6060830184614be4565b9695505050505050565b600060c08252614daa60c0830187614a89565b604080825283519082018190526000906020906060840190828701845b82811015614ece57614ebb848351614b6c565b6080939093019290840190600101614ea8565b50505083810382850152614e6e8186614a50565b60c08082528554908201819052600086815260208120909160e0840190835b81811015614f2957614f138385614ba9565b6002939093019260809290920191600101614f01565b5050602084018790526001600160a01b0386166040850152915061166190506060830184614be4565b93845260208401929092526001600160a01b031660408301521515606082015260800190565b85815260208082018690526080604083018190528201849052600090859060a08401835b87811015614fca578335614faf81615c0b565b6001600160a01b031682529282019290820190600101614f9c565b506001600160a01b03959095166060949094019390935250919695505050505050565b600060208252610e9c6020830184614ace565b901515815260200190565b91151582521515602082015260400190565b90815260200190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000602080835283518082850152825b818110156150785785810183015185820160400152820161505c565b818111156150895783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600f908201526e119bdc99d955985b081b1bd8dad959608a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526010908201526f185b1c9958591e481d5c19dc9859195960821b604082015260600190565b6020808252600d908201526c125b9d985b1a5908185cdcd95d609a1b604082015260600190565b60208082526022908201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604082015261636560f01b606082015260800190565b6020808252600d908201526c29bbb0b8103930ba329037b7b160991b604082015260600190565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4d696e74207175616e74697479203c206d696e20717479000000000000000000604082015260600190565b602080825260089082015267125b881c9958dbdb60c21b604082015260600190565b60208082526014908201527362417373657420717479203c206d696e2071747960601b604082015260600190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b602080825260149082015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600c908201526b4e756c6c206164647265737360a01b604082015260600190565b60208082526018908201527f4f757470757420717479203c206d696e696d756d207174790000000000000000604082015260600190565b60208082526017908201527f4d75737420626520736176696e6773206d616e61676572000000000000000000604082015260600190565b6020808252601390820152722932b232b6b83a34b7b7103930ba329037b7b160691b604082015260600190565b60208082526019908201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604082015260600190565b602080825260139082015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b604082015260600190565b6020808252600e908201526d26b0bc103bb2b4b3b43a1037b7b160911b604082015260600190565b602080825260099082015268556e6865616c74687960b81b604082015260600190565b6020808252601690820152754d75737420636f6c6c65637420736f6d657468696e6760501b604082015260600190565b6020808252600e908201526d4d757374206265203c3d2032302560901b604082015260600190565b6020808252600b908201526a04f7574707574203d3d20360ac1b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b60208082526028908201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616040820152676c6c6f77616e636560c01b606082015260800190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b602080825260159082015274496e76616c69642073776170207175616e7469747960581b604082015260600190565b6020808252601490820152735a65726f206d4173736574207175616e7469747960601b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600f908201526e111d5c1b1a58d85d1948185cdcd95d608a1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600e908201526d26b4b7103bb2b4b3b43a1037b7b160911b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601490820152735a65726f206f7574707574207175616e7469747960601b604082015260600190565b60208082526018908201527f4d7573742072656465656d20736f6d65206d4173736574730000000000000000604082015260600190565b6020808252818101527f52656465656d206d417373657420717479203e206d6178207175616e74697479604082015260600190565b60208082526025908201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604082015264207a65726f60d81b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b948552602085019390935260408401919091526001600160a01b031660608301521515608082015260a00190565b60c0810161598b8285614b6c565b610e9c6080830184614b51565b60e081016159a68287614b6c565b6001600160801b03851660808301528360a08301528260c083015295945050505050565b6060810161091a8284614be4565b6001600160801b0392831681529116602082015260400190565b8581526101208101615a076020830187614b6c565b615a1460a0830186614b51565b6001600160a01b039390931660e082015261010001529392505050565b8581526101208101615a076020830187614ba9565b6001600160401b03948516815292841660208401529083166040830152909116606082015260800190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615aa057615aa0615bf5565b604052919050565b60006001600160801b03808316818516808303821115615aca57615aca615bdf565b01949350505050565b60008219821115615ae657615ae6615bdf565b500190565b600082615b0657634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b2557615b25615bdf565b500290565b60006001600160801b0383811690831681811015615b4a57615b4a615bdf565b039392505050565b600082821015615b6457615b64615bdf565b500390565b60006001600160401b0383811690831681811015615b4a57615b4a615bdf565b600281046001821680615b9d57607f821691505b60208210811415615bbe57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615bd857615bd8615bdf565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461267c57600080fdfea26469706673582212204014dbc26b1298e94a14cc814e26ede056b10538e62ff69a29baf25c11068bed64736f6c63430008000033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061030c5760003560e01c80636d5d6eb11161019d578063aa5d27e9116100e9578063cd6ef2b0116100a2578063dd62ed3e1161007c578063dd62ed3e1461069c578063e5555b8f146106af578063edc832b3146106c2578063f74bfe8e146106ca5761030c565b8063cd6ef2b01461066b578063d5bcb9b514610681578063d7d52266146106945761030c565b8063aa5d27e9146105f5578063ab06346c14610608578063af290bd414610628578063bdfbe29c1461063b578063c3f909d41461064e578063c4db7fa0146106635761030c565b8063905e891411610156578063a1c2515111610130578063a1c25151146105a7578063a3f5c1d2146105ba578063a457c2d7146105cf578063a9059cbb146105e25761030c565b8063905e89141461057957806395d89b411461058c578063969642b9146105945761030c565b80636d5d6eb1146105125780636fb3e89c1461052557806370a082311461053857806372ea90761461054b57806378aa987e1461055e5780637e8901ea146105715761030c565b806326bbe60a1161025c57806343bcfab61161021557806354cf2aeb116101ef57806354cf2aeb146104e2578063598362f0146104ea578063674a64e0146105025780636c36581c1461050a5761030c565b806343bcfab6146104b457806344e3fa3c146104c7578063458f5815146104da5761030c565b806326bbe60a1461042f5780632a2fab22146104425780632f91a72414610458578063313ce5671461047857806339509351146104805780633e37bcbc146104935761030c565b806313888565116102c95780631820783d116102a35780631820783d146103dd5780631d3ce398146103f0578063213c501a1461040657806323b872dd1461041c5761030c565b806313888565146103ba57806317036826146103c257806318160ddd146103d55761030c565b80630357359c1461031157806304de5a731461033d57806306fdde031461035d578063095ea7b3146103725780630b78f9c014610392578063119849cf146103a7575b600080fd5b61032461031f366004614896565b6106dd565b6040516103349493929190614c0e565b60405180910390f35b61035061034b366004614774565b61072d565b604051610334919061501d565b61036561086f565b604051610334919061504c565b6103856103803660046146ac565b610902565b6040516103349190615000565b6103a56103a03660046149c9565b610920565b005b6103506103b53660046146ac565b6109b4565b610350610a78565b6103a56103d03660046145ed565b610a7e565b610350610c1d565b6103a56103eb366004614896565b610c23565b6103f8610c93565b604051610334929190614e8b565b61040e610df0565b6040516103349291906159d8565b61038561042a36600461451e565b610e0a565b6103a561043d3660046144ae565b610ea3565b61044a610f46565b6040516103349291906158fa565b61046b6104663660046144ae565b610ffd565b6040516103349190615a71565b61046b611012565b61038561048e3660046146ac565b61101b565b6104a66104a13660046144ae565b61106a565b60405161033492919061597d565b6103506104c23660046146d7565b6111f5565b6103a56104d53660046149c9565b61125e565b6103506112e2565b6103506112e8565b6104f26112ee565b6040516103349493929190615a46565b61035061131c565b61046b611322565b61040e610520366004614896565b61132b565b6103a5610533366004614720565b611360565b6103506105463660046144ae565b6113de565b61035061055936600461451e565b6113fd565b61035061056c3660046146ac565b611583565b61044a61166a565b6103a56105873660046145bc565b611816565b610365611860565b6103a56105a23660046144ae565b61186f565b6103a56105b5366004614864565b6118ea565b6105c26119f7565b6040516103349190614bfa565b6103856105dd3660046146ac565b611a1b565b6103856105f03660046146ac565b611a96565b6103506106033660046147dc565b611aaa565b61061b6106163660046148c6565b611b7a565b6040516103349190614fed565b6103506106363660046147dc565b611bc7565b6103a56106493660046145bc565b611c79565b610656611cc0565b60405161033491906159ca565b6103a5611cd5565b610673611d50565b60405161033492919061500b565b61035061068f36600461455e565b611d63565b6105c2611dce565b6103506106aa3660046144e6565b611ddd565b6103506106bd366004614774565b611e08565b610673611f10565b6103506106d83660046146d7565b611f22565b604981815481106106ed57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b90041684565b600081801580159061073e57508085145b6107635760405162461bcd60e51b815260040161075a90615467565b60405180910390fd5b60006107a1878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f6f92505050565b506042549091506000906001600160a01b031663d176d694604a8489896107c6612185565b6040518663ffffffff1660e01b81526004016107e6959493929190614e0a565b60206040518083038186803b1580156107fe57600080fd5b505afa158015610812573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083691906148ae565b9050610858604454670de0b6b3a76400006108519190615b52565b82906121d7565b610863906001615ad3565b98975050505050505050565b60606036805461087e90615b89565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90615b89565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b505050505090505b90565b600061091661090f6121f6565b84846121fa565b5060015b92915050565b6109286122ae565b60455482111561094a5760405162461bcd60e51b815260040161075a9061519e565b60455481111561096c5760405162461bcd60e51b815260040161075a90615403565b604482905560468190556040517f64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068906109a890849084906158fa565b60405180910390a15050565b60008082116109d55760405162461bcd60e51b815260040161075a9061578d565b60006109e0846122e8565b506042549091506001600160a01b0316637910213b604a8386610a01612185565b6040518563ffffffff1660e01b8152600401610a209493929190614e78565b60206040518083038186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7091906148ae565b949350505050565b60485481565b6043546001600160a01b0316610aa65760405162461bcd60e51b815260040161075a9061510b565b604380546001600160a01b0319808216909255604d805460ff19166001179055604280546001600160a01b0386811691909416179055604051637fe405b760e01b815291169073da681d409319b1f4122b1402c8b5cd4baedf900190637fe405b790610b1f908490604990604a90604b90600401615026565b60006040518083038186803b158015610b3757600080fd5b505af4158015610b4b573d6000803e3d6000fd5b5050604c805460ff1916600a17905550508151600090610b7690610b7190606490615b0b565b612412565b604080516080810182526001600160401b039290921680835260208084018290526000928401839052606090930191909152604e805467ffffffffffffffff191682176fffffffffffffffff00000000000000001916600160401b909202919091176001600160801b03908116909155938101518051604f805492909301516001600160801b0319909216908616178516600160801b919095160293909317909255505050565b60355490565b610c2b6122ae565b6702c68af0bb140000811115610c535760405162461bcd60e51b815260040161075a9061550f565b60478190556040517f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe790610c8890839061501d565b60405180910390a150565b6060806049604a81805480602002602001604051908101604052809291908181526020016000905b82821015610d72576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610d4057634e487b7160e01b600052602160045260246000fd5b6007811115610d5f57634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610cbb565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610de257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610d99565b505050509050915091509091565b604f546001600160801b0380821691600160801b90041682565b6000610e1784848461243b565b6001600160a01b038416600090815260346020526040812081610e386121f6565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905082811015610e7b5760405162461bcd60e51b815260040161075a906155a2565b610e9685610e876121f6565b610e918685615b52565b6121fa565b60019150505b9392505050565b610eab6122ae565b604254600160a01b900460ff1615610ed55760405162461bcd60e51b815260040161075a9061509f565b6001600160a01b038116610efb5760405162461bcd60e51b815260040161075a9061536f565b604280546001600160a01b0319166001600160a01b0383161790556040517f2e137a82d7f7fe8a4c453313f3d08557c162ad9d78219a2e937e318b41e12f7a90610c88908390614bfa565b600080610f51612558565b6048546001811115610fee57610f68600182615b52565b60016048559250610f793384612587565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015610fc8578160200160208202803683370190505b5060408051600081526020810191829052610fe594939291614cc9565b60405180910390a25b610ff6610c1d565b9150509091565b604b6020526000908152604090205460ff1681565b60385460ff1690565b60006109166110286121f6565b8484603460006110366121f6565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610e919190615ad3565b6110726143d5565b61107a6143fd565b6001600160a01b0383166000908152604b60205260409020546049805460ff90921691829081106110bb57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561113957634e487b7160e01b600052602160045260246000fd5b600781111561115857634e487b7160e01b600052602160045260246000fd5b815250509250836001600160a01b031683600001516001600160a01b0316146111935760405162461bcd60e51b815260040161075a90615135565b604a8160ff16815481106111b757634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b604154600090600160a01b900460ff166112215760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b1916905561123661263b565b6112428585858561267f565b6041805460ff60a01b1916600160a01b17905595945050505050565b6112666122ae565b731e91f826fa8aa4fa4d3f595898af3a64dd18884863e2a5f044604e848461128c6129e1565b60646040518663ffffffff1660e01b81526004016112ae959493929190615908565b60006040518083038186803b1580156112c657600080fd5b505af41580156112da573d6000803e3d6000fd5b505050505050565b60465481565b60445481565b604e546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b60475481565b604c5460ff1681565b604a818154811061133b57600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6113686122ae565b60405163a5bee44b60e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063a5bee44b906113a990604990604b90889088908890600401614f78565b60006040518083038186803b1580156113c157600080fd5b505af41580156113d5573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152603360205260409020545b919050565b6000826001600160a01b0316846001600160a01b031614156114315760405162461bcd60e51b815260040161075a906151c5565b600082116114515760405162461bcd60e51b815260040161075a90615615565b6000604a805480602002602001604051908101604052809291908181526020016000905b828210156114be57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611475565b50505050905060006114cf866122e8565b50905060006114dd866122e8565b506042546044549192506001600160a01b031690630e3c01d3908590859085908a90611507612185565b6040518763ffffffff1660e01b815260040161152896959493929190614dc8565b604080518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157791906149ea565b50979650505050505050565b60008082116115a45760405162461bcd60e51b815260040161075a9061578d565b60006115af846122e8565b50905060006115c960445485612b1e90919063ffffffff16565b6042549091506001600160a01b03166350494dc0604a846115ea8589615b52565b6115f2612185565b6040518563ffffffff1660e01b81526004016116119493929190614e78565b60206040518083038186803b15801561162957600080fd5b505afa15801561163d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166191906148ae565b95945050505050565b600080611675612558565b61167d612b33565b604154600160a01b900460ff166116a65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055604254606090731e91f826fa8aa4fa4d3f595898af3a64dd18884890638b8029b490604990604a906001600160a01b03166116ec612185565b6040518563ffffffff1660e01b815260040161170b9493929190614ee2565b60006040518083038186803b15801561172357600080fd5b505af4158015611737573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261175f9190810190614917565b9093509050826117815760405162461bcd60e51b815260040161075a906154df565b61178b3384612587565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc338560006040519080825280602002602001820160405280156117da578160200160208202803683370190505b50856040516117ec9493929190614cc9565b60405180910390a26117fc610c1d565b6041805460ff60a01b1916600160a01b1790559293915050565b61181e6122ae565b60405163ee60ee2b60e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063ee60ee2b906112ae90604d90604990604b908890889060040161594f565b60606037805461087e90615b89565b6118776122ae565b604051634c1e9da160e11b8152731e91f826fa8aa4fa4d3f595898af3a64dd1888489063983d3b42906118b790604d90604990604b90879060040161592b565b60006040518083038186803b1580156118cf57600080fd5b505af41580156118e3573d6000803e3d6000fd5b5050505050565b6118f26122ae565b604a54611900906002615b0b565b61191290670de0b6b3a7640000615aeb565b826001600160801b0316111561193a5760405162461bcd60e51b815260040161075a90615721565b604a5461194990600190615b52565b61195b90670de0b6b3a7640000615aeb565b816001600160801b031610156119835760405162461bcd60e51b815260040161075a90615494565b6040805180820182526001600160801b038481168083528482166020909301839052604f80546001600160801b031916909117909116600160801b909202919091179055517f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136906109a890849084906159d8565b7f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b60008060346000611a2a6121f6565b6001600160a01b0390811682526020808301939093526040918201600090812091881681529252902054905082811015611a765760405162461bcd60e51b815260040161075a9061587e565b611a8c611a816121f6565b85610e918685615b52565b5060019392505050565b6000610916611aa36121f6565b848461243b565b604154600090600160a01b900460ff16611ad65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611aeb61263b565b611b5c87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a925089918291850190849080828437600092019190915250889250879150612b849050565b6041805460ff60a01b1916600160a01b179055979650505050505050565b604154606090600160a01b900460ff16611ba65760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611bbb61263b565b61124285858585612ff4565b604154600090600160a01b900460ff16611bf35760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611c08612b33565b611b5c87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506134df9050565b611c816122ae565b604051638d18aef960e01b8152731e91f826fa8aa4fa4d3f595898af3a64dd18884890638d18aef9906112ae90604990604b9087908790600401614f52565b611cc8614414565b611cd0612185565b905090565b611cdd6122ae565b731e91f826fa8aa4fa4d3f595898af3a64dd1888486318068e40604e611d016129e1565b6040518363ffffffff1660e01b8152600401611d1e9291906158fa565b60006040518083038186803b158015611d3657600080fd5b505af4158015611d4a573d6000803e3d6000fd5b50505050565b604d5460ff808216916101009004169091565b604154600090600160a01b900460ff16611d8f5760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611da4612b33565b611db1868686868661394b565b6041805460ff60a01b1916600160a01b1790559695505050505050565b6042546001600160a01b031681565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000818015801590611e1957508085145b611e355760405162461bcd60e51b815260040161075a906152fa565b6000611e73878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f6f92505050565b506042549091506001600160a01b031663b7ecbf72604a838888611e95612185565b6040518663ffffffff1660e01b8152600401611eb5959493929190614e0a565b60206040518083038186803b158015611ecd57600080fd5b505afa158015611ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0591906148ae565b979650505050505050565b604d5460ff8082169161010090041682565b604154600090600160a01b900460ff16611f4e5760405162461bcd60e51b815260040161075a906157ad565b6041805460ff60a01b19169055611f63612b33565b61124285858585613e31565b80516060908190806001600160401b03811115611f9c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611fc5578160200160208202803683370190505b509250806001600160401b03811115611fee57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561202757816020015b6120146143d5565b81526020019060019003908161200c5790505b50915060005b8181101561217e5761206585828151811061205857634e487b7160e01b600052603260045260246000fd5b60200260200101516122e8565b85838151811061208557634e487b7160e01b600052603260045260246000fd5b602002602001018584815181106120ac57634e487b7160e01b600052603260045260246000fd5b602090810291909101019190915260ff909116905260006120ce826001615ad3565b90505b8281101561216b578581815181106120f957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061212a57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156121595760405162461bcd60e51b815260040161075a906156b3565b8061216381615bc4565b9150506120d1565b508061217681615bc4565b91505061202d565b5050915091565b61218d614414565b60405180604001604052806121a06129e1565b815260408051808201909152604f546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b6000816121ec670de0b6b3a764000085615b0b565b610e9c9190615aeb565b3390565b6001600160a01b0383166122205760405162461bcd60e51b815260040161075a90615749565b6001600160a01b0382166122465760405162461bcd60e51b815260040161075a906151eb565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906122a190859061501d565b60405180910390a3505050565b6122b661414e565b6001600160a01b0316336001600160a01b0316146122e65760405162461bcd60e51b815260040161075a90615430565b565b60006122f26143d5565b6001600160a01b0383166000908152604b60205260409020546049805460ff9092169350908390811061233557634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156123b357634e487b7160e01b600052602160045260246000fd5b60078111156123d257634e487b7160e01b600052602160045260246000fd5b815250509050826001600160a01b031681600001516001600160a01b03161461240d5760405162461bcd60e51b815260040161075a90615135565b915091565b6000600160401b82106124375760405162461bcd60e51b815260040161075a9061555c565b5090565b6001600160a01b0383166124615760405162461bcd60e51b815260040161075a906156dc565b6001600160a01b0382166124875760405162461bcd60e51b815260040161075a906150c8565b6001600160a01b038316600090815260336020526040902054818110156124c05760405162461bcd60e51b815260040161075a906152b4565b6124ca8282615b52565b6001600160a01b038086166000908152603360205260408082209390935590851681529081208054849290612500908490615ad3565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161254a919061501d565b60405180910390a350505050565b336125616141e1565b6001600160a01b0316146122e65760405162461bcd60e51b815260040161075a906153cc565b6001600160a01b0382166125ad5760405162461bcd60e51b815260040161075a906158c3565b80603560008282546125bf9190615ad3565b90915550506001600160a01b038216600090815260336020526040812080548392906125ec908490615ad3565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061262f90859061501d565b60405180910390a35050565b60408051808201909152604d5460ff8082161580158452610100909204161515602083015261267c5760405162461bcd60e51b815260040161075a90615264565b50565b60006001600160a01b0382166126a75760405162461bcd60e51b815260040161075a906155ea565b600084116126c75760405162461bcd60e51b815260040161075a9061578d565b6000604a805480602002602001604051908101604052809291908181526020016000905b8282101561273457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016126eb565b505050509050600080612746886122e8565b91509150600061276160445489612b1e90919063ffffffff16565b6042549091506001600160a01b03166350494dc08585612781858d615b52565b612789612185565b6040518563ffffffff1660e01b81526004016127a89493929190614d97565b60206040518083038186803b1580156127c057600080fd5b505afa1580156127d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f891906148ae565b94508685101561281a5760405162461bcd60e51b815260040161075a90615286565b6000851161283a5760405162461bcd60e51b815260040161075a90615537565b6128443389614268565b80604860008282546128569190615ad3565b9091555060009050612866614342565b9050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548785888860ff16815181106128a757634e487b7160e01b600052603260045260246000fd5b60200260200101518b86602001516040518663ffffffff1660e01b81526004016128d59594939291906159f2565b60006040518083038186803b1580156128ed57600080fd5b505af4158015612901573d6000803e3d6000fd5b5050505061290e86614399565b858560ff168151811061293157634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516129479190615b2a565b604a8560ff168154811061296b57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055825160405133917f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad8916129cc918b918e91908c908990614c95565b60405180910390a25050505050949350505050565b60408051608081018252604e546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b90910416606082018190526000929042811115612b0b5782516040840151600080612a546001600160401b03841642615b52565b612a5e8487615b69565b6001600160401b031691509150836001600160401b0316866001600160401b03161115612acf578082612a918689615b69565b6001600160401b0316612aa49190615b0b565b612aae9190615aeb565b612ac1906001600160401b038616615ad3565b9750505050505050506108ff565b8082612adb8887615b69565b6001600160401b0316612aee9190615b0b565b612af89190615aeb565b612ac1906001600160401b038616615b52565b506001600160401b031691506108ff9050565b6000610e9c8383670de0b6b3a76400006143be565b60408051808201909152604d5460ff8082161580158085526101009093049091161515602084015290612b6857508060200151155b61267c5760405162461bcd60e51b815260040161075a906154bc565b60006001600160a01b038216612bac5760405162461bcd60e51b815260040161075a906155ea565b83518015801590612bbd5750855181145b612bd95760405162461bcd60e51b815260040161075a90615467565b60008411612bf95760405162461bcd60e51b815260040161075a9061578d565b600080612c0588611f6f565b915091506000604a805480602002602001604051908101604052809291908181526020016000905b82821015612c7657600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612c2d565b50506042549293506000926001600160a01b0316915063d176d694905083868c612c9e612185565b6040518563ffffffff1660e01b8152600401612cbd9493929190614d4e565b60206040518083038186803b158015612cd557600080fd5b505afa158015612ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d0d91906148ae565b9050612d28604454670de0b6b3a76400006108519190615b52565b95506000612d368288615b52565b905060008711612d585760405162461bcd60e51b815260040161075a90615812565b612d63600188615ad3565b965088871115612d855760405162461bcd60e51b815260040161075a90615849565b612d8f3388614268565b8060486000828254612da19190615ad3565b9091555060009050612db1614342565b905060005b87811015612f9b576000878281518110612de057634e487b7160e01b600052603260045260246000fd5b60200260200101519050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548e8481518110612e2457634e487b7160e01b600052603260045260246000fd5b6020026020010151898581518110612e4c57634e487b7160e01b600052603260045260246000fd5b6020026020010151898560ff1681518110612e7757634e487b7160e01b600052603260045260246000fd5b60200260200101518f88602001516040518663ffffffff1660e01b8152600401612ea59594939291906159f2565b60006040518083038186803b158015612ebd57600080fd5b505af4158015612ed1573d6000803e3d6000fd5b50505050612f058d8381518110612ef857634e487b7160e01b600052603260045260246000fd5b6020026020010151614399565b868260ff1681518110612f2857634e487b7160e01b600052603260045260246000fd5b602002602001015160200151612f3e9190615b2a565b604a8260ff1681548110612f6257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080612f9381615bc4565b915050612db6565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8a8f8f87604051612fdd959493929190614d02565b60405180910390a250505050505050949350505050565b60606001600160a01b03821661301c5760405162461bcd60e51b815260040161075a906155ea565b6000851161303c5760405162461bcd60e51b815260040161075a9061578d565b600061305360465487612b1e90919063ffffffff16565b905060006130618288615b52565b905061306d3388614268565b816048600082825461307f9190615ad3565b909155506000905061308f614342565b905060008282600001516130a39190615ad3565b90506000604a805480602002602001604051908101604052809291908181526020016000905b8282101561311257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016130c9565b5050505090506000815190506000816001600160401b0381111561314657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561316f578160200160208202803683370190505b509050816001600160401b0381111561319857634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156131c1578160200160208202803683370190505b50975060005b8281101561349d57600085888684815181106131f357634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b03166132129190615b0b565b61321c9190615aeb565b90506001811161323e5760405162461bcd60e51b815260040161075a90615537565b613249600182615b52565b90508c8c8381811061326b57634e487b7160e01b600052603260045260246000fd5b905060200201358110156132915760405162461bcd60e51b815260040161075a90615286565b80604983815481106132b357634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201548b516001600160a01b03909116908c90859081106132f257634e487b7160e01b600052603260045260246000fd5b6020026020010185858151811061331957634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b0316815250828152505050731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a54826049858154811061337857634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202018886815181106133a657634e487b7160e01b600052603260045260246000fd5b60200260200101518f8c602001516040518663ffffffff1660e01b81526004016133d4959493929190615a31565b60006040518083038186803b1580156133ec57600080fd5b505af4158015613400573d6000803e3d6000fd5b5050505061340d81614399565b85838151811061342d57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516134439190615b2a565b604a838154811061346457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055508061349581615bc4565b9150506131c7565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8e848c8c604051612fdd959493929190614d02565b60006001600160a01b0382166135075760405162461bcd60e51b815260040161075a906155ea565b835180158015906135185750855181145b6135345760405162461bcd60e51b815260040161075a906152fa565b60008061354088611f6f565b915091506000604a805480602002602001604051908101604052809291908181526020016000905b828210156135b157600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613568565b50505050905060006135c1614342565b90506000856001600160401b038111156135eb57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613614578160200160208202803683370190505b50905060005b8681101561381e5760008b828151811061364457634e487b7160e01b600052603260045260246000fd5b60200260200101519050600081111561380b57600087838151811061367957634e487b7160e01b600052603260045260246000fd5b602002602001015190506000868260ff16815181106136a857634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008885815181106136d457634e487b7160e01b600052603260045260246000fd5b602002602001015190506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d3913838560000151888c602001516040518563ffffffff1660e01b81526004016137259493929190615998565b60206040518083038186803b15801561373d57600080fd5b505af4158015613751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377591906148ae565b90508087878151811061379857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506137ad81614399565b83602001516137bc9190615aa8565b604a8560ff16815481106137e057634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055505050505b508061381681615bc4565b91505061361a565b506042546001600160a01b031663b7ecbf7284878461383b612185565b6040518563ffffffff1660e01b815260040161385a9493929190614d4e565b60206040518083038186803b15801561387257600080fd5b505afa158015613886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138aa91906148ae565b9650888710156138cc5760405162461bcd60e51b815260040161075a9061522d565b600087116138ec5760405162461bcd60e51b815260040161075a90615644565b6138f68888612587565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc89898e8e6040516139359493929190614cc9565b60405180910390a2505050505050949350505050565b60006001600160a01b0382166139735760405162461bcd60e51b815260040161075a906155ea565b846001600160a01b0316866001600160a01b031614156139a55760405162461bcd60e51b815260040161075a906151c5565b600084116139c55760405162461bcd60e51b815260040161075a90615615565b6000604a805480602002602001604051908101604052809291908181526020016000905b82821015613a3257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016139e9565b505050509050600080613a44896122e8565b91509150600080613a548a6122e8565b915091506000613a62614342565b90506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d391386898960ff1681518110613aa457634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518e86602001516040518563ffffffff1660e01b8152600401613ad59493929190615998565b60206040518083038186803b158015613aed57600080fd5b505af4158015613b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2591906148ae565b9050613b3081614399565b878760ff1681518110613b5357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613b699190615aa8565b604a8760ff1681548110613b8d57634e487b7160e01b600052603260045260246000fd5b6000918252602082200180546001600160801b03938416600160801b029316929092179091556042546044546001600160a01b0390911690630e3c01d3908a908a9089908790613bdb612185565b6040518763ffffffff1660e01b8152600401613bfc96959493929190614dc8565b604080518083038186803b158015613c1357600080fd5b505afa158015613c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c4b91906149ea565b90995090508a891015613c705760405162461bcd60e51b815260040161075a90615395565b60008911613c905760405162461bcd60e51b815260040161075a906157e4565b731e91f826fa8aa4fa4d3f595898af3a64dd188848634e331a548a868b8960ff1681518110613ccf57634e487b7160e01b600052603260045260246000fd5b60200260200101518e88602001516040518663ffffffff1660e01b8152600401613cfd9594939291906159f2565b60006040518083038186803b158015613d1557600080fd5b505af4158015613d29573d6000803e3d6000fd5b50505050613d3689614399565b888660ff1681518110613d5957634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613d6f9190615b2a565b604a8660ff1681548110613d9357634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790556040830151613dc9908290615ad3565b604881905550336001600160a01b03167f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d876000015186600001518c858f604051613e18959493929190614c3b565b60405180910390a2505050505050505095945050505050565b60006001600160a01b038216613e595760405162461bcd60e51b815260040161075a906155ea565b60008411613e795760405162461bcd60e51b815260040161075a9061578d565b6000604a805480602002602001604051908101604052809291908181526020016000905b82821015613ee657600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613e9d565b505050509050600080613ef8886122e8565b915091506000613f06614342565b90506000731e91f826fa8aa4fa4d3f595898af3a64dd188848634e3d391384878760ff1681518110613f4857634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518c86602001516040518563ffffffff1660e01b8152600401613f799493929190615998565b60206040518083038186803b158015613f9157600080fd5b505af4158015613fa5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fc991906148ae565b6042549091506001600160a01b0316637910213b868684613fe8612185565b6040518563ffffffff1660e01b81526004016140079493929190614d97565b60206040518083038186803b15801561401f57600080fd5b505afa158015614033573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061405791906148ae565b9550878610156140795760405162461bcd60e51b815260040161075a9061522d565b61408281614399565b858560ff16815181106140a557634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516140bb9190615aa8565b604a8560ff16815481106140df57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905561410f8787612587565b336001600160a01b03167f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c788888d856040516129cc9493929190614c6b565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156141a957600080fd5b505afa1580156141bd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd091906144ca565b6040516385acd64160e01b81526000906001600160a01b037f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb316906385acd64190614250907f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf19060040161501d565b60206040518083038186803b1580156141a957600080fd5b6001600160a01b03821661428e5760405162461bcd60e51b815260040161075a90615672565b6001600160a01b038216600090815260336020526040902054818110156142c75760405162461bcd60e51b815260040161075a9061515c565b6142d18282615b52565b6001600160a01b038416600090815260336020526040812091909155603580548492906142ff908490615b52565b90915550506040516000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906122a190869061501d565b61434a61442e565b604854600081614358610c1d565b6143629190615ad3565b9050604051806060016040528082815260200161438a60475484612b1e90919063ffffffff16565b81526020019290925250905090565b6000600160801b82106124375760405162461bcd60e51b815260040161075a90615328565b6000816143cb8486615b0b565b610a709190615aeb565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604080518082019091526000808252602082015290565b6040518060400160405280600081526020016143f86143fd565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f840112614460578081fd5b5081356001600160401b03811115614476578182fd5b602083019150836020808302850101111561449057600080fd5b9250929050565b80356001600160801b03811681146113f857600080fd5b6000602082840312156144bf578081fd5b8135610e9c81615c0b565b6000602082840312156144db578081fd5b8151610e9c81615c0b565b600080604083850312156144f8578081fd5b823561450381615c0b565b9150602083013561451381615c0b565b809150509250929050565b600080600060608486031215614532578081fd5b833561453d81615c0b565b9250602084013561454d81615c0b565b929592945050506040919091013590565b600080600080600060a08688031215614575578081fd5b853561458081615c0b565b9450602086013561459081615c0b565b9350604086013592506060860135915060808601356145ae81615c0b565b809150509295509295909350565b600080604083850312156145ce578182fd5b82356145d981615c0b565b915060208301358015158114614513578182fd5b6000808284036080811215614600578283fd5b833561460b81615c0b565b92506060601f198201121561461e578182fd5b604080518181016001600160401b03828210818311171561464157614641615bf5565b8184526020880135835283603f198601121561465b578586fd5b835194508385019150848210818311171561467857614678615bf5565b508252614686868301614497565b835261469460608701614497565b60208401528260208201528093505050509250929050565b600080604083850312156146be578182fd5b82356146c981615c0b565b946020939093013593505050565b600080600080608085870312156146ec578384fd5b84356146f781615c0b565b93506020850135925060408501359150606085013561471581615c0b565b939692955090935050565b600080600060408486031215614734578283fd5b83356001600160401b03811115614749578384fd5b6147558682870161444f565b909450925050602084013561476981615c0b565b809150509250925092565b60008060008060408587031215614789578182fd5b84356001600160401b038082111561479f578384fd5b6147ab8883890161444f565b909650945060208701359150808211156147c3578384fd5b506147d08782880161444f565b95989497509550505050565b600080600080600080608087890312156147f4578384fd5b86356001600160401b038082111561480a578586fd5b6148168a838b0161444f565b9098509650602089013591508082111561482e578586fd5b5061483b89828a0161444f565b90955093505060408701359150606087013561485681615c0b565b809150509295509295509295565b60008060408385031215614876578182fd5b61487f83614497565b915061488d60208401614497565b90509250929050565b6000602082840312156148a7578081fd5b5035919050565b6000602082840312156148bf578081fd5b5051919050565b600080600080606085870312156148db578182fd5b8435935060208501356001600160401b038111156148f7578283fd5b6149038782880161444f565b909450925050604085013561471581615c0b565b60008060408385031215614929578182fd5b825191506020808401516001600160401b0380821115614947578384fd5b818601915086601f83011261495a578384fd5b81518181111561496c5761496c615bf5565b838102915061497c848301615a7f565b8181528481019084860184860187018b1015614996578788fd5b8795505b838610156149b857805183526001959095019491860191860161499a565b508096505050505050509250929050565b600080604083850312156149db578182fd5b50508035926020909101359150565b600080604083850312156149fc578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b83811015614a455781516001600160a01b031687529582019590820190600101614a20565b509495945050505050565b6000815180845260208085019450808401835b83811015614a4557614a76878351614b51565b6040969096019590820190600101614a63565b6000815480845260208085019450838352808320835b83811015614a455781546001600160801b038116885260801c8388015260409096019560019182019101614a9f565b6000815180845260208085019450808401835b83811015614a4557815187529582019590820190600101614ae1565b6000815180845260208085019450808401835b83811015614a4557815160ff1687529582019590820190600101614b10565b60088110614b4d57634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160801b03908116835260209182015116910152565b60018060a01b03808251168352806020830151166020840152506040810151151560408301526060810151614ba46060840182614b2f565b505050565b60018060a01b038082541683526001820154818116602085015260ff8160a01c1615156040850152611d4a6060850160ff8360a81c16614b2f565b805182526020810151614ba46020840182614b51565b6001600160a01b0391909116815260200190565b6001600160a01b038581168252841660208201528215156040820152608081016116616060830184614b2f565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b03958616815260208101949094529190931660408301526060820192909252608081019190915260a00190565b600060018060a01b038616825284602083015260806040830152614cf06080830185614a0d565b8281036060840152611f058185614ace565b600060018060a01b038716825285602083015260a06040830152614d2960a0830186614a0d565b8281036060840152614d3b8186614ace565b9150508260808301529695505050505050565b600060c08252614d6160c0830187614a50565b8281036020840152614d738187614afd565b90508281036040840152614d878186614ace565b9150506116616060830184614be4565b600060c08252614daa60c0830187614a50565b905060ff851660208301528360408301526116616060830184614be4565b6000610100808352614ddc8184018a614a50565b91505060ff8716602083015260ff86166040830152846060830152836080830152611f0560a0830184614be4565b600060c08252614e1d60c0830188614a89565b8281036020840152614e2f8188614afd565b838103604085015285815290506001600160fb1b03851115614e4f578182fd5b602085028087602084013701602001908152614e6e6060830184614be4565b9695505050505050565b600060c08252614daa60c0830187614a89565b604080825283519082018190526000906020906060840190828701845b82811015614ece57614ebb848351614b6c565b6080939093019290840190600101614ea8565b50505083810382850152614e6e8186614a50565b60c08082528554908201819052600086815260208120909160e0840190835b81811015614f2957614f138385614ba9565b6002939093019260809290920191600101614f01565b5050602084018790526001600160a01b0386166040850152915061166190506060830184614be4565b93845260208401929092526001600160a01b031660408301521515606082015260800190565b85815260208082018690526080604083018190528201849052600090859060a08401835b87811015614fca578335614faf81615c0b565b6001600160a01b031682529282019290820190600101614f9c565b506001600160a01b03959095166060949094019390935250919695505050505050565b600060208252610e9c6020830184614ace565b901515815260200190565b91151582521515602082015260400190565b90815260200190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000602080835283518082850152825b818110156150785785810183015185820160400152820161505c565b818111156150895783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600f908201526e119bdc99d955985b081b1bd8dad959608a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526010908201526f185b1c9958591e481d5c19dc9859195960821b604082015260600190565b6020808252600d908201526c125b9d985b1a5908185cdcd95d609a1b604082015260600190565b60208082526022908201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604082015261636560f01b606082015260800190565b6020808252600d908201526c29bbb0b8103930ba329037b7b160991b604082015260600190565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4d696e74207175616e74697479203c206d696e20717479000000000000000000604082015260600190565b602080825260089082015267125b881c9958dbdb60c21b604082015260600190565b60208082526014908201527362417373657420717479203c206d696e2071747960601b604082015260600190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b602080825260149082015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600c908201526b4e756c6c206164647265737360a01b604082015260600190565b60208082526018908201527f4f757470757420717479203c206d696e696d756d207174790000000000000000604082015260600190565b60208082526017908201527f4d75737420626520736176696e6773206d616e61676572000000000000000000604082015260600190565b6020808252601390820152722932b232b6b83a34b7b7103930ba329037b7b160691b604082015260600190565b60208082526019908201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604082015260600190565b602080825260139082015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b604082015260600190565b6020808252600e908201526d26b0bc103bb2b4b3b43a1037b7b160911b604082015260600190565b602080825260099082015268556e6865616c74687960b81b604082015260600190565b6020808252601690820152754d75737420636f6c6c65637420736f6d657468696e6760501b604082015260600190565b6020808252600e908201526d4d757374206265203c3d2032302560901b604082015260600190565b6020808252600b908201526a04f7574707574203d3d20360ac1b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b60208082526028908201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616040820152676c6c6f77616e636560c01b606082015260800190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b602080825260159082015274496e76616c69642073776170207175616e7469747960581b604082015260600190565b6020808252601490820152735a65726f206d4173736574207175616e7469747960601b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600f908201526e111d5c1b1a58d85d1948185cdcd95d608a1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600e908201526d26b4b7103bb2b4b3b43a1037b7b160911b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601490820152735a65726f206f7574707574207175616e7469747960601b604082015260600190565b60208082526018908201527f4d7573742072656465656d20736f6d65206d4173736574730000000000000000604082015260600190565b6020808252818101527f52656465656d206d417373657420717479203e206d6178207175616e74697479604082015260600190565b60208082526025908201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604082015264207a65726f60d81b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b948552602085019390935260408401919091526001600160a01b031660608301521515608082015260a00190565b60c0810161598b8285614b6c565b610e9c6080830184614b51565b60e081016159a68287614b6c565b6001600160801b03851660808301528360a08301528260c083015295945050505050565b6060810161091a8284614be4565b6001600160801b0392831681529116602082015260400190565b8581526101208101615a076020830187614b6c565b615a1460a0830186614b51565b6001600160a01b039390931660e082015261010001529392505050565b8581526101208101615a076020830187614ba9565b6001600160401b03948516815292841660208401529083166040830152909116606082015260800190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615aa057615aa0615bf5565b604052919050565b60006001600160801b03808316818516808303821115615aca57615aca615bdf565b01949350505050565b60008219821115615ae657615ae6615bdf565b500190565b600082615b0657634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615b2557615b25615bdf565b500290565b60006001600160801b0383811690831681811015615b4a57615b4a615bdf565b039392505050565b600082821015615b6457615b64615bdf565b500390565b60006001600160401b0383811690831681811015615b4a57615b4a615bdf565b600281046001821680615b9d57607f821691505b60208210811415615bbe57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615bd857615bd8615bdf565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461267c57600080fdfea26469706673582212204014dbc26b1298e94a14cc814e26ede056b10538e62ff69a29baf25c11068bed64736f6c63430008000033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Deployed Bytecode Sourcemap
79426:40987:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81433:38;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;101165:687;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;15719:83::-;;;:::i;:::-;;;;;;;:::i;9275:169::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;117033:349::-;;;;;;:::i;:::-;;:::i;:::-;;86976:357;;;;;;:::i;:::-;;:::i;81339:22::-;;;:::i;82345:1061::-;;;;;;:::i;:::-;;:::i;8228:108::-;;;:::i;116062:218::-;;;;;;:::i;:::-;;:::i;109056:209::-;;;:::i;:::-;;;;;;;;:::i;81744:32::-;;;:::i;:::-;;;;;;;;:::i;9926:422::-;;;;;;:::i;:::-;;:::i;116509:354::-;;;;;;:::i;:::-;;:::i;113796:868::-;;;:::i;:::-;;;;;;;;:::i;81515:55::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;16571:83::-;;;:::i;10757:215::-;;;;;;:::i;:::-;;:::i;109498:353::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;97805:326::-;;;;;;:::i;:::-;;:::i;120000:174::-;;;;;;:::i;:::-;;:::i;81246:28::-;;;:::i;81160:22::-;;;:::i;81715:::-;;;:::i;:::-;;;;;;;;;;:::i;81308:24::-;;;:::i;81577:23::-;;;:::i;81478:30::-;;;;;;:::i;:::-;;:::i;118786:240::-;;;;;;:::i;:::-;;:::i;8399:127::-;;;;;;:::i;:::-;;:::i;93512:792::-;;;;;;:::i;:::-;;:::i;100329:512::-;;;;;;:::i;:::-;;:::i;114999:663::-;;;:::i;119350:177::-;;;;;;:::i;:::-;;:::i;15921:87::-;;;:::i;119651:154::-;;;;;;:::i;:::-;;:::i;117553:336::-;;;;;;:::i;:::-;;:::i;19243:29::-;;;:::i;:::-;;;;;;;:::i;11475:377::-;;;;;;:::i;:::-;;:::i;8739:175::-;;;;;;:::i;:::-;;:::i;99570:441::-;;;;;;:::i;:::-;;:::i;98548:331::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;86328:348::-;;;;;;:::i;:::-;;:::i;118138:182::-;;;;;;:::i;:::-;;:::i;109950:113::-;;;:::i;:::-;;;;;;;:::i;120313:97::-;;;:::i;108735:130::-;;;:::i;:::-;;;;;;;;:::i;92698:345::-;;;;;;:::i;:::-;;:::i;80925:41::-;;;:::i;8977:151::-;;;;;;:::i;:::-;;:::i;87703:480::-;;;;;;:::i;:::-;;:::i;81607:25::-;;;:::i;85265:312::-;;;;;;:::i;:::-;;:::i;81433:38::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;81433:38:0;;;;-1:-1:-1;81433:38:0;;;;;-1:-1:-1;;;81433:38:0;;;;;-1:-1:-1;;;81433:38:0;;;;:::o;101165:687::-;101326:22;101375:17;101418:7;;;;;:33;;-1:-1:-1;101429:22:0;;;101418:33;101410:65;;;;-1:-1:-1;;;101410:65:0;;;;;;;:::i;:::-;;;;;;;;;101489:22;101517:21;101529:8;;101517:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101517:11:0;;-1:-1:-1;;;101517:21:0:i;:::-;-1:-1:-1;101682:14:0;;101488:50;;-1:-1:-1;101644:22:0;;-1:-1:-1;;;;;101682:14:0;:33;101716:10;101488:50;101737:17;;101756:12;:10;:12::i;:::-;101682:87;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101644:125;;101797:43;101832:7;;101825:4;:14;;;;:::i;:::-;101797;;:27;:43::i;:::-;:47;;101843:1;101797:47;:::i;:::-;101780:64;101165:687;-1:-1:-1;;;;;;;;101165:687:0:o;15719:83::-;15756:13;15789:5;15782:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15719:83;;:::o;9275:169::-;9358:4;9375:39;9384:12;:10;:12::i;:::-;9398:7;9407:6;9375:8;:39::i;:::-;-1:-1:-1;9432:4:0;9275:169;;;;;:::o;117033:349::-;19677:15;:13;:15::i;:::-;117154:7:::1;;117142:8;:19;;117134:45;;;;-1:-1:-1::0;;;117134:45:0::1;;;;;;;:::i;:::-;117216:7;;117198:14;:25;;117190:57;;;;-1:-1:-1::0;;;117190:57:0::1;;;;;;;:::i;:::-;117260:7;:18:::0;;;117289:13:::1;:30:::0;;;117337:37:::1;::::0;::::1;::::0;::::1;::::0;117270:8;;117305:14;;117337:37:::1;:::i;:::-;;;;;;;;117033:349:::0;;:::o;86976:357::-;87107:18;87168:1;87151:14;:18;87143:37;;;;-1:-1:-1;;;87143:37:0;;;;;;;:::i;:::-;87194:9;87209:17;87219:6;87209:9;:17::i;:::-;-1:-1:-1;87252:14:0;;87193:33;;-1:-1:-1;;;;;;87252:14:0;:26;87279:10;87193:33;87296:14;87312:12;:10;:12::i;:::-;87252:73;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87239:86;86976:357;-1:-1:-1;;;;86976:357:0:o;81339:22::-;;;;:::o;82345:1061::-;82549:24;;-1:-1:-1;;;;;82549:24:0;82541:67;;;;-1:-1:-1;;;82541:67:0;;;;;;;:::i;:::-;82751:24;;;-1:-1:-1;;;;;;82858:37:0;;;;;;82986:6;:29;;-1:-1:-1;;82986:29:0;82751:24;82986:29;;;83028:14;:53;;-1:-1:-1;;;;;83028:53:0;;;;;;;;;;83094:74;;-1:-1:-1;;;83094:74:0;;82751:24;;;83094:8;;:16;;:74;;82751:24;;83126:14;;83142:10;;83154:13;;83094:74;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83224:10:0;:15;;-1:-1:-1;;83224:15:0;83237:2;83224:15;;;-1:-1:-1;;83284:9:0;;83224:10;;83266:42;;83284:23;;81705:3;;83284:23;:::i;:::-;83266:17;:42::i;:::-;83329:29;;;;;;;;-1:-1:-1;;;;;83329:29:0;;;;;;;;;;;;;;-1:-1:-1;83329:29:0;;;;;;;;;;;;;;83319:7;:39;;-1:-1:-1;;83319:39:0;;;-1:-1:-1;;83319:39:0;-1:-1:-1;;;83319:39:0;;;;;;;-1:-1:-1;;;;;83319:39:0;;;;;;83384:14;;;;83369:29;;:12;:29;;;;;;;-1:-1:-1;;;;;;83369:29:0;;;;;;;;;-1:-1:-1;;;83369:29:0;;;;;;;;;;;;-1:-1:-1;;;82345:1061:0:o;8228:108::-;8316:12;;8228:108;:::o;116062:218::-;19677:15;:13;:15::i;:::-;116168:4:::1;116154:10;:18;;116146:45;;;;-1:-1:-1::0;;;116146:45:0::1;;;;;;;:::i;:::-;116204:9;:22:::0;;;116244:28:::1;::::0;::::1;::::0;::::1;::::0;116216:10;;116244:28:::1;:::i;:::-;;;;;;;;116062:218:::0;:::o;109056:209::-;109146:32;109180:24;109230:14;109246:10;109222:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109222:35:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;109222:35:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;109222:35:0;;;;;;;;;;-1:-1:-1;;;109222:35:0;;;;;;;;;;;;;;;-1:-1:-1;;;109222:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109222:35:0;;;;;-1:-1:-1;;;109222:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109056:209;;:::o;81744:32::-;;;-1:-1:-1;;;;;81744:32:0;;;;-1:-1:-1;;;81744:32:0;;;;:::o;9926:422::-;10032:4;10049:36;10059:6;10067:9;10078:6;10049:9;:36::i;:::-;-1:-1:-1;;;;;10125:19:0;;10098:24;10125:19;;;:11;:19;;;;;10098:24;10145:12;:10;:12::i;:::-;-1:-1:-1;;;;;10125:33:0;-1:-1:-1;;;;;10125:33:0;;;;;;;;;;;;;10098:60;;10197:6;10177:16;:26;;10169:79;;;;-1:-1:-1;;;10169:79:0;;;;;;;:::i;:::-;10259:57;10268:6;10276:12;:10;:12::i;:::-;10290:25;10309:6;10290:16;:25;:::i;:::-;10259:8;:57::i;:::-;10336:4;10329:11;;;9926:422;;;;;;:::o;116509:354::-;19677:15;:13;:15::i;:::-;116619:20:::1;::::0;-1:-1:-1;;;116619:20:0;::::1;;;116618:21;116610:49;;;;-1:-1:-1::0;;;116610:49:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116678:32:0;::::1;116670:57;;;;-1:-1:-1::0;;;116670:57:0::1;;;;;;;:::i;:::-;116740:14;:56:::0;;-1:-1:-1;;;;;;116740:56:0::1;-1:-1:-1::0;;;;;116740:56:0;::::1;;::::0;;116814:41:::1;::::0;::::1;::::0;::::1;::::0;116740:56;;116814:41:::1;:::i;113796:868::-:0;113905:18;113925:17;83543:19;:17;:19::i;:::-;114198:7:::1;::::0;114234:1:::1;114220:15:::0;::::1;114216:405;;;114265:15;114279:1;114265:11:::0;:15:::1;:::i;:::-;114305:1;114295:7;:11:::0;114252:28;-1:-1:-1;114374:29:0::1;114380:10;114252:28:::0;114374:5:::1;:29::i;:::-;114461:4;114423:186;114485:10;114514::::0;114557:1:::1;114543:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;114543:16:0::1;-1:-1:-1::0;114578:16:0::1;::::0;;114592:1:::1;114578:16:::0;;::::1;::::0;::::1;::::0;;;;114423:186:::1;::::0;;;;::::1;:::i;:::-;;;;;;;;114216:405;114643:13;:11;:13::i;:::-;114631:25;;83573:1;113796:868:::0;;:::o;81515:55::-;;;;;;;;;;;;;;;:::o;16571:83::-;16637:9;;;;16571:83;:::o;10757:215::-;10845:4;10862:80;10871:12;:10;:12::i;:::-;10885:7;10931:10;10894:11;:25;10906:12;:10;:12::i;:::-;-1:-1:-1;;;;;10894:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;10894:25:0;;;:34;;;;;;;;;;:47;;;;:::i;109498:353::-;109602:30;;:::i;:::-;109634:22;;:::i;:::-;-1:-1:-1;;;;;109686:22:0;;109674:9;109686:22;;;:13;:22;;;;;;109730:14;:19;;109686:22;;;;;;;109730:19;;;;-1:-1:-1;;;109730:19:0;;;;;;;;;;;;;;;;;;109719:30;;;;;;;;109730:19;;;;;;;109719:30;;-1:-1:-1;;;;;109719:30:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;109719:30:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;109719:30:0;;;;;;;;;;-1:-1:-1;;;109719:30:0;;;;;;;;;;;;;;;-1:-1:-1;;;109719:30:0;;;;;;;;;;;;;;;109785:7;-1:-1:-1;;;;;109768:24:0;:8;:13;;;-1:-1:-1;;;;;109768:24:0;;109760:50;;;;-1:-1:-1;;;109760:50:0;;;;;;;:::i;:::-;109828:10;109839:3;109828:15;;;;;;;;-1:-1:-1;;;109828:15:0;;;;;;;;;;;;;;;;;;109821:22;;;;;;;;;109828:15;;109821:22;-1:-1:-1;;;;;109821:22:0;;;;;-1:-1:-1;;;109821:22:0;;;;;;;;;;;109498:353;;109821:22;;-1:-1:-1;;;109498:353:0:o;97805:326::-;24014:11;;98006:22;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;84304:10:::1;:8;:10::i;:::-;98058:65:::2;98066:7;98075:15;98092:18;98112:10;98058:7;:65::i;:::-;24319:11:::0;:18;;-1:-1:-1;;;;24319:18:0;-1:-1:-1;;;24319:18:0;;;98041:82;97805:326;-1:-1:-1;;;;;97805:326:0:o;120000:174::-;19677:15;:13;:15::i;:::-;120093:7:::1;:18;120112:7;120121:8;120131:12;120145:7;:5;:7::i;:::-;81705:3;120093:73;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;120000:174:::0;;:::o;81246:28::-;;;;:::o;81160:22::-;;;;:::o;81715:::-;;;-1:-1:-1;;;;;81715:22:0;;;;-1:-1:-1;;;81715:22:0;;;;;-1:-1:-1;;;81715:22:0;;;;;-1:-1:-1;;;81715:22:0;;;;:::o;81308:24::-;;;;:::o;81577:23::-;;;;;;:::o;81478:30::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;81478:30:0;;;;-1:-1:-1;;;;81478:30:0;;;;;:::o;118786:240::-;19677:15;:13;:15::i;:::-;118938:80:::1;::::0;-1:-1:-1;;;118938:80:0;;:7:::1;::::0;:22:::1;::::0;:80:::1;::::0;118961:14:::1;::::0;118977:13:::1;::::0;118992:8;;;;119002:15;;118938:80:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;118786:240:::0;;;:::o;8399:127::-;-1:-1:-1;;;;;8500:18:0;;8473:7;8500:18;;;:9;:18;;;;;;8399:127;;;;:::o;93512:792::-;93658:18;93707:7;-1:-1:-1;;;;;93697:17:0;:6;-1:-1:-1;;;;;93697:17:0;;;93689:42;;;;-1:-1:-1;;;93689:42:0;;;;;;;:::i;:::-;93767:1;93750:14;:18;93742:52;;;;-1:-1:-1;;;93742:52:0;;;;;;;:::i;:::-;93864:30;93897:10;93864:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;93864:43:0;;;;;-1:-1:-1;;;93864:43:0;;;;;;;;;;;;;;;;;;;;;;;;;93919:14;93939:17;93949:6;93939:9;:17::i;:::-;93918:38;;;93968:15;93989:18;93999:7;93989:9;:18::i;:::-;-1:-1:-1;94109:14:0;;94251:7;;93967:40;;-1:-1:-1;;;;;;94109:14:0;;:26;;94150:10;;94175:8;;93967:40;;94222:14;;94273:12;:10;:12::i;:::-;94109:187;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;94092:204:0;93512:792;-1:-1:-1;;;;;;;93512:792:0:o;100329:512::-;100464:20;100528:1;100510:15;:19;100502:38;;;;-1:-1:-1;;;100502:38:0;;;;;;;:::i;:::-;100554:9;100569:18;100579:7;100569:9;:18::i;:::-;100553:34;;;100600:17;100620:36;100648:7;;100620:15;:27;;:36;;;;:::i;:::-;100682:14;;100600:56;;-1:-1:-1;;;;;;100682:14:0;:28;100725:10;100750:3;100768:27;100600:56;100768:15;:27;:::i;:::-;100810:12;:10;:12::i;:::-;100682:151;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100667:166;100329:512;-1:-1:-1;;;;;100329:512:0:o;114999:663::-;115159:18;115179:17;83543:19;:17;:19::i;:::-;83905:12:::1;:10;:12::i;:::-;24014:11:::2;::::0;-1:-1:-1;;;24014:11:0;::::2;;;24006:55;;;;-1:-1:-1::0;;;24006:55:0::2;;;;;;;:::i;:::-;24139:11;:19:::0;;-1:-1:-1;;;;24139:19:0::2;::::0;;115369:14:::3;::::0;115214:22:::3;::::0;115269:7:::3;::::0;:31:::3;::::0;115315:14:::3;::::0;115344:10:::3;::::0;-1:-1:-1;;;;;115369:14:0::3;115398:12;:10;:12::i;:::-;115269:152;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;::::0;;::::3;-1:-1:-1::0;;115269:152:0::3;::::0;::::3;;::::0;::::3;::::0;;;::::3;::::0;::::3;:::i;:::-;115247:174:::0;;-1:-1:-1;115247:174:0;-1:-1:-1;115442:14:0;115434:49:::3;;;;-1:-1:-1::0;;;115434:49:0::3;;;;;;;:::i;:::-;115496:29;115502:10;115514;115496:5;:29::i;:::-;115561:4;115541:75;115568:10;115580::::0;115606:1:::3;115592:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;115592:16:0::3;;115610:5;115541:75;;;;;;;;;:::i;:::-;;;;;;;;115641:13;:11;:13::i;:::-;24319:11:::2;:18:::0;;-1:-1:-1;;;;24319:18:0::2;-1:-1:-1::0;;;24319:18:0::2;::::0;;114999:663;;;-1:-1:-1;;114999:663:0:o;119350:177::-;19677:15;:13;:15::i;:::-;119439:80:::1;::::0;-1:-1:-1;;;119439:80:0;;:7:::1;::::0;:21:::1;::::0;:80:::1;::::0;119461:6:::1;::::0;119469:14:::1;::::0;119485:13:::1;::::0;119500:7;;119509:9;;119439:80:::1;;;:::i;15921:87::-:0;15960:13;15993:7;15986:14;;;;;:::i;119651:154::-;19677:15;:13;:15::i;:::-;119726:71:::1;::::0;-1:-1:-1;;;119726:71:0;;:7:::1;::::0;:23:::1;::::0;:71:::1;::::0;119750:6:::1;::::0;119758:14:::1;::::0;119774:13:::1;::::0;119789:7;;119726:71:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;119651:154:::0;:::o;117553:336::-;19677:15;:13;:15::i;:::-;117663:10:::1;:17:::0;:21:::1;::::0;117683:1:::1;117663:21;:::i;:::-;117655:30;::::0;:4:::1;:30;:::i;:::-;117647:4;-1:-1:-1::0;;;;;117647:38:0::1;;;117639:65;;;;-1:-1:-1::0;;;117639:65:0::1;;;;;;;:::i;:::-;117739:10;:17:::0;:21:::1;::::0;117759:1:::1;::::0;117739:21:::1;:::i;:::-;117731:30;::::0;:4:::1;:30;:::i;:::-;117723:4;-1:-1:-1::0;;;;;117723:38:0::1;;;117715:65;;;;-1:-1:-1::0;;;117715:65:0::1;;;;;;;:::i;:::-;117808:24;::::0;;;;::::1;::::0;;-1:-1:-1;;;;;117808:24:0;;::::1;::::0;;;;;::::1;;::::0;;::::1;::::0;;;117793:12:::1;:39:::0;;-1:-1:-1;;;;;;117793:39:0::1;::::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;117793:39:0;;::::1;::::0;;;::::1;::::0;;117850:31;::::1;::::0;::::1;::::0;117808:24;;;;117850:31:::1;:::i;19243:29::-:0;;;:::o;11475:377::-;11568:4;11585:24;11612:11;:25;11624:12;:10;:12::i;:::-;-1:-1:-1;;;;;11612:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;11612:25:0;;;:34;;;;;;;;;;;-1:-1:-1;11665:35:0;;;;11657:85;;;;-1:-1:-1;;;11657:85:0;;;;;;;:::i;:::-;11753:67;11762:12;:10;:12::i;:::-;11776:7;11785:34;11804:15;11785:16;:34;:::i;11753:67::-;-1:-1:-1;11840:4:0;;11475:377;-1:-1:-1;;;11475:377:0:o;8739:175::-;8825:4;8842:42;8852:12;:10;:12::i;:::-;8866:9;8877:6;8842:9;:42::i;99570:441::-;24014:11;;99808:22;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;84304:10:::1;:8;:10::i;:::-;99860:143:::2;99894:8;;99860:143;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;99860:143:0::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;;;;;;-1:-1:-1;99917:17:0;;-1:-1:-1;99917:17:0;;;;99860:143;::::2;::::0;99917:17;;99860:143;99917:17;99860:143;::::2;;::::0;::::2;::::0;;;;-1:-1:-1;99949:18:0;;-1:-1:-1;99982:10:0;;-1:-1:-1;99860:19:0::2;::::0;-1:-1:-1;99860:143:0:i:2;:::-;24319:11:::0;:18;;-1:-1:-1;;;;24319:18:0;-1:-1:-1;;;24319:18:0;;;99843:160;99570:441;-1:-1:-1;;;;;;;99570:441:0:o;98548:331::-;24014:11;;98742:33;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;84304:10:::1;:8;:10::i;:::-;98807:64:::2;98821:15;98838:20;;98860:10;98807:13;:64::i;86328:348::-:0;24014:11;;86555:18;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;83905:12:::1;:10;:12::i;:::-;86599:69:::2;86610:7;;86599:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;86599:69:0::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;;;;;;-1:-1:-1;86619:16:0;;-1:-1:-1;86619:16:0;;;;86599:69;::::2;::::0;86619:16;;86599:69;86619:16;86599:69;::::2;;::::0;::::2;::::0;;;;-1:-1:-1;86637:18:0;;-1:-1:-1;86657:10:0;;-1:-1:-1;86599:10:0::2;::::0;-1:-1:-1;86599:69:0:i:2;118138:182::-:0;19677:15;:13;:15::i;:::-;118238:74:::1;::::0;-1:-1:-1;;;118238:74:0;;:7:::1;::::0;:27:::1;::::0;:74:::1;::::0;118266:14:::1;::::0;118282:13:::1;::::0;118297:7;;118306:5;;118238:74:::1;;;:::i;109950:113::-:0;109994:29;;:::i;:::-;110043:12;:10;:12::i;:::-;110036:19;;109950:113;:::o;120313:97::-;19677:15;:13;:15::i;:::-;120367:7:::1;:17;120385:7;120394;:5;:7::i;:::-;120367:35;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;120313:97::o:0;108735:130::-;108819:6;:22;;;;;;;108843:13;;;108735:130;;:::o;92698:345::-;24014:11;;92921:18;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;83905:12:::1;:10;:12::i;:::-;92965:70:::2;92971:6;92979:7;92988:14;93004:18;93024:10;92965:5;:70::i;:::-;24319:11:::0;:18;;-1:-1:-1;;;;24319:18:0;-1:-1:-1;;;24319:18:0;;;92952:83;92698:345;-1:-1:-1;;;;;;92698:345:0:o;80925:41::-;;;-1:-1:-1;;;;;80925:41:0;;:::o;8977:151::-;-1:-1:-1;;;;;9093:18:0;;;9066:7;9093:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;8977:151::o;87703:480::-;87864:18;87914:16;87956:7;;;;;:32;;-1:-1:-1;87967:21:0;;;87956:32;87948:65;;;;-1:-1:-1;;;87948:65:0;;;;;;;:::i;:::-;88025:22;88053:20;88065:7;;88053:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88053:11:0;;-1:-1:-1;;;88053:20:0:i;:::-;-1:-1:-1;88091:14:0;;88024:49;;-1:-1:-1;;;;;;88091:14:0;:31;88123:10;88024:49;88144:16;;88162:12;:10;:12::i;:::-;88091:84;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88084:91;87703:480;-1:-1:-1;;;;;;;87703:480:0:o;81607:25::-;;;;;;;;;;;;;:::o;85265:312::-;24014:11;;85462:18;;-1:-1:-1;;;24014:11:0;;;;24006:55;;;;-1:-1:-1;;;24006:55:0;;;;;;;:::i;:::-;24139:11;:19;;-1:-1:-1;;;;24139:19:0;;;83905:12:::1;:10;:12::i;:::-;85506:63:::2;85514:6;85522:14;85538:18;85558:10;85506:7;:63::i;111747:561::-:0;111933:15;;111845:22;;;;111933:15;-1:-1:-1;;;;;111971:16:0;;;;;-1:-1:-1;;;111971:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;111971:16:0;;111961:26;;112030:3;-1:-1:-1;;;;;112009:25:0;;;;;-1:-1:-1;;;112009:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;111998:36;;112052:9;112047:254;112071:3;112067:1;:7;112047:254;;;112124:22;112134:8;112143:1;112134:11;;;;;;-1:-1:-1;;;112134:11:0;;;;;;;;;;;;;;;112124:9;:22::i;:::-;112097:7;112105:1;112097:10;;;;;;-1:-1:-1;;;112097:10:0;;;;;;;;;;;;;;112109:8;112118:1;112109:11;;;;;;-1:-1:-1;;;112109:11:0;;;;;;;;;;;;;;;;;;112096:50;;;;;;;;;;112168:9;112180:5;:1;112184;112180:5;:::i;:::-;112168:17;;112163:127;112191:3;112187:1;:7;112163:127;;;112243:8;112252:1;112243:11;;;;;;-1:-1:-1;;;112243:11:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;112228:26:0;:8;112237:1;112228:11;;;;;;-1:-1:-1;;;112228:11:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;112228:26:0;;;112220:54;;;;-1:-1:-1;;;112220:54:0;;;;;;;:::i;:::-;112196:3;;;;:::i;:::-;;;;112163:127;;;-1:-1:-1;112076:3:0;;;;:::i;:::-;;;;112047:254;;;;111747:561;;;;:::o;112407:133::-;112452:22;;:::i;:::-;112494:38;;;;;;;;112510:7;:5;:7::i;:::-;112494:38;;;;;;;;;;;112519:12;112494:38;-1:-1:-1;;;;;112494:38:0;;;;;-1:-1:-1;;;112494:38:0;;;;;;;;;;;;;;;;112487:45;-1:-1:-1;112407:133:0;:::o;37796:195::-;37863:7;37982:1;37964:14;34040:4;37964:1;:14;:::i;:::-;37963:20;;;;:::i;4973:107::-;5061:10;4973:107;:::o;14647:346::-;-1:-1:-1;;;;;14749:19:0;;14741:68;;;;-1:-1:-1;;;14741:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14828:21:0;;14820:68;;;;-1:-1:-1;;;14820:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14901:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;;:36;;;14953:32;;;;;14931:6;;14953:32;:::i;:::-;;;;;;;;14647:346;;;:::o;19720:121::-;19792:11;:9;:11::i;:::-;-1:-1:-1;;;;;19778:25:0;:10;-1:-1:-1;;;;;19778:25:0;;19770:63;;;;-1:-1:-1;;;19770:63:0;;;;;;;:::i;:::-;19720:121::o;111197:280::-;111282:9;111293:30;;:::i;:::-;-1:-1:-1;;;;;111347:21:0;;;;;;:13;:21;;;;;;111390:14;:19;;111347:21;;;;;-1:-1:-1;111390:14:0;111347:21;;111390:19;;;;-1:-1:-1;;;111390:19:0;;;;;;;;;;;;;;;;;;111379:30;;;;;;;;111390:19;;;;;;;111379:30;;-1:-1:-1;;;;;111379:30:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;111379:30:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;111379:30:0;;;;;;;;;;-1:-1:-1;;;111379:30:0;;;;;;;;;;;;;;;-1:-1:-1;;;111379:30:0;;;;;;;;;;;;;;;111445:6;-1:-1:-1;;;;;111428:23:0;:8;:13;;;-1:-1:-1;;;;;111428:23:0;;111420:49;;;;-1:-1:-1;;;111420:49:0;;;;;;;:::i;:::-;111197:280;;;:::o;28687:179::-;28743:6;-1:-1:-1;;;28770:5:0;:13;28762:65;;;;-1:-1:-1;;;28762:65:0;;;;;;;:::i;:::-;-1:-1:-1;28852:5:0;28687:179::o;12342:544::-;-1:-1:-1;;;;;12448:20:0;;12440:70;;;;-1:-1:-1;;;12440:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;12529:23:0;;12521:71;;;;-1:-1:-1;;;12521:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;12629:17:0;;12605:21;12629:17;;;:9;:17;;;;;;12665:23;;;;12657:74;;;;-1:-1:-1;;;12657:74:0;;;;;;;:::i;:::-;12762:22;12778:6;12762:13;:22;:::i;:::-;-1:-1:-1;;;;;12742:17:0;;;;;;;:9;:17;;;;;;:42;;;;12795:20;;;;;;;;:30;;12819:6;;12742:17;12795:30;;12819:6;;12795:30;:::i;:::-;;;;;;;;12860:9;-1:-1:-1;;;;;12843:35:0;12852:6;-1:-1:-1;;;;;12843:35:0;;12871:6;12843:35;;;;;;:::i;:::-;;;;;;;;12342:544;;;;:::o;83649:129::-;83732:10;83711:17;:15;:17::i;:::-;-1:-1:-1;;;;;83711:31:0;;83703:67;;;;-1:-1:-1;;;83703:67:0;;;;;;;:::i;13168:276::-;-1:-1:-1;;;;;13252:21:0;;13244:65;;;;-1:-1:-1;;;13244:65:0;;;;;;;:::i;:::-;13338:6;13322:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;13355:18:0;;;;;;:9;:18;;;;;:28;;13377:6;;13355:18;:28;;13377:6;;13355:28;:::i;:::-;;;;-1:-1:-1;;13399:37:0;;-1:-1:-1;;;;;13399:37:0;;;13416:1;;13399:37;;;;13429:6;;13399:37;:::i;:::-;;;;;;;;13168:276;;:::o;84401:144::-;84446:35;;;;;;;;;84475:6;84446:35;;;;;;;;;;;;;;;;;;;;;84492:45;;;;-1:-1:-1;;;84492:45:0;;;;;;;:::i;:::-;84401:144;:::o;102059:1802::-;102226:22;-1:-1:-1;;;;;102269:24:0;;102261:54;;;;-1:-1:-1;;;102261:54:0;;;;;;;:::i;:::-;102351:1;102334:14;:18;102326:37;;;;-1:-1:-1;;;102326:37:0;;;;;;;:::i;:::-;102434:30;102467:10;102434:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;102434:43:0;;;;;-1:-1:-1;;;102434:43:0;;;;;;;;;;;;;;;;;;;;;;;;;102489:17;102508:30;102542:18;102552:7;102542:9;:18::i;:::-;102488:72;;;;102615:17;102635:35;102662:7;;102635:14;:26;;:35;;;;:::i;:::-;102698:14;;102615:55;;-1:-1:-1;;;;;;102698:14:0;:28;102741:10;102766:11;102792:26;102615:55;102792:14;:26;:::i;:::-;102833:12;:10;:12::i;:::-;102698:158;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102681:175;;102893:18;102875:14;:36;;102867:69;;;;-1:-1:-1;;;102867:69:0;;;;;;;:::i;:::-;102972:1;102955:14;:18;102947:42;;;;-1:-1:-1;;;102947:42:0;;;;;;;:::i;:::-;103115:33;103121:10;103133:14;103115:5;:33::i;:::-;103170:9;103159:7;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;103190:18:0;;-1:-1:-1;103211:18:0;:16;:18::i;:::-;103190:39;;103295:7;:22;103332:14;103361:8;103384:10;103395:11;103384:23;;;;;;;;-1:-1:-1;;;103384:23:0;;;;;;;;;;;;;;;103422:10;103447:5;:14;;;103295:177;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103622:34;103641:14;103622:18;:34::i;:::-;103570:10;103581:11;103570:23;;;;;;;;-1:-1:-1;;;103570:23:0;;;;;;;;;;;;;;;:36;;;:86;;;;:::i;:::-;103518:10;103529:11;103518:23;;;;;;;;-1:-1:-1;;;103518:23:0;;;;;;;;;;;;;;;;;;:138;;-1:-1:-1;;;;;103518:138:0;;;-1:-1:-1;;;103518:138:0;;;;;;;;;103776:13;;103674:179;;103697:10;;103674:179;;;;103722:10;;103747:14;;103776:13;103804:14;;103833:9;;103674:179;:::i;:::-;;;;;;;;102059:1802;;;;;;;;;;;:::o;112612:826::-;112672:33;;;;;;;;112698:7;112672:33;-1:-1:-1;;;;;112672:33:0;;;;;-1:-1:-1;;;112672:33:0;;;;;;;;;;-1:-1:-1;;;112672:33:0;;;;;;;;;;;-1:-1:-1;;;112672:33:0;;;;;;;;;;112652:7;;112672:33;112880:15;:25;-1:-1:-1;112876:555:0;;;112938:17;;112989:22;;;;112922:13;;113064:27;-1:-1:-1;;;;;113064:27:0;;:15;:27;:::i;:::-;113093:19;113103:9;113093:7;:19;:::i;:::-;-1:-1:-1;;;;;113028:85:0;;;;;113141:6;-1:-1:-1;;;;;113134:13:0;:4;-1:-1:-1;;;;;113134:13:0;;113130:201;;;113215:5;113204:7;113187:13;113194:6;113187:4;:13;:::i;:::-;-1:-1:-1;;;;;113186:25:0;;;;;:::i;:::-;113185:35;;;;:::i;:::-;113175:46;;-1:-1:-1;;;;;113175:46:0;;;:::i;:::-;113168:53;;;;;;;;;;;113130:201;113309:5;113298:7;113281:13;113290:4;113281:6;:13;:::i;:::-;-1:-1:-1;;;;;113280:25:0;;;;;:::i;:::-;113279:35;;;;:::i;:::-;113269:46;;-1:-1:-1;;;;;113269:46:0;;;:::i;112876:555::-;-1:-1:-1;;;;;;113408:11:0;;-1:-1:-1;113408:11:0;;-1:-1:-1;113408:11:0;35666:135;35732:7;35759:34;35776:1;35779;34040:4;35759:16;:34::i;84004:166::-;84051:35;;;;;;;;;84080:6;84051:35;;;;;;;;;;;;;;;;;;;;;;;;;84105:43;;;84134:7;:14;;;84133:15;84105:43;84097:65;;;;-1:-1:-1;;;84097:65:0;;;;;;;:::i;106369:2116::-;106570:22;-1:-1:-1;;;;;106613:24:0;;106605:54;;;;-1:-1:-1;;;106605:54:0;;;;;;;:::i;:::-;106684:24;;106727:7;;;;;:33;;;106745:8;:15;106738:3;:22;106727:33;106719:65;;;;-1:-1:-1;;;106719:65:0;;;;;;;:::i;:::-;106824:1;106803:18;:22;106795:41;;;;-1:-1:-1;;;106795:41:0;;;;;;;:::i;:::-;106850:22;106874:32;106910:21;106922:8;106910:11;:21::i;:::-;106849:82;;;;106994:30;107027:10;106994:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;106994:43:0;;;;;-1:-1:-1;;;106994:43:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;107118:14:0;;106994:43;;-1:-1:-1;107080:22:0;;-1:-1:-1;;;;;107118:14:0;;-1:-1:-1;107118:33:0;;-1:-1:-1;106994:43:0;107164:7;107173:17;107192:12;:10;:12::i;:::-;107118:87;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;107080:125;;107233:43;107268:7;;107261:4;:14;;;;:::i;107233:43::-;107216:60;-1:-1:-1;107287:11:0;107301:31;107318:14;107216:60;107301:31;:::i;:::-;107287:45;;107368:1;107351:14;:18;107343:55;;;;-1:-1:-1;;;107343:55:0;;;;;;;:::i;:::-;107409:19;107427:1;107409:19;;:::i;:::-;;;107465:18;107447:14;:36;;107439:81;;;;-1:-1:-1;;;107439:81:0;;;;;;;:::i;:::-;107646:33;107652:10;107664:14;107646:5;:33::i;:::-;107701:3;107690:7;;:14;;;;;;;:::i;:::-;;;;-1:-1:-1;107715:18:0;;-1:-1:-1;107736:18:0;:16;:18::i;:::-;107715:39;;107840:9;107835:451;107859:3;107855:1;:7;107835:451;;;107884:9;107896:7;107904:1;107896:10;;;;;;-1:-1:-1;;;107896:10:0;;;;;;;;;;;;;;;107884:22;;107921:7;:22;107962:17;107980:1;107962:20;;;;;;-1:-1:-1;;;107962:20:0;;;;;;;;;;;;;;;108001:8;108010:1;108001:11;;;;;;-1:-1:-1;;;108001:11:0;;;;;;;;;;;;;;;108031:10;108042:3;108031:15;;;;;;;;-1:-1:-1;;;108031:15:0;;;;;;;;;;;;;;;108065:10;108094:5;:14;;;107921:202;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108234:40;108253:17;108271:1;108253:20;;;;;;-1:-1:-1;;;108253:20:0;;;;;;;;;;;;;;;108234:18;:40::i;:::-;108186:10;108197:3;108186:15;;;;;;;;-1:-1:-1;;;108186:15:0;;;;;;;;;;;;;;;:28;;;:88;;;;:::i;:::-;108138:10;108149:3;108138:15;;;;;;;;-1:-1:-1;;;108138:15:0;;;;;;;;;;;;;;;;;;:136;;-1:-1:-1;;;;;108138:136:0;;;-1:-1:-1;;;108138:136:0;;;;;;;;;-1:-1:-1;107864:3:0;;;;:::i;:::-;;;;107835:451;;;;108329:10;-1:-1:-1;;;;;108301:176:0;;108354:10;108379:14;108408:8;108431:17;108463:3;108301:176;;;;;;;;;;:::i;:::-;;;;;;;;106369:2116;;;;;;;;;;;;;:::o;103949:2357::-;104109:33;-1:-1:-1;;;;;104163:24:0;;104155:54;;;;-1:-1:-1;;;104155:54:0;;;;;;;:::i;:::-;104245:1;104228:14;:18;104220:37;;;;-1:-1:-1;;;104220:37:0;;;;;;;:::i;:::-;104321:17;104341:41;104368:13;;104341:14;:26;;:41;;;;:::i;:::-;104321:61;-1:-1:-1;104393:30:0;104426:26;104321:61;104426:14;:26;:::i;:::-;104393:59;;104498:33;104504:10;104516:14;104498:5;:33::i;:::-;104553:9;104542:7;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;104627:18:0;;-1:-1:-1;104648:18:0;:16;:18::i;:::-;104627:39;;104757:19;104803:22;104779:5;:21;;;:46;;;;:::i;:::-;104757:68;;104896:30;104929:10;104896:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;104896:43:0;;;;;-1:-1:-1;;;104896:43:0;;;;;;;;;;;;;;;;;;;;;;;;;104952:11;104966:10;:17;104952:31;;104994:24;105035:3;-1:-1:-1;;;;;105021:18:0;;;;;-1:-1:-1;;;105021:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;105021:18:0;;104994:45;;105083:3;-1:-1:-1;;;;;105069:18:0;;;;;-1:-1:-1;;;105069:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;105069:18:0;;105050:37;;105103:9;105098:1003;105122:3;105118:1;:7;105098:1003;;;105314:17;105390:11;105364:22;105335:10;105346:1;105335:13;;;;;;-1:-1:-1;;;105335:13:0;;;;;;;;;;;;;;;:26;;;-1:-1:-1;;;;;105335:51:0;;;;;:::i;:::-;105334:67;;;;:::i;:::-;105314:87;;105436:1;105424:9;:13;105416:37;;;;-1:-1:-1;;;105416:37:0;;;;;;;:::i;:::-;105468:14;105481:1;105468:14;;:::i;:::-;;;105518:20;;105539:1;105518:23;;;;;-1:-1:-1;;;105518:23:0;;;;;;;;;;;;;;;105505:9;:36;;105497:69;;;;-1:-1:-1;;;105497:69:0;;;;;;;:::i;:::-;105654:9;105665:14;105680:1;105665:17;;;;;;-1:-1:-1;;;105665:17:0;;;;;;;;;;;;;;;;;;;;;;:22;105618:19;;-1:-1:-1;;;;;105665:22:0;;;;105618:16;;105635:1;;105618:19;;;;-1:-1:-1;;;105618:19:0;;;;;;;;;;;;;;105639:7;105647:1;105639:10;;;;;;-1:-1:-1;;;105639:10:0;;;;;;;;;;;;;;105617:71;-1:-1:-1;;;;;105617:71:0;-1:-1:-1;;;;;105617:71:0;;;;;;;;;;105756:7;:22;105797:9;105825:14;105840:1;105825:17;;;;;;-1:-1:-1;;;105825:17:0;;;;;;;;;;;;;;;;;;;105861:10;105872:1;105861:13;;;;;;-1:-1:-1;;;105861:13:0;;;;;;;;;;;;;;;105893:10;105922:5;:14;;;105756:195;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106060:29;106079:9;106060:18;:29::i;:::-;106031:10;106042:1;106031:13;;;;;;-1:-1:-1;;;106031:13:0;;;;;;;;;;;;;;;:26;;;:58;;;;:::i;:::-;106002:10;106013:1;106002:13;;;;;;-1:-1:-1;;;106002:13:0;;;;;;;;;;;;;;;;;;:87;;-1:-1:-1;;;;;106002:87:0;;;-1:-1:-1;;;106002:87:0;;;;;;;;;-1:-1:-1;105127:3:0;;;;:::i;:::-;;;;105098:1003;;;;106146:10;-1:-1:-1;;;;;106118:180:0;;106171:10;106196:14;106225:7;106247:16;106278:9;106118:180;;;;;;;;;;:::i;89920:2036::-;90110:20;-1:-1:-1;;;;;90151:24:0;;90143:54;;;;-1:-1:-1;;;90143:54:0;;;;;;;:::i;:::-;90222:23;;90264:7;;;;;:32;;;90282:7;:14;90275:3;:21;90264:32;90256:65;;;;-1:-1:-1;;;90256:65:0;;;;;;;:::i;:::-;90383:22;90407:33;90444:20;90456:7;90444:11;:20::i;:::-;90382:82;;;;90475:30;90508:10;90475:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90475:43:0;;;;;-1:-1:-1;;;90475:43:0;;;;;;;;;;;;;;;;;;;;;;;;;90529:18;90550;:16;:18::i;:::-;90529:39;;90579:36;90632:3;-1:-1:-1;;;;;90618:18:0;;;;;-1:-1:-1;;;90618:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90618:18:0;;90579:57;;90736:9;90731:676;90755:3;90751:1;:7;90731:676;;;90780:22;90805:16;90822:1;90805:19;;;;;;-1:-1:-1;;;90805:19:0;;;;;;;;;;;;;;;90780:44;;90860:1;90843:14;:18;90839:557;;;90882:9;90894:7;90902:1;90894:10;;;;;;-1:-1:-1;;;90894:10:0;;;;;;;;;;;;;;;90882:22;;90923;90948:10;90959:3;90948:15;;;;;;;;-1:-1:-1;;;90948:15:0;;;;;;;;;;;;;;;90923:40;;90982:30;91015:9;91025:1;91015:12;;;;;;-1:-1:-1;;;91015:12:0;;;;;;;;;;;;;;;90982:45;;91046:25;91095:7;:21;91117:8;91127:4;:10;;;91139:14;91155:5;:14;;;91095:75;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91046:124;;91214:17;91189:19;91209:1;91189:22;;;;;;-1:-1:-1;;;91189:22:0;;;;;;;;;;;;;;:42;;;;;91343:37;91362:17;91343:18;:37::i;:::-;91302:4;:17;;;:78;;;;:::i;:::-;91250:10;91261:3;91250:15;;;;;;;;-1:-1:-1;;;91250:15:0;;;;;;;;;;;;;;;;;;:130;;-1:-1:-1;;;;;91250:130:0;;;-1:-1:-1;;;91250:130:0;;;;;;;;;-1:-1:-1;;;;90839:557:0;-1:-1:-1;90760:3:0;;;;:::i;:::-;;;;90731:676;;;-1:-1:-1;91493:14:0;;-1:-1:-1;;;;;91493:14:0;:31;91539:10;91564:7;91586:19;91620:12;:10;:12::i;:::-;91493:150;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91478:165;;91678:18;91662:12;:34;;91654:70;;;;-1:-1:-1;;;91654:70:0;;;;;;;:::i;:::-;91758:1;91743:12;:16;91735:49;;;;-1:-1:-1;;;91735:49:0;;;;;;;:::i;:::-;91825:31;91831:10;91843:12;91825:5;:31::i;:::-;91884:10;-1:-1:-1;;;;;91872:76:0;;91896:10;91908:12;91922:7;91931:16;91872:76;;;;;;;;;:::i;:::-;;;;;;;;89920:2036;;;;;;;;;;;;:::o;94467:2327::-;94657:18;-1:-1:-1;;;;;94696:24:0;;94688:54;;;;-1:-1:-1;;;94688:54:0;;;;;;;:::i;:::-;94771:7;-1:-1:-1;;;;;94761:17:0;:6;-1:-1:-1;;;;;94761:17:0;;;94753:42;;;;-1:-1:-1;;;94753:42:0;;;;;;;:::i;:::-;94831:1;94814:14;:18;94806:52;;;;-1:-1:-1;;;94806:52:0;;;;;;;:::i;:::-;94928:30;94961:10;94928:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;94928:43:0;;;;;-1:-1:-1;;;94928:43:0;;;;;;;;;;;;;;;;;;;;;;;;;94983:14;94999:35;95038:17;95048:6;95038:9;:17::i;:::-;94982:73;;;;95067:15;95084:36;95124:18;95134:7;95124:9;:18::i;:::-;95066:76;;;;95179:18;95200;:16;:18::i;:::-;95179:39;;95269:25;95310:7;:21;95350:13;95382:10;95393:8;95382:20;;;;;;;;-1:-1:-1;;;95382:20:0;;;;;;;;;;;;;;;:26;;;95427:14;95460:5;:14;;;95310:179;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95269:220;;95640:37;95659:17;95640:18;:37::i;:::-;95591:10;95602:8;95591:20;;;;;;;;-1:-1:-1;;;95591:20:0;;;;;;;;;;;;;;;:33;;;:86;;;;:::i;:::-;95542:10;95553:8;95542:20;;;;;;;;-1:-1:-1;;;95542:20:0;;;;;;;;;;;;;;;;;:135;;-1:-1:-1;;;;;95542:135:0;;;-1:-1:-1;;;95542:135:0;;;;;;;;;;95777:14;;95922:7;;-1:-1:-1;;;;;95777:14:0;;;;:26;;95818:10;;95843:8;;95866:9;;95890:17;;95944:12;:10;:12::i;:::-;95777:190;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;95751:216;;-1:-1:-1;95751:216:0;-1:-1:-1;95986:32:0;;;;95978:69;;;;-1:-1:-1;;;95978:69:0;;;;;;;:::i;:::-;96079:1;96066:10;:14;96058:47;;;;-1:-1:-1;;;96058:47:0;;;;;;;:::i;:::-;96182:7;:22;96219:10;96244:14;96273:10;96284:9;96273:21;;;;;;;;-1:-1:-1;;;96273:21:0;;;;;;;;;;;;;;;96309:10;96334:5;:14;;;96182:177;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96470:30;96489:10;96470:18;:30::i;:::-;96420:10;96431:9;96420:21;;;;;;;;-1:-1:-1;;;96420:21:0;;;;;;;;;;;;;;;:34;;;:80;;;;:::i;:::-;96370:10;96381:9;96370:21;;;;;;;;-1:-1:-1;;;96370:21:0;;;;;;;;;;;;;;;;;;:130;;-1:-1:-1;;;;;96370:130:0;;;-1:-1:-1;;;96370:130:0;;;;;;;;;96561:13;;;;:25;;96577:9;;96561:25;:::i;:::-;96551:7;:35;;;;96624:10;-1:-1:-1;;;;;96602:184:0;;96649:13;:18;;;96682:14;:19;;;96716:10;96741:9;96765:10;96602:184;;;;;;;;;;:::i;:::-;;;;;;;;94467:2327;;;;;;;;;;;;;;;:::o;88349:1535::-;88515:20;-1:-1:-1;;;;;88556:24:0;;88548:54;;;;-1:-1:-1;;;88548:54:0;;;;;;;:::i;:::-;88638:1;88621:14;:18;88613:37;;;;-1:-1:-1;;;88613:37:0;;;;;;;:::i;:::-;88661:30;88694:10;88661:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;88661:43:0;;;;;-1:-1:-1;;;88661:43:0;;;;;;;;;;;;;;;;;;;;;;;;;88716:17;88735:30;88769:17;88779:6;88769:9;:17::i;:::-;88715:71;;;;88797:18;88818;:16;:18::i;:::-;88797:39;;88932:25;88973:7;:21;89013:8;89040:10;89051:11;89040:23;;;;;;;;-1:-1:-1;;;89040:23:0;;;;;;;;;;;;;;;:29;;;89088:14;89121:5;:14;;;88973:177;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89262:14;;88932:218;;-1:-1:-1;;;;;;89262:14:0;:26;89303:10;89328:11;88932:218;89386:12;:10;:12::i;:::-;89262:147;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89247:162;;89444:18;89428:12;:34;;89420:70;;;;-1:-1:-1;;;89420:70:0;;;;;;;:::i;:::-;89682:37;89701:17;89682:18;:37::i;:::-;89630:10;89641:11;89630:23;;;;;;;;-1:-1:-1;;;89630:23:0;;;;;;;;;;;;;;;:36;;;:89;;;;:::i;:::-;89578:10;89589:11;89578:23;;;;;;;;-1:-1:-1;;;89578:23:0;;;;;;;;;;;;;;;;;;:141;;-1:-1:-1;;;;;89578:141:0;;;-1:-1:-1;;;89578:141:0;;;;;;;;;89758:31;89764:10;89776:12;89758:5;:31::i;:::-;89812:10;-1:-1:-1;;;;;89805:71:0;;89824:10;89836:12;89850:6;89858:17;89805:71;;;;;;;;;:::i;20759:95::-;20803:7;20830:5;-1:-1:-1;;;;;20830:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;22515:121::-;22592:36;;-1:-1:-1;;;22592:36:0;;22565:7;;-1:-1:-1;;;;;22592:5:0;:15;;;;:36;;18370:66;;22592:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;13777:432;-1:-1:-1;;;;;13861:21:0;;13853:67;;;;-1:-1:-1;;;13853:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;13958:18:0;;13933:22;13958:18;;;:9;:18;;;;;;13995:24;;;;13987:71;;;;-1:-1:-1;;;13987:71:0;;;;;;;:::i;:::-;14090:23;14107:6;14090:14;:23;:::i;:::-;-1:-1:-1;;;;;14069:18:0;;;;;;:9;:18;;;;;:44;;;;14124:12;:22;;14140:6;;14069:18;14124:22;;14140:6;;14124:22;:::i;:::-;;;;-1:-1:-1;;14164:37:0;;14190:1;;-1:-1:-1;;;;;14164:37:0;;;;;;;14194:6;;14164:37;:::i;110702:275::-;110753:12;;:::i;:::-;110847:7;;110828:16;110847:7;110879:13;:11;:13::i;:::-;:24;;;;:::i;:::-;110865:38;;110921:48;;;;;;;;110927:3;110921:48;;;;110932:26;110948:9;;110932:3;:15;;:26;;;;:::i;:::-;110921:48;;;;;;;;-1:-1:-1;110914:55:0;-1:-1:-1;110702:275:0;:::o;28204:184::-;28261:7;-1:-1:-1;;;28289:5:0;:14;28281:67;;;;-1:-1:-1;;;28281:67:0;;;;;;;:::i;36274:286::-;36394:7;36547:5;36538;36542:1;36538;:5;:::i;:::-;36537:15;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:400:1:-;;;147:3;140:4;132:6;128:17;124:27;114:2;;170:6;162;155:22;114:2;-1:-1:-1;198:20:1;;-1:-1:-1;;;;;230:30:1;;227:2;;;280:8;270;263:26;227:2;324:4;316:6;312:17;300:29;;387:3;380:4;372;364:6;360:17;352:6;348:30;344:41;341:50;338:2;;;404:1;401;394:12;338:2;104:310;;;;;:::o;419:190::-;489:20;;-1:-1:-1;;;;;538:46:1;;528:57;;518:2;;599:1;596;589:12;614:259;;726:2;714:9;705:7;701:23;697:32;694:2;;;747:6;739;732:22;694:2;791:9;778:23;810:33;837:5;810:33;:::i;878:263::-;;1001:2;989:9;980:7;976:23;972:32;969:2;;;1022:6;1014;1007:22;969:2;1059:9;1053:16;1078:33;1105:5;1078:33;:::i;1146:402::-;;;1275:2;1263:9;1254:7;1250:23;1246:32;1243:2;;;1296:6;1288;1281:22;1243:2;1340:9;1327:23;1359:33;1386:5;1359:33;:::i;:::-;1411:5;-1:-1:-1;1468:2:1;1453:18;;1440:32;1481:35;1440:32;1481:35;:::i;:::-;1535:7;1525:17;;;1233:315;;;;;:::o;1553:470::-;;;;1699:2;1687:9;1678:7;1674:23;1670:32;1667:2;;;1720:6;1712;1705:22;1667:2;1764:9;1751:23;1783:33;1810:5;1783:33;:::i;:::-;1835:5;-1:-1:-1;1892:2:1;1877:18;;1864:32;1905:35;1864:32;1905:35;:::i;:::-;1657:366;;1959:7;;-1:-1:-1;;;2013:2:1;1998:18;;;;1985:32;;1657:366::o;2028:683::-;;;;;;2208:3;2196:9;2187:7;2183:23;2179:33;2176:2;;;2230:6;2222;2215:22;2176:2;2274:9;2261:23;2293:33;2320:5;2293:33;:::i;:::-;2345:5;-1:-1:-1;2402:2:1;2387:18;;2374:32;2415:35;2374:32;2415:35;:::i;:::-;2469:7;-1:-1:-1;2523:2:1;2508:18;;2495:32;;-1:-1:-1;2574:2:1;2559:18;;2546:32;;-1:-1:-1;2630:3:1;2615:19;;2602:33;2644:35;2602:33;2644:35;:::i;:::-;2698:7;2688:17;;;2166:545;;;;;;;;:::o;2716:438::-;;;2842:2;2830:9;2821:7;2817:23;2813:32;2810:2;;;2863:6;2855;2848:22;2810:2;2907:9;2894:23;2926:33;2953:5;2926:33;:::i;:::-;2978:5;-1:-1:-1;3035:2:1;3020:18;;3007:32;3077:15;;3070:23;3058:36;;3048:2;;3113:6;3105;3098:22;3159:1174;;;3310:9;3301:7;3297:23;3340:3;3336:2;3332:12;3329:2;;;3362:6;3354;3347:22;3329:2;3406:9;3393:23;3425:33;3452:5;3425:33;:::i;:::-;3477:5;-1:-1:-1;3516:4:1;-1:-1:-1;;3498:16:1;;3494:27;3491:2;;;3539:6;3531;3524:22;3491:2;3567:4;3600:2;3594:9;3642:2;3634:6;3630:15;-1:-1:-1;;;;;3732:6:1;3720:10;3717:22;3712:2;3700:10;3697:18;3694:46;3691:2;;;3743:18;;:::i;:::-;3783:10;3779:2;3772:22;3846:2;3835:9;3831:18;3818:32;3810:6;3803:48;3885:2;3879;3875:7;3871:2;3867:16;3863:25;3860:2;;;3906:6;3898;3891:22;3860:2;3946;3940:9;3924:25;;3992:2;3982:8;3978:17;3958:37;;4049:8;4035:12;4032:26;4027:2;4013:12;4010:20;4007:52;4004:2;;;4062:18;;:::i;:::-;-1:-1:-1;4091:24:1;;4141:40;4162:18;;;4141:40;:::i;:::-;4131:8;4124:58;4217:42;4253:4;4242:9;4238:20;4217:42;:::i;:::-;4212:2;4202:8;4198:17;4191:69;4293:8;4288:2;4280:6;4276:15;4269:33;4321:6;4311:16;;;;;3277:1056;;;;;:::o;4338:327::-;;;4467:2;4455:9;4446:7;4442:23;4438:32;4435:2;;;4488:6;4480;4473:22;4435:2;4532:9;4519:23;4551:33;4578:5;4551:33;:::i;:::-;4603:5;4655:2;4640:18;;;;4627:32;;-1:-1:-1;;;4425:240:1:o;4670:539::-;;;;;4833:3;4821:9;4812:7;4808:23;4804:33;4801:2;;;4855:6;4847;4840:22;4801:2;4899:9;4886:23;4918:33;4945:5;4918:33;:::i;:::-;4970:5;-1:-1:-1;5022:2:1;5007:18;;4994:32;;-1:-1:-1;5073:2:1;5058:18;;5045:32;;-1:-1:-1;5129:2:1;5114:18;;5101:32;5142:35;5101:32;5142:35;:::i;:::-;4791:418;;;;-1:-1:-1;4791:418:1;;-1:-1:-1;;4791:418:1:o;5214:600::-;;;;5378:2;5366:9;5357:7;5353:23;5349:32;5346:2;;;5399:6;5391;5384:22;5346:2;5444:9;5431:23;-1:-1:-1;;;;;5469:6:1;5466:30;5463:2;;;5514:6;5506;5499:22;5463:2;5558:76;5626:7;5617:6;5606:9;5602:22;5558:76;:::i;:::-;5653:8;;-1:-1:-1;5532:102:1;-1:-1:-1;;5738:2:1;5723:18;;5710:32;5751:33;5710:32;5751:33;:::i;:::-;5803:5;5793:15;;;5336:478;;;;;:::o;5819:815::-;;;;;6018:2;6006:9;5997:7;5993:23;5989:32;5986:2;;;6039:6;6031;6024:22;5986:2;6084:9;6071:23;-1:-1:-1;;;;;6154:2:1;6146:6;6143:14;6140:2;;;6175:6;6167;6160:22;6140:2;6219:76;6287:7;6278:6;6267:9;6263:22;6219:76;:::i;:::-;6314:8;;-1:-1:-1;6193:102:1;-1:-1:-1;6402:2:1;6387:18;;6374:32;;-1:-1:-1;6418:16:1;;;6415:2;;;6452:6;6444;6437:22;6415:2;;6496:78;6566:7;6555:8;6544:9;6540:24;6496:78;:::i;:::-;5976:658;;;;-1:-1:-1;6593:8:1;-1:-1:-1;;;;5976:658:1:o;6639:1021::-;;;;;;;6872:3;6860:9;6851:7;6847:23;6843:33;6840:2;;;6894:6;6886;6879:22;6840:2;6939:9;6926:23;-1:-1:-1;;;;;7009:2:1;7001:6;6998:14;6995:2;;;7030:6;7022;7015:22;6995:2;7074:76;7142:7;7133:6;7122:9;7118:22;7074:76;:::i;:::-;7169:8;;-1:-1:-1;7048:102:1;-1:-1:-1;7257:2:1;7242:18;;7229:32;;-1:-1:-1;7273:16:1;;;7270:2;;;7307:6;7299;7292:22;7270:2;;7351:78;7421:7;7410:8;7399:9;7395:24;7351:78;:::i;:::-;7448:8;;-1:-1:-1;7325:104:1;-1:-1:-1;;7530:2:1;7515:18;;7502:32;;-1:-1:-1;7584:2:1;7569:18;;7556:32;7597:33;7556:32;7597:33;:::i;:::-;7649:5;7639:15;;;6830:830;;;;;;;;:::o;7665:274::-;;;7794:2;7782:9;7773:7;7769:23;7765:32;7762:2;;;7815:6;7807;7800:22;7762:2;7843:31;7864:9;7843:31;:::i;:::-;7833:41;;7893:40;7929:2;7918:9;7914:18;7893:40;:::i;:::-;7883:50;;7752:187;;;;;:::o;7944:190::-;;8056:2;8044:9;8035:7;8031:23;8027:32;8024:2;;;8077:6;8069;8062:22;8024:2;-1:-1:-1;8105:23:1;;8014:120;-1:-1:-1;8014:120:1:o;8139:194::-;;8262:2;8250:9;8241:7;8237:23;8233:32;8230:2;;;8283:6;8275;8268:22;8230:2;-1:-1:-1;8311:16:1;;8220:113;-1:-1:-1;8220:113:1:o;8338:668::-;;;;;8519:2;8507:9;8498:7;8494:23;8490:32;8487:2;;;8540:6;8532;8525:22;8487:2;8581:9;8568:23;8558:33;;8642:2;8631:9;8627:18;8614:32;-1:-1:-1;;;;;8661:6:1;8658:30;8655:2;;;8706:6;8698;8691:22;8655:2;8750:76;8818:7;8809:6;8798:9;8794:22;8750:76;:::i;:::-;8845:8;;-1:-1:-1;8724:102:1;-1:-1:-1;;8930:2:1;8915:18;;8902:32;8943:33;8902:32;8943:33;:::i;9011:1053::-;;;9176:2;9164:9;9155:7;9151:23;9147:32;9144:2;;;9197:6;9189;9182:22;9144:2;9231:9;9225:16;9215:26;;9260:2;9306;9295:9;9291:18;9285:25;-1:-1:-1;;;;;9370:2:1;9362:6;9359:14;9356:2;;;9391:6;9383;9376:22;9356:2;9434:6;9423:9;9419:22;9409:32;;9479:7;9472:4;9468:2;9464:13;9460:27;9450:2;;9506:6;9498;9491:22;9450:2;9540;9534:9;9562:2;9558;9555:10;9552:2;;;9568:18;;:::i;:::-;9615:2;9611;9607:11;9597:21;;9638:27;9661:2;9657;9653:11;9638:27;:::i;:::-;9699:15;;;9730:12;;;;9762:11;;;9792;;;9788:20;;9785:33;-1:-1:-1;9782:2:1;;;9836:6;9828;9821:22;9782:2;9863:6;9854:15;;9878:156;9892:2;9889:1;9886:9;9878:156;;;9949:10;;9937:23;;9910:1;9903:9;;;;;9980:12;;;;10012;;9878:156;;;9882:3;10053:5;10043:15;;;;;;;;9134:930;;;;;:::o;10069:258::-;;;10198:2;10186:9;10177:7;10173:23;10169:32;10166:2;;;10219:6;10211;10204:22;10166:2;-1:-1:-1;;10247:23:1;;;10317:2;10302:18;;;10289:32;;-1:-1:-1;10156:171:1:o;10332:255::-;;;10472:2;10460:9;10451:7;10447:23;10443:32;10440:2;;;10493:6;10485;10478:22;10440:2;-1:-1:-1;;10521:16:1;;10577:2;10562:18;;;10556:25;10521:16;;10556:25;;-1:-1:-1;10430:157:1:o;10592:469::-;;10689:5;10683:12;10716:6;10711:3;10704:19;10742:4;10771:2;10766:3;10762:12;10755:19;;10808:2;10801:5;10797:14;10829:3;10841:195;10855:6;10852:1;10849:13;10841:195;;;10920:13;;-1:-1:-1;;;;;10916:39:1;10904:52;;10976:12;;;;11011:15;;;;10952:1;10870:9;10841:195;;;-1:-1:-1;11052:3:1;;10659:402;-1:-1:-1;;;;;10659:402:1:o;11066:481::-;;11174:5;11168:12;11201:6;11196:3;11189:19;11227:4;11256:2;11251:3;11247:12;11240:19;;11293:2;11286:5;11282:14;11314:3;11326:196;11340:6;11337:1;11334:13;11326:196;;;11389:51;11436:3;11427:6;11421:13;11389:51;:::i;:::-;11469:4;11460:14;;;;;11497:15;;;;11362:1;11355:9;11326:196;;11552:636;;11676:5;11670:12;11703:6;11698:3;11691:19;11729:4;11758:2;11753:3;11749:12;11742:19;;11782:5;11777:3;11770:18;11826:2;11821:3;11811:18;11847:3;11859:304;11873:6;11870:1;11867:13;11859:304;;;11939:13;;-1:-1:-1;;;;;11977:50:1;;11965:63;;12066:3;12062:19;12048:12;;;12041:41;12111:4;12102:14;;;;12151:1;12139:14;;;;11888:9;11859:304;;12193:443;;12290:5;12284:12;12317:6;12312:3;12305:19;12343:4;12372:2;12367:3;12363:12;12356:19;;12409:2;12402:5;12398:14;12430:3;12442:169;12456:6;12453:1;12450:13;12442:169;;;12517:13;;12505:26;;12551:12;;;;12586:15;;;;12478:1;12471:9;12442:169;;12641:452;;12736:5;12730:12;12763:6;12758:3;12751:19;12789:4;12818:2;12813:3;12809:12;12802:19;;12855:2;12848:5;12844:14;12876:3;12888:180;12902:6;12899:1;12896:13;12888:180;;;12967:13;;12982:4;12963:24;12951:37;;13008:12;;;;13043:15;;;;12924:1;12917:9;12888:180;;13098:243;13185:1;13178:5;13175:12;13165:2;;13230:10;13225:3;13221:20;13218:1;13211:31;13265:4;13262:1;13255:15;13293:4;13290:1;13283:15;13165:2;13317:18;;13155:186::o;13346:225::-;13482:12;;-1:-1:-1;;;;;13478:21:1;;;13466:34;;13553:4;13542:16;;;13536:23;13532:32;13516:14;;13509:56;13403:168::o;13576:408::-;13674:1;13670;13665:3;13661:11;13657:19;13715:2;13707:5;13701:12;13697:21;13692:3;13685:34;13780:2;13772:4;13765:5;13761:16;13755:23;13751:32;13744:4;13739:3;13735:14;13728:56;;13847:4;13840:5;13836:16;13830:23;13823:31;13816:39;13809:4;13804:3;13800:14;13793:63;13902:4;13895:5;13891:16;13885:23;13917:61;13972:4;13967:3;13963:14;13949:12;13917:61;:::i;:::-;;13637:347;;:::o;13989:424::-;14095:1;14091;14086:3;14082:11;14078:19;14136:2;14128:5;14122:12;14118:21;14113:3;14106:34;14183:4;14176:5;14172:16;14166:23;14236:2;14225:9;14221:18;14214:4;14209:3;14205:14;14198:42;14311:4;14299:9;14294:3;14290:19;14286:30;14279:38;14272:46;14265:4;14260:3;14256:14;14249:70;14328:79;14401:4;14396:3;14392:14;14385:4;14373:9;14368:3;14364:19;14360:30;14328:79;:::i;14418:225::-;14508:5;14502:12;14497:3;14490:25;14561:4;14554:5;14550:16;14544:23;14576:61;14631:4;14626:3;14622:14;14608:12;14576:61;:::i;14648:203::-;-1:-1:-1;;;;;14812:32:1;;;;14794:51;;14782:2;14767:18;;14749:102::o;14856:495::-;-1:-1:-1;;;;;15150:15:1;;;15132:34;;15202:15;;15197:2;15182:18;;15175:43;15261:14;;15254:22;15249:2;15234:18;;15227:50;15081:3;15066:19;;15286:59;15341:2;15326:18;;15318:6;15286:59;:::i;15356:528::-;-1:-1:-1;;;;;15671:15:1;;;15653:34;;15723:15;;;15718:2;15703:18;;15696:43;15770:2;15755:18;;15748:34;;;;15813:2;15798:18;;15791:34;15862:15;;;15856:3;15841:19;;15834:44;15602:3;15587:19;;15569:315::o;15889:447::-;-1:-1:-1;;;;;16176:15:1;;;16158:34;;16223:2;16208:18;;16201:34;;;;16271:15;;16266:2;16251:18;;16244:43;16318:2;16303:18;;16296:34;;;;16107:3;16092:19;;16074:262::o;16341:519::-;-1:-1:-1;;;;;16656:15:1;;;16638:34;;16703:2;16688:18;;16681:34;;;;16751:15;;;;16746:2;16731:18;;16724:43;16798:2;16783:18;;16776:34;;;;16841:3;16826:19;;16819:35;;;;16587:3;16572:19;;16554:306::o;16865:647::-;;17207:1;17203;17198:3;17194:11;17190:19;17182:6;17178:32;17167:9;17160:51;17247:6;17242:2;17231:9;17227:18;17220:34;17290:3;17285:2;17274:9;17270:18;17263:31;17317:63;17375:3;17364:9;17360:19;17352:6;17317:63;:::i;:::-;17428:9;17420:6;17416:22;17411:2;17400:9;17396:18;17389:50;17456;17499:6;17491;17456:50;:::i;17517:719::-;;17887:1;17883;17878:3;17874:11;17870:19;17862:6;17858:32;17847:9;17840:51;17927:6;17922:2;17911:9;17907:18;17900:34;17970:3;17965:2;17954:9;17950:18;17943:31;17997:63;18055:3;18044:9;18040:19;18032:6;17997:63;:::i;:::-;18108:9;18100:6;18096:22;18091:2;18080:9;18076:18;18069:50;18136;18179:6;18171;18136:50;:::i;:::-;18128:58;;;18223:6;18217:3;18206:9;18202:19;18195:35;17830:406;;;;;;;;:::o;18241:909::-;;18714:3;18703:9;18696:22;18741:74;18810:3;18799:9;18795:19;18787:6;18741:74;:::i;:::-;18863:9;18855:6;18851:22;18846:2;18835:9;18831:18;18824:50;18897:48;18938:6;18930;18897:48;:::i;:::-;18883:62;;18993:9;18985:6;18981:22;18976:2;18965:9;18961:18;18954:50;19021;19064:6;19056;19021:50;:::i;:::-;19013:58;;;19080:64;19140:2;19129:9;19125:18;19117:6;19080:64;:::i;19155:644::-;;19528:3;19517:9;19510:22;19549:74;19618:3;19607:9;19603:19;19595:6;19549:74;:::i;:::-;19541:82;;19671:4;19663:6;19659:17;19654:2;19643:9;19639:18;19632:45;19713:6;19708:2;19697:9;19693:18;19686:34;19729:64;19789:2;19778:9;19774:18;19766:6;19729:64;:::i;19804:815::-;;20221:3;20251:2;20240:9;20233:21;20271:73;20340:2;20329:9;20325:18;20317:6;20271:73;:::i;:::-;20263:81;;;20392:4;20384:6;20380:17;20375:2;20364:9;20360:18;20353:45;20446:4;20438:6;20434:17;20429:2;20418:9;20414:18;20407:45;20488:6;20483:2;20472:9;20468:18;20461:34;20532:6;20526:3;20515:9;20511:19;20504:35;20548:65;20608:3;20597:9;20593:19;20585:6;20548:65;:::i;20624:1142::-;;21101:3;21090:9;21083:22;21128:90;21213:3;21202:9;21198:19;21190:6;21128:90;:::i;:::-;21266:9;21258:6;21254:22;21249:2;21238:9;21234:18;21227:50;21300:48;21341:6;21333;21300:48;:::i;:::-;21384:22;;;21379:2;21364:18;;21357:50;21416:22;;;21286:62;-1:-1:-1;;;;;;21450:31:1;;21447:2;;;21497:4;21491;21484:18;21447:2;21539;21531:6;21527:15;21589:6;21581;21576:2;21568:6;21564:15;21551:45;21619:19;21640:2;21615:28;21652:16;;;21696:64;21756:2;21741:18;;21733:6;21696:64;:::i;:::-;21073:693;;;;;;;;:::o;21771:654::-;;22138:3;22127:9;22120:22;22159:90;22244:3;22233:9;22229:19;22221:6;22159:90;:::i;22430:969::-;22810:2;22822:21;;;22892:13;;22795:18;;;22914:22;;;22430:969;;22989:4;;22967:2;22952:18;;;23016:15;;;22430:969;23062:200;23076:6;23073:1;23070:13;23062:200;;;23125:55;23176:3;23167:6;23161:13;23125:55;:::i;:::-;23209:4;23200:14;;;;;23237:15;;;;23098:1;23091:9;23062:200;;;23066:3;;;23307:9;23302:3;23298:19;23293:2;23282:9;23278:18;23271:47;23335:58;23389:3;23381:6;23335:58;:::i;23404:1153::-;23874:3;23887:22;;;23958:13;;23859:19;;;23980:22;;;23404:1153;24046:20;;;24105:4;24089:21;;23404:1153;;24033:3;24018:19;;;23404:1153;24141:203;24155:6;24152:1;24149:13;24141:203;;;24204:56;24256:3;24248:6;24204:56;:::i;:::-;24329:4;24317:17;;;;;24289:4;24280:14;;;;;24177:1;24170:9;24141:203;;;-1:-1:-1;;24395:4:1;24380:20;;24373:36;;;-1:-1:-1;;;;;24445:32:1;;24440:2;24425:18;;24418:60;24361:3;-1:-1:-1;24487:64:1;;-1:-1:-1;24547:2:1;24532:18;;24524:6;24487:64;:::i;24562:507::-;24867:25;;;24923:2;24908:18;;24901:34;;;;-1:-1:-1;;;;;24971:32:1;24966:2;24951:18;;24944:60;25047:14;25040:22;25035:2;25020:18;;25013:50;24854:3;24839:19;;24821:248::o;25074:1032::-;25451:25;;;25495:2;25513:18;;;25506:34;;;25438:3;25571:2;25556:18;;25549:31;;;25423:19;;25615:22;;;25074:1032;;25695:6;;25668:3;25653:19;;25074:1032;25732:279;25746:6;25743:1;25740:13;25732:279;;;25821:6;25808:20;25841:33;25868:5;25841:33;:::i;:::-;-1:-1:-1;;;;;25899:31:1;25887:44;;25986:15;;;;25951:12;;;;25927:1;25761:9;25732:279;;;-1:-1:-1;;;;;;26067:32:1;;;;26062:2;26047:18;;;;26040:60;;;;-1:-1:-1;26028:3:1;;25399:707;-1:-1:-1;;;;;;25399:707:1:o;26111:267::-;;26290:2;26279:9;26272:21;26310:62;26368:2;26357:9;26353:18;26345:6;26310:62;:::i;26383:187::-;26548:14;;26541:22;26523:41;;26511:2;26496:18;;26478:92::o;26575:268::-;26762:14;;26755:22;26737:41;;26821:14;26814:22;26809:2;26794:18;;26787:50;26725:2;26710:18;;26692:151::o;26848:177::-;26994:25;;;26982:2;26967:18;;26949:76::o;27030:565::-;-1:-1:-1;;;;;27427:32:1;;;;27409:51;;27491:2;27476:18;;27469:34;;;;27534:2;27519:18;;27512:34;27577:2;27562:18;;27555:34;27396:3;27381:19;;27363:232::o;28057:603::-;;28198:2;28227;28216:9;28209:21;28259:6;28253:13;28302:6;28297:2;28286:9;28282:18;28275:34;28327:4;28340:140;28354:6;28351:1;28348:13;28340:140;;;28449:14;;;28445:23;;28439:30;28415:17;;;28434:2;28411:26;28404:66;28369:10;;28340:140;;;28498:6;28495:1;28492:13;28489:2;;;28568:4;28563:2;28554:6;28543:9;28539:22;28535:31;28528:45;28489:2;-1:-1:-1;28644:2:1;28623:15;-1:-1:-1;;28619:29:1;28604:45;;;;28651:2;28600:54;;28178:482;-1:-1:-1;;;28178:482:1:o;28665:339::-;28867:2;28849:21;;;28906:2;28886:18;;;28879:30;-1:-1:-1;;;28940:2:1;28925:18;;28918:45;28995:2;28980:18;;28839:165::o;29009:399::-;29211:2;29193:21;;;29250:2;29230:18;;;29223:30;29289:34;29284:2;29269:18;;29262:62;-1:-1:-1;;;29355:2:1;29340:18;;29333:33;29398:3;29383:19;;29183:225::o;29413:340::-;29615:2;29597:21;;;29654:2;29634:18;;;29627:30;-1:-1:-1;;;29688:2:1;29673:18;;29666:46;29744:2;29729:18;;29587:166::o;29758:337::-;29960:2;29942:21;;;29999:2;29979:18;;;29972:30;-1:-1:-1;;;30033:2:1;30018:18;;30011:43;30086:2;30071:18;;29932:163::o;30100:398::-;30302:2;30284:21;;;30341:2;30321:18;;;30314:30;30380:34;30375:2;30360:18;;30353:62;-1:-1:-1;;;30446:2:1;30431:18;;30424:32;30488:3;30473:19;;30274:224::o;30503:337::-;30705:2;30687:21;;;30744:2;30724:18;;;30717:30;-1:-1:-1;;;30778:2:1;30763:18;;30756:43;30831:2;30816:18;;30677:163::o;30845:336::-;31047:2;31029:21;;;31086:2;31066:18;;;31059:30;-1:-1:-1;;;31120:2:1;31105:18;;31098:42;31172:2;31157:18;;31019:162::o;31186:398::-;31388:2;31370:21;;;31427:2;31407:18;;;31400:30;31466:34;31461:2;31446:18;;31439:62;-1:-1:-1;;;31532:2:1;31517:18;;31510:32;31574:3;31559:19;;31360:224::o;31589:347::-;31791:2;31773:21;;;31830:2;31810:18;;;31803:30;31869:25;31864:2;31849:18;;31842:53;31927:2;31912:18;;31763:173::o;31941:331::-;32143:2;32125:21;;;32182:1;32162:18;;;32155:29;-1:-1:-1;;;32215:2:1;32200:18;;32193:38;32263:2;32248:18;;32115:157::o;32277:344::-;32479:2;32461:21;;;32518:2;32498:18;;;32491:30;-1:-1:-1;;;32552:2:1;32537:18;;32530:50;32612:2;32597:18;;32451:170::o;32626:402::-;32828:2;32810:21;;;32867:2;32847:18;;;32840:30;32906:34;32901:2;32886:18;;32879:62;-1:-1:-1;;;32972:2:1;32957:18;;32950:36;33018:3;33003:19;;32800:228::o;33033:344::-;33235:2;33217:21;;;33274:2;33254:18;;;33247:30;-1:-1:-1;;;33308:2:1;33293:18;;33286:50;33368:2;33353:18;;33207:170::o;33382:403::-;33584:2;33566:21;;;33623:2;33603:18;;;33596:30;33662:34;33657:2;33642:18;;33635:62;-1:-1:-1;;;33728:2:1;33713:18;;33706:37;33775:3;33760:19;;33556:229::o;33790:336::-;33992:2;33974:21;;;34031:2;34011:18;;;34004:30;-1:-1:-1;;;34065:2:1;34050:18;;34043:42;34117:2;34102:18;;33964:162::o;34131:348::-;34333:2;34315:21;;;34372:2;34352:18;;;34345:30;34411:26;34406:2;34391:18;;34384:54;34470:2;34455:18;;34305:174::o;34484:347::-;34686:2;34668:21;;;34725:2;34705:18;;;34698:30;34764:25;34759:2;34744:18;;34737:53;34822:2;34807:18;;34658:173::o;34836:343::-;35038:2;35020:21;;;35077:2;35057:18;;;35050:30;-1:-1:-1;;;35111:2:1;35096:18;;35089:49;35170:2;35155:18;;35010:169::o;35184:349::-;35386:2;35368:21;;;35425:2;35405:18;;;35398:30;35464:27;35459:2;35444:18;;35437:55;35524:2;35509:18;;35358:175::o;35538:343::-;35740:2;35722:21;;;35779:2;35759:18;;;35752:30;-1:-1:-1;;;35813:2:1;35798:18;;35791:49;35872:2;35857:18;;35712:169::o;35886:338::-;36088:2;36070:21;;;36127:2;36107:18;;;36100:30;-1:-1:-1;;;36161:2:1;36146:18;;36139:44;36215:2;36200:18;;36060:164::o;36229:332::-;36431:2;36413:21;;;36470:1;36450:18;;;36443:29;-1:-1:-1;;;36503:2:1;36488:18;;36481:39;36552:2;36537:18;;36403:158::o;36566:346::-;36768:2;36750:21;;;36807:2;36787:18;;;36780:30;-1:-1:-1;;;36841:2:1;36826:18;;36819:52;36903:2;36888:18;;36740:172::o;36917:338::-;37119:2;37101:21;;;37158:2;37138:18;;;37131:30;-1:-1:-1;;;37192:2:1;37177:18;;37170:44;37246:2;37231:18;;37091:164::o;37260:335::-;37462:2;37444:21;;;37501:2;37481:18;;;37474:30;-1:-1:-1;;;37535:2:1;37520:18;;37513:41;37586:2;37571:18;;37434:161::o;37600:402::-;37802:2;37784:21;;;37841:2;37821:18;;;37814:30;37880:34;37875:2;37860:18;;37853:62;-1:-1:-1;;;37946:2:1;37931:18;;37924:36;37992:3;37977:19;;37774:228::o;38007:404::-;38209:2;38191:21;;;38248:2;38228:18;;;38221:30;38287:34;38282:2;38267:18;;38260:62;-1:-1:-1;;;38353:2:1;38338:18;;38331:38;38401:3;38386:19;;38181:230::o;38416:341::-;38618:2;38600:21;;;38657:2;38637:18;;;38630:30;-1:-1:-1;;;38691:2:1;38676:18;;38669:47;38748:2;38733:18;;38590:167::o;38762:345::-;38964:2;38946:21;;;39003:2;38983:18;;;38976:30;-1:-1:-1;;;39037:2:1;39022:18;;39015:51;39098:2;39083:18;;38936:171::o;39112:344::-;39314:2;39296:21;;;39353:2;39333:18;;;39326:30;-1:-1:-1;;;39387:2:1;39372:18;;39365:50;39447:2;39432:18;;39286:170::o;39461:397::-;39663:2;39645:21;;;39702:2;39682:18;;;39675:30;39741:34;39736:2;39721:18;;39714:62;-1:-1:-1;;;39807:2:1;39792:18;;39785:31;39848:3;39833:19;;39635:223::o;39863:339::-;40065:2;40047:21;;;40104:2;40084:18;;;40077:30;-1:-1:-1;;;40138:2:1;40123:18;;40116:45;40193:2;40178:18;;40037:165::o;40207:401::-;40409:2;40391:21;;;40448:2;40428:18;;;40421:30;40487:34;40482:2;40467:18;;40460:62;-1:-1:-1;;;40553:2:1;40538:18;;40531:35;40598:3;40583:19;;40381:227::o;40613:338::-;40815:2;40797:21;;;40854:2;40834:18;;;40827:30;-1:-1:-1;;;40888:2:1;40873:18;;40866:44;40942:2;40927:18;;40787:164::o;40956:400::-;41158:2;41140:21;;;41197:2;41177:18;;;41170:30;41236:34;41231:2;41216:18;;41209:62;-1:-1:-1;;;41302:2:1;41287:18;;41280:34;41346:3;41331:19;;41130:226::o;41361:329::-;41563:2;41545:21;;;41602:1;41582:18;;;41575:29;-1:-1:-1;;;41635:2:1;41620:18;;41613:36;41681:2;41666:18;;41535:155::o;41695:355::-;41897:2;41879:21;;;41936:2;41916:18;;;41909:30;41975:33;41970:2;41955:18;;41948:61;42041:2;42026:18;;41869:181::o;42055:344::-;42257:2;42239:21;;;42296:2;42276:18;;;42269:30;-1:-1:-1;;;42330:2:1;42315:18;;42308:50;42390:2;42375:18;;42229:170::o;42404:348::-;42606:2;42588:21;;;42645:2;42625:18;;;42618:30;42684:26;42679:2;42664:18;;42657:54;42743:2;42728:18;;42578:174::o;42757:356::-;42959:2;42941:21;;;42978:18;;;42971:30;43037:34;43032:2;43017:18;;43010:62;43104:2;43089:18;;42931:182::o;43118:401::-;43320:2;43302:21;;;43359:2;43339:18;;;43332:30;43398:34;43393:2;43378:18;;43371:62;-1:-1:-1;;;43464:2:1;43449:18;;43442:35;43509:3;43494:19;;43292:227::o;43524:355::-;43726:2;43708:21;;;43765:2;43745:18;;;43738:30;43804:33;43799:2;43784:18;;43777:61;43870:2;43855:18;;43698:181::o;43884:276::-;44086:25;;;44142:2;44127:18;;44120:34;44074:2;44059:18;;44041:119::o;44165:491::-;44452:25;;;44508:2;44493:18;;44486:34;;;;44551:2;44536:18;;44529:34;;;;44594:2;44579:18;;44572:34;44637:3;44622:19;;44615:35;44439:3;44424:19;;44406:250::o;44661:521::-;44996:25;;;45052:2;45037:18;;45030:34;;;;45095:2;45080:18;;45073:34;-1:-1:-1;;;;;45143:32:1;45138:2;45123:18;;45116:60;44983:3;44968:19;;44950:232::o;45187:603::-;45544:25;;;45600:2;45585:18;;45578:34;;;;45643:2;45628:18;;45621:34;;;;-1:-1:-1;;;;;45691:32:1;45686:2;45671:18;;45664:60;45768:14;45761:22;45755:3;45740:19;;45733:51;45531:3;45516:19;;45498:292::o;45795:416::-;46069:3;46054:19;;46082:54;46058:9;46118:6;46082:54;:::i;:::-;46145:60;46200:3;46189:9;46185:19;46177:6;46145:60;:::i;46216:532::-;46502:3;46487:19;;46515:54;46491:9;46551:6;46515:54;:::i;:::-;-1:-1:-1;;;;;46610:6:1;46606:47;46600:3;46589:9;46585:19;46578:76;46691:6;46685:3;46674:9;46670:19;46663:35;46735:6;46729:3;46718:9;46714:19;46707:35;46469:279;;;;;;;:::o;46753:269::-;46949:2;46934:18;;46961:55;46938:9;46998:6;46961:55;:::i;47027:319::-;-1:-1:-1;;;;;47272:15:1;;;47254:34;;47324:15;;47319:2;47304:18;;47297:43;47189:2;47174:18;;47156:190::o;47533:665::-;47912:25;;;47899:3;47884:19;;47946:63;48005:2;47990:18;;47982:6;47946:63;:::i;:::-;48018:60;48073:3;48062:9;48058:19;48050:6;48018:60;:::i;:::-;-1:-1:-1;;;;;48115:32:1;;;;48109:3;48094:19;;48087:61;48179:3;48164:19;48157:35;47866:332;;-1:-1:-1;;;47866:332:1:o;48203:670::-;48579:25;;;48566:3;48551:19;;48613:71;48680:2;48665:18;;48657:6;48613:71;:::i;49131:456::-;-1:-1:-1;;;;;49409:15:1;;;49391:34;;49461:15;;;49456:2;49441:18;;49434:43;49513:15;;;49508:2;49493:18;;49486:43;49565:15;;;49560:2;49545:18;;49538:43;49341:3;49326:19;;49308:279::o;49592:184::-;49764:4;49752:17;;;;49734:36;;49722:2;49707:18;;49689:87::o;49781:251::-;49851:2;49845:9;49881:17;;;-1:-1:-1;;;;;49913:34:1;;49949:22;;;49910:62;49907:2;;;49975:18;;:::i;:::-;50011:2;50004:22;49825:207;;-1:-1:-1;49825:207:1:o;50037:253::-;;-1:-1:-1;;;;;50166:2:1;50163:1;50159:10;50196:2;50193:1;50189:10;50227:3;50223:2;50219:12;50214:3;50211:21;50208:2;;;50235:18;;:::i;:::-;50271:13;;50085:205;-1:-1:-1;;;;50085:205:1:o;50295:128::-;;50366:1;50362:6;50359:1;50356:13;50353:2;;;50372:18;;:::i;:::-;-1:-1:-1;50408:9:1;;50343:80::o;50428:217::-;;50494:1;50484:2;;-1:-1:-1;;;50519:31:1;;50573:4;50570:1;50563:15;50601:4;50526:1;50591:15;50484:2;-1:-1:-1;50630:9:1;;50474:171::o;50650:168::-;;50756:1;50752;50748:6;50744:14;50741:1;50738:21;50733:1;50726:9;50719:17;50715:45;50712:2;;;50763:18;;:::i;:::-;-1:-1:-1;50803:9:1;;50702:116::o;50823:246::-;;-1:-1:-1;;;;;50976:10:1;;;;50946;;50998:12;;;50995:2;;;51013:18;;:::i;:::-;51050:13;;50872:197;-1:-1:-1;;;50872:197:1:o;51074:125::-;;51142:1;51139;51136:8;51133:2;;;51147:18;;:::i;:::-;-1:-1:-1;51184:9:1;;51123:76::o;51204:229::-;;-1:-1:-1;;;;;51340:10:1;;;;51310;;51362:12;;;51359:2;;;51377:18;;:::i;51438:380::-;51523:1;51513:12;;51570:1;51560:12;;;51581:2;;51635:4;51627:6;51623:17;51613:27;;51581:2;51688;51680:6;51677:14;51657:18;51654:38;51651:2;;;51734:10;51729:3;51725:20;51722:1;51715:31;51769:4;51766:1;51759:15;51797:4;51794:1;51787:15;51651:2;;51493:325;;;:::o;51823:135::-;;-1:-1:-1;;51883:17:1;;51880:2;;;51903:18;;:::i;:::-;-1:-1:-1;51950:1:1;51939:13;;51870:88::o;51963:127::-;52024:10;52019:3;52015:20;52012:1;52005:31;52055:4;52052:1;52045:15;52079:4;52076:1;52069:15;52095:127;52156:10;52151:3;52147:20;52144:1;52137:31;52187:4;52184:1;52177:15;52211:4;52208:1;52201:15;52227:133;-1:-1:-1;;;;;52304:31:1;;52294:42;;52284:2;;52350:1;52347;52340:12
Swarm Source
ipfs://4014dbc26b1298e94a14cc814e26ede056b10538e62ff69a29baf25c11068bed
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.