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 | 16939085 | 525 days ago | IN | 0 ETH | 0.16132337 |
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:
MassetBtcV2
Compiler Version
v0.8.0+commit.c7dfd78e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-03-30 */ /** *Submitted for verification at Etherscan.io on 2021-02-12 */ 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; } // SPDX-License-Identifier: AGPL-3.0-or-later /* * @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 override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view 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 override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view 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 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 override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()] - 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 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 returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - 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 { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] -= 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 { 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 { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] -= amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is 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 { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()] - 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.3._ */ 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.3._ */ 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 { uint256 newAllowance = token.allowance(address(this), spender) - 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 MassetManagerBtcV2 { 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 if (_newIntegration != address(0)) { 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" ); } else { uint256 newCache = IERC20(bAsset).balanceOf(address(this)); require(newCache == sum, "Must cache 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 ); } } } } // External // Internal // Libs /** * @title Masset * @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 MassetBtcV2 is IMasset, Initializable, InitializableToken, ImmutableModule, InitializableReentrancyGuard { 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 Deprecated_BasketManager 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 Initialization function for upgradable proxy contract. // * This function should be called via Proxy just after contract deployment. // * To avoid variable shadowing appended `Arg` after arguments name. // * @param _nameArg Name of the mAsset // * @param _symbolArg Symbol of the mAsset // * @param _forgeValidator Address of the AMM implementation // * @param _bAssets Array of Basset data // */ // function initialize( // string calldata _nameArg, // string calldata _symbolArg, // address _forgeValidator, // BassetPersonal[] calldata _bAssets, // InvariantConfig memory _config // ) public initializer { // InitializableToken._initialize(_nameArg, _symbolArg); // _initializeReentrancyGuard(); // forgeValidator = IInvariantValidator(_forgeValidator); // maxBassets = 10; // uint256 len = _bAssets.length; // require(len > 0, "No bAssets"); // for (uint256 i = 0; i < len; i++) { // Manager.addBasset( // bAssetPersonal, // bAssetData, // bAssetIndexes, // maxBassets, // _bAssets[i].addr, // _bAssets[i].integrator, // 1e8, // _bAssets[i].hasTxFee // ); // } // uint64 startA = SafeCast.toUint64(_config.a * A_PRECISION); // ampData = AmpData(startA, startA, 0, 0); // weightLimits = _config.limits; // MAX_FEE = 2e16; // swapFee = 6e14; // redemptionFee = 3e14; // cacheSize = 1e17; // } /** * @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 = MassetManagerBtcV2.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 = MassetManagerBtcV2.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 = MassetManagerBtcV2.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 MassetManagerBtcV2.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 MassetManagerBtcV2.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 MassetManagerBtcV2.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]; MassetManagerBtcV2.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) = MassetManagerBtcV2.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 { MassetManagerBtcV2.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 { MassetManagerBtcV2.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 { MassetManagerBtcV2.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 { MassetManagerBtcV2.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 { MassetManagerBtcV2.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 { MassetManagerBtcV2.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":"_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
60a06040523480156200001157600080fd5b506040516200587c3803806200587c83398101604081905262000034916200007e565b806001600160a01b038116620000675760405162461bcd60e51b81526004016200005e90620000ae565b60405180910390fd5b60601b6001600160601b03191660805250620000e5565b60006020828403121562000090578081fd5b81516001600160a01b0381168114620000a7578182fd5b9392505050565b60208082526015908201527f4e657875732061646472657373206973207a65726f0000000000000000000000604082015260600190565b60805160601c61576a620001126000396000818161182c01528181613f120152613fbb015261576a6000f3fe608060405234801561001057600080fd5b50600436106102f15760003560e01c80636d5d6eb11161019d578063aa5d27e9116100e9578063cd6ef2b0116100a2578063dd62ed3e1161007c578063dd62ed3e1461066e578063e5555b8f14610681578063edc832b314610694578063f74bfe8e1461069c576102f1565b8063cd6ef2b01461063d578063d5bcb9b514610653578063d7d5226614610666576102f1565b8063aa5d27e9146105c7578063ab06346c146105da578063af290bd4146105fa578063bdfbe29c1461060d578063c3f909d414610620578063c4db7fa014610635576102f1565b8063905e891411610156578063a1c2515111610130578063a1c2515114610579578063a3f5c1d21461058c578063a457c2d7146105a1578063a9059cbb146105b4576102f1565b8063905e89141461054b57806395d89b411461055e578063969642b914610566576102f1565b80636d5d6eb1146104e45780636fb3e89c146104f757806370a082311461050a57806372ea90761461051d57806378aa987e146105305780637e8901ea14610543576102f1565b806326bbe60a1161025c57806343bcfab61161021557806354cf2aeb116101ef57806354cf2aeb146104b4578063598362f0146104bc578063674a64e0146104d45780636c36581c146104dc576102f1565b806343bcfab61461048657806344e3fa3c14610499578063458f5815146104ac576102f1565b806326bbe60a146104015780632a2fab22146104145780632f91a7241461042a578063313ce5671461044a57806339509351146104525780633e37bcbc14610465576102f1565b806313888565116102ae578063138885651461039f57806318160ddd146103a75780631820783d146103af5780631d3ce398146103c2578063213c501a146103d857806323b872dd146103ee576102f1565b80630357359c146102f657806304de5a731461032257806306fdde0314610342578063095ea7b3146103575780630b78f9c014610377578063119849cf1461038c575b600080fd5b61030961030436600461456b565b6106af565b60405161031994939291906148f6565b60405180910390f35b610335610330366004614449565b6106ff565b6040516103199190614d05565b61034a610847565b6040516103199190614d0e565b61036a610365366004614381565b6108da565b6040516103199190614ce8565b61038a6103853660046146b1565b6108f8565b005b61033561039a366004614381565b61098c565b610335610a56565b610335610a5c565b61038a6103bd36600461456b565b610a62565b6103ca610ad2565b604051610319929190614b73565b6103e0610c2f565b604051610319929190615515565b61036a6103fc3660046142b2565b610c49565b61038a61040f366004614242565b610cbf565b61041c610d69565b604051610319929190615437565b61043d610438366004614242565b610e20565b60405161031991906155ae565b61043d610e35565b61036a610460366004614381565b610e3e565b610478610473366004614242565b610e8d565b6040516103199291906154ba565b6103356104943660046143ac565b611018565b61038a6104a73660046146b1565b611079565b6103356110fd565b610335611103565b6104c4611109565b6040516103199493929190615583565b610335611137565b61043d61113d565b6103e06104f236600461456b565b611146565b61038a6105053660046143f5565b61117b565b610335610518366004614242565b6111f9565b61033561052b3660046142b2565b611218565b61033561053e366004614381565b6113aa565b61041c611497565b61038a610559366004614350565b611640565b61034a61168a565b61038a610574366004614242565b611699565b61038a610587366004614539565b611714565b61059461182a565b60405161031991906148e2565b61036a6105af366004614381565b61184e565b61036a6105c2366004614381565b61189d565b6103356105d53660046144b1565b6118b1565b6105ed6105e836600461459b565b611979565b6040516103199190614cd5565b6103356106083660046144b1565b6119c2565b61038a61061b366004614350565b611a70565b610628611ab7565b6040516103199190615507565b61038a611acc565b610645611b47565b604051610319929190614cf3565b6103356106613660046142f2565b611b5a565b610594611bbd565b61033561067c36600461427a565b611bd2565b61033561068f366004614449565b611bfd565b610645611d0b565b6103356106aa3660046143ac565b611d1d565b603f81815481106106bf57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b90041684565b600081801580159061071057508085145b6107355760405162461bcd60e51b815260040161072c90615077565b60405180910390fd5b6000610773878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d6692505050565b506038549091506000906201000090046001600160a01b031663d176d694604084898961079e611f7c565b6040518663ffffffff1660e01b81526004016107be959493929190614af2565b60206040518083038186803b1580156107d657600080fd5b505afa1580156107ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080e9190614583565b9050610830603a54670de0b6b3a76400006108299190615666565b8290611fce565b61083b9060016155e7565b98975050505050505050565b6060603680546108569061569d565b80601f01602080910402602001604051908101604052809291908181526020018280546108829061569d565b80156108cf5780601f106108a4576101008083540402835291602001916108cf565b820191906000526020600020905b8154815290600101906020018083116108b257829003601f168201915b505050505090505b90565b60006108ee6108e7611fed565b8484611ff1565b5060015b92915050565b6109006120a5565b603b548211156109225760405162461bcd60e51b815260040161072c90614df4565b603b548111156109445760405162461bcd60e51b815260040161072c90615013565b603a829055603c8190556040517f64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068906109809084908490615437565b60405180910390a15050565b60008082116109ad5760405162461bcd60e51b815260040161072c9061530f565b60006109b8846120df565b506038549091506201000090046001600160a01b0316637910213b604083866109df611f7c565b6040518563ffffffff1660e01b81526004016109fe9493929190614b60565b60206040518083038186803b158015610a1657600080fd5b505afa158015610a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4e9190614583565b949350505050565b603e5481565b60355490565b610a6a6120a5565b6702c68af0bb140000811115610a925760405162461bcd60e51b815260040161072c9061511f565b603d8190556040517f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe790610ac7908390614d05565b60405180910390a150565b606080603f604081805480602002602001604051908101604052809291908181526020016000905b82821015610bb1576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610b7f57634e487b7160e01b600052602160045260246000fd5b6007811115610b9e57634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610afa565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610c2157600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610bd8565b505050509050915091509091565b6045546001600160801b0380821691600160801b90041682565b6000610c56848484612209565b610cb484610c62611fed565b6001600160a01b03871660009081526034602052604081208691610c84611fed565b6001600160a01b03166001600160a01b0316815260200190815260200160002054610caf9190615666565b611ff1565b5060015b9392505050565b610cc76120a5565b603854600160b01b900460ff1615610cf15760405162461bcd60e51b815260040161072c90614d61565b6001600160a01b038116610d175760405162461bcd60e51b815260040161072c90614f7f565b6038805462010000600160b01b031916620100006001600160a01b038416021790556040517f2e137a82d7f7fe8a4c453313f3d08557c162ad9d78219a2e937e318b41e12f7a90610ac79083906148e2565b600080610d746122f4565b603e546001811115610e1157610d8b600182615666565b6001603e559250610d9c3384612323565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015610deb578160200160208202803683370190505b5060408051600081526020810191829052610e08949392916149b1565b60405180910390a25b610e19610a5c565b9150509091565b60416020526000908152604090205460ff1681565b60385460ff1690565b60006108ee610e4b611fed565b848460346000610e59611fed565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610caf91906155e7565b610e95614169565b610e9d614191565b6001600160a01b038316600090815260416020526040902054603f805460ff9092169182908110610ede57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610f5c57634e487b7160e01b600052602160045260246000fd5b6007811115610f7b57634e487b7160e01b600052602160045260246000fd5b815250509250836001600160a01b031683600001516001600160a01b031614610fb65760405162461bcd60e51b815260040161072c90614dcd565b60408160ff1681548110610fda57634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b603854600090610100900460ff166110425760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556110556123d7565b6110618585858561241b565b6038805461ff00191661010017905595945050505050565b6110816120a5565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c6524963e2a5f044604484846110a7612783565b60646040518663ffffffff1660e01b81526004016110c9959493929190615445565b60006040518083038186803b1580156110e157600080fd5b505af41580156110f5573d6000803e3d6000fd5b505050505050565b603c5481565b603a5481565b6044546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b603d5481565b60425460ff1681565b6040818154811061115657600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6111836120a5565b60405163a5bee44b60e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063a5bee44b906111c490603f90604190889088908890600401614c60565b60006040518083038186803b1580156111dc57600080fd5b505af41580156111f0573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152603360205260409020545b919050565b6000826001600160a01b0316846001600160a01b0316141561124c5760405162461bcd60e51b815260040161072c90614e1b565b6000821161126c5760405162461bcd60e51b815260040161072c90615197565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156112d957600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611290565b50505050905060006112ea866120df565b50905060006112f8866120df565b509050603860029054906101000a90046001600160a01b03166001600160a01b0316630e3c01d384848489603a5461132e611f7c565b6040518763ffffffff1660e01b815260040161134f96959493929190614ab0565b604080518083038186803b15801561136657600080fd5b505afa15801561137a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139e91906146d2565b50979650505050505050565b60008082116113cb5760405162461bcd60e51b815260040161072c9061530f565b60006113d6846120df565b50905060006113f0603a54856128c090919063ffffffff16565b6038549091506201000090046001600160a01b03166350494dc06040846114178589615666565b61141f611f7c565b6040518563ffffffff1660e01b815260040161143e9493929190614b60565b60206040518083038186803b15801561145657600080fd5b505afa15801561146a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148e9190614583565b95945050505050565b6000806114a26122f4565b6114aa6128d5565b603854610100900460ff166114d15760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169081905560609073c3ff9c67fd926e84bf0555f38da7ceb0a1c6524990638b8029b490603f906040906201000090046001600160a01b031661151a611f7c565b6040518563ffffffff1660e01b81526004016115399493929190614bca565b60006040518083038186803b15801561155157600080fd5b505af4158015611565573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261158d91908101906145ec565b9093509050826115af5760405162461bcd60e51b815260040161072c906150ef565b6115b93384612323565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015611608578160200160208202803683370190505b508560405161161a94939291906149b1565b60405180910390a261162a610a5c565b6038805461ff0019166101001790559293915050565b6116486120a5565b60405163ee60ee2b60e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063ee60ee2b906110c990604390603f906041908890889060040161548c565b6060603780546108569061569d565b6116a16120a5565b604051634c1e9da160e11b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063983d3b42906116e190604390603f906041908790600401615468565b60006040518083038186803b1580156116f957600080fd5b505af415801561170d573d6000803e3d6000fd5b5050505050565b61171c6120a5565b60405461172a90600261561f565b61173c90670de0b6b3a76400006155ff565b826001600160801b031611156117645760405162461bcd60e51b815260040161072c906152a3565b60405461177390600190615666565b61178590670de0b6b3a76400006155ff565b816001600160801b031610156117ad5760405162461bcd60e51b815260040161072c906150a4565b6040805180820182526001600160801b038481168083528482166020909301839052604580546fffffffffffffffffffffffffffffffff1916909117909116600160801b909202919091179055517f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136906109809084908490615515565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006108ee61185b611fed565b848460346000611869611fed565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610caf9190615666565b60006108ee6118aa611fed565b8484612209565b603854600090610100900460ff166118db5760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556118ee6123d7565b61195f87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506129269050565b6038805461ff001916610100179055979650505050505050565b603854606090610100900460ff166119a35760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556119b66123d7565b61106185858585612d96565b603854600090610100900460ff166119ec5760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556119ff6128d5565b61195f87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506132819050565b611a786120a5565b604051638d18aef960e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c6524990638d18aef9906110c990603f9060419087908790600401614c3a565b611abf6141a8565b611ac7611f7c565b905090565b611ad46120a5565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c652496318068e406044611af8612783565b6040518363ffffffff1660e01b8152600401611b15929190615437565b60006040518083038186803b158015611b2d57600080fd5b505af4158015611b41573d6000803e3d6000fd5b50505050565b60435460ff808216916101009004169091565b603854600090610100900460ff16611b845760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169055611b976128d5565b611ba486868686866136ed565b6038805461ff0019166101001790559695505050505050565b6038546201000090046001600160a01b031681565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000818015801590611c0e57508085145b611c2a5760405162461bcd60e51b815260040161072c90614f0a565b6000611c68878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d6692505050565b506038549091506201000090046001600160a01b031663b7ecbf726040838888611c90611f7c565b6040518663ffffffff1660e01b8152600401611cb0959493929190614af2565b60206040518083038186803b158015611cc857600080fd5b505afa158015611cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d009190614583565b979650505050505050565b60435460ff8082169161010090041682565b603854600090610100900460ff16611d475760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169055611d5a6128d5565b61106185858585613beb565b80516060908190806001600160401b03811115611d9357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611dbc578160200160208202803683370190505b509250806001600160401b03811115611de557634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611e1e57816020015b611e0b614169565b815260200190600190039081611e035790505b50915060005b81811015611f7557611e5c858281518110611e4f57634e487b7160e01b600052603260045260246000fd5b60200260200101516120df565b858381518110611e7c57634e487b7160e01b600052603260045260246000fd5b60200260200101858481518110611ea357634e487b7160e01b600052603260045260246000fd5b602090810291909101019190915260ff90911690526000611ec58260016155e7565b90505b82811015611f6257858181518110611ef057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316868381518110611f2157634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161415611f505760405162461bcd60e51b815260040161072c90615235565b80611f5a816156d8565b915050611ec8565b5080611f6d816156d8565b915050611e24565b5050915091565b611f846141a8565b6040518060400160405280611f97612783565b8152604080518082019091526045546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b600081611fe3670de0b6b3a76400008561561f565b610cb891906155ff565b3390565b6001600160a01b0383166120175760405162461bcd60e51b815260040161072c906152cb565b6001600160a01b03821661203d5760405162461bcd60e51b815260040161072c90614e41565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612098908590614d05565b60405180910390a3505050565b6120ad613f0e565b6001600160a01b0316336001600160a01b0316146120dd5760405162461bcd60e51b815260040161072c90615040565b565b60006120e9614169565b6001600160a01b038316600090815260416020526040902054603f805460ff9092169350908390811061212c57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156121aa57634e487b7160e01b600052602160045260246000fd5b60078111156121c957634e487b7160e01b600052602160045260246000fd5b815250509050826001600160a01b031681600001516001600160a01b0316146122045760405162461bcd60e51b815260040161072c90614dcd565b915091565b6001600160a01b03831661222f5760405162461bcd60e51b815260040161072c9061525e565b6001600160a01b0382166122555760405162461bcd60e51b815260040161072c90614d8a565b6001600160a01b0383166000908152603360205260408120805483929061227d908490615666565b90915550506001600160a01b038216600090815260336020526040812080548392906122aa9084906155e7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516120989190614d05565b336122fd613fa1565b6001600160a01b0316146120dd5760405162461bcd60e51b815260040161072c90614fdc565b6001600160a01b0382166123495760405162461bcd60e51b815260040161072c90615400565b806035600082825461235b91906155e7565b90915550506001600160a01b038216600090815260336020526040812080548392906123889084906155e7565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123cb908590614d05565b60405180910390a35050565b6040805180820190915260435460ff808216158015845261010090920416151560208301526124185760405162461bcd60e51b815260040161072c90614eba565b50565b60006001600160a01b0382166124435760405162461bcd60e51b815260040161072c9061516c565b600084116124635760405162461bcd60e51b815260040161072c9061530f565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156124d057600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612487565b5050505090506000806124e2886120df565b9150915060006124fd603a54896128c090919063ffffffff16565b6038549091506201000090046001600160a01b03166350494dc08585612523858d615666565b61252b611f7c565b6040518563ffffffff1660e01b815260040161254a9493929190614a7f565b60206040518083038186803b15801561256257600080fd5b505afa158015612576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259a9190614583565b9450868510156125bc5760405162461bcd60e51b815260040161072c90614edc565b600085116125dc5760405162461bcd60e51b815260040161072c90615147565b6125e63389614028565b80603e60008282546125f891906155e7565b90915550600090506126086140d2565b905073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548785888860ff168151811061264957634e487b7160e01b600052603260045260246000fd5b60200260200101518b86602001516040518663ffffffff1660e01b815260040161267795949392919061552f565b60006040518083038186803b15801561268f57600080fd5b505af41580156126a3573d6000803e3d6000fd5b505050506126b086614129565b858560ff16815181106126d357634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516126e9919061563e565b60408560ff168154811061270d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055825160405133917f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad89161276e918b918e91908c90899061497d565b60405180910390a25050505050949350505050565b604080516080810182526044546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b909104166060820181905260009290428111156128ad57825160408401516000806127f66001600160401b03841642615666565b612800848761567d565b6001600160401b031691509150836001600160401b0316866001600160401b03161115612871578082612833868961567d565b6001600160401b0316612846919061561f565b61285091906155ff565b612863906001600160401b0386166155e7565b9750505050505050506108d7565b808261287d888761567d565b6001600160401b0316612890919061561f565b61289a91906155ff565b612863906001600160401b038616615666565b506001600160401b031691506108d79050565b6000610cb88383670de0b6b3a7640000614152565b6040805180820190915260435460ff808216158015808552610100909304909116151560208401529061290a57508060200151155b6124185760405162461bcd60e51b815260040161072c906150cc565b60006001600160a01b03821661294e5760405162461bcd60e51b815260040161072c9061516c565b8351801580159061295f5750855181145b61297b5760405162461bcd60e51b815260040161072c90615077565b6000841161299b5760405162461bcd60e51b815260040161072c9061530f565b6000806129a788611d66565b6040805481516020808302820181018452828252949650929450600093849084015b82821015612a1257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016129c9565b50506038549293506000926201000090046001600160a01b0316915063d176d694905083868c612a40611f7c565b6040518563ffffffff1660e01b8152600401612a5f9493929190614a36565b60206040518083038186803b158015612a7757600080fd5b505afa158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190614583565b9050612aca603a54670de0b6b3a76400006108299190615666565b95506000612ad88288615666565b905060008711612afa5760405162461bcd60e51b815260040161072c90615394565b612b056001886155e7565b965088871115612b275760405162461bcd60e51b815260040161072c906153cb565b612b313388614028565b80603e6000828254612b4391906155e7565b9091555060009050612b536140d2565b905060005b87811015612d3d576000878281518110612b8257634e487b7160e01b600052603260045260246000fd5b6020026020010151905073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548e8481518110612bc657634e487b7160e01b600052603260045260246000fd5b6020026020010151898581518110612bee57634e487b7160e01b600052603260045260246000fd5b6020026020010151898560ff1681518110612c1957634e487b7160e01b600052603260045260246000fd5b60200260200101518f88602001516040518663ffffffff1660e01b8152600401612c4795949392919061552f565b60006040518083038186803b158015612c5f57600080fd5b505af4158015612c73573d6000803e3d6000fd5b50505050612ca78d8381518110612c9a57634e487b7160e01b600052603260045260246000fd5b6020026020010151614129565b868260ff1681518110612cca57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151612ce0919061563e565b60408260ff1681548110612d0457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080612d35816156d8565b915050612b58565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8a8f8f87604051612d7f9594939291906149ea565b60405180910390a250505050505050949350505050565b60606001600160a01b038216612dbe5760405162461bcd60e51b815260040161072c9061516c565b60008511612dde5760405162461bcd60e51b815260040161072c9061530f565b6000612df5603c54876128c090919063ffffffff16565b90506000612e038288615666565b9050612e0f3388614028565b81603e6000828254612e2191906155e7565b9091555060009050612e316140d2565b90506000828260000151612e4591906155e7565b905060006040805480602002602001604051908101604052809291908181526020016000905b82821015612eb457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612e6b565b5050505090506000815190506000816001600160401b03811115612ee857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612f11578160200160208202803683370190505b509050816001600160401b03811115612f3a57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612f63578160200160208202803683370190505b50975060005b8281101561323f5760008588868481518110612f9557634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b0316612fb4919061561f565b612fbe91906155ff565b905060018111612fe05760405162461bcd60e51b815260040161072c90615147565b612feb600182615666565b90508c8c8381811061300d57634e487b7160e01b600052603260045260246000fd5b905060200201358110156130335760405162461bcd60e51b815260040161072c90614edc565b80603f838154811061305557634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201548b516001600160a01b03909116908c908590811061309457634e487b7160e01b600052603260045260246000fd5b602002602001018585815181106130bb57634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b031681525082815250505073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a5482603f858154811061311a57634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020188868151811061314857634e487b7160e01b600052603260045260246000fd5b60200260200101518f8c602001516040518663ffffffff1660e01b815260040161317695949392919061556e565b60006040518083038186803b15801561318e57600080fd5b505af41580156131a2573d6000803e3d6000fd5b505050506131af81614129565b8583815181106131cf57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516131e5919061563e565b6040838154811061320657634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080613237816156d8565b915050612f69565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8e848c8c604051612d7f9594939291906149ea565b60006001600160a01b0382166132a95760405162461bcd60e51b815260040161072c9061516c565b835180158015906132ba5750855181145b6132d65760405162461bcd60e51b815260040161072c90614f0a565b6000806132e288611d66565b6040805481516020808302820181018452828252949650929450600093849084015b8282101561334d57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613304565b505050509050600061335d6140d2565b90506000856001600160401b0381111561338757634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156133b0578160200160208202803683370190505b50905060005b868110156135ba5760008b82815181106133e057634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156135a757600087838151811061341557634e487b7160e01b600052603260045260246000fd5b602002602001015190506000868260ff168151811061344457634e487b7160e01b600052603260045260246000fd5b60200260200101519050600088858151811061347057634e487b7160e01b600052603260045260246000fd5b60200260200101519050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d3913838560000151888c602001516040518563ffffffff1660e01b81526004016134c194939291906154d5565b60206040518083038186803b1580156134d957600080fd5b505af41580156134ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135119190614583565b90508087878151811061353457634e487b7160e01b600052603260045260246000fd5b60200260200101818152505061354981614129565b836020015161355891906155bc565b60408560ff168154811061357c57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055505050505b50806135b2816156d8565b9150506133b6565b506038546201000090046001600160a01b031663b7ecbf728487846135dd611f7c565b6040518563ffffffff1660e01b81526004016135fc9493929190614a36565b60206040518083038186803b15801561361457600080fd5b505afa158015613628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364c9190614583565b96508887101561366e5760405162461bcd60e51b815260040161072c90614e83565b6000871161368e5760405162461bcd60e51b815260040161072c906151c6565b6136988888612323565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc89898e8e6040516136d794939291906149b1565b60405180910390a2505050505050949350505050565b60006001600160a01b0382166137155760405162461bcd60e51b815260040161072c9061516c565b846001600160a01b0316866001600160a01b031614156137475760405162461bcd60e51b815260040161072c90614e1b565b600084116137675760405162461bcd60e51b815260040161072c90615197565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156137d457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161378b565b5050505090506000806137e6896120df565b915091506000806137f68a6120df565b9150915060006138046140d2565b9050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d391386898960ff168151811061384657634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518e86602001516040518563ffffffff1660e01b815260040161387794939291906154d5565b60206040518083038186803b15801561388f57600080fd5b505af41580156138a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138c79190614583565b90506138d281614129565b878760ff16815181106138f557634e487b7160e01b600052603260045260246000fd5b60200260200101516020015161390b91906155bc565b60408760ff168154811061392f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200160000160106101000a8154816001600160801b0302191690836001600160801b031602179055506000603860029054906101000a90046001600160a01b03166001600160a01b0316630e3c01d389898886603a54613995611f7c565b6040518763ffffffff1660e01b81526004016139b696959493929190614ab0565b604080518083038186803b1580156139cd57600080fd5b505afa1580156139e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0591906146d2565b90995090508a891015613a2a5760405162461bcd60e51b815260040161072c90614fa5565b60008911613a4a5760405162461bcd60e51b815260040161072c90615366565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548a868b8960ff1681518110613a8957634e487b7160e01b600052603260045260246000fd5b60200260200101518e88602001516040518663ffffffff1660e01b8152600401613ab795949392919061552f565b60006040518083038186803b158015613acf57600080fd5b505af4158015613ae3573d6000803e3d6000fd5b50505050613af089614129565b888660ff1681518110613b1357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613b29919061563e565b60408660ff1681548110613b4d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790556040830151613b839082906155e7565b603e81905550336001600160a01b03167f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d876000015186600001518c858f604051613bd2959493929190614923565b60405180910390a2505050505050505095945050505050565b60006001600160a01b038216613c135760405162461bcd60e51b815260040161072c9061516c565b60008411613c335760405162461bcd60e51b815260040161072c9061530f565b60006040805480602002602001604051908101604052809291908181526020016000905b82821015613ca057600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613c57565b505050509050600080613cb2886120df565b915091506000613cc06140d2565b9050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d391384878760ff1681518110613d0257634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518c86602001516040518563ffffffff1660e01b8152600401613d3394939291906154d5565b60206040518083038186803b158015613d4b57600080fd5b505af4158015613d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d839190614583565b6038549091506201000090046001600160a01b0316637910213b868684613da8611f7c565b6040518563ffffffff1660e01b8152600401613dc79493929190614a7f565b60206040518083038186803b158015613ddf57600080fd5b505afa158015613df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e179190614583565b955087861015613e395760405162461bcd60e51b815260040161072c90614e83565b613e4281614129565b858560ff1681518110613e6557634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613e7b91906155bc565b60408560ff1681548110613e9f57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055613ecf8787612323565b336001600160a01b03167f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c788888d8560405161276e9493929190614953565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac7919061425e565b6040516385acd64160e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385acd64190614010907f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf190600401614d05565b60206040518083038186803b158015613f6957600080fd5b6001600160a01b03821661404e5760405162461bcd60e51b815260040161072c906151f4565b6001600160a01b03821660009081526033602052604081208054839290614076908490615666565b92505081905550806035600082825461408f9190615666565b90915550506040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123cb908590614d05565b6140da6141c2565b603e546000816140e8610a5c565b6140f291906155e7565b9050604051806060016040528082815260200161411a603d54846128c090919063ffffffff16565b81526020019290925250905090565b6000600160801b821061414e5760405162461bcd60e51b815260040161072c90614f38565b5090565b60008161415f848661561f565b610a4e91906155ff565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604080518082019091526000808252602082015290565b60405180604001604052806000815260200161418c614191565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f8401126141f4578081fd5b5081356001600160401b0381111561420a578182fd5b602083019150836020808302850101111561422457600080fd5b9250929050565b80356001600160801b038116811461121357600080fd5b600060208284031215614253578081fd5b8135610cb88161571f565b60006020828403121561426f578081fd5b8151610cb88161571f565b6000806040838503121561428c578081fd5b82356142978161571f565b915060208301356142a78161571f565b809150509250929050565b6000806000606084860312156142c6578081fd5b83356142d18161571f565b925060208401356142e18161571f565b929592945050506040919091013590565b600080600080600060a08688031215614309578081fd5b85356143148161571f565b945060208601356143248161571f565b9350604086013592506060860135915060808601356143428161571f565b809150509295509295909350565b60008060408385031215614362578182fd5b823561436d8161571f565b9150602083013580151581146142a7578182fd5b60008060408385031215614393578182fd5b823561439e8161571f565b946020939093013593505050565b600080600080608085870312156143c1578384fd5b84356143cc8161571f565b9350602085013592506040850135915060608501356143ea8161571f565b939692955090935050565b600080600060408486031215614409578283fd5b83356001600160401b0381111561441e578384fd5b61442a868287016141e3565b909450925050602084013561443e8161571f565b809150509250925092565b6000806000806040858703121561445e578384fd5b84356001600160401b0380821115614474578586fd5b614480888389016141e3565b90965094506020870135915080821115614498578384fd5b506144a5878288016141e3565b95989497509550505050565b600080600080600080608087890312156144c9578081fd5b86356001600160401b03808211156144df578283fd5b6144eb8a838b016141e3565b90985096506020890135915080821115614503578283fd5b5061451089828a016141e3565b90955093505060408701359150606087013561452b8161571f565b809150509295509295509295565b6000806040838503121561454b578182fd5b6145548361422b565b91506145626020840161422b565b90509250929050565b60006020828403121561457c578081fd5b5035919050565b600060208284031215614594578081fd5b5051919050565b600080600080606085870312156145b0578182fd5b8435935060208501356001600160401b038111156145cc578283fd5b6145d8878288016141e3565b90945092505060408501356143ea8161571f565b600080604083850312156145fe578182fd5b825191506020808401516001600160401b038082111561461c578384fd5b818601915086601f83011261462f578384fd5b81518181111561464157614641615709565b8381026040518582820101818110858211171561466057614660615709565b604052828152858101935084860182860187018b101561467e578788fd5b8795505b838610156146a0578051855260019590950194938601938601614682565b508096505050505050509250929050565b600080604083850312156146c3578182fd5b50508035926020909101359150565b600080604083850312156146e4578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b8381101561472d5781516001600160a01b031687529582019590820190600101614708565b509495945050505050565b6000815180845260208085019450808401835b8381101561472d5761475e878351614839565b604096909601959082019060010161474b565b6000815480845260208085019450838352808320835b8381101561472d5781546001600160801b038116885260801c8388015260409096019560019182019101614787565b6000815180845260208085019450808401835b8381101561472d578151875295820195908201906001016147c9565b6000815180845260208085019450808401835b8381101561472d57815160ff16875295820195908201906001016147f8565b6008811061483557634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160801b03908116835260209182015116910152565b60018060a01b0380825116835280602083015116602084015250604081015115156040830152606081015161488c6060840182614817565b505050565b60018060a01b038082541683526001820154818116602085015260ff8160a01c1615156040850152611b416060850160ff8360a81c16614817565b80518252602081015161488c6020840182614839565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015282151560408201526080810161148e6060830184614817565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b03958616815260208101949094529190931660408301526060820192909252608081019190915260a00190565b600060018060a01b0386168252846020830152608060408301526149d860808301856146f5565b8281036060840152611d0081856147b6565b600060018060a01b038716825285602083015260a06040830152614a1160a08301866146f5565b8281036060840152614a2381866147b6565b9150508260808301529695505050505050565b600060c08252614a4960c0830187614738565b8281036020840152614a5b81876147e5565b90508281036040840152614a6f81866147b6565b91505061148e60608301846148cc565b600060c08252614a9260c0830187614738565b905060ff8516602083015283604083015261148e60608301846148cc565b6000610100808352614ac48184018a614738565b91505060ff8716602083015260ff86166040830152846060830152836080830152611d0060a08301846148cc565b600060c08252614b0560c0830188614771565b8281036020840152614b1781886147e5565b838103604085015285815290506001600160fb1b03851115614b37578182fd5b602085028087602084013701602001908152614b5660608301846148cc565b9695505050505050565b600060c08252614a9260c0830187614771565b604080825283519082018190526000906020906060840190828701845b82811015614bb657614ba3848351614854565b6080939093019290840190600101614b90565b50505083810382850152614b568186614738565b60c08082528554908201819052600086815260208120909160e0840190835b81811015614c1157614bfb8385614891565b6002939093019260809290920191600101614be9565b5050602084018790526001600160a01b0386166040850152915061148e905060608301846148cc565b93845260208401929092526001600160a01b031660408301521515606082015260800190565b85815260208082018690526080604083018190528201849052600090859060a08401835b87811015614cb2578335614c978161571f565b6001600160a01b031682529282019290820190600101614c84565b506001600160a01b03959095166060949094019390935250919695505050505050565b600060208252610cb860208301846147b6565b901515815260200190565b91151582521515602082015260400190565b90815260200190565b6000602080835283518082850152825b81811015614d3a57858101830151858201604001528201614d1e565b81811115614d4b5783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600f908201526e119bdc99d955985b081b1bd8dad959608a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6020808252600d908201526c125b9d985b1a5908185cdcd95d609a1b604082015260600190565b6020808252600d908201526c29bbb0b8103930ba329037b7b160991b604082015260600190565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4d696e74207175616e74697479203c206d696e20717479000000000000000000604082015260600190565b602080825260089082015267125b881c9958dbdb60c21b604082015260600190565b60208082526014908201527362417373657420717479203c206d696e2071747960601b604082015260600190565b602080825260149082015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600c908201526b4e756c6c206164647265737360a01b604082015260600190565b60208082526018908201527f4f757470757420717479203c206d696e696d756d207174790000000000000000604082015260600190565b60208082526017908201527f4d75737420626520736176696e6773206d616e61676572000000000000000000604082015260600190565b6020808252601390820152722932b232b6b83a34b7b7103930ba329037b7b160691b604082015260600190565b60208082526019908201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604082015260600190565b602080825260139082015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b604082015260600190565b6020808252600e908201526d26b0bc103bb2b4b3b43a1037b7b160911b604082015260600190565b602080825260099082015268556e6865616c74687960b81b604082015260600190565b6020808252601690820152754d75737420636f6c6c65637420736f6d657468696e6760501b604082015260600190565b6020808252600e908201526d4d757374206265203c3d2032302560901b604082015260600190565b6020808252600b908201526a04f7574707574203d3d20360ac1b604082015260600190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b602080825260159082015274496e76616c69642073776170207175616e7469747960581b604082015260600190565b6020808252601490820152735a65726f206d4173736574207175616e7469747960601b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600f908201526e111d5c1b1a58d85d1948185cdcd95d608a1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600e908201526d26b4b7103bb2b4b3b43a1037b7b160911b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601490820152735a65726f206f7574707574207175616e7469747960601b604082015260600190565b60208082526018908201527f4d7573742072656465656d20736f6d65206d4173736574730000000000000000604082015260600190565b6020808252818101527f52656465656d206d417373657420717479203e206d6178207175616e74697479604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b948552602085019390935260408401919091526001600160a01b031660608301521515608082015260a00190565b60c081016154c88285614854565b610cb86080830184614839565b60e081016154e38287614854565b6001600160801b03851660808301528360a08301528260c083015295945050505050565b606081016108f282846148cc565b6001600160801b0392831681529116602082015260400190565b85815261012081016155446020830187614854565b61555160a0830186614839565b6001600160a01b039390931660e082015261010001529392505050565b85815261012081016155446020830187614891565b6001600160401b03948516815292841660208401529083166040830152909116606082015260800190565b60ff91909116815260200190565b60006001600160801b038083168185168083038211156155de576155de6156f3565b01949350505050565b600082198211156155fa576155fa6156f3565b500190565b60008261561a57634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615639576156396156f3565b500290565b60006001600160801b038381169083168181101561565e5761565e6156f3565b039392505050565b600082821015615678576156786156f3565b500390565b60006001600160401b038381169083168181101561565e5761565e6156f3565b6002810460018216806156b157607f821691505b602082108114156156d257634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156156ec576156ec6156f3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461241857600080fdfea2646970667358221220af3c4c0b4e5eb78b3bd030aeca63dd38ef79a65a2ef13e1484d268c12f499f7764736f6c63430008000033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102f15760003560e01c80636d5d6eb11161019d578063aa5d27e9116100e9578063cd6ef2b0116100a2578063dd62ed3e1161007c578063dd62ed3e1461066e578063e5555b8f14610681578063edc832b314610694578063f74bfe8e1461069c576102f1565b8063cd6ef2b01461063d578063d5bcb9b514610653578063d7d5226614610666576102f1565b8063aa5d27e9146105c7578063ab06346c146105da578063af290bd4146105fa578063bdfbe29c1461060d578063c3f909d414610620578063c4db7fa014610635576102f1565b8063905e891411610156578063a1c2515111610130578063a1c2515114610579578063a3f5c1d21461058c578063a457c2d7146105a1578063a9059cbb146105b4576102f1565b8063905e89141461054b57806395d89b411461055e578063969642b914610566576102f1565b80636d5d6eb1146104e45780636fb3e89c146104f757806370a082311461050a57806372ea90761461051d57806378aa987e146105305780637e8901ea14610543576102f1565b806326bbe60a1161025c57806343bcfab61161021557806354cf2aeb116101ef57806354cf2aeb146104b4578063598362f0146104bc578063674a64e0146104d45780636c36581c146104dc576102f1565b806343bcfab61461048657806344e3fa3c14610499578063458f5815146104ac576102f1565b806326bbe60a146104015780632a2fab22146104145780632f91a7241461042a578063313ce5671461044a57806339509351146104525780633e37bcbc14610465576102f1565b806313888565116102ae578063138885651461039f57806318160ddd146103a75780631820783d146103af5780631d3ce398146103c2578063213c501a146103d857806323b872dd146103ee576102f1565b80630357359c146102f657806304de5a731461032257806306fdde0314610342578063095ea7b3146103575780630b78f9c014610377578063119849cf1461038c575b600080fd5b61030961030436600461456b565b6106af565b60405161031994939291906148f6565b60405180910390f35b610335610330366004614449565b6106ff565b6040516103199190614d05565b61034a610847565b6040516103199190614d0e565b61036a610365366004614381565b6108da565b6040516103199190614ce8565b61038a6103853660046146b1565b6108f8565b005b61033561039a366004614381565b61098c565b610335610a56565b610335610a5c565b61038a6103bd36600461456b565b610a62565b6103ca610ad2565b604051610319929190614b73565b6103e0610c2f565b604051610319929190615515565b61036a6103fc3660046142b2565b610c49565b61038a61040f366004614242565b610cbf565b61041c610d69565b604051610319929190615437565b61043d610438366004614242565b610e20565b60405161031991906155ae565b61043d610e35565b61036a610460366004614381565b610e3e565b610478610473366004614242565b610e8d565b6040516103199291906154ba565b6103356104943660046143ac565b611018565b61038a6104a73660046146b1565b611079565b6103356110fd565b610335611103565b6104c4611109565b6040516103199493929190615583565b610335611137565b61043d61113d565b6103e06104f236600461456b565b611146565b61038a6105053660046143f5565b61117b565b610335610518366004614242565b6111f9565b61033561052b3660046142b2565b611218565b61033561053e366004614381565b6113aa565b61041c611497565b61038a610559366004614350565b611640565b61034a61168a565b61038a610574366004614242565b611699565b61038a610587366004614539565b611714565b61059461182a565b60405161031991906148e2565b61036a6105af366004614381565b61184e565b61036a6105c2366004614381565b61189d565b6103356105d53660046144b1565b6118b1565b6105ed6105e836600461459b565b611979565b6040516103199190614cd5565b6103356106083660046144b1565b6119c2565b61038a61061b366004614350565b611a70565b610628611ab7565b6040516103199190615507565b61038a611acc565b610645611b47565b604051610319929190614cf3565b6103356106613660046142f2565b611b5a565b610594611bbd565b61033561067c36600461427a565b611bd2565b61033561068f366004614449565b611bfd565b610645611d0b565b6103356106aa3660046143ac565b611d1d565b603f81815481106106bf57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b90041684565b600081801580159061071057508085145b6107355760405162461bcd60e51b815260040161072c90615077565b60405180910390fd5b6000610773878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d6692505050565b506038549091506000906201000090046001600160a01b031663d176d694604084898961079e611f7c565b6040518663ffffffff1660e01b81526004016107be959493929190614af2565b60206040518083038186803b1580156107d657600080fd5b505afa1580156107ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080e9190614583565b9050610830603a54670de0b6b3a76400006108299190615666565b8290611fce565b61083b9060016155e7565b98975050505050505050565b6060603680546108569061569d565b80601f01602080910402602001604051908101604052809291908181526020018280546108829061569d565b80156108cf5780601f106108a4576101008083540402835291602001916108cf565b820191906000526020600020905b8154815290600101906020018083116108b257829003601f168201915b505050505090505b90565b60006108ee6108e7611fed565b8484611ff1565b5060015b92915050565b6109006120a5565b603b548211156109225760405162461bcd60e51b815260040161072c90614df4565b603b548111156109445760405162461bcd60e51b815260040161072c90615013565b603a829055603c8190556040517f64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068906109809084908490615437565b60405180910390a15050565b60008082116109ad5760405162461bcd60e51b815260040161072c9061530f565b60006109b8846120df565b506038549091506201000090046001600160a01b0316637910213b604083866109df611f7c565b6040518563ffffffff1660e01b81526004016109fe9493929190614b60565b60206040518083038186803b158015610a1657600080fd5b505afa158015610a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4e9190614583565b949350505050565b603e5481565b60355490565b610a6a6120a5565b6702c68af0bb140000811115610a925760405162461bcd60e51b815260040161072c9061511f565b603d8190556040517f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe790610ac7908390614d05565b60405180910390a150565b606080603f604081805480602002602001604051908101604052809291908181526020016000905b82821015610bb1576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610b7f57634e487b7160e01b600052602160045260246000fd5b6007811115610b9e57634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610afa565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610c2157600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610bd8565b505050509050915091509091565b6045546001600160801b0380821691600160801b90041682565b6000610c56848484612209565b610cb484610c62611fed565b6001600160a01b03871660009081526034602052604081208691610c84611fed565b6001600160a01b03166001600160a01b0316815260200190815260200160002054610caf9190615666565b611ff1565b5060015b9392505050565b610cc76120a5565b603854600160b01b900460ff1615610cf15760405162461bcd60e51b815260040161072c90614d61565b6001600160a01b038116610d175760405162461bcd60e51b815260040161072c90614f7f565b6038805462010000600160b01b031916620100006001600160a01b038416021790556040517f2e137a82d7f7fe8a4c453313f3d08557c162ad9d78219a2e937e318b41e12f7a90610ac79083906148e2565b600080610d746122f4565b603e546001811115610e1157610d8b600182615666565b6001603e559250610d9c3384612323565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015610deb578160200160208202803683370190505b5060408051600081526020810191829052610e08949392916149b1565b60405180910390a25b610e19610a5c565b9150509091565b60416020526000908152604090205460ff1681565b60385460ff1690565b60006108ee610e4b611fed565b848460346000610e59611fed565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610caf91906155e7565b610e95614169565b610e9d614191565b6001600160a01b038316600090815260416020526040902054603f805460ff9092169182908110610ede57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610f5c57634e487b7160e01b600052602160045260246000fd5b6007811115610f7b57634e487b7160e01b600052602160045260246000fd5b815250509250836001600160a01b031683600001516001600160a01b031614610fb65760405162461bcd60e51b815260040161072c90614dcd565b60408160ff1681548110610fda57634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b603854600090610100900460ff166110425760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556110556123d7565b6110618585858561241b565b6038805461ff00191661010017905595945050505050565b6110816120a5565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c6524963e2a5f044604484846110a7612783565b60646040518663ffffffff1660e01b81526004016110c9959493929190615445565b60006040518083038186803b1580156110e157600080fd5b505af41580156110f5573d6000803e3d6000fd5b505050505050565b603c5481565b603a5481565b6044546001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b603d5481565b60425460ff1681565b6040818154811061115657600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6111836120a5565b60405163a5bee44b60e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063a5bee44b906111c490603f90604190889088908890600401614c60565b60006040518083038186803b1580156111dc57600080fd5b505af41580156111f0573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152603360205260409020545b919050565b6000826001600160a01b0316846001600160a01b0316141561124c5760405162461bcd60e51b815260040161072c90614e1b565b6000821161126c5760405162461bcd60e51b815260040161072c90615197565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156112d957600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611290565b50505050905060006112ea866120df565b50905060006112f8866120df565b509050603860029054906101000a90046001600160a01b03166001600160a01b0316630e3c01d384848489603a5461132e611f7c565b6040518763ffffffff1660e01b815260040161134f96959493929190614ab0565b604080518083038186803b15801561136657600080fd5b505afa15801561137a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139e91906146d2565b50979650505050505050565b60008082116113cb5760405162461bcd60e51b815260040161072c9061530f565b60006113d6846120df565b50905060006113f0603a54856128c090919063ffffffff16565b6038549091506201000090046001600160a01b03166350494dc06040846114178589615666565b61141f611f7c565b6040518563ffffffff1660e01b815260040161143e9493929190614b60565b60206040518083038186803b15801561145657600080fd5b505afa15801561146a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148e9190614583565b95945050505050565b6000806114a26122f4565b6114aa6128d5565b603854610100900460ff166114d15760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169081905560609073c3ff9c67fd926e84bf0555f38da7ceb0a1c6524990638b8029b490603f906040906201000090046001600160a01b031661151a611f7c565b6040518563ffffffff1660e01b81526004016115399493929190614bca565b60006040518083038186803b15801561155157600080fd5b505af4158015611565573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261158d91908101906145ec565b9093509050826115af5760405162461bcd60e51b815260040161072c906150ef565b6115b93384612323565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc33856000604051908082528060200260200182016040528015611608578160200160208202803683370190505b508560405161161a94939291906149b1565b60405180910390a261162a610a5c565b6038805461ff0019166101001790559293915050565b6116486120a5565b60405163ee60ee2b60e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063ee60ee2b906110c990604390603f906041908890889060040161548c565b6060603780546108569061569d565b6116a16120a5565b604051634c1e9da160e11b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c652499063983d3b42906116e190604390603f906041908790600401615468565b60006040518083038186803b1580156116f957600080fd5b505af415801561170d573d6000803e3d6000fd5b5050505050565b61171c6120a5565b60405461172a90600261561f565b61173c90670de0b6b3a76400006155ff565b826001600160801b031611156117645760405162461bcd60e51b815260040161072c906152a3565b60405461177390600190615666565b61178590670de0b6b3a76400006155ff565b816001600160801b031610156117ad5760405162461bcd60e51b815260040161072c906150a4565b6040805180820182526001600160801b038481168083528482166020909301839052604580546fffffffffffffffffffffffffffffffff1916909117909116600160801b909202919091179055517f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136906109809084908490615515565b7f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b60006108ee61185b611fed565b848460346000611869611fed565b6001600160a01b03908116825260208083019390935260409182016000908120918b1681529252902054610caf9190615666565b60006108ee6118aa611fed565b8484612209565b603854600090610100900460ff166118db5760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556118ee6123d7565b61195f87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506129269050565b6038805461ff001916610100179055979650505050505050565b603854606090610100900460ff166119a35760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556119b66123d7565b61106185858585612d96565b603854600090610100900460ff166119ec5760405162461bcd60e51b815260040161072c9061532f565b6038805461ff00191690556119ff6128d5565b61195f87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808b0282810182019093528a82529093508a9250899182918501908490808284376000920191909152508892508791506132819050565b611a786120a5565b604051638d18aef960e01b815273c3ff9c67fd926e84bf0555f38da7ceb0a1c6524990638d18aef9906110c990603f9060419087908790600401614c3a565b611abf6141a8565b611ac7611f7c565b905090565b611ad46120a5565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c652496318068e406044611af8612783565b6040518363ffffffff1660e01b8152600401611b15929190615437565b60006040518083038186803b158015611b2d57600080fd5b505af4158015611b41573d6000803e3d6000fd5b50505050565b60435460ff808216916101009004169091565b603854600090610100900460ff16611b845760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169055611b976128d5565b611ba486868686866136ed565b6038805461ff0019166101001790559695505050505050565b6038546201000090046001600160a01b031681565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000818015801590611c0e57508085145b611c2a5760405162461bcd60e51b815260040161072c90614f0a565b6000611c68878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d6692505050565b506038549091506201000090046001600160a01b031663b7ecbf726040838888611c90611f7c565b6040518663ffffffff1660e01b8152600401611cb0959493929190614af2565b60206040518083038186803b158015611cc857600080fd5b505afa158015611cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d009190614583565b979650505050505050565b60435460ff8082169161010090041682565b603854600090610100900460ff16611d475760405162461bcd60e51b815260040161072c9061532f565b6038805461ff0019169055611d5a6128d5565b61106185858585613beb565b80516060908190806001600160401b03811115611d9357634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611dbc578160200160208202803683370190505b509250806001600160401b03811115611de557634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611e1e57816020015b611e0b614169565b815260200190600190039081611e035790505b50915060005b81811015611f7557611e5c858281518110611e4f57634e487b7160e01b600052603260045260246000fd5b60200260200101516120df565b858381518110611e7c57634e487b7160e01b600052603260045260246000fd5b60200260200101858481518110611ea357634e487b7160e01b600052603260045260246000fd5b602090810291909101019190915260ff90911690526000611ec58260016155e7565b90505b82811015611f6257858181518110611ef057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316868381518110611f2157634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161415611f505760405162461bcd60e51b815260040161072c90615235565b80611f5a816156d8565b915050611ec8565b5080611f6d816156d8565b915050611e24565b5050915091565b611f846141a8565b6040518060400160405280611f97612783565b8152604080518082019091526045546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b600081611fe3670de0b6b3a76400008561561f565b610cb891906155ff565b3390565b6001600160a01b0383166120175760405162461bcd60e51b815260040161072c906152cb565b6001600160a01b03821661203d5760405162461bcd60e51b815260040161072c90614e41565b6001600160a01b0380841660008181526034602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612098908590614d05565b60405180910390a3505050565b6120ad613f0e565b6001600160a01b0316336001600160a01b0316146120dd5760405162461bcd60e51b815260040161072c90615040565b565b60006120e9614169565b6001600160a01b038316600090815260416020526040902054603f805460ff9092169350908390811061212c57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156121aa57634e487b7160e01b600052602160045260246000fd5b60078111156121c957634e487b7160e01b600052602160045260246000fd5b815250509050826001600160a01b031681600001516001600160a01b0316146122045760405162461bcd60e51b815260040161072c90614dcd565b915091565b6001600160a01b03831661222f5760405162461bcd60e51b815260040161072c9061525e565b6001600160a01b0382166122555760405162461bcd60e51b815260040161072c90614d8a565b6001600160a01b0383166000908152603360205260408120805483929061227d908490615666565b90915550506001600160a01b038216600090815260336020526040812080548392906122aa9084906155e7565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516120989190614d05565b336122fd613fa1565b6001600160a01b0316146120dd5760405162461bcd60e51b815260040161072c90614fdc565b6001600160a01b0382166123495760405162461bcd60e51b815260040161072c90615400565b806035600082825461235b91906155e7565b90915550506001600160a01b038216600090815260336020526040812080548392906123889084906155e7565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123cb908590614d05565b60405180910390a35050565b6040805180820190915260435460ff808216158015845261010090920416151560208301526124185760405162461bcd60e51b815260040161072c90614eba565b50565b60006001600160a01b0382166124435760405162461bcd60e51b815260040161072c9061516c565b600084116124635760405162461bcd60e51b815260040161072c9061530f565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156124d057600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612487565b5050505090506000806124e2886120df565b9150915060006124fd603a54896128c090919063ffffffff16565b6038549091506201000090046001600160a01b03166350494dc08585612523858d615666565b61252b611f7c565b6040518563ffffffff1660e01b815260040161254a9493929190614a7f565b60206040518083038186803b15801561256257600080fd5b505afa158015612576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259a9190614583565b9450868510156125bc5760405162461bcd60e51b815260040161072c90614edc565b600085116125dc5760405162461bcd60e51b815260040161072c90615147565b6125e63389614028565b80603e60008282546125f891906155e7565b90915550600090506126086140d2565b905073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548785888860ff168151811061264957634e487b7160e01b600052603260045260246000fd5b60200260200101518b86602001516040518663ffffffff1660e01b815260040161267795949392919061552f565b60006040518083038186803b15801561268f57600080fd5b505af41580156126a3573d6000803e3d6000fd5b505050506126b086614129565b858560ff16815181106126d357634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516126e9919061563e565b60408560ff168154811061270d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055825160405133917f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad89161276e918b918e91908c90899061497d565b60405180910390a25050505050949350505050565b604080516080810182526044546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b909104166060820181905260009290428111156128ad57825160408401516000806127f66001600160401b03841642615666565b612800848761567d565b6001600160401b031691509150836001600160401b0316866001600160401b03161115612871578082612833868961567d565b6001600160401b0316612846919061561f565b61285091906155ff565b612863906001600160401b0386166155e7565b9750505050505050506108d7565b808261287d888761567d565b6001600160401b0316612890919061561f565b61289a91906155ff565b612863906001600160401b038616615666565b506001600160401b031691506108d79050565b6000610cb88383670de0b6b3a7640000614152565b6040805180820190915260435460ff808216158015808552610100909304909116151560208401529061290a57508060200151155b6124185760405162461bcd60e51b815260040161072c906150cc565b60006001600160a01b03821661294e5760405162461bcd60e51b815260040161072c9061516c565b8351801580159061295f5750855181145b61297b5760405162461bcd60e51b815260040161072c90615077565b6000841161299b5760405162461bcd60e51b815260040161072c9061530f565b6000806129a788611d66565b6040805481516020808302820181018452828252949650929450600093849084015b82821015612a1257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016129c9565b50506038549293506000926201000090046001600160a01b0316915063d176d694905083868c612a40611f7c565b6040518563ffffffff1660e01b8152600401612a5f9493929190614a36565b60206040518083038186803b158015612a7757600080fd5b505afa158015612a8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aaf9190614583565b9050612aca603a54670de0b6b3a76400006108299190615666565b95506000612ad88288615666565b905060008711612afa5760405162461bcd60e51b815260040161072c90615394565b612b056001886155e7565b965088871115612b275760405162461bcd60e51b815260040161072c906153cb565b612b313388614028565b80603e6000828254612b4391906155e7565b9091555060009050612b536140d2565b905060005b87811015612d3d576000878281518110612b8257634e487b7160e01b600052603260045260246000fd5b6020026020010151905073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548e8481518110612bc657634e487b7160e01b600052603260045260246000fd5b6020026020010151898581518110612bee57634e487b7160e01b600052603260045260246000fd5b6020026020010151898560ff1681518110612c1957634e487b7160e01b600052603260045260246000fd5b60200260200101518f88602001516040518663ffffffff1660e01b8152600401612c4795949392919061552f565b60006040518083038186803b158015612c5f57600080fd5b505af4158015612c73573d6000803e3d6000fd5b50505050612ca78d8381518110612c9a57634e487b7160e01b600052603260045260246000fd5b6020026020010151614129565b868260ff1681518110612cca57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151612ce0919061563e565b60408260ff1681548110612d0457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080612d35816156d8565b915050612b58565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8a8f8f87604051612d7f9594939291906149ea565b60405180910390a250505050505050949350505050565b60606001600160a01b038216612dbe5760405162461bcd60e51b815260040161072c9061516c565b60008511612dde5760405162461bcd60e51b815260040161072c9061530f565b6000612df5603c54876128c090919063ffffffff16565b90506000612e038288615666565b9050612e0f3388614028565b81603e6000828254612e2191906155e7565b9091555060009050612e316140d2565b90506000828260000151612e4591906155e7565b905060006040805480602002602001604051908101604052809291908181526020016000905b82821015612eb457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612e6b565b5050505090506000815190506000816001600160401b03811115612ee857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612f11578160200160208202803683370190505b509050816001600160401b03811115612f3a57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612f63578160200160208202803683370190505b50975060005b8281101561323f5760008588868481518110612f9557634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b0316612fb4919061561f565b612fbe91906155ff565b905060018111612fe05760405162461bcd60e51b815260040161072c90615147565b612feb600182615666565b90508c8c8381811061300d57634e487b7160e01b600052603260045260246000fd5b905060200201358110156130335760405162461bcd60e51b815260040161072c90614edc565b80603f838154811061305557634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201548b516001600160a01b03909116908c908590811061309457634e487b7160e01b600052603260045260246000fd5b602002602001018585815181106130bb57634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b031681525082815250505073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a5482603f858154811061311a57634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020188868151811061314857634e487b7160e01b600052603260045260246000fd5b60200260200101518f8c602001516040518663ffffffff1660e01b815260040161317695949392919061556e565b60006040518083038186803b15801561318e57600080fd5b505af41580156131a2573d6000803e3d6000fd5b505050506131af81614129565b8583815181106131cf57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516131e5919061563e565b6040838154811061320657634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080613237816156d8565b915050612f69565b50336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e8a8e848c8c604051612d7f9594939291906149ea565b60006001600160a01b0382166132a95760405162461bcd60e51b815260040161072c9061516c565b835180158015906132ba5750855181145b6132d65760405162461bcd60e51b815260040161072c90614f0a565b6000806132e288611d66565b6040805481516020808302820181018452828252949650929450600093849084015b8282101561334d57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613304565b505050509050600061335d6140d2565b90506000856001600160401b0381111561338757634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156133b0578160200160208202803683370190505b50905060005b868110156135ba5760008b82815181106133e057634e487b7160e01b600052603260045260246000fd5b6020026020010151905060008111156135a757600087838151811061341557634e487b7160e01b600052603260045260246000fd5b602002602001015190506000868260ff168151811061344457634e487b7160e01b600052603260045260246000fd5b60200260200101519050600088858151811061347057634e487b7160e01b600052603260045260246000fd5b60200260200101519050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d3913838560000151888c602001516040518563ffffffff1660e01b81526004016134c194939291906154d5565b60206040518083038186803b1580156134d957600080fd5b505af41580156134ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135119190614583565b90508087878151811061353457634e487b7160e01b600052603260045260246000fd5b60200260200101818152505061354981614129565b836020015161355891906155bc565b60408560ff168154811061357c57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055505050505b50806135b2816156d8565b9150506133b6565b506038546201000090046001600160a01b031663b7ecbf728487846135dd611f7c565b6040518563ffffffff1660e01b81526004016135fc9493929190614a36565b60206040518083038186803b15801561361457600080fd5b505afa158015613628573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364c9190614583565b96508887101561366e5760405162461bcd60e51b815260040161072c90614e83565b6000871161368e5760405162461bcd60e51b815260040161072c906151c6565b6136988888612323565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc89898e8e6040516136d794939291906149b1565b60405180910390a2505050505050949350505050565b60006001600160a01b0382166137155760405162461bcd60e51b815260040161072c9061516c565b846001600160a01b0316866001600160a01b031614156137475760405162461bcd60e51b815260040161072c90614e1b565b600084116137675760405162461bcd60e51b815260040161072c90615197565b60006040805480602002602001604051908101604052809291908181526020016000905b828210156137d457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161378b565b5050505090506000806137e6896120df565b915091506000806137f68a6120df565b9150915060006138046140d2565b9050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d391386898960ff168151811061384657634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518e86602001516040518563ffffffff1660e01b815260040161387794939291906154d5565b60206040518083038186803b15801561388f57600080fd5b505af41580156138a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138c79190614583565b90506138d281614129565b878760ff16815181106138f557634e487b7160e01b600052603260045260246000fd5b60200260200101516020015161390b91906155bc565b60408760ff168154811061392f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200160000160106101000a8154816001600160801b0302191690836001600160801b031602179055506000603860029054906101000a90046001600160a01b03166001600160a01b0316630e3c01d389898886603a54613995611f7c565b6040518763ffffffff1660e01b81526004016139b696959493929190614ab0565b604080518083038186803b1580156139cd57600080fd5b505afa1580156139e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0591906146d2565b90995090508a891015613a2a5760405162461bcd60e51b815260040161072c90614fa5565b60008911613a4a5760405162461bcd60e51b815260040161072c90615366565b73c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e331a548a868b8960ff1681518110613a8957634e487b7160e01b600052603260045260246000fd5b60200260200101518e88602001516040518663ffffffff1660e01b8152600401613ab795949392919061552f565b60006040518083038186803b158015613acf57600080fd5b505af4158015613ae3573d6000803e3d6000fd5b50505050613af089614129565b888660ff1681518110613b1357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613b29919061563e565b60408660ff1681548110613b4d57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790556040830151613b839082906155e7565b603e81905550336001600160a01b03167f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d876000015186600001518c858f604051613bd2959493929190614923565b60405180910390a2505050505050505095945050505050565b60006001600160a01b038216613c135760405162461bcd60e51b815260040161072c9061516c565b60008411613c335760405162461bcd60e51b815260040161072c9061530f565b60006040805480602002602001604051908101604052809291908181526020016000905b82821015613ca057600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101613c57565b505050509050600080613cb2886120df565b915091506000613cc06140d2565b9050600073c3ff9c67fd926e84bf0555f38da7ceb0a1c65249634e3d391384878760ff1681518110613d0257634e487b7160e01b600052603260045260246000fd5b6020026020010151600001518c86602001516040518563ffffffff1660e01b8152600401613d3394939291906154d5565b60206040518083038186803b158015613d4b57600080fd5b505af4158015613d5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d839190614583565b6038549091506201000090046001600160a01b0316637910213b868684613da8611f7c565b6040518563ffffffff1660e01b8152600401613dc79493929190614a7f565b60206040518083038186803b158015613ddf57600080fd5b505afa158015613df3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e179190614583565b955087861015613e395760405162461bcd60e51b815260040161072c90614e83565b613e4281614129565b858560ff1681518110613e6557634e487b7160e01b600052603260045260246000fd5b602002602001015160200151613e7b91906155bc565b60408560ff1681548110613e9f57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055613ecf8787612323565b336001600160a01b03167f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c788888d8560405161276e9493929190614953565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac7919061425e565b6040516385acd64160e01b81526000906001600160a01b037f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb316906385acd64190614010907f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf190600401614d05565b60206040518083038186803b158015613f6957600080fd5b6001600160a01b03821661404e5760405162461bcd60e51b815260040161072c906151f4565b6001600160a01b03821660009081526033602052604081208054839290614076908490615666565b92505081905550806035600082825461408f9190615666565b90915550506040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906123cb908590614d05565b6140da6141c2565b603e546000816140e8610a5c565b6140f291906155e7565b9050604051806060016040528082815260200161411a603d54846128c090919063ffffffff16565b81526020019290925250905090565b6000600160801b821061414e5760405162461bcd60e51b815260040161072c90614f38565b5090565b60008161415f848661561f565b610a4e91906155ff565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604080518082019091526000808252602082015290565b60405180604001604052806000815260200161418c614191565b60405180606001604052806000815260200160008152602001600081525090565b60008083601f8401126141f4578081fd5b5081356001600160401b0381111561420a578182fd5b602083019150836020808302850101111561422457600080fd5b9250929050565b80356001600160801b038116811461121357600080fd5b600060208284031215614253578081fd5b8135610cb88161571f565b60006020828403121561426f578081fd5b8151610cb88161571f565b6000806040838503121561428c578081fd5b82356142978161571f565b915060208301356142a78161571f565b809150509250929050565b6000806000606084860312156142c6578081fd5b83356142d18161571f565b925060208401356142e18161571f565b929592945050506040919091013590565b600080600080600060a08688031215614309578081fd5b85356143148161571f565b945060208601356143248161571f565b9350604086013592506060860135915060808601356143428161571f565b809150509295509295909350565b60008060408385031215614362578182fd5b823561436d8161571f565b9150602083013580151581146142a7578182fd5b60008060408385031215614393578182fd5b823561439e8161571f565b946020939093013593505050565b600080600080608085870312156143c1578384fd5b84356143cc8161571f565b9350602085013592506040850135915060608501356143ea8161571f565b939692955090935050565b600080600060408486031215614409578283fd5b83356001600160401b0381111561441e578384fd5b61442a868287016141e3565b909450925050602084013561443e8161571f565b809150509250925092565b6000806000806040858703121561445e578384fd5b84356001600160401b0380821115614474578586fd5b614480888389016141e3565b90965094506020870135915080821115614498578384fd5b506144a5878288016141e3565b95989497509550505050565b600080600080600080608087890312156144c9578081fd5b86356001600160401b03808211156144df578283fd5b6144eb8a838b016141e3565b90985096506020890135915080821115614503578283fd5b5061451089828a016141e3565b90955093505060408701359150606087013561452b8161571f565b809150509295509295509295565b6000806040838503121561454b578182fd5b6145548361422b565b91506145626020840161422b565b90509250929050565b60006020828403121561457c578081fd5b5035919050565b600060208284031215614594578081fd5b5051919050565b600080600080606085870312156145b0578182fd5b8435935060208501356001600160401b038111156145cc578283fd5b6145d8878288016141e3565b90945092505060408501356143ea8161571f565b600080604083850312156145fe578182fd5b825191506020808401516001600160401b038082111561461c578384fd5b818601915086601f83011261462f578384fd5b81518181111561464157614641615709565b8381026040518582820101818110858211171561466057614660615709565b604052828152858101935084860182860187018b101561467e578788fd5b8795505b838610156146a0578051855260019590950194938601938601614682565b508096505050505050509250929050565b600080604083850312156146c3578182fd5b50508035926020909101359150565b600080604083850312156146e4578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b8381101561472d5781516001600160a01b031687529582019590820190600101614708565b509495945050505050565b6000815180845260208085019450808401835b8381101561472d5761475e878351614839565b604096909601959082019060010161474b565b6000815480845260208085019450838352808320835b8381101561472d5781546001600160801b038116885260801c8388015260409096019560019182019101614787565b6000815180845260208085019450808401835b8381101561472d578151875295820195908201906001016147c9565b6000815180845260208085019450808401835b8381101561472d57815160ff16875295820195908201906001016147f8565b6008811061483557634e487b7160e01b600052602160045260246000fd5b9052565b80516001600160801b03908116835260209182015116910152565b60018060a01b0380825116835280602083015116602084015250604081015115156040830152606081015161488c6060840182614817565b505050565b60018060a01b038082541683526001820154818116602085015260ff8160a01c1615156040850152611b416060850160ff8360a81c16614817565b80518252602081015161488c6020840182614839565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015282151560408201526080810161148e6060830184614817565b6001600160a01b039586168152938516602085015260408401929092526060830152909116608082015260a00190565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b6001600160a01b03958616815260208101949094529190931660408301526060820192909252608081019190915260a00190565b600060018060a01b0386168252846020830152608060408301526149d860808301856146f5565b8281036060840152611d0081856147b6565b600060018060a01b038716825285602083015260a06040830152614a1160a08301866146f5565b8281036060840152614a2381866147b6565b9150508260808301529695505050505050565b600060c08252614a4960c0830187614738565b8281036020840152614a5b81876147e5565b90508281036040840152614a6f81866147b6565b91505061148e60608301846148cc565b600060c08252614a9260c0830187614738565b905060ff8516602083015283604083015261148e60608301846148cc565b6000610100808352614ac48184018a614738565b91505060ff8716602083015260ff86166040830152846060830152836080830152611d0060a08301846148cc565b600060c08252614b0560c0830188614771565b8281036020840152614b1781886147e5565b838103604085015285815290506001600160fb1b03851115614b37578182fd5b602085028087602084013701602001908152614b5660608301846148cc565b9695505050505050565b600060c08252614a9260c0830187614771565b604080825283519082018190526000906020906060840190828701845b82811015614bb657614ba3848351614854565b6080939093019290840190600101614b90565b50505083810382850152614b568186614738565b60c08082528554908201819052600086815260208120909160e0840190835b81811015614c1157614bfb8385614891565b6002939093019260809290920191600101614be9565b5050602084018790526001600160a01b0386166040850152915061148e905060608301846148cc565b93845260208401929092526001600160a01b031660408301521515606082015260800190565b85815260208082018690526080604083018190528201849052600090859060a08401835b87811015614cb2578335614c978161571f565b6001600160a01b031682529282019290820190600101614c84565b506001600160a01b03959095166060949094019390935250919695505050505050565b600060208252610cb860208301846147b6565b901515815260200190565b91151582521515602082015260400190565b90815260200190565b6000602080835283518082850152825b81811015614d3a57858101830151858201604001528201614d1e565b81811115614d4b5783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600f908201526e119bdc99d955985b081b1bd8dad959608a1b604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b6020808252600d908201526c125b9d985b1a5908185cdcd95d609a1b604082015260600190565b6020808252600d908201526c29bbb0b8103930ba329037b7b160991b604082015260600190565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526017908201527f4d696e74207175616e74697479203c206d696e20717479000000000000000000604082015260600190565b602080825260089082015267125b881c9958dbdb60c21b604082015260600190565b60208082526014908201527362417373657420717479203c206d696e2071747960601b604082015260600190565b602080825260149082015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600c908201526b4e756c6c206164647265737360a01b604082015260600190565b60208082526018908201527f4f757470757420717479203c206d696e696d756d207174790000000000000000604082015260600190565b60208082526017908201527f4d75737420626520736176696e6773206d616e61676572000000000000000000604082015260600190565b6020808252601390820152722932b232b6b83a34b7b7103930ba329037b7b160691b604082015260600190565b60208082526019908201527f4f6e6c7920676f7665726e6f722063616e206578656375746500000000000000604082015260600190565b602080825260139082015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b604082015260600190565b6020808252600e908201526d26b0bc103bb2b4b3b43a1037b7b160911b604082015260600190565b602080825260099082015268556e6865616c74687960b81b604082015260600190565b6020808252601690820152754d75737420636f6c6c65637420736f6d657468696e6760501b604082015260600190565b6020808252600e908201526d4d757374206265203c3d2032302560901b604082015260600190565b6020808252600b908201526a04f7574707574203d3d20360ac1b604082015260600190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b602080825260159082015274496e76616c69642073776170207175616e7469747960581b604082015260600190565b6020808252601490820152735a65726f206d4173736574207175616e7469747960601b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600f908201526e111d5c1b1a58d85d1948185cdcd95d608a1b604082015260600190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600e908201526d26b4b7103bb2b4b3b43a1037b7b160911b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601490820152735a65726f206f7574707574207175616e7469747960601b604082015260600190565b60208082526018908201527f4d7573742072656465656d20736f6d65206d4173736574730000000000000000604082015260600190565b6020808252818101527f52656465656d206d417373657420717479203e206d6178207175616e74697479604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b918252602082015260400190565b948552602085019390935260408401919091526060830152608082015260a00190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b948552602085019390935260408401919091526001600160a01b031660608301521515608082015260a00190565b60c081016154c88285614854565b610cb86080830184614839565b60e081016154e38287614854565b6001600160801b03851660808301528360a08301528260c083015295945050505050565b606081016108f282846148cc565b6001600160801b0392831681529116602082015260400190565b85815261012081016155446020830187614854565b61555160a0830186614839565b6001600160a01b039390931660e082015261010001529392505050565b85815261012081016155446020830187614891565b6001600160401b03948516815292841660208401529083166040830152909116606082015260800190565b60ff91909116815260200190565b60006001600160801b038083168185168083038211156155de576155de6156f3565b01949350505050565b600082198211156155fa576155fa6156f3565b500190565b60008261561a57634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615639576156396156f3565b500290565b60006001600160801b038381169083168181101561565e5761565e6156f3565b039392505050565b600082821015615678576156786156f3565b500390565b60006001600160401b038381169083168181101561565e5761565e6156f3565b6002810460018216806156b157607f821691505b602082108114156156d257634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156156ec576156ec6156f3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461241857600080fdfea2646970667358221220af3c4c0b4e5eb78b3bd030aeca63dd38ef79a65a2ef13e1484d268c12f499f7764736f6c63430008000033
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
75640:41451:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77641:38;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;97697:737;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;15688:83::-;;;:::i;:::-;;;;;;;:::i;9517:161::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;113652:349::-;;;;;;:::i;:::-;;:::i;:::-;;83496:341;;;;;;:::i;:::-;;:::i;77547:22::-;;;:::i;8502:100::-;;;:::i;112681:218::-;;;;;;:::i;:::-;;:::i;105721:209::-;;;:::i;:::-;;;;;;;;:::i;77952:32::-;;;:::i;:::-;;;;;;;;:::i;10150:300::-;;;;;;:::i;:::-;;:::i;113128:354::-;;;;;;:::i;:::-;;:::i;110404:868::-;;;:::i;:::-;;;;;;;;:::i;77723:55::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;16540:83::-;;;:::i;10859:207::-;;;;;;:::i;:::-;;:::i;106163:328::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;94353:326::-;;;;;;:::i;:::-;;:::i;116656:185::-;;;;;;:::i;:::-;;:::i;77454:28::-;;;:::i;77368:22::-;;;:::i;77923:::-;;;:::i;:::-;;;;;;;;;;:::i;77516:24::-;;;:::i;77785:23::-;;;:::i;77686:30::-;;;;;;:::i;:::-;;:::i;115416:244::-;;;;;;:::i;:::-;;:::i;8665:119::-;;;;;;:::i;:::-;;:::i;90071:792::-;;;;;;:::i;:::-;;:::i;96877:496::-;;;;;;:::i;:::-;;:::i;111607:674::-;;;:::i;115984:188::-;;;;;;:::i;:::-;;:::i;15890:87::-;;;:::i;116296:165::-;;;;;;:::i;:::-;;:::i;114172:336::-;;;;;;:::i;:::-;;:::i;19212:29::-;;;:::i;:::-;;;;;;;:::i;11569:217::-;;;;;;:::i;:::-;;:::i;8997:167::-;;;;;;:::i;:::-;;:::i;96118:441::-;;;;;;:::i;:::-;;:::i;95096:331::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;82848:348::-;;;;;;:::i;:::-;;:::i;114757:193::-;;;;;;:::i;:::-;;:::i;106590:113::-;;;:::i;:::-;;;;;;;:::i;116980:108::-;;;:::i;105400:130::-;;;:::i;:::-;;;;;;;;:::i;89257:345::-;;;;;;:::i;:::-;;:::i;77116:41::-;;;:::i;9227:143::-;;;;;;:::i;:::-;;:::i;84207:464::-;;;;;;:::i;:::-;;:::i;77815:25::-;;;:::i;81785:312::-;;;;;;:::i;:::-;;:::i;77641:38::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77641:38:0;;;;-1:-1:-1;77641:38:0;;;;;-1:-1:-1;;;77641:38:0;;;;;-1:-1:-1;;;77641:38:0;;;;:::o;97697:737::-;97858:22;97907:17;97950:7;;;;;:33;;-1:-1:-1;97961:22:0;;;97950:33;97942:65;;;;-1:-1:-1;;;97942:65:0;;;;;;;:::i;:::-;;;;;;;;;98021:22;98049:21;98061:8;;98049:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;98049:11:0;;-1:-1:-1;;;98049:21:0:i;:::-;-1:-1:-1;98201:14:0;;98020:50;;-1:-1:-1;98176:22:0;;98201:14;;;-1:-1:-1;;;;;98201:14:0;:33;98249:10;98020:50;98296:17;;98328:12;:10;:12::i;:::-;98201:150;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98176:175;;98379:43;98414:7;;98407:4;:14;;;;:::i;:::-;98379;;:27;:43::i;:::-;:47;;98425:1;98379:47;:::i;:::-;98362:64;97697:737;-1:-1:-1;;;;;;;;97697:737:0:o;15688:83::-;15725:13;15758:5;15751:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15688:83;;:::o;9517:161::-;9592:4;9609:39;9618:12;:10;:12::i;:::-;9632:7;9641:6;9609:8;:39::i;:::-;-1:-1:-1;9666:4:0;9517:161;;;;;:::o;113652:349::-;19646:15;:13;:15::i;:::-;113773:7:::1;;113761:8;:19;;113753:45;;;;-1:-1:-1::0;;;113753:45:0::1;;;;;;;:::i;:::-;113835:7;;113817:14;:25;;113809:57;;;;-1:-1:-1::0;;;113809:57:0::1;;;;;;;:::i;:::-;113879:7;:18:::0;;;113908:13:::1;:30:::0;;;113956:37:::1;::::0;::::1;::::0;::::1;::::0;113889:8;;113924:14;;113956:37:::1;:::i;:::-;;;;;;;;113652:349:::0;;:::o;83496:341::-;83616:18;83672:1;83655:14;:18;83647:37;;;;-1:-1:-1;;;83647:37:0;;;;;;;:::i;:::-;83698:9;83713:17;83723:6;83713:9;:17::i;:::-;-1:-1:-1;83756:14:0;;83697:33;;-1:-1:-1;83756:14:0;;;-1:-1:-1;;;;;83756:14:0;:26;83783:10;83697:33;83800:14;83816:12;:10;:12::i;:::-;83756:73;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83743:86;83496:341;-1:-1:-1;;;;83496:341:0:o;77547:22::-;;;;:::o;8502:100::-;8582:12;;8502:100;:::o;112681:218::-;19646:15;:13;:15::i;:::-;112787:4:::1;112773:10;:18;;112765:45;;;;-1:-1:-1::0;;;112765:45:0::1;;;;;;;:::i;:::-;112823:9;:22:::0;;;112863:28:::1;::::0;::::1;::::0;::::1;::::0;112835:10;;112863:28:::1;:::i;:::-;;;;;;;;112681:218:::0;:::o;105721:209::-;105811:32;105845:24;105895:14;105911:10;105887:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;105887:35:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;105887:35:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;105887:35:0;;;;;;;;;;-1:-1:-1;;;105887:35:0;;;;;;;;;;;;;;;-1:-1:-1;;;105887:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;105887:35:0;;;;;-1:-1:-1;;;105887:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105721:209;;:::o;77952:32::-;;;-1:-1:-1;;;;;77952:32:0;;;;-1:-1:-1;;;77952:32:0;;;;:::o;10150:300::-;10282:4;10299:36;10309:6;10317:9;10328:6;10299:9;:36::i;:::-;10346:74;10355:6;10363:12;:10;:12::i;:::-;-1:-1:-1;;;;;10377:19:0;;;;;;:11;:19;;;;;10413:6;;10397:12;:10;:12::i;:::-;-1:-1:-1;;;;;10377:33:0;-1:-1:-1;;;;;10377:33:0;;;;;;;;;;;;;:42;;;;:::i;:::-;10346:8;:74::i;:::-;-1:-1:-1;10438:4:0;10150:300;;;;;;:::o;113128:354::-;19646:15;:13;:15::i;:::-;113238:20:::1;::::0;-1:-1:-1;;;113238:20:0;::::1;;;113237:21;113229:49;;;;-1:-1:-1::0;;;113229:49:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;113297:32:0;::::1;113289:57;;;;-1:-1:-1::0;;;113289:57:0::1;;;;;;;:::i;:::-;113359:14;:56:::0;;-1:-1:-1;;;;;;113359:56:0::1;::::0;-1:-1:-1;;;;;113359:56:0;::::1;;;::::0;;113433:41:::1;::::0;::::1;::::0;::::1;::::0;113359:56;;113433:41:::1;:::i;110404:868::-:0;110513:18;110533:17;80063:19;:17;:19::i;:::-;110806:7:::1;::::0;110842:1:::1;110828:15:::0;::::1;110824:405;;;110873:15;110887:1;110873:11:::0;:15:::1;:::i;:::-;110913:1;110903:7;:11:::0;110860:28;-1:-1:-1;110982:29:0::1;110988:10;110860:28:::0;110982:5:::1;:29::i;:::-;111069:4;111031:186;111093:10;111122::::0;111165:1:::1;111151:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;111151:16:0::1;-1:-1:-1::0;111186:16:0::1;::::0;;111200:1:::1;111186:16:::0;;::::1;::::0;::::1;::::0;;;;111031:186:::1;::::0;;;;::::1;:::i;:::-;;;;;;;;110824:405;111251:13;:11;:13::i;:::-;111239:25;;80093:1;110404:868:::0;;:::o;77723:55::-;;;;;;;;;;;;;;;:::o;16540:83::-;16606:9;;;;16540:83;:::o;10859:207::-;10939:4;10956:80;10965:12;:10;:12::i;:::-;10979:7;11025:10;10988:11;:25;11000:12;:10;:12::i;:::-;-1:-1:-1;;;;;10988:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;10988:25:0;;;:34;;;;;;;;;;:47;;;;:::i;106163:328::-;106247:30;;:::i;:::-;106279:22;;:::i;:::-;-1:-1:-1;;;;;106326:22:0;;106314:9;106326:22;;;:13;:22;;;;;;106370:14;:19;;106326:22;;;;;;;106370:19;;;;-1:-1:-1;;;106370:19:0;;;;;;;;;;;;;;;;;;106359:30;;;;;;;;106370:19;;;;;;;106359:30;;-1:-1:-1;;;;;106359:30:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;106359:30:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;106359:30:0;;;;;;;;;;-1:-1:-1;;;106359:30:0;;;;;;;;;;;;;;;-1:-1:-1;;;106359:30:0;;;;;;;;;;;;;;;106425:7;-1:-1:-1;;;;;106408:24:0;:8;:13;;;-1:-1:-1;;;;;106408:24:0;;106400:50;;;;-1:-1:-1;;;106400:50:0;;;;;;;:::i;:::-;106468:10;106479:3;106468:15;;;;;;;;-1:-1:-1;;;106468:15:0;;;;;;;;;;;;;;;;;;106461:22;;;;;;;;;106468:15;;106461:22;-1:-1:-1;;;;;106461:22:0;;;;;-1:-1:-1;;;106461:22:0;;;;;;;;;;;106163:328;;106461:22;;-1:-1:-1;;;106163:328:0:o;94353:326::-;23983:11;;94554:22;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80824:10:::1;:8;:10::i;:::-;94606:65:::2;94614:7;94623:15;94640:18;94660:10;94606:7;:65::i;:::-;24288:11:::0;:18;;-1:-1:-1;;24288:18:0;;;;;94589:82;94353:326;-1:-1:-1;;;;;94353:326:0:o;116656:185::-;19646:15;:13;:15::i;:::-;116749:18:::1;:29;116779:7;116788:8;116798:12;116812:7;:5;:7::i;:::-;77913:3;116749:84;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;116656:185:::0;;:::o;77454:28::-;;;;:::o;77368:22::-;;;;:::o;77923:::-;;;-1:-1:-1;;;;;77923:22:0;;;;-1:-1:-1;;;77923:22:0;;;;;-1:-1:-1;;;77923:22:0;;;;;-1:-1:-1;;;77923:22:0;;;;:::o;77516:24::-;;;;:::o;77785:23::-;;;;;;:::o;77686:30::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77686:30:0;;;;-1:-1:-1;;;;77686:30:0;;;;;:::o;115416:244::-;19646:15;:13;:15::i;:::-;115561:91:::1;::::0;-1:-1:-1;;;115561:91:0;;:18:::1;::::0;:33:::1;::::0;:91:::1;::::0;115595:14:::1;::::0;115611:13:::1;::::0;115626:8;;;;115636:15;;115561:91:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;115416:244:::0;;;:::o;8665:119::-;-1:-1:-1;;;;;8758:18:0;;8731:7;8758:18;;;:9;:18;;;;;;8665:119;;;;:::o;90071:792::-;90217:18;90266:7;-1:-1:-1;;;;;90256:17:0;:6;-1:-1:-1;;;;;90256:17:0;;;90248:42;;;;-1:-1:-1;;;90248:42:0;;;;;;;:::i;:::-;90326:1;90309:14;:18;90301:52;;;;-1:-1:-1;;;90301:52:0;;;;;;;:::i;:::-;90423:30;90456:10;90423:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90423:43:0;;;;;-1:-1:-1;;;90423:43:0;;;;;;;;;;;;;;;;;;;;;;;;;90478:14;90498:17;90508:6;90498:9;:17::i;:::-;90477:38;;;90527:15;90548:18;90558:7;90548:9;:18::i;:::-;90526:40;;;90668:14;;;;;;;;;-1:-1:-1;;;;;90668:14:0;-1:-1:-1;;;;;90668:26:0;;90709:10;90734:8;90757:9;90781:14;90810:7;;90832:12;:10;:12::i;:::-;90668:187;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;90651:204:0;90071:792;-1:-1:-1;;;;;;;90071:792:0:o;96877:496::-;97001:20;97060:1;97042:15;:19;97034:38;;;;-1:-1:-1;;;97034:38:0;;;;;;;:::i;:::-;97086:9;97101:18;97111:7;97101:9;:18::i;:::-;97085:34;;;97132:17;97152:36;97180:7;;97152:15;:27;;:36;;;;:::i;:::-;97214:14;;97132:56;;-1:-1:-1;97214:14:0;;;-1:-1:-1;;;;;97214:14:0;:28;97257:10;97282:3;97300:27;97132:56;97300:15;:27;:::i;:::-;97342:12;:10;:12::i;:::-;97214:151;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97199:166;96877:496;-1:-1:-1;;;;;96877:496:0:o;111607:674::-;111767:18;111787:17;80063:19;:17;:19::i;:::-;80425:12:::1;:10;:12::i;:::-;23983:11:::2;::::0;::::2;::::0;::::2;;;23975:55;;;;-1:-1:-1::0;;;23975:55:0::2;;;;;;;:::i;:::-;24108:11;:19:::0;;-1:-1:-1;;24108:19:0::2;::::0;;;;111822:22:::3;::::0;111877:18:::3;::::0;:42:::3;::::0;111934:14:::3;::::0;111963:10:::3;::::0;111988:14;;::::3;-1:-1:-1::0;;;;;111988:14:0::3;112017:12;:10;:12::i;:::-;111877:163;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;::::0;;::::3;-1:-1:-1::0;;111877:163:0::3;::::0;::::3;;::::0;::::3;::::0;;;::::3;::::0;::::3;:::i;:::-;111855:185:::0;;-1:-1:-1;111855:185:0;-1:-1:-1;112061:14:0;112053:49:::3;;;;-1:-1:-1::0;;;112053:49:0::3;;;;;;;:::i;:::-;112115:29;112121:10;112133;112115:5;:29::i;:::-;112180:4;112160:75;112187:10;112199::::0;112225:1:::3;112211:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;112211:16:0::3;;112229:5;112160:75;;;;;;;;;:::i;:::-;;;;;;;;112260:13;:11;:13::i;:::-;24288:11:::2;:18:::0;;-1:-1:-1;;24288:18:0::2;;;::::0;;111607:674;;;-1:-1:-1;;111607:674:0:o;115984:188::-;19646:15;:13;:15::i;:::-;116073:91:::1;::::0;-1:-1:-1;;;116073:91:0;;:18:::1;::::0;:32:::1;::::0;:91:::1;::::0;116106:6:::1;::::0;116114:14:::1;::::0;116130:13:::1;::::0;116145:7;;116154:9;;116073:91:::1;;;:::i;15890:87::-:0;15929:13;15962:7;15955:14;;;;;:::i;116296:165::-;19646:15;:13;:15::i;:::-;116371:82:::1;::::0;-1:-1:-1;;;116371:82:0;;:18:::1;::::0;:34:::1;::::0;:82:::1;::::0;116406:6:::1;::::0;116414:14:::1;::::0;116430:13:::1;::::0;116445:7;;116371:82:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;116296:165:::0;:::o;114172:336::-;19646:15;:13;:15::i;:::-;114282:10:::1;:17:::0;:21:::1;::::0;114302:1:::1;114282:21;:::i;:::-;114274:30;::::0;:4:::1;:30;:::i;:::-;114266:4;-1:-1:-1::0;;;;;114266:38:0::1;;;114258:65;;;;-1:-1:-1::0;;;114258:65:0::1;;;;;;;:::i;:::-;114358:10;:17:::0;:21:::1;::::0;114378:1:::1;::::0;114358:21:::1;:::i;:::-;114350:30;::::0;:4:::1;:30;:::i;:::-;114342:4;-1:-1:-1::0;;;;;114342:38:0::1;;;114334:65;;;;-1:-1:-1::0;;;114334:65:0::1;;;;;;;:::i;:::-;114427:24;::::0;;;;::::1;::::0;;-1:-1:-1;;;;;114427:24:0;;::::1;::::0;;;;;::::1;;::::0;;::::1;::::0;;;114412:12:::1;:39:::0;;-1:-1:-1;;114412:39:0::1;::::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;114412:39:0;;::::1;::::0;;;::::1;::::0;;114469:31;::::1;::::0;::::1;::::0;114427:24;;;;114469:31:::1;:::i;19212:29::-:0;;;:::o;11569:217::-;11654:4;11671:85;11680:12;:10;:12::i;:::-;11694:7;11740:15;11703:11;:25;11715:12;:10;:12::i;:::-;-1:-1:-1;;;;;11703:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;11703:25:0;;;:34;;;;;;;;;;:52;;;;:::i;8997:167::-;9075:4;9092:42;9102:12;:10;:12::i;:::-;9116:9;9127:6;9092:9;:42::i;96118:441::-;23983:11;;96356:22;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80824:10:::1;:8;:10::i;:::-;96408:143:::2;96442:8;;96408:143;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;96408:143:0::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;;;;;;-1:-1:-1;96465:17:0;;-1:-1:-1;96465:17:0;;;;96408:143;::::2;::::0;96465:17;;96408:143;96465:17;96408:143;::::2;;::::0;::::2;::::0;;;;-1:-1:-1;96497:18:0;;-1:-1:-1;96530:10:0;;-1:-1:-1;96408:19:0::2;::::0;-1:-1:-1;96408:143:0:i:2;:::-;24288:11:::0;:18;;-1:-1:-1;;24288:18:0;;;;;96391:160;96118:441;-1:-1:-1;;;;;;;96118:441:0:o;95096:331::-;23983:11;;95290:33;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80824:10:::1;:8;:10::i;:::-;95355:64:::2;95369:15;95386:20;;95408:10;95355:13;:64::i;82848:348::-:0;23983:11;;83075:18;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80425:12:::1;:10;:12::i;:::-;83119:69:::2;83130:7;;83119:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;83119:69:0::2;::::0;;::::2;::::0;;::::2;::::0;;;;;;;;;;;;;-1:-1:-1;83139:16:0;;-1:-1:-1;83139:16:0;;;;83119:69;::::2;::::0;83139:16;;83119:69;83139:16;83119:69;::::2;;::::0;::::2;::::0;;;;-1:-1:-1;83157:18:0;;-1:-1:-1;83177:10:0;;-1:-1:-1;83119:10:0::2;::::0;-1:-1:-1;83119:69:0:i:2;114757:193::-:0;19646:15;:13;:15::i;:::-;114857:85:::1;::::0;-1:-1:-1;;;114857:85:0;;:18:::1;::::0;:38:::1;::::0;:85:::1;::::0;114896:14:::1;::::0;114912:13:::1;::::0;114927:7;;114936:5;;114857:85:::1;;;:::i;106590:113::-:0;106634:29;;:::i;:::-;106683:12;:10;:12::i;:::-;106676:19;;106590:113;:::o;116980:108::-;19646:15;:13;:15::i;:::-;117034:18:::1;:28;117063:7;117072;:5;:7::i;:::-;117034:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;116980:108::o:0;105400:130::-;105484:6;:22;;;;;;;105508:13;;;105400:130;;:::o;89257:345::-;23983:11;;89480:18;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80425:12:::1;:10;:12::i;:::-;89524:70:::2;89530:6;89538:7;89547:14;89563:18;89583:10;89524:5;:70::i;:::-;24288:11:::0;:18;;-1:-1:-1;;24288:18:0;;;;;89511:83;89257:345;-1:-1:-1;;;;;;89257:345:0:o;77116:41::-;;;;;;-1:-1:-1;;;;;77116:41:0;;:::o;9227:143::-;-1:-1:-1;;;;;9335:18:0;;;9308:7;9335:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;9227:143::o;84207:464::-;84357:18;84402:16;84444:7;;;;;:32;;-1:-1:-1;84455:21:0;;;84444:32;84436:65;;;;-1:-1:-1;;;84436:65:0;;;;;;;:::i;:::-;84513:22;84541:20;84553:7;;84541:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84541:11:0;;-1:-1:-1;;;84541:20:0:i;:::-;-1:-1:-1;84579:14:0;;84512:49;;-1:-1:-1;84579:14:0;;;-1:-1:-1;;;;;84579:14:0;:31;84611:10;84512:49;84632:16;;84650:12;:10;:12::i;:::-;84579:84;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84572:91;84207:464;-1:-1:-1;;;;;;;84207:464:0:o;77815:25::-;;;;;;;;;;;;;:::o;81785:312::-;23983:11;;81982:18;;23983:11;;;;;23975:55;;;;-1:-1:-1;;;23975:55:0;;;;;;;:::i;:::-;24108:11;:19;;-1:-1:-1;;24108:19:0;;;80425:12:::1;:10;:12::i;:::-;82026:63:::2;82034:6;82042:14;82058:18;82078:10;82026:7;:63::i;108371:545::-:0;108541:15;;108458:22;;;;108541:15;-1:-1:-1;;;;;108579:16:0;;;;;-1:-1:-1;;;108579:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;108579:16:0;;108569:26;;108638:3;-1:-1:-1;;;;;108617:25:0;;;;;-1:-1:-1;;;108617:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;108606:36;;108660:9;108655:254;108679:3;108675:1;:7;108655:254;;;108732:22;108742:8;108751:1;108742:11;;;;;;-1:-1:-1;;;108742:11:0;;;;;;;;;;;;;;;108732:9;:22::i;:::-;108705:7;108713:1;108705:10;;;;;;-1:-1:-1;;;108705:10:0;;;;;;;;;;;;;;108717:8;108726:1;108717:11;;;;;;-1:-1:-1;;;108717:11:0;;;;;;;;;;;;;;;;;;108704:50;;;;;;;;;;108776:9;108788:5;:1;108792;108788:5;:::i;:::-;108776:17;;108771:127;108799:3;108795:1;:7;108771:127;;;108851:8;108860:1;108851:11;;;;;;-1:-1:-1;;;108851:11:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;108836:26:0;:8;108845:1;108836:11;;;;;;-1:-1:-1;;;108836:11:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;108836:26:0;;;108828:54;;;;-1:-1:-1;;;108828:54:0;;;;;;;:::i;:::-;108804:3;;;;:::i;:::-;;;;108771:127;;;-1:-1:-1;108684:3:0;;;;:::i;:::-;;;;108655:254;;;;108371:545;;;;:::o;109015:133::-;109060:22;;:::i;:::-;109102:38;;;;;;;;109118:7;:5;:7::i;:::-;109102:38;;;;;;;;;;;109127:12;109102:38;-1:-1:-1;;;;;109102:38:0;;;;;-1:-1:-1;;;109102:38:0;;;;;;;;;;;;;;;;109095:45;-1:-1:-1;109015:133:0;:::o;37700:195::-;37767:7;37886:1;37868:14;33978:4;37868:1;:14;:::i;:::-;37867:20;;;;:::i;5216:107::-;5304:10;5216:107;:::o;14249:338::-;-1:-1:-1;;;;;14343:19:0;;14335:68;;;;-1:-1:-1;;;14335:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14422:21:0;;14414:68;;;;-1:-1:-1;;;14414:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;14495:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;;:36;;;14547:32;;;;;14525:6;;14547:32;:::i;:::-;;;;;;;;14249:338;;;:::o;19689:121::-;19761:11;:9;:11::i;:::-;-1:-1:-1;;;;;19747:25:0;:10;-1:-1:-1;;;;;19747:25:0;;19739:63;;;;-1:-1:-1;;;19739:63:0;;;;;;;:::i;:::-;19689:121::o;107837:264::-;107911:9;107922:30;;:::i;:::-;-1:-1:-1;;;;;107971:21:0;;;;;;:13;:21;;;;;;108014:14;:19;;107971:21;;;;;-1:-1:-1;108014:14:0;107971:21;;108014:19;;;;-1:-1:-1;;;108014:19:0;;;;;;;;;;;;;;;;;;108003:30;;;;;;;;108014:19;;;;;;;108003:30;;-1:-1:-1;;;;;108003:30:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;108003:30:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;108003:30:0;;;;;;;;;;-1:-1:-1;;;108003:30:0;;;;;;;;;;;;;;;-1:-1:-1;;;108003:30:0;;;;;;;;;;;;;;;108069:6;-1:-1:-1;;;;;108052:23:0;:8;:13;;;-1:-1:-1;;;;;108052:23:0;;108044:49;;;;-1:-1:-1;;;108044:49:0;;;;;;;:::i;:::-;107837:264;;;:::o;12276:382::-;-1:-1:-1;;;;;12374:20:0;;12366:70;;;;-1:-1:-1;;;12366:70:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;12455:23:0;;12447:71;;;;-1:-1:-1;;;12447:71:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;12531:17:0;;;;;;:9;:17;;;;;:27;;12552:6;;12531:17;:27;;12552:6;;12531:27;:::i;:::-;;;;-1:-1:-1;;;;;;;12569:20:0;;;;;;:9;:20;;;;;:30;;12593:6;;12569:20;:30;;12593:6;;12569:30;:::i;:::-;;;;;;;;12632:9;-1:-1:-1;;;;;12615:35:0;12624:6;-1:-1:-1;;;;;12615:35:0;;12643:6;12615:35;;;;;;:::i;80169:129::-;80252:10;80231:17;:15;:17::i;:::-;-1:-1:-1;;;;;80231:31:0;;80223:67;;;;-1:-1:-1;;;80223:67:0;;;;;;;:::i;12939:268::-;-1:-1:-1;;;;;13015:21:0;;13007:65;;;;-1:-1:-1;;;13007:65:0;;;;;;;:::i;:::-;13101:6;13085:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;13118:18:0;;;;;;:9;:18;;;;;:28;;13140:6;;13118:18;:28;;13140:6;;13118:28;:::i;:::-;;;;-1:-1:-1;;13162:37:0;;-1:-1:-1;;;;;13162:37:0;;;13179:1;;13162:37;;;;13192:6;;13162:37;:::i;:::-;;;;;;;;12939:268;;:::o;80921:144::-;80966:35;;;;;;;;;80995:6;80966:35;;;;;;;;;;;;;;;;;;;;;81012:45;;;;-1:-1:-1;;;81012:45:0;;;;;;;:::i;:::-;80921:144;:::o;98641:1813::-;98808:22;-1:-1:-1;;;;;98851:24:0;;98843:54;;;;-1:-1:-1;;;98843:54:0;;;;;;;:::i;:::-;98933:1;98916:14;:18;98908:37;;;;-1:-1:-1;;;98908:37:0;;;;;;;:::i;:::-;99016:30;99049:10;99016:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;99016:43:0;;;;;-1:-1:-1;;;99016:43:0;;;;;;;;;;;;;;;;;;;;;;;;;99071:17;99090:30;99124:18;99134:7;99124:9;:18::i;:::-;99070:72;;;;99197:17;99217:35;99244:7;;99217:14;:26;;:35;;;;:::i;:::-;99280:14;;99197:55;;-1:-1:-1;99280:14:0;;;-1:-1:-1;;;;;99280:14:0;:28;99323:10;99348:11;99374:26;99197:55;99374:14;:26;:::i;:::-;99415:12;:10;:12::i;:::-;99280:158;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99263:175;;99475:18;99457:14;:36;;99449:69;;;;-1:-1:-1;;;99449:69:0;;;;;;;:::i;:::-;99554:1;99537:14;:18;99529:42;;;;-1:-1:-1;;;99529:42:0;;;;;;;:::i;:::-;99697:33;99703:10;99715:14;99697:5;:33::i;:::-;99752:9;99741:7;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;99772:18:0;;-1:-1:-1;99793:18:0;:16;:18::i;:::-;99772:39;;99877:18;:33;99925:14;99954:8;99977:10;99988:11;99977:23;;;;;;;;-1:-1:-1;;;99977:23:0;;;;;;;;;;;;;;;100015:10;100040:5;:14;;;99877:188;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100215:34;100234:14;100215:18;:34::i;:::-;100163:10;100174:11;100163:23;;;;;;;;-1:-1:-1;;;100163:23:0;;;;;;;;;;;;;;;:36;;;:86;;;;:::i;:::-;100111:10;100122:11;100111:23;;;;;;;;-1:-1:-1;;;100111:23:0;;;;;;;;;;;;;;;;;;:138;;-1:-1:-1;;;;;100111:138:0;;;-1:-1:-1;;;100111:138:0;;;;;;;;;100369:13;;100267:179;;100290:10;;100267:179;;;;100315:10;;100340:14;;100369:13;100397:14;;100426:9;;100267:179;:::i;:::-;;;;;;;;98641:1813;;;;;;;;;;;:::o;109220:826::-;109280:33;;;;;;;;109306:7;109280:33;-1:-1:-1;;;;;109280:33:0;;;;;-1:-1:-1;;;109280:33:0;;;;;;;;;;-1:-1:-1;;;109280:33:0;;;;;;;;;;;-1:-1:-1;;;109280:33:0;;;;;;;;;;109260:7;;109280:33;109488:15;:25;-1:-1:-1;109484:555:0;;;109546:17;;109597:22;;;;109530:13;;109672:27;-1:-1:-1;;;;;109672:27:0;;:15;:27;:::i;:::-;109701:19;109711:9;109701:7;:19;:::i;:::-;-1:-1:-1;;;;;109636:85:0;;;;;109749:6;-1:-1:-1;;;;;109742:13:0;:4;-1:-1:-1;;;;;109742:13:0;;109738:201;;;109823:5;109812:7;109795:13;109802:6;109795:4;:13;:::i;:::-;-1:-1:-1;;;;;109794:25:0;;;;;:::i;:::-;109793:35;;;;:::i;:::-;109783:46;;-1:-1:-1;;;;;109783:46:0;;;:::i;:::-;109776:53;;;;;;;;;;;109738:201;109917:5;109906:7;109889:13;109898:4;109889:6;:13;:::i;:::-;-1:-1:-1;;;;;109888:25:0;;;;;:::i;:::-;109887:35;;;;:::i;:::-;109877:46;;-1:-1:-1;;;;;109877:46:0;;;:::i;109484:555::-;-1:-1:-1;;;;;;110016:11:0;;-1:-1:-1;110016:11:0;;-1:-1:-1;110016:11:0;35604:135;35670:7;35697:34;35714:1;35717;33978:4;35697:16;:34::i;80524:166::-;80571:35;;;;;;;;;80600:6;80571:35;;;;;;;;;;;;;;;;;;;;;;;;;80625:43;;;80654:7;:14;;;80653:15;80625:43;80617:65;;;;-1:-1:-1;;;80617:65:0;;;;;;;:::i;102973:2177::-;103174:22;-1:-1:-1;;;;;103217:24:0;;103209:54;;;;-1:-1:-1;;;103209:54:0;;;;;;;:::i;:::-;103288:24;;103331:7;;;;;:33;;;103349:8;:15;103342:3;:22;103331:33;103323:65;;;;-1:-1:-1;;;103323:65:0;;;;;;;:::i;:::-;103428:1;103407:18;:22;103399:41;;;;-1:-1:-1;;;103399:41:0;;;;;;;:::i;:::-;103454:22;103478:32;103514:21;103526:8;103514:11;:21::i;:::-;103631:10;103598:43;;;;;;;;;;;;;;;;;103453:82;;-1:-1:-1;103453:82:0;;-1:-1:-1;103598:30:0;;;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;103598:43:0;;;;;-1:-1:-1;;;103598:43:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;103709:14:0;;103598:43;;-1:-1:-1;103684:22:0;;103709:14;;;-1:-1:-1;;;;;103709:14:0;;-1:-1:-1;103709:33:0;;-1:-1:-1;103598:43:0;103782:7;103804:17;103836:12;:10;:12::i;:::-;103709:150;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103684:175;;103887:43;103922:7;;103915:4;:14;;;;:::i;103887:43::-;103870:60;-1:-1:-1;103941:11:0;103955:31;103972:14;103870:60;103955:31;:::i;:::-;103941:45;;104022:1;104005:14;:18;103997:55;;;;-1:-1:-1;;;103997:55:0;;;;;;;:::i;:::-;104063:19;104081:1;104063:19;;:::i;:::-;;;104119:18;104101:14;:36;;104093:81;;;;-1:-1:-1;;;104093:81:0;;;;;;;:::i;:::-;104300:33;104306:10;104318:14;104300:5;:33::i;:::-;104355:3;104344:7;;:14;;;;;;;:::i;:::-;;;;-1:-1:-1;104369:18:0;;-1:-1:-1;104390:18:0;:16;:18::i;:::-;104369:39;;104494:9;104489:462;104513:3;104509:1;:7;104489:462;;;104538:9;104550:7;104558:1;104550:10;;;;;;-1:-1:-1;;;104550:10:0;;;;;;;;;;;;;;;104538:22;;104575:18;:33;104627:17;104645:1;104627:20;;;;;;-1:-1:-1;;;104627:20:0;;;;;;;;;;;;;;;104666:8;104675:1;104666:11;;;;;;-1:-1:-1;;;104666:11:0;;;;;;;;;;;;;;;104696:10;104707:3;104696:15;;;;;;;;-1:-1:-1;;;104696:15:0;;;;;;;;;;;;;;;104730:10;104759:5;:14;;;104575:213;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104899:40;104918:17;104936:1;104918:20;;;;;;-1:-1:-1;;;104918:20:0;;;;;;;;;;;;;;;104899:18;:40::i;:::-;104851:10;104862:3;104851:15;;;;;;;;-1:-1:-1;;;104851:15:0;;;;;;;;;;;;;;;:28;;;:88;;;;:::i;:::-;104803:10;104814:3;104803:15;;;;;;;;-1:-1:-1;;;104803:15:0;;;;;;;;;;;;;;;;;;:136;;-1:-1:-1;;;;;104803:136:0;;;-1:-1:-1;;;104803:136:0;;;;;;;;;-1:-1:-1;104518:3:0;;;;:::i;:::-;;;;104489:462;;;;104994:10;-1:-1:-1;;;;;104966:176:0;;105019:10;105044:14;105073:8;105096:17;105128:3;104966:176;;;;;;;;;;:::i;:::-;;;;;;;;102973:2177;;;;;;;;;;;;;:::o;100542:2368::-;100702:33;-1:-1:-1;;;;;100756:24:0;;100748:54;;;;-1:-1:-1;;;100748:54:0;;;;;;;:::i;:::-;100838:1;100821:14;:18;100813:37;;;;-1:-1:-1;;;100813:37:0;;;;;;;:::i;:::-;100914:17;100934:41;100961:13;;100934:14;:26;;:41;;;;:::i;:::-;100914:61;-1:-1:-1;100986:30:0;101019:26;100914:61;101019:14;:26;:::i;:::-;100986:59;;101091:33;101097:10;101109:14;101091:5;:33::i;:::-;101146:9;101135:7;;:20;;;;;;;:::i;:::-;;;;-1:-1:-1;101220:18:0;;-1:-1:-1;101241:18:0;:16;:18::i;:::-;101220:39;;101350:19;101396:22;101372:5;:21;;;:46;;;;:::i;:::-;101350:68;;101489:30;101522:10;101489:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;101489:43:0;;;;;-1:-1:-1;;;101489:43:0;;;;;;;;;;;;;;;;;;;;;;;;;101545:11;101559:10;:17;101545:31;;101587:24;101628:3;-1:-1:-1;;;;;101614:18:0;;;;;-1:-1:-1;;;101614:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101614:18:0;;101587:45;;101676:3;-1:-1:-1;;;;;101662:18:0;;;;;-1:-1:-1;;;101662:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101662:18:0;;101643:37;;101696:9;101691:1014;101715:3;101711:1;:7;101691:1014;;;101907:17;101983:11;101957:22;101928:10;101939:1;101928:13;;;;;;-1:-1:-1;;;101928:13:0;;;;;;;;;;;;;;;:26;;;-1:-1:-1;;;;;101928:51:0;;;;;:::i;:::-;101927:67;;;;:::i;:::-;101907:87;;102029:1;102017:9;:13;102009:37;;;;-1:-1:-1;;;102009:37:0;;;;;;;:::i;:::-;102061:14;102074:1;102061:14;;:::i;:::-;;;102111:20;;102132:1;102111:23;;;;;-1:-1:-1;;;102111:23:0;;;;;;;;;;;;;;;102098:9;:36;;102090:69;;;;-1:-1:-1;;;102090:69:0;;;;;;;:::i;:::-;102247:9;102258:14;102273:1;102258:17;;;;;;-1:-1:-1;;;102258:17:0;;;;;;;;;;;;;;;;;;;;;;:22;102211:19;;-1:-1:-1;;;;;102258:22:0;;;;102211:16;;102228:1;;102211:19;;;;-1:-1:-1;;;102211:19:0;;;;;;;;;;;;;;102232:7;102240:1;102232:10;;;;;;-1:-1:-1;;;102232:10:0;;;;;;;;;;;;;;102210:71;-1:-1:-1;;;;;102210:71:0;-1:-1:-1;;;;;102210:71:0;;;;;;;;;;102349:18;:33;102401:9;102429:14;102444:1;102429:17;;;;;;-1:-1:-1;;;102429:17:0;;;;;;;;;;;;;;;;;;;102465:10;102476:1;102465:13;;;;;;-1:-1:-1;;;102465:13:0;;;;;;;;;;;;;;;102497:10;102526:5;:14;;;102349:206;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102664:29;102683:9;102664:18;:29::i;:::-;102635:10;102646:1;102635:13;;;;;;-1:-1:-1;;;102635:13:0;;;;;;;;;;;;;;;:26;;;:58;;;;:::i;:::-;102606:10;102617:1;102606:13;;;;;;-1:-1:-1;;;102606:13:0;;;;;;;;;;;;;;;;;;:87;;-1:-1:-1;;;;;102606:87:0;;;-1:-1:-1;;;102606:87:0;;;;;;;;;-1:-1:-1;101720:3:0;;;;:::i;:::-;;;;101691:1014;;;;102750:10;-1:-1:-1;;;;;102722:180:0;;102775:10;102800:14;102829:7;102851:16;102882:9;102722:180;;;;;;;;;;:::i;86386:2129::-;86576:20;-1:-1:-1;;;;;86617:24:0;;86609:54;;;;-1:-1:-1;;;86609:54:0;;;;;;;:::i;:::-;86688:23;;86730:7;;;;;:32;;;86748:7;:14;86741:3;:21;86730:32;86722:65;;;;-1:-1:-1;;;86722:65:0;;;;;;;:::i;:::-;86849:22;86873:33;86910:20;86922:7;86910:11;:20::i;:::-;86974:10;86941:43;;;;;;;;;;;;;;;;;86848:82;;-1:-1:-1;86848:82:0;;-1:-1:-1;86941:30:0;;;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;86941:43:0;;;;;-1:-1:-1;;;86941:43:0;;;;;;;;;;;;;;;;;;;;;;;;;86995:18;87016;:16;:18::i;:::-;86995:39;;87045:36;87098:3;-1:-1:-1;;;;;87084:18:0;;;;;-1:-1:-1;;;87084:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87084:18:0;;87045:57;;87202:9;87197:769;87221:3;87217:1;:7;87197:769;;;87246:22;87271:16;87288:1;87271:19;;;;;;-1:-1:-1;;;87271:19:0;;;;;;;;;;;;;;;87246:44;;87326:1;87309:14;:18;87305:650;;;87348:9;87360:7;87368:1;87360:10;;;;;;-1:-1:-1;;;87360:10:0;;;;;;;;;;;;;;;87348:22;;87389;87414:10;87425:3;87414:15;;;;;;;;-1:-1:-1;;;87414:15:0;;;;;;;;;;;;;;;87389:40;;87448:30;87481:9;87491:1;87481:12;;;;;;-1:-1:-1;;;87481:12:0;;;;;;;;;;;;;;;87448:45;;87512:25;87540:18;:32;87595:8;87626:4;:10;;;87659:14;87696:5;:14;;;87540:189;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87512:217;;87773:17;87748:19;87768:1;87748:22;;;;;;-1:-1:-1;;;87748:22:0;;;;;;;;;;;;;;:42;;;;;87902:37;87921:17;87902:18;:37::i;:::-;87861:4;:17;;;:78;;;;:::i;:::-;87809:10;87820:3;87809:15;;;;;;;;-1:-1:-1;;;87809:15:0;;;;;;;;;;;;;;;;;;:130;;-1:-1:-1;;;;;87809:130:0;;;-1:-1:-1;;;87809:130:0;;;;;;;;;-1:-1:-1;;;;87305:650:0;-1:-1:-1;87226:3:0;;;;:::i;:::-;;;;87197:769;;;-1:-1:-1;88052:14:0;;;;;-1:-1:-1;;;;;88052:14:0;:31;88098:10;88123:7;88145:19;88179:12;:10;:12::i;:::-;88052:150;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88037:165;;88237:18;88221:12;:34;;88213:70;;;;-1:-1:-1;;;88213:70:0;;;;;;;:::i;:::-;88317:1;88302:12;:16;88294:49;;;;-1:-1:-1;;;88294:49:0;;;;;;;:::i;:::-;88384:31;88390:10;88402:12;88384:5;:31::i;:::-;88443:10;-1:-1:-1;;;;;88431:76:0;;88455:10;88467:12;88481:7;88490:16;88431:76;;;;;;;;;:::i;:::-;;;;;;;;86386:2129;;;;;;;;;;;;:::o;91026:2316::-;91216:18;-1:-1:-1;;;;;91255:24:0;;91247:54;;;;-1:-1:-1;;;91247:54:0;;;;;;;:::i;:::-;91330:7;-1:-1:-1;;;;;91320:17:0;:6;-1:-1:-1;;;;;91320:17:0;;;91312:42;;;;-1:-1:-1;;;91312:42:0;;;;;;;:::i;:::-;91390:1;91373:14;:18;91365:52;;;;-1:-1:-1;;;91365:52:0;;;;;;;:::i;:::-;91487:30;91520:10;91487:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91487:43:0;;;;;-1:-1:-1;;;91487:43:0;;;;;;;;;;;;;;;;;;;;;;;;;91542:14;91558:35;91597:17;91607:6;91597:9;:17::i;:::-;91541:73;;;;91626:15;91643:36;91683:18;91693:7;91683:9;:18::i;:::-;91625:76;;;;91738:18;91759;:16;:18::i;:::-;91738:39;;91828:25;91856:18;:32;91903:13;91931:10;91942:8;91931:20;;;;;;;;-1:-1:-1;;;91931:20:0;;;;;;;;;;;;;;;:26;;;91972:14;92001:5;:14;;;91856:170;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91828:198;;92177:37;92196:17;92177:18;:37::i;:::-;92128:10;92139:8;92128:20;;;;;;;;-1:-1:-1;;;92128:20:0;;;;;;;;;;;;;;;:33;;;:86;;;;:::i;:::-;92079:10;92090:8;92079:20;;;;;;;;-1:-1:-1;;;92079:20:0;;;;;;;;;;;;;;;;:33;;;:135;;;;;-1:-1:-1;;;;;92079:135:0;;;;;-1:-1:-1;;;;;92079:135:0;;;;;;92260:17;92314:14;;;;;;;;;-1:-1:-1;;;;;92314:14:0;-1:-1:-1;;;;;92314:26:0;;92355:10;92380:8;92403:9;92427:17;92459:7;;92481:12;:10;:12::i;:::-;92314:190;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;92288:216;;-1:-1:-1;92288:216:0;-1:-1:-1;92523:32:0;;;;92515:69;;;;-1:-1:-1;;;92515:69:0;;;;;;;:::i;:::-;92616:1;92603:10;:14;92595:47;;;;-1:-1:-1;;;92595:47:0;;;;;;;:::i;:::-;92719:18;:33;92767:10;92792:14;92821:10;92832:9;92821:21;;;;;;;;-1:-1:-1;;;92821:21:0;;;;;;;;;;;;;;;92857:10;92882:5;:14;;;92719:188;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93018:30;93037:10;93018:18;:30::i;:::-;92968:10;92979:9;92968:21;;;;;;;;-1:-1:-1;;;92968:21:0;;;;;;;;;;;;;;;:34;;;:80;;;;:::i;:::-;92918:10;92929:9;92918:21;;;;;;;;-1:-1:-1;;;92918:21:0;;;;;;;;;;;;;;;;;;:130;;-1:-1:-1;;;;;92918:130:0;;;-1:-1:-1;;;92918:130:0;;;;;;;;;93109:13;;;;:25;;93125:9;;93109:25;:::i;:::-;93099:7;:35;;;;93172:10;-1:-1:-1;;;;;93150:184:0;;93197:13;:18;;;93230:14;:19;;;93264:10;93289:9;93313:10;93150:184;;;;;;;;;;:::i;:::-;;;;;;;;91026:2316;;;;;;;;;;;;;;;:::o;84837:1513::-;85003:20;-1:-1:-1;;;;;85044:24:0;;85036:54;;;;-1:-1:-1;;;85036:54:0;;;;;;;:::i;:::-;85126:1;85109:14;:18;85101:37;;;;-1:-1:-1;;;85101:37:0;;;;;;;:::i;:::-;85149:30;85182:10;85149:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;85149:43:0;;;;;-1:-1:-1;;;85149:43:0;;;;;;;;;;;;;;;;;;;;;;;;;85204:17;85223:30;85257:17;85267:6;85257:9;:17::i;:::-;85203:71;;;;85285:18;85306;:16;:18::i;:::-;85285:39;;85420:25;85448:18;:32;85495:8;85518:10;85529:11;85518:23;;;;;;;;-1:-1:-1;;;85518:23:0;;;;;;;;;;;;;;;:29;;;85562:14;85591:5;:14;;;85448:168;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85728:14;;85420:196;;-1:-1:-1;85728:14:0;;;-1:-1:-1;;;;;85728:14:0;:26;85769:10;85794:11;85420:196;85852:12;:10;:12::i;:::-;85728:147;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85713:162;;85910:18;85894:12;:34;;85886:70;;;;-1:-1:-1;;;85886:70:0;;;;;;;:::i;:::-;86148:37;86167:17;86148:18;:37::i;:::-;86096:10;86107:11;86096:23;;;;;;;;-1:-1:-1;;;86096:23:0;;;;;;;;;;;;;;;:36;;;:89;;;;:::i;:::-;86044:10;86055:11;86044:23;;;;;;;;-1:-1:-1;;;86044:23:0;;;;;;;;;;;;;;;;;;:141;;-1:-1:-1;;;;;86044:141:0;;;-1:-1:-1;;;86044:141:0;;;;;;;;;86224:31;86230:10;86242:12;86224:5;:31::i;:::-;86278:10;-1:-1:-1;;;;;86271:71:0;;86290:10;86302:12;86316:6;86324:17;86271:71;;;;;;;;;:::i;20728:95::-;20772:7;20799:5;-1:-1:-1;;;;;20799:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;22484:121::-;22561:36;;-1:-1:-1;;;22561:36:0;;22534:7;;-1:-1:-1;;;;;22561:5:0;:15;;;;:36;;18339:66;;22561:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;13539:270;-1:-1:-1;;;;;13615:21:0;;13607:67;;;;-1:-1:-1;;;13607:67:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;13687:18:0;;;;;;:9;:18;;;;;:28;;13709:6;;13687:18;:28;;13709:6;;13687:28;:::i;:::-;;;;;;;;13742:6;13726:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;13764:37:0;;13790:1;;-1:-1:-1;;;;;13764:37:0;;;;;;;13794:6;;13764:37;:::i;107342:275::-;107393:12;;:::i;:::-;107487:7;;107468:16;107487:7;107519:13;:11;:13::i;:::-;:24;;;;:::i;:::-;107505:38;;107561:48;;;;;;;;107567:3;107561:48;;;;107572:26;107588:9;;107572:3;:15;;:26;;;;:::i;:::-;107561:48;;;;;;;;-1:-1:-1;107554:55:0;-1:-1:-1;107342:275:0;:::o;28120:185::-;28177:7;-1:-1:-1;;;28205:5:0;:16;28197:68;;;;-1:-1:-1;;;28197:68:0;;;;;;;:::i;:::-;-1:-1:-1;28291:5:0;28120:185::o;36212:252::-;36298:7;36451:5;36442;36446:1;36442;:5;:::i;:::-;36441: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:327;;;3288:2;3276:9;3267:7;3263:23;3259:32;3256:2;;;3309:6;3301;3294:22;3256:2;3353:9;3340:23;3372:33;3399:5;3372:33;:::i;:::-;3424:5;3476:2;3461:18;;;;3448:32;;-1:-1:-1;;;3246:240:1:o;3491:539::-;;;;;3654:3;3642:9;3633:7;3629:23;3625:33;3622:2;;;3676:6;3668;3661:22;3622:2;3720:9;3707:23;3739:33;3766:5;3739:33;:::i;:::-;3791:5;-1:-1:-1;3843:2:1;3828:18;;3815:32;;-1:-1:-1;3894:2:1;3879:18;;3866:32;;-1:-1:-1;3950:2:1;3935:18;;3922:32;3963:35;3922:32;3963:35;:::i;:::-;3612:418;;;;-1:-1:-1;3612:418:1;;-1:-1:-1;;3612:418:1:o;4035:600::-;;;;4199:2;4187:9;4178:7;4174:23;4170:32;4167:2;;;4220:6;4212;4205:22;4167:2;4265:9;4252:23;-1:-1:-1;;;;;4290:6:1;4287:30;4284:2;;;4335:6;4327;4320:22;4284:2;4379:76;4447:7;4438:6;4427:9;4423:22;4379:76;:::i;:::-;4474:8;;-1:-1:-1;4353:102:1;-1:-1:-1;;4559:2:1;4544:18;;4531:32;4572:33;4531:32;4572:33;:::i;:::-;4624:5;4614:15;;;4157:478;;;;;:::o;4640:815::-;;;;;4839:2;4827:9;4818:7;4814:23;4810:32;4807:2;;;4860:6;4852;4845:22;4807:2;4905:9;4892:23;-1:-1:-1;;;;;4975:2:1;4967:6;4964:14;4961:2;;;4996:6;4988;4981:22;4961:2;5040:76;5108:7;5099:6;5088:9;5084:22;5040:76;:::i;:::-;5135:8;;-1:-1:-1;5014:102:1;-1:-1:-1;5223:2:1;5208:18;;5195:32;;-1:-1:-1;5239:16:1;;;5236:2;;;5273:6;5265;5258:22;5236:2;;5317:78;5387:7;5376:8;5365:9;5361:24;5317:78;:::i;:::-;4797:658;;;;-1:-1:-1;5414:8:1;-1:-1:-1;;;;4797:658:1:o;5460:1021::-;;;;;;;5693:3;5681:9;5672:7;5668:23;5664:33;5661:2;;;5715:6;5707;5700:22;5661:2;5760:9;5747:23;-1:-1:-1;;;;;5830:2:1;5822:6;5819:14;5816:2;;;5851:6;5843;5836:22;5816:2;5895:76;5963:7;5954:6;5943:9;5939:22;5895:76;:::i;:::-;5990:8;;-1:-1:-1;5869:102:1;-1:-1:-1;6078:2:1;6063:18;;6050:32;;-1:-1:-1;6094:16:1;;;6091:2;;;6128:6;6120;6113:22;6091:2;;6172:78;6242:7;6231:8;6220:9;6216:24;6172:78;:::i;:::-;6269:8;;-1:-1:-1;6146:104:1;-1:-1:-1;;6351:2:1;6336:18;;6323:32;;-1:-1:-1;6405:2:1;6390:18;;6377:32;6418:33;6377:32;6418:33;:::i;:::-;6470:5;6460:15;;;5651:830;;;;;;;;:::o;6486:274::-;;;6615:2;6603:9;6594:7;6590:23;6586:32;6583:2;;;6636:6;6628;6621:22;6583:2;6664:31;6685:9;6664:31;:::i;:::-;6654:41;;6714:40;6750:2;6739:9;6735:18;6714:40;:::i;:::-;6704:50;;6573:187;;;;;:::o;6765:190::-;;6877:2;6865:9;6856:7;6852:23;6848:32;6845:2;;;6898:6;6890;6883:22;6845:2;-1:-1:-1;6926:23:1;;6835:120;-1:-1:-1;6835:120:1:o;6960:194::-;;7083:2;7071:9;7062:7;7058:23;7054:32;7051:2;;;7104:6;7096;7089:22;7051:2;-1:-1:-1;7132:16:1;;7041:113;-1:-1:-1;7041:113:1:o;7159:668::-;;;;;7340:2;7328:9;7319:7;7315:23;7311:32;7308:2;;;7361:6;7353;7346:22;7308:2;7402:9;7389:23;7379:33;;7463:2;7452:9;7448:18;7435:32;-1:-1:-1;;;;;7482:6:1;7479:30;7476:2;;;7527:6;7519;7512:22;7476:2;7571:76;7639:7;7630:6;7619:9;7615:22;7571:76;:::i;:::-;7666:8;;-1:-1:-1;7545:102:1;-1:-1:-1;;7751:2:1;7736:18;;7723:32;7764:33;7723:32;7764:33;:::i;7832:1209::-;;;7997:2;7985:9;7976:7;7972:23;7968:32;7965:2;;;8018:6;8010;8003:22;7965:2;8052:9;8046:16;8036:26;;8081:2;8127;8116:9;8112:18;8106:25;-1:-1:-1;;;;;8191:2:1;8183:6;8180:14;8177:2;;;8212:6;8204;8197:22;8177:2;8255:6;8244:9;8240:22;8230:32;;8300:7;8293:4;8289:2;8285:13;8281:27;8271:2;;8327:6;8319;8312:22;8271:2;8361;8355:9;8383:2;8379;8376:10;8373:2;;;8389:18;;:::i;:::-;8436:2;8432;8428:11;8468:2;8462:9;8519:2;8514;8506:6;8502:15;8498:24;8572:6;8560:10;8557:22;8552:2;8540:10;8537:18;8534:46;8531:2;;;8583:18;;:::i;:::-;8619:2;8612:22;8669:18;;;8703:15;;;;-1:-1:-1;8738:11:1;;;8768;;;8764:20;;8761:33;-1:-1:-1;8758:2:1;;;8812:6;8804;8797:22;8758:2;8839:6;8830:15;;8854:156;8868:2;8865:1;8862:9;8854:156;;;8925:10;;8913:23;;8886:1;8879:9;;;;;8956:12;;;;8988;;8854:156;;;8858:3;9029:6;9019:16;;;;;;;;7955:1086;;;;;:::o;9046:258::-;;;9175:2;9163:9;9154:7;9150:23;9146:32;9143:2;;;9196:6;9188;9181:22;9143:2;-1:-1:-1;;9224:23:1;;;9294:2;9279:18;;;9266:32;;-1:-1:-1;9133:171:1:o;9309:255::-;;;9449:2;9437:9;9428:7;9424:23;9420:32;9417:2;;;9470:6;9462;9455:22;9417:2;-1:-1:-1;;9498:16:1;;9554:2;9539:18;;;9533:25;9498:16;;9533:25;;-1:-1:-1;9407:157:1:o;9569:469::-;;9666:5;9660:12;9693:6;9688:3;9681:19;9719:4;9748:2;9743:3;9739:12;9732:19;;9785:2;9778:5;9774:14;9806:3;9818:195;9832:6;9829:1;9826:13;9818:195;;;9897:13;;-1:-1:-1;;;;;9893:39:1;9881:52;;9953:12;;;;9988:15;;;;9929:1;9847:9;9818:195;;;-1:-1:-1;10029:3:1;;9636:402;-1:-1:-1;;;;;9636:402:1:o;10043:481::-;;10151:5;10145:12;10178:6;10173:3;10166:19;10204:4;10233:2;10228:3;10224:12;10217:19;;10270:2;10263:5;10259:14;10291:3;10303:196;10317:6;10314:1;10311:13;10303:196;;;10366:51;10413:3;10404:6;10398:13;10366:51;:::i;:::-;10446:4;10437:14;;;;;10474:15;;;;10339:1;10332:9;10303:196;;10529:636;;10653:5;10647:12;10680:6;10675:3;10668:19;10706:4;10735:2;10730:3;10726:12;10719:19;;10759:5;10754:3;10747:18;10803:2;10798:3;10788:18;10824:3;10836:304;10850:6;10847:1;10844:13;10836:304;;;10916:13;;-1:-1:-1;;;;;10954:50:1;;10942:63;;11043:3;11039:19;11025:12;;;11018:41;11088:4;11079:14;;;;11128:1;11116:14;;;;10865:9;10836:304;;11170:443;;11267:5;11261:12;11294:6;11289:3;11282:19;11320:4;11349:2;11344:3;11340:12;11333:19;;11386:2;11379:5;11375:14;11407:3;11419:169;11433:6;11430:1;11427:13;11419:169;;;11494:13;;11482:26;;11528:12;;;;11563:15;;;;11455:1;11448:9;11419:169;;11618:452;;11713:5;11707:12;11740:6;11735:3;11728:19;11766:4;11795:2;11790:3;11786:12;11779:19;;11832:2;11825:5;11821:14;11853:3;11865:180;11879:6;11876:1;11873:13;11865:180;;;11944:13;;11959:4;11940:24;11928:37;;11985:12;;;;12020:15;;;;11901:1;11894:9;11865:180;;12075:243;12162:1;12155:5;12152:12;12142:2;;12207:10;12202:3;12198:20;12195:1;12188:31;12242:4;12239:1;12232:15;12270:4;12267:1;12260:15;12142:2;12294:18;;12132:186::o;12323:225::-;12459:12;;-1:-1:-1;;;;;12455:21:1;;;12443:34;;12530:4;12519:16;;;12513:23;12509:32;12493:14;;12486:56;12380:168::o;12553:408::-;12651:1;12647;12642:3;12638:11;12634:19;12692:2;12684:5;12678:12;12674:21;12669:3;12662:34;12757:2;12749:4;12742:5;12738:16;12732:23;12728:32;12721:4;12716:3;12712:14;12705:56;;12824:4;12817:5;12813:16;12807:23;12800:31;12793:39;12786:4;12781:3;12777:14;12770:63;12879:4;12872:5;12868:16;12862:23;12894:61;12949:4;12944:3;12940:14;12926:12;12894:61;:::i;:::-;;12614:347;;:::o;12966:424::-;13072:1;13068;13063:3;13059:11;13055:19;13113:2;13105:5;13099:12;13095:21;13090:3;13083:34;13160:4;13153:5;13149:16;13143:23;13213:2;13202:9;13198:18;13191:4;13186:3;13182:14;13175:42;13288:4;13276:9;13271:3;13267:19;13263:30;13256:38;13249:46;13242:4;13237:3;13233:14;13226:70;13305:79;13378:4;13373:3;13369:14;13362:4;13350:9;13345:3;13341:19;13337:30;13305:79;:::i;13395:225::-;13485:5;13479:12;13474:3;13467:25;13538:4;13531:5;13527:16;13521:23;13553:61;13608:4;13603:3;13599:14;13585:12;13553:61;:::i;13625:203::-;-1:-1:-1;;;;;13789:32:1;;;;13771:51;;13759:2;13744:18;;13726:102::o;13833:495::-;-1:-1:-1;;;;;14127:15:1;;;14109:34;;14179:15;;14174:2;14159:18;;14152:43;14238:14;;14231:22;14226:2;14211:18;;14204:50;14058:3;14043:19;;14263:59;14318:2;14303:18;;14295:6;14263:59;:::i;14333:528::-;-1:-1:-1;;;;;14648:15:1;;;14630:34;;14700:15;;;14695:2;14680:18;;14673:43;14747:2;14732:18;;14725:34;;;;14790:2;14775:18;;14768:34;14839:15;;;14833:3;14818:19;;14811:44;14579:3;14564:19;;14546:315::o;14866:447::-;-1:-1:-1;;;;;15153:15:1;;;15135:34;;15200:2;15185:18;;15178:34;;;;15248:15;;15243:2;15228:18;;15221:43;15295:2;15280:18;;15273:34;;;;15084:3;15069:19;;15051:262::o;15318:519::-;-1:-1:-1;;;;;15633:15:1;;;15615:34;;15680:2;15665:18;;15658:34;;;;15728:15;;;;15723:2;15708:18;;15701:43;15775:2;15760:18;;15753:34;;;;15818:3;15803:19;;15796:35;;;;15564:3;15549:19;;15531:306::o;15842:647::-;;16184:1;16180;16175:3;16171:11;16167:19;16159:6;16155:32;16144:9;16137:51;16224:6;16219:2;16208:9;16204:18;16197:34;16267:3;16262:2;16251:9;16247:18;16240:31;16294:63;16352:3;16341:9;16337:19;16329:6;16294:63;:::i;:::-;16405:9;16397:6;16393:22;16388:2;16377:9;16373:18;16366:50;16433;16476:6;16468;16433:50;:::i;16494:719::-;;16864:1;16860;16855:3;16851:11;16847:19;16839:6;16835:32;16824:9;16817:51;16904:6;16899:2;16888:9;16884:18;16877:34;16947:3;16942:2;16931:9;16927:18;16920:31;16974:63;17032:3;17021:9;17017:19;17009:6;16974:63;:::i;:::-;17085:9;17077:6;17073:22;17068:2;17057:9;17053:18;17046:50;17113;17156:6;17148;17113:50;:::i;:::-;17105:58;;;17200:6;17194:3;17183:9;17179:19;17172:35;16807:406;;;;;;;;:::o;17218:909::-;;17691:3;17680:9;17673:22;17718:74;17787:3;17776:9;17772:19;17764:6;17718:74;:::i;:::-;17840:9;17832:6;17828:22;17823:2;17812:9;17808:18;17801:50;17874:48;17915:6;17907;17874:48;:::i;:::-;17860:62;;17970:9;17962:6;17958:22;17953:2;17942:9;17938:18;17931:50;17998;18041:6;18033;17998:50;:::i;:::-;17990:58;;;18057:64;18117:2;18106:9;18102:18;18094:6;18057:64;:::i;18132:644::-;;18505:3;18494:9;18487:22;18526:74;18595:3;18584:9;18580:19;18572:6;18526:74;:::i;:::-;18518:82;;18648:4;18640:6;18636:17;18631:2;18620:9;18616:18;18609:45;18690:6;18685:2;18674:9;18670:18;18663:34;18706:64;18766:2;18755:9;18751:18;18743:6;18706:64;:::i;18781:815::-;;19198:3;19228:2;19217:9;19210:21;19248:73;19317:2;19306:9;19302:18;19294:6;19248:73;:::i;:::-;19240:81;;;19369:4;19361:6;19357:17;19352:2;19341:9;19337:18;19330:45;19423:4;19415:6;19411:17;19406:2;19395:9;19391:18;19384:45;19465:6;19460:2;19449:9;19445:18;19438:34;19509:6;19503:3;19492:9;19488:19;19481:35;19525:65;19585:3;19574:9;19570:19;19562:6;19525:65;:::i;19601:1142::-;;20078:3;20067:9;20060:22;20105:90;20190:3;20179:9;20175:19;20167:6;20105:90;:::i;:::-;20243:9;20235:6;20231:22;20226:2;20215:9;20211:18;20204:50;20277:48;20318:6;20310;20277:48;:::i;:::-;20361:22;;;20356:2;20341:18;;20334:50;20393:22;;;20263:62;-1:-1:-1;;;;;;20427:31:1;;20424:2;;;20474:4;20468;20461:18;20424:2;20516;20508:6;20504:15;20566:6;20558;20553:2;20545:6;20541:15;20528:45;20596:19;20617:2;20592:28;20629:16;;;20673:64;20733:2;20718:18;;20710:6;20673:64;:::i;:::-;20050:693;;;;;;;;:::o;20748:654::-;;21115:3;21104:9;21097:22;21136:90;21221:3;21210:9;21206:19;21198:6;21136:90;:::i;21407:969::-;21787:2;21799:21;;;21869:13;;21772:18;;;21891:22;;;21407:969;;21966:4;;21944:2;21929:18;;;21993:15;;;21407:969;22039:200;22053:6;22050:1;22047:13;22039:200;;;22102:55;22153:3;22144:6;22138:13;22102:55;:::i;:::-;22186:4;22177:14;;;;;22214:15;;;;22075:1;22068:9;22039:200;;;22043:3;;;22284:9;22279:3;22275:19;22270:2;22259:9;22255:18;22248:47;22312:58;22366:3;22358:6;22312:58;:::i;22381:1153::-;22851:3;22864:22;;;22935:13;;22836:19;;;22957:22;;;22381:1153;23023:20;;;23082:4;23066:21;;22381:1153;;23010:3;22995:19;;;22381:1153;23118:203;23132:6;23129:1;23126:13;23118:203;;;23181:56;23233:3;23225:6;23181:56;:::i;:::-;23306:4;23294:17;;;;;23266:4;23257:14;;;;;23154:1;23147:9;23118:203;;;-1:-1:-1;;23372:4:1;23357:20;;23350:36;;;-1:-1:-1;;;;;23422:32:1;;23417:2;23402:18;;23395:60;23338:3;-1:-1:-1;23464:64:1;;-1:-1:-1;23524:2:1;23509:18;;23501:6;23464:64;:::i;23539:507::-;23844:25;;;23900:2;23885:18;;23878:34;;;;-1:-1:-1;;;;;23948:32:1;23943:2;23928:18;;23921:60;24024:14;24017:22;24012:2;23997:18;;23990:50;23831:3;23816:19;;23798:248::o;24051:1032::-;24428:25;;;24472:2;24490:18;;;24483:34;;;24415:3;24548:2;24533:18;;24526:31;;;24400:19;;24592:22;;;24051:1032;;24672:6;;24645:3;24630:19;;24051:1032;24709:279;24723:6;24720:1;24717:13;24709:279;;;24798:6;24785:20;24818:33;24845:5;24818:33;:::i;:::-;-1:-1:-1;;;;;24876:31:1;24864:44;;24963:15;;;;24928:12;;;;24904:1;24738:9;24709:279;;;-1:-1:-1;;;;;;25044:32:1;;;;25039:2;25024:18;;;;25017:60;;;;-1:-1:-1;25005:3:1;;24376:707;-1:-1:-1;;;;;;24376:707:1:o;25088:267::-;;25267:2;25256:9;25249:21;25287:62;25345:2;25334:9;25330:18;25322:6;25287:62;:::i;25360:187::-;25525:14;;25518:22;25500:41;;25488:2;25473:18;;25455:92::o;25552:268::-;25739:14;;25732:22;25714:41;;25798:14;25791:22;25786:2;25771:18;;25764:50;25702:2;25687:18;;25669:151::o;25825:177::-;25971:25;;;25959:2;25944:18;;25926:76::o;26464:603::-;;26605:2;26634;26623:9;26616:21;26666:6;26660:13;26709:6;26704:2;26693:9;26689:18;26682:34;26734:4;26747:140;26761:6;26758:1;26755:13;26747:140;;;26856:14;;;26852:23;;26846:30;26822:17;;;26841:2;26818:26;26811:66;26776:10;;26747:140;;;26905:6;26902:1;26899:13;26896:2;;;26975:4;26970:2;26961:6;26950:9;26946:22;26942:31;26935:45;26896:2;-1:-1:-1;27051:2:1;27030:15;-1:-1:-1;;27026:29:1;27011:45;;;;27058:2;27007:54;;26585:482;-1:-1:-1;;;26585:482:1:o;27072:339::-;27274:2;27256:21;;;27313:2;27293:18;;;27286:30;-1:-1:-1;;;27347:2:1;27332:18;;27325:45;27402:2;27387:18;;27246:165::o;27416:399::-;27618:2;27600:21;;;27657:2;27637:18;;;27630:30;27696:34;27691:2;27676:18;;27669:62;-1:-1:-1;;;27762:2:1;27747:18;;27740:33;27805:3;27790:19;;27590:225::o;27820:337::-;28022:2;28004:21;;;28061:2;28041:18;;;28034:30;-1:-1:-1;;;28095:2:1;28080:18;;28073:43;28148:2;28133:18;;27994:163::o;28162:337::-;28364:2;28346:21;;;28403:2;28383:18;;;28376:30;-1:-1:-1;;;28437:2:1;28422:18;;28415:43;28490:2;28475:18;;28336:163::o;28504:336::-;28706:2;28688:21;;;28745:2;28725:18;;;28718:30;-1:-1:-1;;;28779:2:1;28764:18;;28757:42;28831:2;28816:18;;28678:162::o;28845:398::-;29047:2;29029:21;;;29086:2;29066:18;;;29059:30;29125:34;29120:2;29105:18;;29098:62;-1:-1:-1;;;29191:2:1;29176:18;;29169:32;29233:3;29218:19;;29019:224::o;29248:347::-;29450:2;29432:21;;;29489:2;29469:18;;;29462:30;29528:25;29523:2;29508:18;;29501:53;29586:2;29571:18;;29422:173::o;29600:331::-;29802:2;29784:21;;;29841:1;29821:18;;;29814:29;-1:-1:-1;;;29874:2:1;29859:18;;29852:38;29922:2;29907:18;;29774:157::o;29936:344::-;30138:2;30120:21;;;30177:2;30157:18;;;30150:30;-1:-1:-1;;;30211:2:1;30196:18;;30189:50;30271:2;30256:18;;30110:170::o;30285:344::-;30487:2;30469:21;;;30526:2;30506:18;;;30499:30;-1:-1:-1;;;30560:2:1;30545:18;;30538:50;30620:2;30605:18;;30459:170::o;30634:403::-;30836:2;30818:21;;;30875:2;30855:18;;;30848:30;30914:34;30909:2;30894:18;;30887:62;-1:-1:-1;;;30980:2:1;30965:18;;30958:37;31027:3;31012:19;;30808:229::o;31042:336::-;31244:2;31226:21;;;31283:2;31263:18;;;31256:30;-1:-1:-1;;;31317:2:1;31302:18;;31295:42;31369:2;31354:18;;31216:162::o;31383:348::-;31585:2;31567:21;;;31624:2;31604:18;;;31597:30;31663:26;31658:2;31643:18;;31636:54;31722:2;31707:18;;31557:174::o;31736:347::-;31938:2;31920:21;;;31977:2;31957:18;;;31950:30;32016:25;32011:2;31996:18;;31989:53;32074:2;32059:18;;31910:173::o;32088:343::-;32290:2;32272:21;;;32329:2;32309:18;;;32302:30;-1:-1:-1;;;32363:2:1;32348:18;;32341:49;32422:2;32407:18;;32262:169::o;32436:349::-;32638:2;32620:21;;;32677:2;32657:18;;;32650:30;32716:27;32711:2;32696:18;;32689:55;32776:2;32761:18;;32610:175::o;32790:343::-;32992:2;32974:21;;;33031:2;33011:18;;;33004:30;-1:-1:-1;;;33065:2:1;33050:18;;33043:49;33124:2;33109:18;;32964:169::o;33138:338::-;33340:2;33322:21;;;33379:2;33359:18;;;33352:30;-1:-1:-1;;;33413:2:1;33398:18;;33391:44;33467:2;33452:18;;33312:164::o;33481:332::-;33683:2;33665:21;;;33722:1;33702:18;;;33695:29;-1:-1:-1;;;33755:2:1;33740:18;;33733:39;33804:2;33789:18;;33655:158::o;33818:346::-;34020:2;34002:21;;;34059:2;34039:18;;;34032:30;-1:-1:-1;;;34093:2:1;34078:18;;34071:52;34155:2;34140:18;;33992:172::o;34169:338::-;34371:2;34353:21;;;34410:2;34390:18;;;34383:30;-1:-1:-1;;;34444:2:1;34429:18;;34422:44;34498:2;34483:18;;34343:164::o;34512:335::-;34714:2;34696:21;;;34753:2;34733:18;;;34726:30;-1:-1:-1;;;34787:2:1;34772:18;;34765:41;34838:2;34823:18;;34686:161::o;34852:341::-;35054:2;35036:21;;;35093:2;35073:18;;;35066:30;-1:-1:-1;;;35127:2:1;35112:18;;35105:47;35184:2;35169:18;;35026:167::o;35198:345::-;35400:2;35382:21;;;35439:2;35419:18;;;35412:30;-1:-1:-1;;;35473:2:1;35458:18;;35451:51;35534:2;35519:18;;35372:171::o;35548:344::-;35750:2;35732:21;;;35789:2;35769:18;;;35762:30;-1:-1:-1;;;35823:2:1;35808:18;;35801:50;35883:2;35868:18;;35722:170::o;35897:397::-;36099:2;36081:21;;;36138:2;36118:18;;;36111:30;36177:34;36172:2;36157:18;;36150:62;-1:-1:-1;;;36243:2:1;36228:18;;36221:31;36284:3;36269:19;;36071:223::o;36299:339::-;36501:2;36483:21;;;36540:2;36520:18;;;36513:30;-1:-1:-1;;;36574:2:1;36559:18;;36552:45;36629:2;36614:18;;36473:165::o;36643:401::-;36845:2;36827:21;;;36884:2;36864:18;;;36857:30;36923:34;36918:2;36903:18;;36896:62;-1:-1:-1;;;36989:2:1;36974:18;;36967:35;37034:3;37019:19;;36817:227::o;37049:338::-;37251:2;37233:21;;;37290:2;37270:18;;;37263:30;-1:-1:-1;;;37324:2:1;37309:18;;37302:44;37378:2;37363:18;;37223:164::o;37392:400::-;37594:2;37576:21;;;37633:2;37613:18;;;37606:30;37672:34;37667:2;37652:18;;37645:62;-1:-1:-1;;;37738:2:1;37723:18;;37716:34;37782:3;37767:19;;37566:226::o;37797:329::-;37999:2;37981:21;;;38038:1;38018:18;;;38011:29;-1:-1:-1;;;38071:2:1;38056:18;;38049:36;38117:2;38102:18;;37971:155::o;38131:355::-;38333:2;38315:21;;;38372:2;38352:18;;;38345:30;38411:33;38406:2;38391:18;;38384:61;38477:2;38462:18;;38305:181::o;38491:344::-;38693:2;38675:21;;;38732:2;38712:18;;;38705:30;-1:-1:-1;;;38766:2:1;38751:18;;38744:50;38826:2;38811:18;;38665:170::o;38840:348::-;39042:2;39024:21;;;39081:2;39061:18;;;39054:30;39120:26;39115:2;39100:18;;39093:54;39179:2;39164:18;;39014:174::o;39193:356::-;39395:2;39377:21;;;39414:18;;;39407:30;39473:34;39468:2;39453:18;;39446:62;39540:2;39525:18;;39367:182::o;39554:355::-;39756:2;39738:21;;;39795:2;39775:18;;;39768:30;39834:33;39829:2;39814:18;;39807:61;39900:2;39885:18;;39728:181::o;39914:276::-;40116:25;;;40172:2;40157:18;;40150:34;40104:2;40089:18;;40071:119::o;40195:491::-;40482:25;;;40538:2;40523:18;;40516:34;;;;40581:2;40566:18;;40559:34;;;;40624:2;40609:18;;40602:34;40667:3;40652:19;;40645:35;40469:3;40454:19;;40436:250::o;40691:521::-;41026:25;;;41082:2;41067:18;;41060:34;;;;41125:2;41110:18;;41103:34;-1:-1:-1;;;;;41173:32:1;41168:2;41153:18;;41146:60;41013:3;40998:19;;40980:232::o;41217:603::-;41574:25;;;41630:2;41615:18;;41608:34;;;;41673:2;41658:18;;41651:34;;;;-1:-1:-1;;;;;41721:32:1;41716:2;41701:18;;41694:60;41798:14;41791:22;41785:3;41770:19;;41763:51;41561:3;41546:19;;41528:292::o;41825:416::-;42099:3;42084:19;;42112:54;42088:9;42148:6;42112:54;:::i;:::-;42175:60;42230:3;42219:9;42215:19;42207:6;42175:60;:::i;42246:532::-;42532:3;42517:19;;42545:54;42521:9;42581:6;42545:54;:::i;:::-;-1:-1:-1;;;;;42640:6:1;42636:47;42630:3;42619:9;42615:19;42608:76;42721:6;42715:3;42704:9;42700:19;42693:35;42765:6;42759:3;42748:9;42744:19;42737:35;42499:279;;;;;;;:::o;42783:269::-;42979:2;42964:18;;42991:55;42968:9;43028:6;42991:55;:::i;43057:319::-;-1:-1:-1;;;;;43302:15:1;;;43284:34;;43354:15;;43349:2;43334:18;;43327:43;43219:2;43204:18;;43186:190::o;43563:665::-;43942:25;;;43929:3;43914:19;;43976:63;44035:2;44020:18;;44012:6;43976:63;:::i;:::-;44048:60;44103:3;44092:9;44088:19;44080:6;44048:60;:::i;:::-;-1:-1:-1;;;;;44145:32:1;;;;44139:3;44124:19;;44117:61;44209:3;44194:19;44187:35;43896:332;;-1:-1:-1;;;43896:332:1:o;44233:670::-;44609:25;;;44596:3;44581:19;;44643:71;44710:2;44695:18;;44687:6;44643:71;:::i;45161:456::-;-1:-1:-1;;;;;45439:15:1;;;45421:34;;45491:15;;;45486:2;45471:18;;45464:43;45543:15;;;45538:2;45523:18;;45516:43;45595:15;;;45590:2;45575:18;;45568:43;45371:3;45356:19;;45338:279::o;45622:184::-;45794:4;45782:17;;;;45764:36;;45752:2;45737:18;;45719:87::o;45811:253::-;;-1:-1:-1;;;;;45940:2:1;45937:1;45933:10;45970:2;45967:1;45963:10;46001:3;45997:2;45993:12;45988:3;45985:21;45982:2;;;46009:18;;:::i;:::-;46045:13;;45859:205;-1:-1:-1;;;;45859:205:1:o;46069:128::-;;46140:1;46136:6;46133:1;46130:13;46127:2;;;46146:18;;:::i;:::-;-1:-1:-1;46182:9:1;;46117:80::o;46202:217::-;;46268:1;46258:2;;-1:-1:-1;;;46293:31:1;;46347:4;46344:1;46337:15;46375:4;46300:1;46365:15;46258:2;-1:-1:-1;46404:9:1;;46248:171::o;46424:168::-;;46530:1;46526;46522:6;46518:14;46515:1;46512:21;46507:1;46500:9;46493:17;46489:45;46486:2;;;46537:18;;:::i;:::-;-1:-1:-1;46577:9:1;;46476:116::o;46597:246::-;;-1:-1:-1;;;;;46750:10:1;;;;46720;;46772:12;;;46769:2;;;46787:18;;:::i;:::-;46824:13;;46646:197;-1:-1:-1;;;46646:197:1:o;46848:125::-;;46916:1;46913;46910:8;46907:2;;;46921:18;;:::i;:::-;-1:-1:-1;46958:9:1;;46897:76::o;46978:229::-;;-1:-1:-1;;;;;47114:10:1;;;;47084;;47136:12;;;47133:2;;;47151:18;;:::i;47212:380::-;47297:1;47287:12;;47344:1;47334:12;;;47355:2;;47409:4;47401:6;47397:17;47387:27;;47355:2;47462;47454:6;47451:14;47431:18;47428:38;47425:2;;;47508:10;47503:3;47499:20;47496:1;47489:31;47543:4;47540:1;47533:15;47571:4;47568:1;47561:15;47425:2;;47267:325;;;:::o;47597:135::-;;-1:-1:-1;;47657:17:1;;47654:2;;;47677:18;;:::i;:::-;-1:-1:-1;47724:1:1;47713:13;;47644:88::o;47737:127::-;47798:10;47793:3;47789:20;47786:1;47779:31;47829:4;47826:1;47819:15;47853:4;47850:1;47843:15;47869:127;47930:10;47925:3;47921:20;47918:1;47911:31;47961:4;47958:1;47951:15;47985:4;47982:1;47975:15;48001:133;-1:-1:-1;;;;;48078:31:1;;48068:42;;48058:2;;48124:1;48121;48114:12
Swarm Source
ipfs://af3c4c0b4e5eb78b3bd030aeca63dd38ef79a65a2ef13e1484d268c12f499f77
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.