Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
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 Source Code Verified (Exact Match)
Contract Name:
FeederPool
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-07-11 */ pragma solidity 0.8.2; 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; } abstract contract IMasset { // 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); function getPrice() external view virtual returns (uint256 price, uint256 k); // 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 setFees(uint256 _swapFee, uint256 _redemptionFee) external virtual; function setTransferFeesFlag(address _bAsset, bool _flag) external virtual; function migrateBassets(address[] calldata _bAssets, address _newIntegration) external virtual; } // 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 FeederConfig { uint256 supply; uint256 a; WeightLimits limits; } struct InvariantConfig { uint256 supply; uint256 a; WeightLimits limits; uint256 recolFee; } struct BasicConfig { uint256 a; WeightLimits limits; } struct WeightLimits { uint128 min; uint128 max; } struct AmpData { uint64 initialA; uint64 targetA; uint64 rampStartTime; uint64 rampEndTime; } struct FeederData { uint256 swapFee; uint256 redemptionFee; uint256 govFee; uint256 pendingFees; uint256 cacheSize; BassetPersonal[] bAssetPersonal; BassetData[] bAssetData; AmpData ampData; WeightLimits weightLimits; } struct MassetData { uint256 swapFee; uint256 redemptionFee; uint256 cacheSize; uint256 surplus; BassetPersonal[] bAssetPersonal; BassetData[] bAssetData; BasketState basket; AmpData ampData; WeightLimits weightLimits; } struct AssetData { uint8 idx; uint256 amt; BassetPersonal personal; } struct Asset { uint8 idx; address addr; bool exists; } abstract contract IFeederPool { // 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 _fpTokenQuantity, uint256 _minOutputQuantity, address _recipient ) external virtual returns (uint256 outputQuantity); function redeemProportionately( uint256 _fpTokenQuantity, 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 _fpTokenQuantity) external view virtual returns (uint256 bAssetOutput); function getRedeemExactBassetsOutput( address[] calldata _outputs, uint256[] calldata _outputQuantities ) external view virtual returns (uint256 mAssetAmount); // Views function mAsset() external view virtual returns (address); function getPrice() public view virtual returns (uint256 price, uint256 k); function getConfig() external view virtual returns (FeederConfig memory config); 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); // SavingsManager function collectPlatformInterest() external virtual returns (uint256 mintAmount, uint256 newSupply); function collectPendingFees() external virtual; } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } abstract 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 protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } } /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. // constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return payable(msg.sender); } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } contract ERC205 is Context, IERC20 { mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } } abstract contract InitializableERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. * @notice To avoid variable shadowing appended `Arg` after arguments name. */ function _initialize( string memory nameArg, string memory symbolArg, uint8 decimalsArg ) internal { _name = nameArg; _symbol = symbolArg; _decimals = decimalsArg; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } abstract contract InitializableToken is ERC205, InitializableERC20Detailed { /** * @dev Initialization function for implementing contract * @notice To avoid variable shadowing appended `Arg` after arguments name. */ function _initialize(string memory _nameArg, string memory _symbolArg) internal { InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18); } } contract ModuleKeys { // Governance // =========== // keccak256("Governance"); bytes32 internal constant KEY_GOVERNANCE = 0x9409903de1e6fd852dfc61c9dacb48196c48535b60e25abf92acc92dd689078d; //keccak256("Staking"); bytes32 internal constant KEY_STAKING = 0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034; //keccak256("ProxyAdmin"); bytes32 internal constant KEY_PROXY_ADMIN = 0x96ed0203eb7e975a4cbcaa23951943fa35c5d8288117d50c12b3d48b0fab48d1; // mStable // ======= // keccak256("OracleHub"); bytes32 internal constant KEY_ORACLE_HUB = 0x8ae3a082c61a7379e2280f3356a5131507d9829d222d853bfa7c9fe1200dd040; // keccak256("Manager"); bytes32 internal constant KEY_MANAGER = 0x6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f; //keccak256("Recollateraliser"); bytes32 internal constant KEY_RECOLLATERALISER = 0x39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f; //keccak256("MetaToken"); bytes32 internal constant KEY_META_TOKEN = 0xea7469b14936af748ee93c53b2fe510b9928edbdccac3963321efca7eb1a57a2; // keccak256("SavingsManager"); bytes32 internal constant KEY_SAVINGS_MANAGER = 0x12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf1; // keccak256("Liquidator"); bytes32 internal constant KEY_LIQUIDATOR = 0x1e9cb14d7560734a61fa5ff9273953e971ff3cd9283c03d8346e3264617933d4; // keccak256("InterestValidator"); bytes32 internal constant KEY_INTEREST_VALIDATOR = 0xc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f; } 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 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 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); } /** * @dev Return Recollateraliser Module address from the Nexus * @return Address of the Recollateraliser Module contract (Phase 2) */ function _liquidator() internal view returns (address) { return nexus.getModule(KEY_LIQUIDATOR); } /** * @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); } } abstract contract PausableModule is ImmutableModule { /** * @dev Emitted when the pause is triggered by Governor */ event Paused(address account); /** * @dev Emitted when the pause is lifted by Governor */ event Unpaused(address account); bool internal _paused = false; /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Initializes the contract in unpaused state. * Hooks into the Module to give the Governor ability to pause * @param _nexus Nexus contract address */ constructor(address _nexus) ImmutableModule(_nexus) { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. * @return Returns `true` when paused, otherwise `false` */ function paused() external view returns (bool) { return _paused; } /** * @dev Called by the Governor to pause, triggers stopped state. */ function pause() external onlyGovernor whenNotPaused { _paused = true; emit Paused(msg.sender); } /** * @dev Called by Governor to unpause, returns to normal state. */ function unpause() external onlyGovernor whenPaused { _paused = false; emit Unpaused(msg.sender); } } 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; } } interface IBasicToken { function decimals() external view returns (uint8); } 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); } } /** * @dev Interface of the ERC20 standard as defined in the EIP. */ library SafeERC20 { using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } library 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 9e36 / 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); } library FeederManager { using SafeERC20 for IERC20; using StableMath for uint256; event BassetsMigrated(address[] bAssets, address newIntegrator); 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; /** * @dev Calculates the gains accrued across all lending markets. * @param _bAssetPersonal Basset personal storage array * @param _bAssetData Basset data storage array * @return idxs Array [0,1] * @return rawGains Raw increases in vault Balance */ function calculatePlatformInterest( BassetPersonal[] memory _bAssetPersonal, BassetData[] storage _bAssetData ) external returns (uint8[] memory idxs, uint256[] memory rawGains) { // Get basket details BassetData[] memory bAssetData_ = _bAssetData; uint256 count = bAssetData_.length; idxs = 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++) { idxs[i] = uint8(i); BassetPersonal memory bPersonal = _bAssetPersonal[i]; 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 == BassetStatus.Normal) { _bAssetData[i].vaultBalance = SafeCast.toUint128(balance); uint256 interestDelta = balance - oldVaultBalance; rawGains[i] = interestDelta; } else { rawGains[i] = 0; } } } /** * @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 _bAssets Array of basket assets to migrate * @param _newIntegration Address of the new platform integration */ function migrateBassets( BassetPersonal[] storage _bAssetPersonal, 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, bAsset); require(!_bAssetPersonal[index].hasTxFee, "A bAsset has a transfer fee"); // 2. Withdraw everything from the old platform integration address oldAddress = _bAssetPersonal[index].integrator; require(oldAddress != _newIntegration, "Must transfer to new integrator"); (uint256 cache, uint256 lendingBal) = (0, 0); if (oldAddress == address(0)) { cache = IERC20(bAsset).balanceOf(address(this)); } else { IPlatformIntegration oldIntegration = IPlatformIntegration(oldAddress); cache = IERC20(bAsset).balanceOf(address(oldIntegration)); // 2.1. Withdraw from the lending market lendingBal = oldIntegration.checkBalance(bAsset); if (lendingBal > 0) { oldIntegration.withdraw(address(this), bAsset, lendingBal, false); } // 2.2. Withdraw from the cache, if any if (cache > 0) { oldIntegration.withdrawRaw(address(this), bAsset, cache); } } uint256 sum = lendingBal + cache; // 3. Update the integration address for this bAsset _bAssetPersonal[index].integrator = _newIntegration; // 4. Deposit everything into the new // This should fail if we did not receive the full amount from the platform withdrawal // 4.1. Deposit all bAsset IERC20(bAsset).safeTransfer(_newIntegration, sum); IPlatformIntegration newIntegration = IPlatformIntegration(_newIntegration); if (lendingBal > 0) { newIntegration.deposit(bAsset, lendingBal, false); } // 4.2. Check balances uint256 newLendingBal = newIntegration.checkBalance(bAsset); uint256 newCache = IERC20(bAsset).balanceOf(address(newIntegration)); uint256 upperMargin = 10001e14; uint256 lowerMargin = 9999e14; require( newLendingBal >= lendingBal.mulTruncate(lowerMargin) && newLendingBal <= lendingBal.mulTruncate(upperMargin), "Must transfer full amount" ); require( newCache >= cache.mulTruncate(lowerMargin) && newCache <= cache.mulTruncate(upperMargin), "Must transfer full amount" ); } emit BassetsMigrated(_bAssets, _newIntegration); } /** * @dev Simply gets the asset index by looping through bAssets. Given there are only * ever 2 assets, should not be gas intensive. */ function _getAssetIndex(BassetPersonal[] storage _bAssetPersonal, address _asset) internal view returns (uint8 idx) { uint256 len = _bAssetPersonal.length; for (uint8 i = 0; i < len; i++) { if (_bAssetPersonal[i].addr == _asset) return i; } revert("Invalid asset"); } /** * @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( 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(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); } } library Root { /** * @dev Returns the square root of a given number * @param x Input * @return y Square root of Input */ function sqrt(uint256 x) internal pure returns (uint256 y) { if (x == 0) return 0; else { uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint256(r < r1 ? r : r1); } } } 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 FeederLogic { using StableMath for uint256; using SafeERC20 for IERC20; uint256 internal constant A_PRECISION = 100; /*************************************** MINT ****************************************/ /** * @notice Transfers token in, updates internal balances and computes the fpToken output * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _input Data on the bAsset to deposit for the minted fpToken. * @param _inputQuantity Quantity in input token units. * @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage. * @return mintOutput Quantity of fpToken minted from the deposited bAsset. */ function mint( FeederData storage _data, FeederConfig calldata _config, Asset calldata _input, uint256 _inputQuantity, uint256 _minOutputQuantity ) external returns (uint256 mintOutput) { BassetData[] memory cachedBassetData = _data.bAssetData; AssetData memory inputData = _transferIn(_data, _config, cachedBassetData, _input, _inputQuantity); // Validation should be after token transfer, as real input amt is unknown before mintOutput = computeMint(cachedBassetData, inputData.idx, inputData.amt, _config); require(mintOutput >= _minOutputQuantity, "Mint quantity < min qty"); } /** * @notice Transfers tokens in, updates internal balances and computes the fpToken output. * Only fAsset & mAsset are supported in this path. * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _indices Non-duplicate addresses of the bAssets to deposit for the minted fpToken. * @param _inputQuantities Quantity of each input in input token units. * @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage. * @return mintOutput Quantity of fpToken minted from the deposited bAsset. */ function mintMulti( FeederData storage _data, FeederConfig calldata _config, uint8[] calldata _indices, uint256[] calldata _inputQuantities, uint256 _minOutputQuantity ) external returns (uint256 mintOutput) { uint256 len = _indices.length; uint256[] memory quantitiesDeposited = new uint256[](len); // Load bAssets from storage into memory BassetData[] memory allBassets = _data.bAssetData; uint256 maxCache = _getCacheDetails(_data, _config.supply); // Transfer the Bassets to the integrator & update storage for (uint256 i = 0; i < len; i++) { if (_inputQuantities[i] > 0) { uint8 idx = _indices[i]; BassetData memory bData = allBassets[idx]; quantitiesDeposited[i] = _depositTokens( _data.bAssetPersonal[idx], bData.ratio, _inputQuantities[i], maxCache ); _data.bAssetData[idx].vaultBalance = bData.vaultBalance + SafeCast.toUint128(quantitiesDeposited[i]); } } // Validate the proposed mint, after token transfer mintOutput = computeMintMulti(allBassets, _indices, quantitiesDeposited, _config); require(mintOutput >= _minOutputQuantity, "Mint quantity < min qty"); require(mintOutput > 0, "Zero mAsset quantity"); } /*************************************** SWAP ****************************************/ /** * @notice Swaps two assets - either internally between fAsset<>mAsset, or between fAsset<>mpAsset by * first routing through the mAsset pool. * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _input Data on bAsset to deposit * @param _output Data on bAsset to withdraw * @param _inputQuantity Units of input bAsset to swap in * @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 * @return localFee Fee paid, in fpToken terms */ function swap( FeederData storage _data, FeederConfig calldata _config, Asset calldata _input, Asset calldata _output, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external returns (uint256 swapOutput, uint256 localFee) { BassetData[] memory cachedBassetData = _data.bAssetData; AssetData memory inputData = _transferIn(_data, _config, cachedBassetData, _input, _inputQuantity); // 1. [f/mAsset ->][ f/mAsset] : Y - normal in, SWAP, normal out // 3. [mpAsset -> mAsset][ -> fAsset] : Y - mint in , SWAP, normal out if (_output.exists) { (swapOutput, localFee) = _swapLocal( _data, _config, cachedBassetData, inputData, _output, _minOutputQuantity, _recipient ); } // 2. [fAsset ->][ mAsset][ -> mpAsset] : Y - normal in, SWAP, mpOut else { address mAsset = _data.bAssetPersonal[0].addr; (swapOutput, localFee) = _swapLocal( _data, _config, cachedBassetData, inputData, Asset(0, mAsset, true), 0, address(this) ); swapOutput = IMasset(mAsset).redeem( _output.addr, swapOutput, _minOutputQuantity, _recipient ); } } /*************************************** REDEEM ****************************************/ /** * @notice Burns a specified quantity of the senders fpToken in return for a bAsset. The output amount is derived * from the invariant. Supports redemption into either the fAsset, mAsset or assets in the mAsset basket. * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _output Data on bAsset to withdraw * @param _fpTokenQuantity Quantity of fpToken to burn * @param _minOutputQuantity Minimum bAsset quantity to receive for the burnt fpToken. This protects against slippage. * @param _recipient Address to transfer the withdrawn bAssets to. * @return outputQuantity Quanity of bAsset units received for the burnt fpToken * @return localFee Fee paid, in fpToken terms */ function redeem( FeederData storage _data, FeederConfig calldata _config, Asset calldata _output, uint256 _fpTokenQuantity, uint256 _minOutputQuantity, address _recipient ) external returns (uint256 outputQuantity, uint256 localFee) { if (_output.exists) { (outputQuantity, localFee) = _redeemLocal( _data, _config, _output, _fpTokenQuantity, _minOutputQuantity, _recipient ); } else { address mAsset = _data.bAssetPersonal[0].addr; (outputQuantity, localFee) = _redeemLocal( _data, _config, Asset(0, mAsset, true), _fpTokenQuantity, 0, address(this) ); outputQuantity = IMasset(mAsset).redeem( _output.addr, outputQuantity, _minOutputQuantity, _recipient ); } } /** * @dev Credits a recipient with a proportionate amount of bAssets, relative to current vault * balance levels and desired fpToken quantity. Burns the fpToken as payment. Only fAsset & mAsset are supported in this path. * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _inputQuantity Quantity of fpToken to redeem * @param _minOutputQuantities Min units of output to receive * @param _recipient Address to credit the withdrawn bAssets * @return scaledFee Fee collected in fpToken terms * @return outputs Array of output asset addresses * @return outputQuantities Array of output asset quantities */ function redeemProportionately( FeederData storage _data, FeederConfig calldata _config, uint256 _inputQuantity, uint256[] calldata _minOutputQuantities, address _recipient ) external returns ( uint256 scaledFee, address[] memory outputs, uint256[] memory outputQuantities ) { // Calculate mAsset redemption quantities scaledFee = _inputQuantity.mulTruncate(_data.redemptionFee); // cache = (config.supply - inputQuantity) * 0.2 uint256 maxCache = _getCacheDetails(_data, _config.supply - _inputQuantity); // Load the bAsset data from storage into memory BassetData[] memory allBassets = _data.bAssetData; uint256 len = allBassets.length; outputs = new address[](len); outputQuantities = new uint256[](len); for (uint256 i = 0; i < len; i++) { // Get amount out, proportionate to redemption quantity uint256 amountOut = (allBassets[i].vaultBalance * (_inputQuantity - scaledFee)) / _config.supply; require(amountOut > 1, "Output == 0"); amountOut -= 1; require(amountOut >= _minOutputQuantities[i], "bAsset qty < min qty"); // Set output in array (outputQuantities[i], outputs[i]) = (amountOut, _data.bAssetPersonal[i].addr); // Transfer the bAsset to the recipient _withdrawTokens( amountOut, _data.bAssetPersonal[i], allBassets[i], _recipient, maxCache ); // Reduce vaultBalance _data.bAssetData[i].vaultBalance = allBassets[i].vaultBalance - SafeCast.toUint128(amountOut); } } /** * @dev Credits a recipient with a certain quantity of selected bAssets, in exchange for burning the * relative fpToken quantity from the sender. Only fAsset & mAsset (0,1) are supported in this path. * @param _data Feeder pool storage state * @param _config Core config for use in the invariant validator * @param _indices Indices of the bAssets to receive * @param _outputQuantities Units of the bAssets to receive * @param _maxInputQuantity Maximum fpToken quantity to burn for the received bAssets. This protects against slippage. * @param _recipient Address to receive the withdrawn bAssets * @return fpTokenQuantity Quantity of fpToken units to burn as payment * @return localFee Fee collected, in fpToken terms */ function redeemExactBassets( FeederData storage _data, FeederConfig memory _config, uint8[] calldata _indices, uint256[] calldata _outputQuantities, uint256 _maxInputQuantity, address _recipient ) external returns (uint256 fpTokenQuantity, uint256 localFee) { // Load bAsset data from storage to memory BassetData[] memory allBassets = _data.bAssetData; // Validate redemption uint256 fpTokenRequired = computeRedeemExact(allBassets, _indices, _outputQuantities, _config); fpTokenQuantity = fpTokenRequired.divPrecisely(1e18 - _data.redemptionFee); localFee = fpTokenQuantity - fpTokenRequired; require(fpTokenQuantity > 0, "Must redeem some mAssets"); fpTokenQuantity += 1; require(fpTokenQuantity <= _maxInputQuantity, "Redeem mAsset qty > max quantity"); // Burn the full amount of Masset uint256 maxCache = _getCacheDetails(_data, _config.supply - fpTokenQuantity); // Transfer the Bassets to the recipient for (uint256 i = 0; i < _outputQuantities.length; i++) { _withdrawTokens( _outputQuantities[i], _data.bAssetPersonal[_indices[i]], allBassets[_indices[i]], _recipient, maxCache ); _data.bAssetData[_indices[i]].vaultBalance = allBassets[_indices[i]].vaultBalance - SafeCast.toUint128(_outputQuantities[i]); } } /*************************************** FORGING - INTERNAL ****************************************/ /** * @dev Transfers an asset in and updates vault balance. Supports fAsset, mAsset and mpAsset. * Transferring an mpAsset requires first a mint in the main pool, and consequent depositing of * the mAsset. */ function _transferIn( FeederData storage _data, FeederConfig memory _config, BassetData[] memory _cachedBassetData, Asset memory _input, uint256 _inputQuantity ) internal returns (AssetData memory inputData) { // fAsset / mAsset transfers if (_input.exists) { BassetPersonal memory personal = _data.bAssetPersonal[_input.idx]; uint256 amt = _depositTokens( personal, _cachedBassetData[_input.idx].ratio, _inputQuantity, _getCacheDetails(_data, _config.supply) ); inputData = AssetData(_input.idx, amt, personal); } // mpAsset transfers else { inputData = _mpMint( _data, _input, _inputQuantity, _getCacheDetails(_data, _config.supply) ); require(inputData.amt > 0, "Must mint something from mp"); } _data.bAssetData[inputData.idx].vaultBalance = _cachedBassetData[inputData.idx].vaultBalance + SafeCast.toUint128(inputData.amt); } /** * @dev Mints an asset in the main mAsset pool. Input asset must be supported by the mAsset * or else the call will revert. After minting, check if the balance exceeds the cache upper limit * and consequently deposit if necessary. */ function _mpMint( FeederData storage _data, Asset memory _input, uint256 _inputQuantity, uint256 _maxCache ) internal returns (AssetData memory mAssetData) { mAssetData = AssetData(0, 0, _data.bAssetPersonal[0]); IERC20(_input.addr).safeTransferFrom(msg.sender, address(this), _inputQuantity); address integrator = mAssetData.personal.integrator == address(0) ? address(this) : mAssetData.personal.integrator; uint256 balBefore = IERC20(mAssetData.personal.addr).balanceOf(integrator); // Mint will revert if the _input.addr is not whitelisted on that mAsset IMasset(mAssetData.personal.addr).mint(_input.addr, _inputQuantity, 0, integrator); uint256 balAfter = IERC20(mAssetData.personal.addr).balanceOf(integrator); mAssetData.amt = balAfter - balBefore; // Route the mAsset to platform integration if (integrator != address(this)) { if (balAfter > _maxCache) { uint256 delta = balAfter - (_maxCache / 2); IPlatformIntegration(integrator).deposit(mAssetData.personal.addr, delta, false); } } } /** * @dev Performs a swap between fAsset and mAsset. If the output is an mAsset, do not * charge the swap fee. */ function _swapLocal( FeederData storage _data, FeederConfig memory _config, BassetData[] memory _cachedBassetData, AssetData memory _inputData, Asset memory _output, uint256 _minOutputQuantity, address _recipient ) internal returns (uint256 swapOutput, uint256 scaledFee) { // Validate the swap (swapOutput, scaledFee) = computeSwap( _cachedBassetData, _inputData.idx, _output.idx, _inputData.amt, _output.idx == 0 ? 0 : _data.swapFee, _config ); require(swapOutput >= _minOutputQuantity, "Output qty < minimum qty"); require(swapOutput > 0, "Zero output quantity"); // Settle the swap _withdrawTokens( swapOutput, _data.bAssetPersonal[_output.idx], _cachedBassetData[_output.idx], _recipient, _getCacheDetails(_data, _config.supply) ); // Decrease output bal _data.bAssetData[_output.idx].vaultBalance = _cachedBassetData[_output.idx].vaultBalance - SafeCast.toUint128(swapOutput); } /** * @dev Performs a local redemption into either fAsset or mAsset. */ function _redeemLocal( FeederData storage _data, FeederConfig memory _config, Asset memory _output, uint256 _fpTokenQuantity, uint256 _minOutputQuantity, address _recipient ) internal returns (uint256 outputQuantity, uint256 scaledFee) { BassetData[] memory allBassets = _data.bAssetData; // Subtract the redemption fee scaledFee = _fpTokenQuantity.mulTruncate(_data.redemptionFee); // Calculate redemption quantities outputQuantity = computeRedeem( allBassets, _output.idx, _fpTokenQuantity - scaledFee, _config ); require(outputQuantity >= _minOutputQuantity, "bAsset qty < min qty"); require(outputQuantity > 0, "Output == 0"); // Transfer the bAssets to the recipient _withdrawTokens( outputQuantity, _data.bAssetPersonal[_output.idx], allBassets[_output.idx], _recipient, _getCacheDetails(_data, _config.supply - _fpTokenQuantity) ); // Set vault balance _data.bAssetData[_output.idx].vaultBalance = allBassets[_output.idx].vaultBalance - SafeCast.toUint128(outputQuantity); } /** * @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( BassetPersonal memory _bAsset, uint256 _bAssetRatio, uint256 _quantity, uint256 _maxCache ) internal 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, BassetPersonal memory _personal, BassetData memory _data, address _recipient, uint256 _maxCache ) internal { if (_quantity == 0) return; // 1.0 If there is no integrator, send from here if (_personal.integrator == address(0)) { // If this is part of a cross-swap or cross-redeem, and there is no // integrator.. then we don't need to transfer anywhere if (_recipient == address(this)) return; 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 ); } } } /** * @dev Gets the max cache size, given the supply of fpToken * @return maxCache Max units of any given bAsset that should be held in the cache */ function _getCacheDetails(FeederData storage _data, uint256 _supply) internal view returns (uint256 maxCache) { maxCache = (_supply * _data.cacheSize) / 1e18; } /*************************************** INVARIANT ****************************************/ /** * @notice Compute the amount of fpToken received for minting * with `quantity` amount of bAsset index `i`. * @param _bAssets Array of all bAsset Data * @param _i Index of bAsset with which to mint * @param _rawInput Raw amount of bAsset to use in mint * @param _config Generalised FeederConfig stored externally * @return mintAmount Quantity of fpTokens minted */ function computeMint( BassetData[] memory _bAssets, uint8 _i, uint256 _rawInput, FeederConfig memory _config ) public pure returns (uint256 mintAmount) { // 1. Get raw reserves (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); // 2. Get value of reserves according to invariant uint256 k0 = _invariant(x, sum, _config.a); uint256 scaledInput = (_rawInput * _bAssets[_i].ratio) / 1e8; require(scaledInput > 1e6, "Must add > 1e6 units"); // 3. Add deposit to x and sum x[_i] += scaledInput; sum += scaledInput; // 4. Finalise mint require(_inBounds(x, sum, _config.limits), "Exceeds weight limits"); mintAmount = _computeMintOutput(x, sum, k0, _config); } /** * @notice Compute the amount of fpToken received for minting * with the given array of inputs. * @param _bAssets Array of all bAsset Data * @param _indices Indexes of bAssets with which to mint * @param _rawInputs Raw amounts of bAssets to use in mint * @param _config Generalised FeederConfig stored externally * @return mintAmount Quantity of fpTokens minted */ function computeMintMulti( BassetData[] memory _bAssets, uint8[] memory _indices, uint256[] memory _rawInputs, FeederConfig memory _config ) public pure returns (uint256 mintAmount) { // 1. Get raw reserves (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); // 2. Get value of reserves according to invariant uint256 k0 = _invariant(x, sum, _config.a); // 3. Add deposits to x and sum uint256 len = _indices.length; uint8 idx; uint256 scaledInput; for (uint256 i = 0; i < len; i++) { idx = _indices[i]; scaledInput = (_rawInputs[i] * _bAssets[idx].ratio) / 1e8; x[idx] += scaledInput; sum += scaledInput; } // 4. Finalise mint require(_inBounds(x, sum, _config.limits), "Exceeds weight limits"); mintAmount = _computeMintOutput(x, sum, k0, _config); } /** * @notice Compute the amount of bAsset received for swapping * `quantity` amount of index `input_idx` to index `output_idx`. * @param _bAssets Array of all bAsset Data * @param _i Index of bAsset to swap IN * @param _o Index of bAsset to swap OUT * @param _rawInput Raw amounts of input bAsset to input * @param _feeRate Swap fee rate to apply to output * @param _config Generalised FeederConfig stored externally * @return bAssetOutputQuantity Raw bAsset output quantity * @return scaledSwapFee Swap fee collected, in fpToken terms */ function computeSwap( BassetData[] memory _bAssets, uint8 _i, uint8 _o, uint256 _rawInput, uint256 _feeRate, FeederConfig memory _config ) public pure returns (uint256 bAssetOutputQuantity, uint256 scaledSwapFee) { // 1. Get raw reserves (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); // 2. Get value of reserves according to invariant uint256 k0 = _invariant(x, sum, _config.a); // 3. Add deposits to x and sum uint256 scaledInput = (_rawInput * _bAssets[_i].ratio) / 1e8; require(scaledInput > 1e6, "Must add > 1e6 units"); x[_i] += scaledInput; sum += scaledInput; // 4. Calc total fpToken q uint256 k1 = _invariant(x, sum, _config.a); scaledSwapFee = ((k1 - k0) * _feeRate) / 1e18; // 5. Calc output bAsset uint256 newOutputReserve = _solveInvariant(x, _config.a, _o, k0 + scaledSwapFee); // Convert swap fee to fpToken terms // fpFee = fee * s / k scaledSwapFee = (scaledSwapFee * _config.supply) / k0; uint256 output = x[_o] - newOutputReserve - 1; bAssetOutputQuantity = (output * 1e8) / _bAssets[_o].ratio; // 6. Check for bounds x[_o] -= output; sum -= output; require(_inBounds(x, sum, _config.limits), "Exceeds weight limits"); } /** * @notice Compute the amount of bAsset index `i` received for * redeeming `quantity` amount of fpToken. * @param _bAssets Array of all bAsset Data * @param _o Index of output bAsset * @param _netRedeemInput Net amount of fpToken to redeem * @param _config Generalised FeederConfig stored externally * @return rawOutputUnits Raw bAsset output returned */ function computeRedeem( BassetData[] memory _bAssets, uint8 _o, uint256 _netRedeemInput, FeederConfig memory _config ) public pure returns (uint256 rawOutputUnits) { require(_netRedeemInput > 1e6, "Must redeem > 1e6 units"); // 1. Get raw reserves (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); // 2. Get value of reserves according to invariant uint256 k0 = _invariant(x, sum, _config.a); uint256 kFinal = (k0 * (_config.supply - _netRedeemInput)) / _config.supply + 1; // 3. Compute bAsset output uint256 newOutputReserve = _solveInvariant(x, _config.a, _o, kFinal); uint256 output = x[_o] - newOutputReserve - 1; rawOutputUnits = (output * 1e8) / _bAssets[_o].ratio; // 4. Check for max weight x[_o] -= output; sum -= output; require(_inBounds(x, sum, _config.limits), "Exceeds weight limits"); } /** * @notice Compute the amount of fpToken required to redeem * a given selection of bAssets. * @param _bAssets Array of all bAsset Data * @param _indices Indexes of output bAssets * @param _rawOutputs Desired raw bAsset outputs * @param _config Generalised FeederConfig stored externally * @return redeemInput Amount of fpToken required to redeem bAssets */ function computeRedeemExact( BassetData[] memory _bAssets, uint8[] memory _indices, uint256[] memory _rawOutputs, FeederConfig memory _config ) public pure returns (uint256 redeemInput) { // 1. Get raw reserves (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); // 2. Get value of reserves according to invariant uint256 k0 = _invariant(x, sum, _config.a); // 3. Sub deposits from x and sum uint256 len = _indices.length; uint256 ratioed; for (uint256 i = 0; i < len; i++) { ratioed = (_rawOutputs[i] * _bAssets[_indices[i]].ratio) / 1e8; x[_indices[i]] -= ratioed; sum -= ratioed; } require(_inBounds(x, sum, _config.limits), "Exceeds weight limits"); // 4. Get new value of reserves according to invariant uint256 k1 = _invariant(x, sum, _config.a); // 5. Total fpToken is the difference between values redeemInput = (_config.supply * (k0 - k1)) / k0; require(redeemInput > 1e6, "Must redeem > 1e6 units"); } /** * @notice Gets the price of the fpToken, and invariant value k * @param _bAssets Array of all bAsset Data * @param _config Generalised FeederConfig stored externally * @return price Price of an fpToken * @return k Total value of basket, k */ function computePrice(BassetData[] memory _bAssets, FeederConfig memory _config) public pure returns (uint256 price, uint256 k) { (uint256[] memory x, uint256 sum) = _getReserves(_bAssets); k = _invariant(x, sum, _config.a); price = (1e18 * k) / _config.supply; } /*************************************** INTERNAL ****************************************/ /** * @dev Computes the actual mint output after adding mint inputs * to the vault balances * @param _x Scaled vaultBalances * @param _sum Sum of vaultBalances, to avoid another loop * @param _k Previous value of invariant, k, before addition * @param _config Generalised FeederConfig stored externally * @return mintAmount Amount of value added to invariant, in fpToken terms */ function _computeMintOutput( uint256[] memory _x, uint256 _sum, uint256 _k, FeederConfig memory _config ) internal pure returns (uint256 mintAmount) { // 1. Get value of reserves according to invariant uint256 kFinal = _invariant(_x, _sum, _config.a); // 2. Total minted is the difference between values, with respect to total supply if (_config.supply == 0) { mintAmount = kFinal - _k; } else { mintAmount = (_config.supply * (kFinal - _k)) / _k; } } /** * @dev Simply scaled raw reserve values and returns the sum * @param _bAssets All bAssets * @return x Scaled vault balances * @return sum Sum of scaled vault balances */ function _getReserves(BassetData[] memory _bAssets) internal pure returns (uint256[] memory x, uint256 sum) { uint256 len = _bAssets.length; x = new uint256[](len); uint256 r; for (uint256 i = 0; i < len; i++) { BassetData memory bAsset = _bAssets[i]; r = (bAsset.vaultBalance * bAsset.ratio) / 1e8; x[i] = r; sum += r; } } /** * @dev Checks that no bAsset reserves exceed max weight * @param _x Scaled bAsset reserves * @param _sum Sum of x, precomputed * @param _limits Config object containing max and min weights * @return inBounds Bool, true if all assets are within bounds */ function _inBounds( uint256[] memory _x, uint256 _sum, WeightLimits memory _limits ) internal pure returns (bool inBounds) { uint256 len = _x.length; inBounds = true; uint256 w; for (uint256 i = 0; i < len; i++) { w = (_x[i] * 1e18) / _sum; if (w > _limits.max || w < _limits.min) return false; } } /*************************************** INVARIANT ****************************************/ /** * @dev Compute the invariant f(x) for a given array of supplies `x`. * @param _x Scaled vault balances * @param _sum Sum of scaled vault balances * @param _a Precise amplification coefficient * @return k Cumulative value of all assets according to the invariant */ function _invariant( uint256[] memory _x, uint256 _sum, uint256 _a ) internal pure returns (uint256 k) { if (_sum == 0) return 0; uint256 var1 = _x[0] * _x[1]; uint256 var2 = (_a * var1) / (_x[0] + _x[1]) / A_PRECISION; // result = 2 * (isqrt(var2**2 + (A + A_PRECISION) * var1 // A_PRECISION) - var2) + 1 k = 2 * (Root.sqrt((var2**2) + (((_a + A_PRECISION) * var1) / A_PRECISION)) - var2) + 1; } /** * @dev Solves the invariant for _i with respect to target K, given an array of reserves. * @param _x Scaled reserve balances * @param _a Precise amplification coefficient * @param _idx Index of asset for which to solve * @param _targetK Target invariant value K * @return y New reserve of _i */ function _solveInvariant( uint256[] memory _x, uint256 _a, uint8 _idx, uint256 _targetK ) internal pure returns (uint256 y) { require(_idx == 0 || _idx == 1, "Invalid index"); uint256 x = _idx == 0 ? _x[1] : _x[0]; uint256 var1 = _a + A_PRECISION; uint256 var2 = ((_targetK**2) * A_PRECISION) / var1; // var3 = var2 // (4 * x) + k * _a // var1 - x uint256 tmp = var2 / (4 * x) + ((_targetK * _a) / var1); uint256 var3 = tmp >= x ? tmp - x : x - tmp; // result = (sqrt(var3**2 + var2) + var3) // 2 y = ((Root.sqrt((var3**2) + var2) + tmp - x) / 2) + 1; } } // SPDX-License-Identifier: AGPL-3.0-or-later // External // Internal // Libs /** * @title FeederPool * @author mStable * @notice Base contract for Feeder Pools (fPools). Feeder Pools are combined of 50/50 fAsset and mAsset. This supports * efficient swaps into and out of mAssets and the bAssets in the mAsset basket (a.k.a mpAssets). There is 0 * fee to trade from fAsset into mAsset, providing low cost on-ramps into mAssets. * @dev VERSION: 1.0 * DATE: 2021-03-01 */ contract FeederPool is IFeederPool, Initializable, InitializableToken, PausableModule, InitializableReentrancyGuard { using SafeERC20 for IERC20; using StableMath for uint256; // Forging Events event Minted( address indexed minter, address recipient, uint256 output, address input, uint256 inputQuantity ); event MintedMulti( address indexed minter, address recipient, uint256 output, address[] inputs, uint256[] inputQuantities ); event Swapped( address indexed swapper, address input, address output, uint256 outputAmount, uint256 fee, 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, uint256 govFee); event WeightLimitsChanged(uint128 min, uint128 max); // FeederManager Events event BassetsMigrated(address[] bAssets, address newIntegrator); event StartRampA(uint256 currentA, uint256 targetA, uint256 startTime, uint256 rampEndTime); event StopRampA(uint256 currentA, uint256 time); // Constants uint256 private constant MAX_FEE = 1e16; uint256 private constant A_PRECISION = 100; address public immutable override mAsset; // Core data storage FeederData public data; /** * @dev Constructor to set immutable bytecode * @param _nexus Nexus address * @param _mAsset Immutable mAsset address */ constructor(address _nexus, address _mAsset) PausableModule(_nexus) { mAsset = _mAsset; } /** * @dev Basic initializer. Sets up core state and importantly provides infinite approvals to the mAsset pool * to support the cross pool swaps. bAssetData and bAssetPersonal are always ordered [mAsset, fAsset]. * @param _nameArg Name of the fPool token (a.k.a. fpToken) * @param _symbolArg Symbol of the fPool token * @param _mAsset Details on the base mAsset * @param _fAsset Details on the attached fAsset * @param _mpAssets Array of bAssets from the mAsset (to approve) * @param _config Starting invariant config */ function initialize( string calldata _nameArg, string calldata _symbolArg, BassetPersonal calldata _mAsset, BassetPersonal calldata _fAsset, address[] calldata _mpAssets, BasicConfig memory _config ) public initializer { InitializableToken._initialize(_nameArg, _symbolArg); _initializeReentrancyGuard(); require(_mAsset.addr == mAsset, "mAsset incorrect"); data.bAssetPersonal.push( BassetPersonal(_mAsset.addr, _mAsset.integrator, false, BassetStatus.Normal) ); data.bAssetData.push(BassetData(1e8, 0)); data.bAssetPersonal.push( BassetPersonal(_fAsset.addr, _fAsset.integrator, _fAsset.hasTxFee, BassetStatus.Normal) ); data.bAssetData.push( BassetData(SafeCast.toUint128(10**(26 - IBasicToken(_fAsset.addr).decimals())), 0) ); for (uint256 i = 0; i < _mpAssets.length; i++) { // Call will fail if bAsset does not exist IMasset(_mAsset.addr).getBasset(_mpAssets[i]); IERC20(_mpAssets[i]).safeApprove(_mAsset.addr, 2**255); } uint64 startA = SafeCast.toUint64(_config.a * A_PRECISION); data.ampData = AmpData(startA, startA, 0, 0); data.weightLimits = _config.limits; data.swapFee = 4e14; data.redemptionFee = 4e14; data.cacheSize = 1e17; data.govFee = 1e17; } /** * @dev System will be halted during a recollateralisation event */ modifier whenInOperation() { _isOperational(); _; } // Internal fn for modifier to reduce deployment size function _isOperational() internal view { require(!_paused || msg.sender == _recollateraliser(), "Unhealthy"); } /** * @dev Verifies that the caller is the Interest Validator contract */ modifier onlyInterestValidator() { require(nexus.getModule(KEY_INTEREST_VALIDATOR) == msg.sender, "Only validator"); _; } /*************************************** MINTING ****************************************/ /** * @notice Mint fpTokens with a single bAsset. This contract must have approval to spend the senders bAsset. * Supports either fAsset, mAsset or mpAsset as input - with mpAssets used to mint mAsset before depositing. * @param _input Address of the bAsset to deposit. * @param _inputQuantity Quantity in input token units. * @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage. * @param _recipient Receipient of the newly minted fpTokens * @return mintOutput Quantity of fpToken minted from the deposited bAsset. */ function mint( address _input, uint256 _inputQuantity, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenInOperation returns (uint256 mintOutput) { require(_recipient != address(0), "Invalid recipient"); require(_inputQuantity > 0, "Qty==0"); Asset memory input = _getAsset(_input); mintOutput = FeederLogic.mint( data, _getConfig(), input, _inputQuantity, _minOutputQuantity ); // Mint the fpToken _mint(_recipient, mintOutput); emit Minted(msg.sender, _recipient, mintOutput, _input, _inputQuantity); } /** * @notice Mint fpTokens with multiple bAssets. This contract must have approval to spend the senders bAssets. * Supports only fAsset or mAsset as inputs. * @param _inputs Address of the bAssets to deposit. * @param _inputQuantities Quantity in input token units. * @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage. * @param _recipient Receipient of the newly minted fpTokens * @return mintOutput Quantity of fpToken minted from the deposited bAssets. */ function mintMulti( address[] calldata _inputs, uint256[] calldata _inputQuantities, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenInOperation returns (uint256 mintOutput) { require(_recipient != address(0), "Invalid recipient"); uint256 len = _inputQuantities.length; require(len > 0 && len == _inputs.length, "Input array mismatch"); uint8[] memory indexes = _getAssets(_inputs); mintOutput = FeederLogic.mintMulti( data, _getConfig(), indexes, _inputQuantities, _minOutputQuantity ); // Mint the fpToken _mint(_recipient, mintOutput); emit MintedMulti(msg.sender, _recipient, mintOutput, _inputs, _inputQuantities); } /** * @notice Get the projected output of a given mint. * @param _input Address of the bAsset to deposit * @param _inputQuantity Quantity in bAsset units * @return mintOutput Estimated mint output in fpToken terms */ function getMintOutput(address _input, uint256 _inputQuantity) external view override returns (uint256 mintOutput) { require(_inputQuantity > 0, "Qty==0"); Asset memory input = _getAsset(_input); if (input.exists) { mintOutput = FeederLogic.computeMint( data.bAssetData, input.idx, _inputQuantity, _getConfig() ); } else { uint256 estimatedMasset = IMasset(mAsset).getMintOutput(_input, _inputQuantity); mintOutput = FeederLogic.computeMint(data.bAssetData, 0, estimatedMasset, _getConfig()); } } /** * @notice 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 fpToken. * @return mintOutput Estimated mint output in fpToken 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 = _getAssets(_inputs); return FeederLogic.computeMintMulti(data.bAssetData, indexes, _inputQuantities, _getConfig()); } /*************************************** SWAPPING ****************************************/ /** * @notice Swaps two assets - either internally between fAsset<>mAsset, or between fAsset<>mpAsset by * first routing through the mAsset pool. * @param _input Address of bAsset to deposit * @param _output Address of bAsset to withdraw * @param _inputQuantity Units of input bAsset to swap in * @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 whenInOperation returns (uint256 swapOutput) { require(_recipient != address(0), "Invalid recipient"); require(_input != _output, "Invalid pair"); require(_inputQuantity > 0, "Qty==0"); Asset memory input = _getAsset(_input); Asset memory output = _getAsset(_output); require(_pathIsValid(input, output), "Invalid pair"); uint256 localFee; (swapOutput, localFee) = FeederLogic.swap( data, _getConfig(), input, output, _inputQuantity, _minOutputQuantity, _recipient ); uint256 govFee = data.govFee; if (govFee > 0) { data.pendingFees += ((localFee * govFee) / 1e18); } emit Swapped(msg.sender, input.addr, output.addr, swapOutput, localFee, _recipient); } /** * @notice 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, "Qty==0"); Asset memory input = _getAsset(_input); Asset memory output = _getAsset(_output); require(_pathIsValid(input, output), "Invalid pair"); // Internal swap between fAsset and mAsset if (input.exists && output.exists) { (swapOutput, ) = FeederLogic.computeSwap( data.bAssetData, input.idx, output.idx, _inputQuantity, output.idx == 0 ? 0 : data.swapFee, _getConfig() ); return swapOutput; } // Swapping out of fAsset if (input.exists) { // Swap into mAsset > Redeem into mpAsset (swapOutput, ) = FeederLogic.computeSwap( data.bAssetData, 1, 0, _inputQuantity, 0, _getConfig() ); swapOutput = IMasset(mAsset).getRedeemOutput(_output, swapOutput); } // Else we are swapping into fAsset else { // Mint mAsset from mp > Swap into fAsset here swapOutput = IMasset(mAsset).getMintOutput(_input, _inputQuantity); (swapOutput, ) = FeederLogic.computeSwap( data.bAssetData, 0, 1, swapOutput, data.swapFee, _getConfig() ); } } /** * @dev Checks if a given swap path is valid. Only fAsset<>mAsset & fAsset<>mpAsset swaps are supported. */ function _pathIsValid(Asset memory _in, Asset memory _out) internal pure returns (bool isValid) { // mpAsset -> mpAsset if (!_in.exists && !_out.exists) return false; // f/mAsset -> f/mAsset if (_in.exists && _out.exists) return true; // fAsset -> mpAsset if (_in.exists && _in.idx == 1) return true; // mpAsset -> fAsset if (_out.exists && _out.idx == 1) return true; // Path is into or out of mAsset - just use main pool for this return false; } /*************************************** REDEMPTION ****************************************/ /** * @notice Burns a specified quantity of the senders fpToken in return for a bAsset. The output amount is derived * from the invariant. Supports redemption into either the fAsset, mAsset or assets in the mAsset basket. * @param _output Address of the bAsset to withdraw * @param _fpTokenQuantity Quantity of LP Token to burn * @param _minOutputQuantity Minimum bAsset quantity to receive for the burnt fpToken. This protects against slippage. * @param _recipient Address to transfer the withdrawn bAssets to. * @return outputQuantity Quanity of bAsset units received for the burnt fpToken */ function redeem( address _output, uint256 _fpTokenQuantity, uint256 _minOutputQuantity, address _recipient ) external override nonReentrant whenInOperation returns (uint256 outputQuantity) { require(_recipient != address(0), "Invalid recipient"); require(_fpTokenQuantity > 0, "Qty==0"); Asset memory output = _getAsset(_output); // Get config before burning. Config > Burn > CacheSize FeederConfig memory config = _getConfig(); _burn(msg.sender, _fpTokenQuantity); uint256 localFee; (outputQuantity, localFee) = FeederLogic.redeem( data, config, output, _fpTokenQuantity, _minOutputQuantity, _recipient ); uint256 govFee = data.govFee; if (govFee > 0) { data.pendingFees += ((localFee * govFee) / 1e18); } emit Redeemed( msg.sender, _recipient, _fpTokenQuantity, output.addr, outputQuantity, localFee ); } /** * @dev Credits a recipient with a proportionate amount of bAssets, relative to current vault * balance levels and desired fpToken quantity. Burns the fpToken as payment. Only fAsset & mAsset are supported in this path. * @param _inputQuantity Quantity of fpToken to redeem * @param _minOutputQuantities Min units of output to receive * @param _recipient Address to credit the withdrawn bAssets * @return outputQuantities Array of output asset quantities */ function redeemProportionately( uint256 _inputQuantity, uint256[] calldata _minOutputQuantities, address _recipient ) external override nonReentrant whenInOperation returns (uint256[] memory outputQuantities) { require(_recipient != address(0), "Invalid recipient"); require(_inputQuantity > 0, "Qty==0"); // Get config before burning. Burn > CacheSize FeederConfig memory config = _getConfig(); _burn(msg.sender, _inputQuantity); address[] memory outputs; uint256 scaledFee; (scaledFee, outputs, outputQuantities) = FeederLogic.redeemProportionately( data, config, _inputQuantity, _minOutputQuantities, _recipient ); uint256 govFee = data.govFee; if (govFee > 0) { data.pendingFees += ((scaledFee * govFee) / 1e18); } emit RedeemedMulti( msg.sender, _recipient, _inputQuantity, outputs, outputQuantities, scaledFee ); } /** * @dev Credits a recipient with a certain quantity of selected bAssets, in exchange for burning the * relative fpToken quantity from the sender. Only fAsset & mAsset (0,1) are supported in this path. * @param _outputs Addresses of the bAssets to receive * @param _outputQuantities Units of the bAssets to receive * @param _maxInputQuantity Maximum fpToken quantity to burn for the received bAssets. This protects against slippage. * @param _recipient Address to receive the withdrawn bAssets * @return fpTokenQuantity Quantity of fpToken units burned as payment */ function redeemExactBassets( address[] calldata _outputs, uint256[] calldata _outputQuantities, uint256 _maxInputQuantity, address _recipient ) external override nonReentrant whenInOperation returns (uint256 fpTokenQuantity) { require(_recipient != address(0), "Invalid recipient"); uint256 len = _outputQuantities.length; require(len > 0 && len == _outputs.length, "Invalid array input"); require(_maxInputQuantity > 0, "Qty==0"); uint8[] memory indexes = _getAssets(_outputs); uint256 localFee; (fpTokenQuantity, localFee) = FeederLogic.redeemExactBassets( data, _getConfig(), indexes, _outputQuantities, _maxInputQuantity, _recipient ); _burn(msg.sender, fpTokenQuantity); uint256 govFee = data.govFee; if (govFee > 0) { data.pendingFees += ((localFee * govFee) / 1e18); } emit RedeemedMulti( msg.sender, _recipient, fpTokenQuantity, _outputs, _outputQuantities, localFee ); } /** * @notice Gets the estimated output from a given redeem * @param _output Address of the bAsset to receive * @param _fpTokenQuantity Quantity of fpToken to redeem * @return bAssetOutput Estimated quantity of bAsset units received for the burnt fpTokens */ function getRedeemOutput(address _output, uint256 _fpTokenQuantity) external view override returns (uint256 bAssetOutput) { require(_fpTokenQuantity > 0, "Qty==0"); Asset memory output = _getAsset(_output); uint256 scaledFee = _fpTokenQuantity.mulTruncate(data.redemptionFee); bAssetOutput = FeederLogic.computeRedeem( data.bAssetData, output.exists ? output.idx : 0, _fpTokenQuantity - scaledFee, _getConfig() ); // Extra step for mpAsset redemption if (!output.exists) { bAssetOutput = IMasset(mAsset).getRedeemOutput(output.addr, bAssetOutput); } } /** * @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 fpTokenQuantity Estimated quantity of fpToken units needed to burn to receive output */ function getRedeemExactBassetsOutput( address[] calldata _outputs, uint256[] calldata _outputQuantities ) external view override returns (uint256 fpTokenQuantity) { uint256 len = _outputQuantities.length; require(len > 0 && len == _outputs.length, "Invalid array input"); uint8[] memory indexes = _getAssets(_outputs); uint256 mAssetRedeemed = FeederLogic.computeRedeemExact( data.bAssetData, indexes, _outputQuantities, _getConfig() ); fpTokenQuantity = mAssetRedeemed.divPrecisely(1e18 - data.redemptionFee); if (fpTokenQuantity > 0) fpTokenQuantity += 1; } /*************************************** GETTERS ****************************************/ /** * @notice Gets the price of the fpToken, and invariant value k * @return price Price of an fpToken * @return k Total value of basket, k */ function getPrice() public view override returns (uint256 price, uint256 k) { return FeederLogic.computePrice(data.bAssetData, _getConfig()); } /** * @notice Gets all config needed for general InvariantValidator calls */ function getConfig() external view override returns (FeederConfig memory config) { return _getConfig(); } /** * @notice Get data for a specific bAsset, if it exists * @param _bAsset Address of bAsset * @return personal Struct with personal data * @return vaultData Struct with full bAsset data */ function getBasset(address _bAsset) external view override returns (BassetPersonal memory personal, BassetData memory vaultData) { Asset memory asset = _getAsset(_bAsset); require(asset.exists, "Invalid asset"); personal = data.bAssetPersonal[asset.idx]; vaultData = data.bAssetData[asset.idx]; } /** * @notice Get data for a all bAssets in basket * @return personal Struct[] with full bAsset data * @return vaultData Number of bAssets in the Basket */ function getBassets() external view override returns (BassetPersonal[] memory, BassetData[] memory vaultData) { return (data.bAssetPersonal, data.bAssetData); } /*************************************** GETTERS - INTERNAL ****************************************/ /** * @dev Checks if a given asset exists in basket and return the index. * @return status Data containing address, index and whether it exists in basket */ function _getAsset(address _asset) internal view returns (Asset memory status) { // if input is mAsset then we know the position if (_asset == mAsset) return Asset(0, _asset, true); // else it exists if the position 1 is _asset return Asset(1, _asset, data.bAssetPersonal[1].addr == _asset); } /** * @dev Validates an array of input assets and returns their indexes. Assets must exist * in order to be valid, as mintMulti and redeemMulti do not support external bAssets. */ function _getAssets(address[] memory _assets) internal view returns (uint8[] memory indexes) { uint256 len = _assets.length; indexes = new uint8[](len); Asset memory input_; for (uint256 i = 0; i < len; i++) { input_ = _getAsset(_assets[i]); indexes[i] = input_.idx; require(input_.exists, "Invalid asset"); for (uint256 j = i + 1; j < len; j++) { require(_assets[i] != _assets[j], "Duplicate asset"); } } } /** * @dev Gets all config needed for general InvariantValidator calls */ function _getConfig() internal view returns (FeederConfig memory) { return FeederConfig(totalSupply() + data.pendingFees, _getA(), data.weightLimits); } /** * @dev Gets current amplification var A */ function _getA() internal view returns (uint256) { AmpData memory ampData_ = data.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 Collects the interest generated from the lending markets, performing a theoretical mint, which * is then validated by the interest validator to protect against accidental hyper inflation. * @return mintAmount fpToken units generated from interest collected from lending markets * @return newSupply fpToken total supply after mint */ function collectPlatformInterest() external override onlyInterestValidator whenInOperation nonReentrant returns (uint256 mintAmount, uint256 newSupply) { (uint8[] memory idxs, uint256[] memory gains) = FeederManager.calculatePlatformInterest(data.bAssetPersonal, data.bAssetData); // Calculate potential mint amount. This will be validated by the interest validator mintAmount = FeederLogic.computeMintMulti(data.bAssetData, idxs, gains, _getConfig()); newSupply = totalSupply() + data.pendingFees + mintAmount; uint256 govFee = data.govFee; if (govFee > 0) { data.pendingFees += ((mintAmount * govFee) / 1e18); } // Dummy mint event to catch the collections here emit MintedMulti(address(this), msg.sender, 0, new address[](0), gains); } /** * @dev Collects the pending gov fees extracted from swap, redeem and platform interest. */ function collectPendingFees() external override onlyInterestValidator { uint256 fees = data.pendingFees; if (fees > 1) { uint256 mintAmount = fees - 1; data.pendingFees = 1; _mint(msg.sender, mintAmount); emit MintedMulti( address(this), msg.sender, mintAmount, new address[](0), new uint256[](0) ); } } /*************************************** 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 fpToken supply to hold for each bAsset */ function setCacheSize(uint256 _cacheSize) external onlyGovernor { require(_cacheSize <= 2e17, "Must be <= 20%"); data.cacheSize = _cacheSize; emit CacheSizeChanged(_cacheSize); } /** * @dev Set the ecosystem fee for sewapping bAssets or redeeming specific bAssets * @param _swapFee Fee calculated in (%/100 * 1e18) * @param _redemptionFee Fee calculated in (%/100 * 1e18) * @param _govFee Fee calculated in (%/100 * 1e18) */ function setFees( uint256 _swapFee, uint256 _redemptionFee, uint256 _govFee ) external onlyGovernor { require(_swapFee <= MAX_FEE, "Swap rate oob"); require(_redemptionFee <= MAX_FEE, "Redemption rate oob"); require(_govFee <= 5e17, "Gov fee rate oob"); data.swapFee = _swapFee; data.redemptionFee = _redemptionFee; data.govFee = _govFee; emit FeesChanged(_swapFee, _redemptionFee, _govFee); } /** * @dev Set the maximum weight across all bAssets * @param _min Weight where 100% = 1e18 * @param _max Weight where 100% = 1e18 */ function setWeightLimits(uint128 _min, uint128 _max) external onlyGovernor { require(_min <= 3e17 && _max >= 7e17, "Weights oob"); data.weightLimits = WeightLimits(_min, _max); emit WeightLimitsChanged(_min, _max); } /** * @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 onlyGovernor { FeederManager.migrateBassets(data.bAssetPersonal, _bAssets, _newIntegration); } /** * @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 { FeederManager.startRampA(data.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 { FeederManager.stopRampA(data.ampData, _getA()); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_nexus","type":"address"},{"internalType":"address","name":"_mAsset","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":"address[]","name":"bAssets","type":"address[]"},{"indexed":false,"internalType":"address","name":"newIntegrator","type":"address"}],"name":"BassetsMigrated","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"},{"indexed":false,"internalType":"uint256","name":"govFee","type":"uint256"}],"name":"FeesChanged","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":"output","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":"output","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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":false,"internalType":"uint256","name":"currentA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rampEndTime","type":"uint256"}],"name":"StartRampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StopRampA","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":"fee","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":"address","name":"account","type":"address"}],"name":"Unpaused","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":[{"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":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collectPendingFees","outputs":[],"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":"data","outputs":[{"internalType":"uint256","name":"swapFee","type":"uint256"},{"internalType":"uint256","name":"redemptionFee","type":"uint256"},{"internalType":"uint256","name":"govFee","type":"uint256"},{"internalType":"uint256","name":"pendingFees","type":"uint256"},{"internalType":"uint256","name":"cacheSize","type":"uint256"},{"components":[{"internalType":"uint64","name":"initialA","type":"uint64"},{"internalType":"uint64","name":"targetA","type":"uint64"},{"internalType":"uint64","name":"rampStartTime","type":"uint64"},{"internalType":"uint64","name":"rampEndTime","type":"uint64"}],"internalType":"struct AmpData","name":"ampData","type":"tuple"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"weightLimits","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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 BassetStatus","name":"status","type":"uint8"}],"internalType":"struct BassetPersonal","name":"personal","type":"tuple"},{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData","name":"vaultData","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 BassetStatus","name":"status","type":"uint8"}],"internalType":"struct BassetPersonal[]","name":"","type":"tuple[]"},{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"vaultData","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","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":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"k","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":"fpTokenQuantity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_fpTokenQuantity","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":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_nameArg","type":"string"},{"internalType":"string","name":"_symbolArg","type":"string"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"bool","name":"hasTxFee","type":"bool"},{"internalType":"enum BassetStatus","name":"status","type":"uint8"}],"internalType":"struct BassetPersonal","name":"_mAsset","type":"tuple"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"integrator","type":"address"},{"internalType":"bool","name":"hasTxFee","type":"bool"},{"internalType":"enum BassetStatus","name":"status","type":"uint8"}],"internalType":"struct BassetPersonal","name":"_fAsset","type":"tuple"},{"internalType":"address[]","name":"_mpAssets","type":"address[]"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct BasicConfig","name":"_config","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"nexus","outputs":[{"internalType":"contract INexus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_output","type":"address"},{"internalType":"uint256","name":"_fpTokenQuantity","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":"_maxInputQuantity","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"redeemExactBassets","outputs":[{"internalType":"uint256","name":"fpTokenQuantity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_inputQuantity","type":"uint256"},{"internalType":"uint256[]","name":"_minOutputQuantities","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"redeemProportionately","outputs":[{"internalType":"uint256[]","name":"outputQuantities","type":"uint256[]"}],"stateMutability":"nonpayable","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"},{"internalType":"uint256","name":"_govFee","type":"uint256"}],"name":"setFees","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":[{"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":"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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040526006805461ff00191690553480156200001c57600080fd5b5060405162005e3d38038062005e3d8339810160408190526200003f91620000e9565b81806001600160a01b0381166200009c5760405162461bcd60e51b815260206004820152601560248201527f4e657875732061646472657373206973207a65726f0000000000000000000000604482015260640160405180910390fd5b6001600160601b0319606091821b81166080526006805461ff001916905592901b90911660a05250620001209050565b80516001600160a01b0381168114620000e457600080fd5b919050565b60008060408385031215620000fc578182fd5b6200010783620000cc565b91506200011760208401620000cc565b90509250929050565b60805160601c60a05160601c615cab62000192600039600081816102ce0152818161097401528181610e6f01528181611c7601528181611d1f01528181611f75015261389501526000818161052401528181612019015281816124840152818161425901526144320152615cab6000f3fe608060405234801561001057600080fd5b50600436106102535760003560e01c806373d4a13a11610146578063a9059cbb116100c3578063c4db7fa011610087578063c4db7fa0146105c7578063cec10c11146105cf578063d5bcb9b5146105e2578063dd62ed3e146105f5578063e5555b8f1461062e578063f74bfe8e1461064157610253565b8063a9059cbb14610559578063aa5d27e91461056c578063af290bd41461057f578063c1db77ec14610592578063c3f909d4146105b257610253565b806398d5fdca1161010a57806398d5fdca146104fc57806398fec3af14610504578063a1c251511461050c578063a3f5c1d21461051f578063a457c2d71461054657610253565b806373d4a13a1461042257806378aa987e146104bc5780637e8901ea146104cf5780638456cb59146104ec57806395d89b41146104f457610253565b8063313ce567116101d457806344e3fa3c1161019857806344e3fa3c146103c55780635c975abb146103d85780636fb3e89c146103e957806370a08231146103fc57806372ea90761461040f57610253565b8063313ce5671461036157806339509351146103765780633e37bcbc146103895780633f4ba83a146103aa57806343bcfab6146103b257610253565b806318160ddd1161021b57806318160ddd146103085780631820783d146103105780631d3ce3981461032557806323b872dd1461033b57806323fb4bd31461034e57610253565b806304de5a731461025857806306fdde031461027e578063095ea7b314610293578063119849cf146102b6578063178d341f146102c9575b600080fd5b61026b610266366004614987565b610654565b6040519081526020015b60405180910390f35b6102866107c9565b60405161027591906155c6565b6102a66102a13660046148bf565b61085c565b6040519015158152602001610275565b61026b6102c43660046148bf565b610873565b6102f07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610275565b60035461026b565b61032361031e366004614d8e565b610a93565b005b61032d610b1f565b60405161027592919061540e565b6102a6610349366004614821565b610c82565b61032361035c366004614b6f565b610d35565b60065460405160ff9091168152602001610275565b6102a66103843660046148bf565b61149f565b61039c6103973660046147b1565b6114d6565b6040516102759291906156a1565b610323611674565b61026b6103c03660046148ea565b61170b565b6103236103d3366004614eda565b61190b565b6102a6600654610100900460ff1690565b6103236103f7366004614933565b6119a7565b61026b61040a3660046147b1565b611a22565b61026b61041d366004614821565b611a41565b600754600854600954600a54600b5460408051608081018252600e546001600160401b038082168352600160401b82048116602080850191909152600160801b808404831685870152600160c01b90930490911660608401528351808501909452600f546001600160801b038082168652929004909116908301526104a996959493929187565b60405161027597969594939291906158e7565b61026b6104ca3660046148bf565b611e4a565b6104d7611fd5565b60408051928352602083019190915201610275565b610323612309565b61028661239b565b6104d76123aa565b610323612445565b61032361051a366004614d61565b6125e8565b6102f07f000000000000000000000000000000000000000000000000000000000000000081565b6102a66105543660046148bf565b6126d4565b6102a66105673660046148bf565b61276f565b61026b61057a3660046149ef565b61277c565b61026b61058d3660046149ef565b6129e8565b6105a56105a0366004614e89565b612bec565b60405161027591906155b3565b6105ba612da9565b60405161027591906156d1565b610323612dbe565b6103236105dd366004614f1e565b612e40565b61026b6105f0366004614861565b612f7c565b61026b6106033660046147e9565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61026b61063c366004614987565b6131d9565b61026b61064f3660046148ea565b61330f565b600081801580159061066557508085145b6106ac5760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b60448201526064015b60405180910390fd5b60006106ea8787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b90506000732837c77527c37d61d9763f53005211dacb4125de637cdc8e40600d8489896107156136c2565b6040518663ffffffff1660e01b81526004016107359594939291906152ad565b60206040518083038186803b15801561074d57600080fd5b505af4158015610761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107859190614da6565b6008549091506107a8906107a190670de0b6b3a7640000615b33565b8290613732565b935083156107be576107bb6001856159c5565b93505b505050949350505050565b6060600480546107d890615bc1565b80601f016020809104026020016040519081016040528092919081815260200182805461080490615bc1565b80156108515780601f1061082657610100808354040283529160200191610851565b820191906000526020600020905b81548152906001019060200180831161083457829003601f168201915b505050505090505b90565b6000610869338484613751565b5060015b92915050565b60008082116108945760405162461bcd60e51b81526004016106a39061564a565b600061089f84613876565b905080604001511561094b578051732837c77527c37d61d9763f53005211dacb4125de9063d1be552890600d90866108d56136c2565b6040518563ffffffff1660e01b81526004016108f494939291906153bb565b60206040518083038186803b15801561090c57600080fd5b505af4158015610920573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109449190614da6565b9150610a8c565b60405163119849cf60e01b81526001600160a01b038581166004830152602482018590526000917f00000000000000000000000000000000000000000000000000000000000000009091169063119849cf9060440160206040518083038186803b1580156109b857600080fd5b505afa1580156109cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f09190614da6565b9050732837c77527c37d61d9763f53005211dacb4125de63d1be5528600d600084610a196136c2565b6040518563ffffffff1660e01b8152600401610a3894939291906153bb565b60206040518083038186803b158015610a5057600080fd5b505af4158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190614da6565b9250505b5092915050565b610a9b61396f565b6702c68af0bb140000811115610ae45760405162461bcd60e51b815260206004820152600e60248201526d4d757374206265203c3d2032302560901b60448201526064016106a3565b600b8190556040518181527f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe79060200160405180910390a150565b6060806007600501600760060181805480602002602001604051908101604052809291908181526020016000905b82821015610c04576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610bd257634e487b7160e01b600052602160045260246000fd5b6007811115610bf157634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610b4d565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610c7457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610c2b565b505050509050915091509091565b6000610c8f8484846139d9565b6001600160a01b038416600090815260026020908152604080832033845290915290205482811015610d145760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016106a3565b610d288533610d238685615b33565b613751565b60019150505b9392505050565b600054610100900460ff1680610d4e575060005460ff16155b610db15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106a3565b600054610100900460ff16158015610ddc576000805460ff1961ff0019909116610100171660011790555b610e4f8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600092019190915250613bb192505050565b610e656006805462ff0000191662010000179055565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610e9c60208801886147b1565b6001600160a01b031614610ee55760405162461bcd60e51b815260206004820152601060248201526f1b505cdcd95d081a5b98dbdc9c9958dd60821b60448201526064016106a3565b6040805160808101909152600c9080610f0160208a018a6147b1565b6001600160a01b03168152602001886020016020810190610f2291906147b1565b6001600160a01b0316815260006020820152604001600190528154600181810184556000938452602093849020835160029093020180546001600160a01b039384166001600160a01b031991821617825594840151918101805460408601511515600160a01b0260ff60a01b19949095169616959095179190911691909117808455606083015192939192919060ff60a81b1916600160a81b836007811115610fdb57634e487b7160e01b600052602160045260246000fd5b0217905550506040805180820182526305f5e100815260006020808301828152600d8054600181018255935292517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5909201805493516001600160801b03199094166001600160801b03938416178316600160801b9390941692909202929092179055815160808101909252600c92508190611079908901896147b1565b6001600160a01b0316815260200187602001602081019061109a91906147b1565b6001600160a01b031681526020016110b86060890160408a01614b37565b15158152602001600190528154600181810184556000938452602093849020835160029093020180546001600160a01b039384166001600160a01b031991821617825594840151918101805460408601511515600160a01b0260ff60a01b19949095169616959095179190911691909117808455606083015192939192919060ff60a81b1916600160a81b83600781111561116357634e487b7160e01b600052602160045260246000fd5b02179055505060408051808201909152600d91508061121361118860208a018a6147b1565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190614f49565b61120390601a615b72565b61120e90600a615a43565b613bc1565b6001600160801b03908116825260006020928301819052845460018101865594815282812084519501805494909301518216600160801b029482166001600160801b03199094169390931716929092179091555b838110156113a55761127c60208801886147b1565b6001600160a01b0316633e37bcbc8686848181106112aa57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906112bf91906147b1565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160c06040518083038186803b1580156112fe57600080fd5b505afa158015611312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113369190614ca2565b50611393905061134960208901896147b1565b600160ff1b87878581811061136e57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061138391906147b1565b6001600160a01b03169190613c2a565b8061139d81615bf6565b915050611267565b5060006113c1606484600001516113bc9190615b14565b613d75565b604080516080810182526001600160401b039290921680835260208084018290526000928401839052606090930191909152600e805467ffffffffffffffff191682176fffffffffffffffff00000000000000001916600160401b909202919091176001600160801b03908116909155848201518051600f805492909401516001600160801b0319909216908316178216600160801b91909216021790555066016bcc41e90000600781905560085567016345785d8a0000600b8190556009558015611493576000805461ff00191690555b50505050505050505050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610869918590610d239086906159c5565b6114de614596565b604080518082019091526000808252602082015260006114fd84613876565b905080604001516115405760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b60448201526064016106a3565b8051600c8054909160ff1690811061156857634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156115e657634e487b7160e01b600052602160045260246000fd5b600781111561160557634e487b7160e01b600052602160045260246000fd5b8152505092506007600601816000015160ff168154811061163657634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b61167c61396f565b600654610100900460ff166116ca5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106a3565b6006805461ff00191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60065460009062010000900460ff166117365760405162461bcd60e51b81526004016106a39061566a565b6006805462ff00001916905561174a613dd9565b6001600160a01b0382166117705760405162461bcd60e51b81526004016106a39061561f565b600084116117905760405162461bcd60e51b81526004016106a39061564a565b600061179b86613876565b905060006117a76136c2565b90506117b33387613e40565b60405163f134c4fb60e01b8152600090732837c77527c37d61d9763f53005211dacb4125de9063f134c4fb906117f890600790869088908d908d908d90600401615852565b604080518083038186803b15801561180f57600080fd5b505af4158015611823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118479190614efb565b6009549195509150801561188a57670de0b6b3a76400006118688284615b14565b61187291906159dd565b600a80546000906118849084906159c5565b90915550505b602084810151604080516001600160a01b038a811682529381018c90529290911690820152606081018690526080810183905233907f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad89060a0015b60405180910390a250506006805462ff0000191662010000179055509095945050505050565b61191361396f565b7390ae544e8cc76d2867987ee4f5456c02c50abd8b63bd5b0ac6600e8484611939613f8f565b6040516001600160e01b031960e087901b168152600481019490945260248401929092526044830152606482810191909152608482015260a40160006040518083038186803b15801561198b57600080fd5b505af415801561199f573d6000803e3d6000fd5b505050505050565b6119af61396f565b604051637203e78b60e01b81527390ae544e8cc76d2867987ee4f5456c02c50abd8b90637203e78b906119ed90600c908790879087906004016154b1565b60006040518083038186803b158015611a0557600080fd5b505af4158015611a19573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152600160205260409020545b919050565b6000826001600160a01b0316846001600160a01b03161415611a755760405162461bcd60e51b81526004016106a3906155f9565b60008211611a955760405162461bcd60e51b81526004016106a39061564a565b6000611aa085613876565b90506000611aad85613876565b9050611ab982826140cc565b611ad55760405162461bcd60e51b81526004016106a3906155f9565b81604001518015611ae7575080604001515b15611ba85781518151732837c77527c37d61d9763f53005211dacb4125de9163dce9bf6a91600d91908860ff821615611b2257600754611b25565b60005b611b2d6136c2565b6040518763ffffffff1660e01b8152600401611b4e96959493929190615379565b604080518083038186803b158015611b6557600080fd5b505af4158015611b79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9d9190614efb565b509250610d2e915050565b816040015115611cf957732837c77527c37d61d9763f53005211dacb4125de63dce9bf6a600d600160008881611bdc6136c2565b6040518763ffffffff1660e01b8152600401611bfd96959493929190615379565b604080518083038186803b158015611c1457600080fd5b505af4158015611c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4c9190614efb565b50604051633c554c3f60e11b81526001600160a01b038781166004830152602482018390529194507f0000000000000000000000000000000000000000000000000000000000000000909116906378aa987e9060440160206040518083038186803b158015611cba57600080fd5b505afa158015611cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf29190614da6565b9250611e41565b60405163119849cf60e01b81526001600160a01b038781166004830152602482018690527f0000000000000000000000000000000000000000000000000000000000000000169063119849cf9060440160206040518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d999190614da6565b9250732837c77527c37d61d9763f53005211dacb4125de63dce9bf6a60076006016000600187600760000154611dcd6136c2565b6040518763ffffffff1660e01b8152600401611dee96959493929190615379565b604080518083038186803b158015611e0557600080fd5b505af4158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d9190614efb565b5092505b50509392505050565b6000808211611e6b5760405162461bcd60e51b81526004016106a39061564a565b6000611e7684613876565b600854909150600090611e8a908590614161565b9050732837c77527c37d61d9763f53005211dacb4125de639e60b1c560076006018460400151611ebb576000611ebe565b84515b611ec88589615b33565b611ed06136c2565b6040518563ffffffff1660e01b8152600401611eef94939291906153bb565b60206040518083038186803b158015611f0757600080fd5b505af4158015611f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3f9190614da6565b92508160400151611fcd576020820151604051633c554c3f60e11b81526001600160a01b039182166004820152602481018590527f0000000000000000000000000000000000000000000000000000000000000000909116906378aa987e9060440160206040518083038186803b158015611fb957600080fd5b505afa158015610a64573d6000803e3d6000fd5b505092915050565b6040516385acd64160e01b81527fc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f6004820152600090819033906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385acd6419060240160206040518083038186803b15801561205b57600080fd5b505afa15801561206f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209391906147cd565b6001600160a01b0316146120da5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c903b30b634b230ba37b960911b60448201526064016106a3565b6120e2613dd9565b60065462010000900460ff1661210a5760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055604051630735024560e51b815260009081907390ae544e8cc76d2867987ee4f5456c02c50abd8b9063e6a048a09061215690600c90600d9060040161551f565b60006040518083038186803b15801561216e57600080fd5b505af4158015612182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121aa9190810190614a77565b9092509050732837c77527c37d61d9763f53005211dacb4125de637116e818600d84846121d56136c2565b6040518563ffffffff1660e01b81526004016121f49493929190615301565b60206040518083038186803b15801561220c57600080fd5b505af4158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190614da6565b600a54600354919550859161225991906159c5565b61226391906159c5565b60095490935080156122a457670de0b6b3a76400006122828287615b14565b61228c91906159dd565b600a805460009061229e9084906159c5565b90915550505b604080516000808252602082019283905230927f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc926122e99233929091908890615190565b60405180910390a250506006805462ff0000191662010000179055509091565b61231161396f565b600654610100900460ff161561235c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106a3565b6006805461ff0019166101001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001611701565b6060600580546107d890615bc1565b600080732837c77527c37d61d9763f53005211dacb4125de635dd72f5d600d6123d16136c2565b6040518363ffffffff1660e01b81526004016123ee9291906153ec565b604080518083038186803b15801561240557600080fd5b505af4158015612419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243d9190614efb565b915091509091565b6040516385acd64160e01b81527fc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f600482015233906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385acd6419060240160206040518083038186803b1580156124c657600080fd5b505afa1580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe91906147cd565b6001600160a01b0316146125455760405162461bcd60e51b815260206004820152600e60248201526d27b7363c903b30b634b230ba37b960911b60448201526064016106a3565b600a5460018111156125e557600061255e600183615b33565b6001600a55905061256f3382614176565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc338360006040519080825280602002602001820160405280156125be578160200160208202803683370190505b50604080516000815260208101918290526125db94939291615190565b60405180910390a2505b50565b6125f061396f565b670429d069189e0000826001600160801b03161115801561262257506709b6e64a8ec60000816001600160801b031610155b61265c5760405162461bcd60e51b815260206004820152600b60248201526a2bb2b4b3b43a399037b7b160a91b60448201526064016106a3565b6040805180820182526001600160801b038481168083528482166020938401819052600f80546001600160801b0319168317909316600160801b8202179092558351908152918201527f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136910160405180910390a15050565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156127565760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016106a3565b6127653385610d238685615b33565b5060019392505050565b60006108693384846139d9565b60065460009062010000900460ff166127a75760405162461bcd60e51b81526004016106a39061566a565b6006805462ff0000191690556127bb613dd9565b6001600160a01b0382166127e15760405162461bcd60e51b81526004016106a39061561f565b8380158015906127f057508087145b6128325760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b60448201526064016106a3565b600084116128525760405162461bcd60e51b81526004016106a39061564a565b60006128908989808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b90506000732837c77527c37d61d9763f53005211dacb4125de638c913b9460076128b86136c2565b858c8c8c8c6040518863ffffffff1660e01b81526004016128df979695949392919061575f565b604080518083038186803b1580156128f657600080fd5b505af415801561290a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292e9190614efb565b909450905061293d3385613e40565b600954801561297b57670de0b6b3a76400006129598284615b14565b61296391906159dd565b600a80546000906129759084906159c5565b90915550505b336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e87878e8e8e8e896040516129c09796959493929190615211565b60405180910390a250506006805462ff00001916620100001790555090979650505050505050565b60065460009062010000900460ff16612a135760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612a27613dd9565b6001600160a01b038216612a4d5760405162461bcd60e51b81526004016106a39061561f565b838015801590612a5c57508087145b612a9f5760405162461bcd60e51b8152602060048201526014602482015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b60448201526064016106a3565b6000612add8989808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b9050732837c77527c37d61d9763f53005211dacb4125de63b4ff6eae6007612b036136c2565b848b8b8b6040518763ffffffff1660e01b8152600401612b289695949392919061570f565b60206040518083038186803b158015612b4057600080fd5b505af4158015612b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b789190614da6565b9250612b848484614176565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc85858c8c8c8c604051612bc7969594939291906151c9565b60405180910390a250506006805462ff00001916620100001790559695505050505050565b60065460609062010000900460ff16612c175760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612c2b613dd9565b6001600160a01b038216612c515760405162461bcd60e51b81526004016106a39061561f565b60008511612c715760405162461bcd60e51b81526004016106a39061564a565b6000612c7b6136c2565b9050612c873387613e40565b60606000732837c77527c37d61d9763f53005211dacb4125de636fdc2ea26007858b8b8b8b6040518763ffffffff1660e01b8152600401612ccd9695949392919061589d565b60006040518083038186803b158015612ce557600080fd5b505af4158015612cf9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d219190810190614dbe565b6009549096509093509091508015612d6857670de0b6b3a7640000612d468284615b14565b612d5091906159dd565b600a8054600090612d629084906159c5565b90915550505b336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e878b8689876040516118e5959493929190615261565b612db16145be565b612db96136c2565b905090565b612dc661396f565b7390ae544e8cc76d2867987ee4f5456c02c50abd8b63ceb5ad27600e612dea613f8f565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160006040518083038186803b158015612e2657600080fd5b505af4158015612e3a573d6000803e3d6000fd5b50505050565b612e4861396f565b662386f26fc10000831115612e8f5760405162461bcd60e51b815260206004820152600d60248201526c29bbb0b8103930ba329037b7b160991b60448201526064016106a3565b662386f26fc10000821115612edc5760405162461bcd60e51b81526020600482015260136024820152722932b232b6b83a34b7b7103930ba329037b7b160691b60448201526064016106a3565b6706f05b59d3b20000811115612f275760405162461bcd60e51b815260206004820152601060248201526f23b7bb103332b2903930ba329037b7b160811b60448201526064016106a3565b60078390556008829055600981905560408051848152602081018490529081018290527fe06a46af1c04656f68e4f75cbbb23baa176651c7f99930a378ef9f1616dc2b8c9060600160405180910390a1505050565b60065460009062010000900460ff16612fa75760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612fbb613dd9565b6001600160a01b038216612fe15760405162461bcd60e51b81526004016106a39061561f565b846001600160a01b0316866001600160a01b031614156130135760405162461bcd60e51b81526004016106a3906155f9565b600084116130335760405162461bcd60e51b81526004016106a39061564a565b600061303e87613876565b9050600061304b87613876565b905061305782826140cc565b6130735760405162461bcd60e51b81526004016106a3906155f9565b6000732837c77527c37d61d9763f53005211dacb4125de635c1ba5f060076130996136c2565b86868c8c8c6040518863ffffffff1660e01b81526004016130c097969594939291906157c1565b604080518083038186803b1580156130d757600080fd5b505af41580156130eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061310f9190614efb565b6009549195509150801561315257670de0b6b3a76400006131308284615b14565b61313a91906159dd565b600a805460009061314c9084906159c5565b90915550505b60208481015184820151604080516001600160a01b03938416815291831693820193909352918201879052606082018490528716608082015233907f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d9060a00160405180910390a250506006805462ff000019166201000017905550909695505050505050565b60008180158015906131ea57508085145b61322d5760405162461bcd60e51b8152602060048201526014602482015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b60448201526064016106a3565b600061326b8787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b9050732837c77527c37d61d9763f53005211dacb4125de637116e818600d8388886132946136c2565b6040518663ffffffff1660e01b81526004016132b49594939291906152ad565b60206040518083038186803b1580156132cc57600080fd5b505af41580156132e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133049190614da6565b979650505050505050565b60065460009062010000900460ff1661333a5760405162461bcd60e51b81526004016106a39061566a565b6006805462ff00001916905561334e613dd9565b6001600160a01b0382166133745760405162461bcd60e51b81526004016106a39061561f565b600084116133945760405162461bcd60e51b81526004016106a39061564a565b600061339f86613876565b9050732837c77527c37d61d9763f53005211dacb4125de636089efbc60076133c56136c2565b8489896040518663ffffffff1660e01b81526004016133e895949392919061581b565b60206040518083038186803b15801561340057600080fd5b505af4158015613414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134389190614da6565b91506134448383614176565b604080516001600160a01b0385811682526020820185905288168183015260608101879052905133917f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c7919081900360800190a2506006805462ff0000191662010000179055949350505050565b8051606090806001600160401b038111156134dd57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613506578160200160208202803683370190505b50604080516060810182526000808252602082018190529181018290529193505b828110156136ba5761355f85828151811061355257634e487b7160e01b600052603260045260246000fd5b6020026020010151613876565b9150816000015184828151811061358657634e487b7160e01b600052603260045260246000fd5b602002602001019060ff16908160ff168152505081604001516135db5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b60448201526064016106a3565b60006135e88260016159c5565b90505b838110156136a75785818151811061361357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061364457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156136955760405162461bcd60e51b815260206004820152600f60248201526e111d5c1b1a58d85d1948185cdcd95d608a1b60448201526064016106a3565b8061369f81615bf6565b9150506135eb565b50806136b281615bf6565b915050613527565b505050919050565b6136ca6145be565b60405180606001604052806007600301546136e460035490565b6136ee91906159c5565b81526020016136fb613f8f565b815260408051808201909152600f546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b600081613747670de0b6b3a764000085615b14565b610d2e91906159dd565b6001600160a01b0383166137b35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016106a3565b6001600160a01b0382166138145760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016106a3565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60408051606081018252600080825260208201819052918101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156138f9575060408051606081018252600081526001600160a01b0383166020820152600191810191909152611a3c565b6040518060600160405280600160ff168152602001836001600160a01b03168152602001836001600160a01b0316600760050160018154811061394c57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b031614905292915050565b613977614255565b6001600160a01b0316336001600160a01b0316146139d75760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e20657865637574650000000000000060448201526064016106a3565b565b6001600160a01b038316613a3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106a3565b6001600160a01b038216613a9f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106a3565b6001600160a01b03831660009081526001602052604090205481811015613b175760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016106a3565b613b218282615b33565b6001600160a01b038086166000908152600160205260408082209390935590851681529081208054849290613b579084906159c5565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613ba391815260200190565b60405180910390a350505050565b613bbd828260126142e8565b5050565b6000600160801b8210613c265760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016106a3565b5090565b801580613cb35750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613c7957600080fd5b505afa158015613c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cb19190614da6565b155b613d1e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016106a3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613d70908490614328565b505050565b6000600160401b8210613c265760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016106a3565b600654610100900460ff161580613e085750613df36143fa565b6001600160a01b0316336001600160a01b0316145b6139d75760405162461bcd60e51b8152602060048201526009602482015268556e6865616c74687960b81b60448201526064016106a3565b6001600160a01b038216613ea05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016106a3565b6001600160a01b03821660009081526001602052604090205481811015613f145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016106a3565b613f1e8282615b33565b6001600160a01b03841660009081526001602052604081209190915560038054849290613f4c908490615b33565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613869565b60408051608081018252600e546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b909104166060820181905260009290428111156140b957825160408401516000806140026001600160401b03841642615b33565b61400c8487615b4a565b6001600160401b031691509150836001600160401b0316866001600160401b0316111561407d57808261403f8689615b4a565b6001600160401b03166140529190615b14565b61405c91906159dd565b61406f906001600160401b0386166159c5565b975050505050505050610859565b80826140898887615b4a565b6001600160401b031661409c9190615b14565b6140a691906159dd565b61406f906001600160401b038616615b33565b506001600160401b031691506108599050565b600082604001511580156140e257508160400151155b156140ef5750600061086d565b82604001518015614101575081604001515b1561410e5750600161086d565b826040015180156141265750826000015160ff166001145b156141335750600161086d565b8160400151801561414b5750816000015160ff166001145b156141585750600161086d565b50600092915050565b6000610d2e8383670de0b6b3a764000061447c565b6001600160a01b0382166141cc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106a3565b80600360008282546141de91906159c5565b90915550506001600160a01b0382166000908152600160205260408120805483929061420b9084906159c5565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156142b057600080fd5b505afa1580156142c4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db991906147cd565b82516142fb906004906020860190614606565b50815161430f906005906020850190614606565b506006805460ff191660ff929092169190911790555050565b600061437d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661449b9092919063ffffffff16565b805190915015613d70578080602001905181019061439b9190614b53565b613d705760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106a3565b6040516385acd64160e01b81527f39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906385acd6419060240160206040518083038186803b1580156142b057600080fd5b6000816144898486615b14565b61449391906159dd565b949350505050565b6060614493848460008585843b6144f45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106a3565b600080866001600160a01b031685876040516145109190615174565b60006040518083038185875af1925050503d806000811461454d576040519150601f19603f3d011682016040523d82523d6000602084013e614552565b606091505b50915091506133048282866060831561456c575081610d2e565b82511561457c5782518084602001fd5b8160405162461bcd60e51b81526004016106a391906155c6565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604051806060016040528060008152602001600081526020016145b9604051806040016040528060006001600160801b0316815260200160006001600160801b031681525090565b82805461461290615bc1565b90600052602060002090601f016020900481019282614634576000855561467a565b82601f1061464d57805160ff191683800117855561467a565b8280016001018555821561467a579182015b8281111561467a57825182559160200191906001019061465f565b50613c269291505b80821115613c265760008155600101614682565b60008083601f8401126146a7578182fd5b5081356001600160401b038111156146bd578182fd5b60208301915083602080830285010111156146d757600080fd5b9250929050565b600082601f8301126146ee578081fd5b815160206147036146fe836159a2565b615972565b828152818101908583018385028701840188101561471f578586fd5b855b8581101561473d57815184529284019290840190600101614721565b5090979650505050505050565b60008083601f84011261475b578182fd5b5081356001600160401b03811115614771578182fd5b6020830191508360208285010111156146d757600080fd5b60006080828403121561479a578081fd5b50919050565b805160ff81168114611a3c57600080fd5b6000602082840312156147c2578081fd5b8135610d2e81615c3d565b6000602082840312156147de578081fd5b8151610d2e81615c3d565b600080604083850312156147fb578081fd5b823561480681615c3d565b9150602083013561481681615c3d565b809150509250929050565b600080600060608486031215614835578081fd5b833561484081615c3d565b9250602084013561485081615c3d565b929592945050506040919091013590565b600080600080600060a08688031215614878578283fd5b853561488381615c3d565b9450602086013561489381615c3d565b9350604086013592506060860135915060808601356148b181615c3d565b809150509295509295909350565b600080604083850312156148d1578182fd5b82356148dc81615c3d565b946020939093013593505050565b600080600080608085870312156148ff578182fd5b843561490a81615c3d565b93506020850135925060408501359150606085013561492881615c3d565b939692955090935050565b600080600060408486031215614947578081fd5b83356001600160401b0381111561495c578182fd5b61496886828701614696565b909450925050602084013561497c81615c3d565b809150509250925092565b6000806000806040858703121561499c578182fd5b84356001600160401b03808211156149b2578384fd5b6149be88838901614696565b909650945060208701359150808211156149d6578384fd5b506149e387828801614696565b95989497509550505050565b60008060008060008060808789031215614a07578384fd5b86356001600160401b0380821115614a1d578586fd5b614a298a838b01614696565b90985096506020890135915080821115614a41578586fd5b50614a4e89828a01614696565b909550935050604087013591506060870135614a6981615c3d565b809150509295509295509295565b60008060408385031215614a89578182fd5b82516001600160401b0380821115614a9f578384fd5b818501915085601f830112614ab2578384fd5b81516020614ac26146fe836159a2565b82815281810190858301838502870184018b1015614ade578889fd5b8896505b84871015614b0757614af3816147a0565b835260019690960195918301918301614ae2565b5091880151919650909350505080821115614b20578283fd5b50614b2d858286016146de565b9150509250929050565b600060208284031215614b48578081fd5b8135610d2e81615c52565b600060208284031215614b64578081fd5b8151610d2e81615c52565b6000806000806000806000806000898b036101c0811215614b8e578788fd5b8a356001600160401b0380821115614ba457898afd5b614bb08e838f0161474a565b909c509a5060208d0135915080821115614bc857898afd5b614bd48e838f0161474a565b909a509850889150614be98e60408f01614789565b9750614bf88e60c08f01614789565b96506101408d0135915080821115614c0e578586fd5b50614c1b8d828e01614696565b909550935050606061015f1982011215614c33578182fd5b614c3d6040615972565b6101608c01358152604061017f1983011215614c57578283fd5b614c616040615972565b91506101808c0135614c7281615c60565b82526101a08c0135614c8381615c60565b8060208401525081602082015280925050509295985092959850929598565b60008082840360c0811215614cb5578283fd5b6080811215614cc2578283fd5b614ccc6080615972565b8451614cd781615c3d565b81526020850151614ce781615c3d565b60208201526040850151614cfa81615c52565b6040820152606085015160088110614d10578485fd5b606082015292506040607f1982011215614d28578182fd5b50614d336040615972565b6080840151614d4181615c60565b815260a0840151614d5181615c60565b6020820152919491935090915050565b60008060408385031215614d73578182fd5b8235614d7e81615c60565b9150602083013561481681615c60565b600060208284031215614d9f578081fd5b5035919050565b600060208284031215614db7578081fd5b5051919050565b600080600060608486031215614dd2578081fd5b835192506020808501516001600160401b0380821115614df0578384fd5b818701915087601f830112614e03578384fd5b8151614e116146fe826159a2565b81815284810190848601868402860187018c1015614e2d578788fd5b8795505b83861015614e58578051614e4481615c3d565b835260019590950194918601918601614e31565b5060408a01519097509450505080831115614e71578384fd5b5050614e7f868287016146de565b9150509250925092565b60008060008060608587031215614e9e578182fd5b8435935060208501356001600160401b03811115614eba578283fd5b614ec687828801614696565b909450925050604085013561492881615c3d565b60008060408385031215614eec578182fd5b50508035926020909101359150565b60008060408385031215614f0d578182fd5b505080516020909101519092909150565b600080600060608486031215614f32578081fd5b505081359360208301359350604090920135919050565b600060208284031215614f5a578081fd5b610d2e826147a0565b60008284526020808501945082825b85811015614fa0578135614f8581615c3d565b6001600160a01b031687529582019590820190600101614f72565b509495945050505050565b6000815180845260208085019450808401835b83811015614fa05781516001600160a01b031687529582019590820190600101614fbe565b6000815480845260208085019450838352808320835b83811015614fa05781546001600160801b038116885260801c8388015260409096019560019182019101614ff9565b81835260006001600160fb1b03831115615040578081fd5b6020830280836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b83811015614fa05781518752958201959082019060010161506f565b6000815180845260208085019450808401835b83811015614fa057815160ff168752958201959082019060010161509e565b600881106150db57634e487b7160e01b600052602160045260246000fd5b9052565b805160ff1682526020808201516001600160a01b0316908301526040908101511515910152565b60018060a01b03808251168352806020830151166020840152506040810151151560408301526060810151613d7060608401826150bd565b80518252602081015160208301526040810151613d70604084018280516001600160801b03908116835260209182015116910152565b60008251615186818460208701615b95565b9190910192915050565b600060018060a01b0386168252846020830152608060408301526151b76080830185614fab565b8281036060840152613304818561505c565b600060018060a01b0388168252866020830152608060408301526151f1608083018688614f63565b8281036060840152615204818587615028565b9998505050505050505050565b600060018060a01b038916825287602083015260a0604083015261523960a083018789614f63565b828103606084015261524c818688615028565b91505082608083015298975050505050505050565b600060018060a01b038716825285602083015260a0604083015261528860a0830186614fab565b828103606084015261529a818661505c565b9150508260808301529695505050505050565b600060e082526152c060e0830188614fe3565b82810360208401526152d2818861508b565b905082810360408401526152e7818688615028565b9150506152f7606083018461513e565b9695505050505050565b600060e0825261531460e0830187614fe3565b602083820381850152615327828861508b565b84810360408601528651808252828801935090820190845b8181101561535b5784518352938301939183019160010161533f565b5050809350505050615370606083018461513e565b95945050505050565b600061012080835261538d8184018a614fe3565b91505060ff8716602083015260ff8616604083015284606083015283608083015261330460a083018461513e565b600060e082526153ce60e0830187614fe3565b905060ff85166020830152836040830152615370606083018461513e565b600060a082526153ff60a0830185614fe3565b9050610d2e602083018461513e565b60408082528351828201819052600091906020906060850190828801855b828110156154525761543f848351615106565b608093909301929084019060010161542c565b50505084810382860152855180825286830191830190855b818110156154a35761549383855180516001600160801b03908116835260209182015116910152565b928401929185019160010161546a565b509098975050505050505050565b84815260606020808301829052908201849052600090859060808401835b878110156154fd5783356154e281615c3d565b6001600160a01b0316825292820192908201906001016154cf565b506001600160a01b039590951660409490940193909352509195945050505050565b600060408083018184528086548083526060925082860191508785526020808620865b8381101561559f5781546001600160a01b03908116865260018301549081168487015260ff60a082901c81161515898801529061558788880160a883901c84166150bd565b50506080949094019360029190910190600101615542565b505095909501959095525092949350505050565b600060208252610d2e602083018461505c565b60006020825282518060208401526155e5816040850160208701615b95565b601f01601f19169190910160400192915050565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60c081016156af8285615106565b82516001600160801b03908116608084015260208401511660a0830152610d2e565b600060808201905082518252602083015160208301526040830151610a8c604084018280516001600160801b03908116835260209182015116910152565b6000610100888352615724602084018961513e565b8060a08401526157368184018861508b565b905082810360c084015261574b818688615028565b9150508260e0830152979650505050505050565b6000610120898352615774602084018a61513e565b8060a08401526157868184018961508b565b905082810360c084015261579b818789615028565b60e084019590955250506001600160a01b03919091166101009091015295945050505050565b8781526101c081016157d6602083018961513e565b6157e360a08301886150df565b6157f16101008301876150df565b6101608201949094526101808101929092526001600160a01b03166101a090910152949350505050565b8581526101408101615830602083018761513e565b61583d60a08301866150df565b61010082019390935261012001529392505050565b8681526101608101615867602083018861513e565b61587460a08301876150df565b6101008201949094526101208101929092526001600160a01b0316610140909101529392505050565b60006101008883526158b2602084018961513e565b8660a08401528060c08401526158cb8184018688615028565b91505060018060a01b03831660e0830152979650505050505050565b6000610160820190508882528760208301528660408301528560608301528460808301526001600160401b038085511660a08401528060208601511660c08401528060408601511660e0840152806060860151166101008401525061596661012083018480516001600160801b03908116835260209182015116910152565b98975050505050505050565b604051601f8201601f191681016001600160401b038111828210171561599a5761599a615c27565b604052919050565b60006001600160401b038211156159bb576159bb615c27565b5060209081020190565b600082198211156159d8576159d8615c11565b500190565b6000826159f857634e487b7160e01b81526012600452602481fd5b500490565b80825b6001808611615a0f5750615a3a565b818704821115615a2157615a21615c11565b80861615615a2e57918102915b9490941c938002615a00565b94509492505050565b6000610d2e60001960ff851684600082615a5f57506001610d2e565b81615a6c57506000610d2e565b8160018114615a825760028114615a8c57615ab9565b6001915050610d2e565b60ff841115615a9d57615a9d615c11565b6001841b915084821115615ab357615ab3615c11565b50610d2e565b5060208310610133831016604e8410600b8410161715615aec575081810a83811115615ae757615ae7615c11565b610d2e565b615af984848460016159fd565b808604821115615b0b57615b0b615c11565b02949350505050565b6000816000190483118215151615615b2e57615b2e615c11565b500290565b600082821015615b4557615b45615c11565b500390565b60006001600160401b0383811690831681811015615b6a57615b6a615c11565b039392505050565b600060ff821660ff841680821015615b8c57615b8c615c11565b90039392505050565b60005b83811015615bb0578181015183820152602001615b98565b83811115612e3a5750506000910152565b600281046001821680615bd557607f821691505b6020821081141561479a57634e487b7160e01b600052602260045260246000fd5b6000600019821415615c0a57615c0a615c11565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146125e557600080fd5b80151581146125e557600080fd5b6001600160801b03811681146125e557600080fdfea2646970667358221220850dd1f167ac97afe719deef338bad5974094486512a857d3b35961d8341c7f664736f6c63430008020033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102535760003560e01c806373d4a13a11610146578063a9059cbb116100c3578063c4db7fa011610087578063c4db7fa0146105c7578063cec10c11146105cf578063d5bcb9b5146105e2578063dd62ed3e146105f5578063e5555b8f1461062e578063f74bfe8e1461064157610253565b8063a9059cbb14610559578063aa5d27e91461056c578063af290bd41461057f578063c1db77ec14610592578063c3f909d4146105b257610253565b806398d5fdca1161010a57806398d5fdca146104fc57806398fec3af14610504578063a1c251511461050c578063a3f5c1d21461051f578063a457c2d71461054657610253565b806373d4a13a1461042257806378aa987e146104bc5780637e8901ea146104cf5780638456cb59146104ec57806395d89b41146104f457610253565b8063313ce567116101d457806344e3fa3c1161019857806344e3fa3c146103c55780635c975abb146103d85780636fb3e89c146103e957806370a08231146103fc57806372ea90761461040f57610253565b8063313ce5671461036157806339509351146103765780633e37bcbc146103895780633f4ba83a146103aa57806343bcfab6146103b257610253565b806318160ddd1161021b57806318160ddd146103085780631820783d146103105780631d3ce3981461032557806323b872dd1461033b57806323fb4bd31461034e57610253565b806304de5a731461025857806306fdde031461027e578063095ea7b314610293578063119849cf146102b6578063178d341f146102c9575b600080fd5b61026b610266366004614987565b610654565b6040519081526020015b60405180910390f35b6102866107c9565b60405161027591906155c6565b6102a66102a13660046148bf565b61085c565b6040519015158152602001610275565b61026b6102c43660046148bf565b610873565b6102f07f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a581565b6040516001600160a01b039091168152602001610275565b60035461026b565b61032361031e366004614d8e565b610a93565b005b61032d610b1f565b60405161027592919061540e565b6102a6610349366004614821565b610c82565b61032361035c366004614b6f565b610d35565b60065460405160ff9091168152602001610275565b6102a66103843660046148bf565b61149f565b61039c6103973660046147b1565b6114d6565b6040516102759291906156a1565b610323611674565b61026b6103c03660046148ea565b61170b565b6103236103d3366004614eda565b61190b565b6102a6600654610100900460ff1690565b6103236103f7366004614933565b6119a7565b61026b61040a3660046147b1565b611a22565b61026b61041d366004614821565b611a41565b600754600854600954600a54600b5460408051608081018252600e546001600160401b038082168352600160401b82048116602080850191909152600160801b808404831685870152600160c01b90930490911660608401528351808501909452600f546001600160801b038082168652929004909116908301526104a996959493929187565b60405161027597969594939291906158e7565b61026b6104ca3660046148bf565b611e4a565b6104d7611fd5565b60408051928352602083019190915201610275565b610323612309565b61028661239b565b6104d76123aa565b610323612445565b61032361051a366004614d61565b6125e8565b6102f07f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b6102a66105543660046148bf565b6126d4565b6102a66105673660046148bf565b61276f565b61026b61057a3660046149ef565b61277c565b61026b61058d3660046149ef565b6129e8565b6105a56105a0366004614e89565b612bec565b60405161027591906155b3565b6105ba612da9565b60405161027591906156d1565b610323612dbe565b6103236105dd366004614f1e565b612e40565b61026b6105f0366004614861565b612f7c565b61026b6106033660046147e9565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61026b61063c366004614987565b6131d9565b61026b61064f3660046148ea565b61330f565b600081801580159061066557508085145b6106ac5760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b60448201526064015b60405180910390fd5b60006106ea8787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b90506000732837c77527c37d61d9763f53005211dacb4125de637cdc8e40600d8489896107156136c2565b6040518663ffffffff1660e01b81526004016107359594939291906152ad565b60206040518083038186803b15801561074d57600080fd5b505af4158015610761573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107859190614da6565b6008549091506107a8906107a190670de0b6b3a7640000615b33565b8290613732565b935083156107be576107bb6001856159c5565b93505b505050949350505050565b6060600480546107d890615bc1565b80601f016020809104026020016040519081016040528092919081815260200182805461080490615bc1565b80156108515780601f1061082657610100808354040283529160200191610851565b820191906000526020600020905b81548152906001019060200180831161083457829003601f168201915b505050505090505b90565b6000610869338484613751565b5060015b92915050565b60008082116108945760405162461bcd60e51b81526004016106a39061564a565b600061089f84613876565b905080604001511561094b578051732837c77527c37d61d9763f53005211dacb4125de9063d1be552890600d90866108d56136c2565b6040518563ffffffff1660e01b81526004016108f494939291906153bb565b60206040518083038186803b15801561090c57600080fd5b505af4158015610920573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109449190614da6565b9150610a8c565b60405163119849cf60e01b81526001600160a01b038581166004830152602482018590526000917f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a59091169063119849cf9060440160206040518083038186803b1580156109b857600080fd5b505afa1580156109cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f09190614da6565b9050732837c77527c37d61d9763f53005211dacb4125de63d1be5528600d600084610a196136c2565b6040518563ffffffff1660e01b8152600401610a3894939291906153bb565b60206040518083038186803b158015610a5057600080fd5b505af4158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190614da6565b9250505b5092915050565b610a9b61396f565b6702c68af0bb140000811115610ae45760405162461bcd60e51b815260206004820152600e60248201526d4d757374206265203c3d2032302560901b60448201526064016106a3565b600b8190556040518181527f2f5a6b1defeafd30e7568ea5c176aa0702b0af5b00ba41fa20e58b2c72e8afe79060200160405180910390a150565b6060806007600501600760060181805480602002602001604051908101604052809291908181526020016000905b82821015610c04576000848152602090819020604080516080810182526002860290920180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115610bd257634e487b7160e01b600052602160045260246000fd5b6007811115610bf157634e487b7160e01b600052602160045260246000fd5b8152505081526020019060010190610b4d565b50505050915080805480602002602001604051908101604052809291908181526020016000905b82821015610c7457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610c2b565b505050509050915091509091565b6000610c8f8484846139d9565b6001600160a01b038416600090815260026020908152604080832033845290915290205482811015610d145760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084016106a3565b610d288533610d238685615b33565b613751565b60019150505b9392505050565b600054610100900460ff1680610d4e575060005460ff16155b610db15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106a3565b600054610100900460ff16158015610ddc576000805460ff1961ff0019909116610100171660011790555b610e4f8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600092019190915250613bb192505050565b610e656006805462ff0000191662010000179055565b6001600160a01b037f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a516610e9c60208801886147b1565b6001600160a01b031614610ee55760405162461bcd60e51b815260206004820152601060248201526f1b505cdcd95d081a5b98dbdc9c9958dd60821b60448201526064016106a3565b6040805160808101909152600c9080610f0160208a018a6147b1565b6001600160a01b03168152602001886020016020810190610f2291906147b1565b6001600160a01b0316815260006020820152604001600190528154600181810184556000938452602093849020835160029093020180546001600160a01b039384166001600160a01b031991821617825594840151918101805460408601511515600160a01b0260ff60a01b19949095169616959095179190911691909117808455606083015192939192919060ff60a81b1916600160a81b836007811115610fdb57634e487b7160e01b600052602160045260246000fd5b0217905550506040805180820182526305f5e100815260006020808301828152600d8054600181018255935292517fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5909201805493516001600160801b03199094166001600160801b03938416178316600160801b9390941692909202929092179055815160808101909252600c92508190611079908901896147b1565b6001600160a01b0316815260200187602001602081019061109a91906147b1565b6001600160a01b031681526020016110b86060890160408a01614b37565b15158152602001600190528154600181810184556000938452602093849020835160029093020180546001600160a01b039384166001600160a01b031991821617825594840151918101805460408601511515600160a01b0260ff60a01b19949095169616959095179190911691909117808455606083015192939192919060ff60a81b1916600160a81b83600781111561116357634e487b7160e01b600052602160045260246000fd5b02179055505060408051808201909152600d91508061121361118860208a018a6147b1565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156111c057600080fd5b505afa1580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f89190614f49565b61120390601a615b72565b61120e90600a615a43565b613bc1565b6001600160801b03908116825260006020928301819052845460018101865594815282812084519501805494909301518216600160801b029482166001600160801b03199094169390931716929092179091555b838110156113a55761127c60208801886147b1565b6001600160a01b0316633e37bcbc8686848181106112aa57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906112bf91906147b1565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160c06040518083038186803b1580156112fe57600080fd5b505afa158015611312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113369190614ca2565b50611393905061134960208901896147b1565b600160ff1b87878581811061136e57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061138391906147b1565b6001600160a01b03169190613c2a565b8061139d81615bf6565b915050611267565b5060006113c1606484600001516113bc9190615b14565b613d75565b604080516080810182526001600160401b039290921680835260208084018290526000928401839052606090930191909152600e805467ffffffffffffffff191682176fffffffffffffffff00000000000000001916600160401b909202919091176001600160801b03908116909155848201518051600f805492909401516001600160801b0319909216908316178216600160801b91909216021790555066016bcc41e90000600781905560085567016345785d8a0000600b8190556009558015611493576000805461ff00191690555b50505050505050505050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610869918590610d239086906159c5565b6114de614596565b604080518082019091526000808252602082015260006114fd84613876565b905080604001516115405760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b60448201526064016106a3565b8051600c8054909160ff1690811061156857634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156115e657634e487b7160e01b600052602160045260246000fd5b600781111561160557634e487b7160e01b600052602160045260246000fd5b8152505092506007600601816000015160ff168154811061163657634e487b7160e01b600052603260045260246000fd5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915292949293505050565b61167c61396f565b600654610100900460ff166116ca5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106a3565b6006805461ff00191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60065460009062010000900460ff166117365760405162461bcd60e51b81526004016106a39061566a565b6006805462ff00001916905561174a613dd9565b6001600160a01b0382166117705760405162461bcd60e51b81526004016106a39061561f565b600084116117905760405162461bcd60e51b81526004016106a39061564a565b600061179b86613876565b905060006117a76136c2565b90506117b33387613e40565b60405163f134c4fb60e01b8152600090732837c77527c37d61d9763f53005211dacb4125de9063f134c4fb906117f890600790869088908d908d908d90600401615852565b604080518083038186803b15801561180f57600080fd5b505af4158015611823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118479190614efb565b6009549195509150801561188a57670de0b6b3a76400006118688284615b14565b61187291906159dd565b600a80546000906118849084906159c5565b90915550505b602084810151604080516001600160a01b038a811682529381018c90529290911690820152606081018690526080810183905233907f105ffcfe6c5fa767ff5a53039fdd9ba80ce97196d4daa0beb1bfbfa0ed838ad89060a0015b60405180910390a250506006805462ff0000191662010000179055509095945050505050565b61191361396f565b7390ae544e8cc76d2867987ee4f5456c02c50abd8b63bd5b0ac6600e8484611939613f8f565b6040516001600160e01b031960e087901b168152600481019490945260248401929092526044830152606482810191909152608482015260a40160006040518083038186803b15801561198b57600080fd5b505af415801561199f573d6000803e3d6000fd5b505050505050565b6119af61396f565b604051637203e78b60e01b81527390ae544e8cc76d2867987ee4f5456c02c50abd8b90637203e78b906119ed90600c908790879087906004016154b1565b60006040518083038186803b158015611a0557600080fd5b505af4158015611a19573d6000803e3d6000fd5b50505050505050565b6001600160a01b0381166000908152600160205260409020545b919050565b6000826001600160a01b0316846001600160a01b03161415611a755760405162461bcd60e51b81526004016106a3906155f9565b60008211611a955760405162461bcd60e51b81526004016106a39061564a565b6000611aa085613876565b90506000611aad85613876565b9050611ab982826140cc565b611ad55760405162461bcd60e51b81526004016106a3906155f9565b81604001518015611ae7575080604001515b15611ba85781518151732837c77527c37d61d9763f53005211dacb4125de9163dce9bf6a91600d91908860ff821615611b2257600754611b25565b60005b611b2d6136c2565b6040518763ffffffff1660e01b8152600401611b4e96959493929190615379565b604080518083038186803b158015611b6557600080fd5b505af4158015611b79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9d9190614efb565b509250610d2e915050565b816040015115611cf957732837c77527c37d61d9763f53005211dacb4125de63dce9bf6a600d600160008881611bdc6136c2565b6040518763ffffffff1660e01b8152600401611bfd96959493929190615379565b604080518083038186803b158015611c1457600080fd5b505af4158015611c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4c9190614efb565b50604051633c554c3f60e11b81526001600160a01b038781166004830152602482018390529194507f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5909116906378aa987e9060440160206040518083038186803b158015611cba57600080fd5b505afa158015611cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf29190614da6565b9250611e41565b60405163119849cf60e01b81526001600160a01b038781166004830152602482018690527f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5169063119849cf9060440160206040518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d999190614da6565b9250732837c77527c37d61d9763f53005211dacb4125de63dce9bf6a60076006016000600187600760000154611dcd6136c2565b6040518763ffffffff1660e01b8152600401611dee96959493929190615379565b604080518083038186803b158015611e0557600080fd5b505af4158015611e19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3d9190614efb565b5092505b50509392505050565b6000808211611e6b5760405162461bcd60e51b81526004016106a39061564a565b6000611e7684613876565b600854909150600090611e8a908590614161565b9050732837c77527c37d61d9763f53005211dacb4125de639e60b1c560076006018460400151611ebb576000611ebe565b84515b611ec88589615b33565b611ed06136c2565b6040518563ffffffff1660e01b8152600401611eef94939291906153bb565b60206040518083038186803b158015611f0757600080fd5b505af4158015611f1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3f9190614da6565b92508160400151611fcd576020820151604051633c554c3f60e11b81526001600160a01b039182166004820152602481018590527f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5909116906378aa987e9060440160206040518083038186803b158015611fb957600080fd5b505afa158015610a64573d6000803e3d6000fd5b505092915050565b6040516385acd64160e01b81527fc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f6004820152600090819033906001600160a01b037f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb316906385acd6419060240160206040518083038186803b15801561205b57600080fd5b505afa15801561206f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209391906147cd565b6001600160a01b0316146120da5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c903b30b634b230ba37b960911b60448201526064016106a3565b6120e2613dd9565b60065462010000900460ff1661210a5760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055604051630735024560e51b815260009081907390ae544e8cc76d2867987ee4f5456c02c50abd8b9063e6a048a09061215690600c90600d9060040161551f565b60006040518083038186803b15801561216e57600080fd5b505af4158015612182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526121aa9190810190614a77565b9092509050732837c77527c37d61d9763f53005211dacb4125de637116e818600d84846121d56136c2565b6040518563ffffffff1660e01b81526004016121f49493929190615301565b60206040518083038186803b15801561220c57600080fd5b505af4158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190614da6565b600a54600354919550859161225991906159c5565b61226391906159c5565b60095490935080156122a457670de0b6b3a76400006122828287615b14565b61228c91906159dd565b600a805460009061229e9084906159c5565b90915550505b604080516000808252602082019283905230927f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc926122e99233929091908890615190565b60405180910390a250506006805462ff0000191662010000179055509091565b61231161396f565b600654610100900460ff161561235c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106a3565b6006805461ff0019166101001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001611701565b6060600580546107d890615bc1565b600080732837c77527c37d61d9763f53005211dacb4125de635dd72f5d600d6123d16136c2565b6040518363ffffffff1660e01b81526004016123ee9291906153ec565b604080518083038186803b15801561240557600080fd5b505af4158015612419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243d9190614efb565b915091509091565b6040516385acd64160e01b81527fc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f600482015233906001600160a01b037f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb316906385acd6419060240160206040518083038186803b1580156124c657600080fd5b505afa1580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe91906147cd565b6001600160a01b0316146125455760405162461bcd60e51b815260206004820152600e60248201526d27b7363c903b30b634b230ba37b960911b60448201526064016106a3565b600a5460018111156125e557600061255e600183615b33565b6001600a55905061256f3382614176565b307f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc338360006040519080825280602002602001820160405280156125be578160200160208202803683370190505b50604080516000815260208101918290526125db94939291615190565b60405180910390a2505b50565b6125f061396f565b670429d069189e0000826001600160801b03161115801561262257506709b6e64a8ec60000816001600160801b031610155b61265c5760405162461bcd60e51b815260206004820152600b60248201526a2bb2b4b3b43a399037b7b160a91b60448201526064016106a3565b6040805180820182526001600160801b038481168083528482166020938401819052600f80546001600160801b0319168317909316600160801b8202179092558351908152918201527f1633022fee8dcf5a3cdeb5f1b49d5b734a3cfef7fc093e30cfdd28ddde8cd136910160405180910390a15050565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156127565760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016106a3565b6127653385610d238685615b33565b5060019392505050565b60006108693384846139d9565b60065460009062010000900460ff166127a75760405162461bcd60e51b81526004016106a39061566a565b6006805462ff0000191690556127bb613dd9565b6001600160a01b0382166127e15760405162461bcd60e51b81526004016106a39061561f565b8380158015906127f057508087145b6128325760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908185c9c985e481a5b9c1d5d606a1b60448201526064016106a3565b600084116128525760405162461bcd60e51b81526004016106a39061564a565b60006128908989808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b90506000732837c77527c37d61d9763f53005211dacb4125de638c913b9460076128b86136c2565b858c8c8c8c6040518863ffffffff1660e01b81526004016128df979695949392919061575f565b604080518083038186803b1580156128f657600080fd5b505af415801561290a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061292e9190614efb565b909450905061293d3385613e40565b600954801561297b57670de0b6b3a76400006129598284615b14565b61296391906159dd565b600a80546000906129759084906159c5565b90915550505b336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e87878e8e8e8e896040516129c09796959493929190615211565b60405180910390a250506006805462ff00001916620100001790555090979650505050505050565b60065460009062010000900460ff16612a135760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612a27613dd9565b6001600160a01b038216612a4d5760405162461bcd60e51b81526004016106a39061561f565b838015801590612a5c57508087145b612a9f5760405162461bcd60e51b8152602060048201526014602482015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b60448201526064016106a3565b6000612add8989808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b9050732837c77527c37d61d9763f53005211dacb4125de63b4ff6eae6007612b036136c2565b848b8b8b6040518763ffffffff1660e01b8152600401612b289695949392919061570f565b60206040518083038186803b158015612b4057600080fd5b505af4158015612b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b789190614da6565b9250612b848484614176565b336001600160a01b03167f7d3ff197e9071095bd36b627028ef523ecf46fcbf17cbde745a4b65aec88b6bc85858c8c8c8c604051612bc7969594939291906151c9565b60405180910390a250506006805462ff00001916620100001790559695505050505050565b60065460609062010000900460ff16612c175760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612c2b613dd9565b6001600160a01b038216612c515760405162461bcd60e51b81526004016106a39061561f565b60008511612c715760405162461bcd60e51b81526004016106a39061564a565b6000612c7b6136c2565b9050612c873387613e40565b60606000732837c77527c37d61d9763f53005211dacb4125de636fdc2ea26007858b8b8b8b6040518763ffffffff1660e01b8152600401612ccd9695949392919061589d565b60006040518083038186803b158015612ce557600080fd5b505af4158015612cf9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d219190810190614dbe565b6009549096509093509091508015612d6857670de0b6b3a7640000612d468284615b14565b612d5091906159dd565b600a8054600090612d629084906159c5565b90915550505b336001600160a01b03167fdf5bf345d5d6eedd0e8667d799d60af65d7127e3b0417e04bef4d954d2a4750e878b8689876040516118e5959493929190615261565b612db16145be565b612db96136c2565b905090565b612dc661396f565b7390ae544e8cc76d2867987ee4f5456c02c50abd8b63ceb5ad27600e612dea613f8f565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160006040518083038186803b158015612e2657600080fd5b505af4158015612e3a573d6000803e3d6000fd5b50505050565b612e4861396f565b662386f26fc10000831115612e8f5760405162461bcd60e51b815260206004820152600d60248201526c29bbb0b8103930ba329037b7b160991b60448201526064016106a3565b662386f26fc10000821115612edc5760405162461bcd60e51b81526020600482015260136024820152722932b232b6b83a34b7b7103930ba329037b7b160691b60448201526064016106a3565b6706f05b59d3b20000811115612f275760405162461bcd60e51b815260206004820152601060248201526f23b7bb103332b2903930ba329037b7b160811b60448201526064016106a3565b60078390556008829055600981905560408051848152602081018490529081018290527fe06a46af1c04656f68e4f75cbbb23baa176651c7f99930a378ef9f1616dc2b8c9060600160405180910390a1505050565b60065460009062010000900460ff16612fa75760405162461bcd60e51b81526004016106a39061566a565b6006805462ff000019169055612fbb613dd9565b6001600160a01b038216612fe15760405162461bcd60e51b81526004016106a39061561f565b846001600160a01b0316866001600160a01b031614156130135760405162461bcd60e51b81526004016106a3906155f9565b600084116130335760405162461bcd60e51b81526004016106a39061564a565b600061303e87613876565b9050600061304b87613876565b905061305782826140cc565b6130735760405162461bcd60e51b81526004016106a3906155f9565b6000732837c77527c37d61d9763f53005211dacb4125de635c1ba5f060076130996136c2565b86868c8c8c6040518863ffffffff1660e01b81526004016130c097969594939291906157c1565b604080518083038186803b1580156130d757600080fd5b505af41580156130eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061310f9190614efb565b6009549195509150801561315257670de0b6b3a76400006131308284615b14565b61313a91906159dd565b600a805460009061314c9084906159c5565b90915550505b60208481015184820151604080516001600160a01b03938416815291831693820193909352918201879052606082018490528716608082015233907f1eeaa4acf3c225a4033105c2647625dbb298dec93b14e16253c4231e26c02b1d9060a00160405180910390a250506006805462ff000019166201000017905550909695505050505050565b60008180158015906131ea57508085145b61322d5760405162461bcd60e51b8152602060048201526014602482015273092dce0eae840c2e4e4c2f240dad2e6dac2e8c6d60631b60448201526064016106a3565b600061326b8787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506134b292505050565b9050732837c77527c37d61d9763f53005211dacb4125de637116e818600d8388886132946136c2565b6040518663ffffffff1660e01b81526004016132b49594939291906152ad565b60206040518083038186803b1580156132cc57600080fd5b505af41580156132e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133049190614da6565b979650505050505050565b60065460009062010000900460ff1661333a5760405162461bcd60e51b81526004016106a39061566a565b6006805462ff00001916905561334e613dd9565b6001600160a01b0382166133745760405162461bcd60e51b81526004016106a39061561f565b600084116133945760405162461bcd60e51b81526004016106a39061564a565b600061339f86613876565b9050732837c77527c37d61d9763f53005211dacb4125de636089efbc60076133c56136c2565b8489896040518663ffffffff1660e01b81526004016133e895949392919061581b565b60206040518083038186803b15801561340057600080fd5b505af4158015613414573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134389190614da6565b91506134448383614176565b604080516001600160a01b0385811682526020820185905288168183015260608101879052905133917f30873c596f54a2e2e09894670d7e1a48b2433c00204f81fbedf557353c36e7c7919081900360800190a2506006805462ff0000191662010000179055949350505050565b8051606090806001600160401b038111156134dd57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015613506578160200160208202803683370190505b50604080516060810182526000808252602082018190529181018290529193505b828110156136ba5761355f85828151811061355257634e487b7160e01b600052603260045260246000fd5b6020026020010151613876565b9150816000015184828151811061358657634e487b7160e01b600052603260045260246000fd5b602002602001019060ff16908160ff168152505081604001516135db5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908185cdcd95d609a1b60448201526064016106a3565b60006135e88260016159c5565b90505b838110156136a75785818151811061361357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031686838151811061364457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614156136955760405162461bcd60e51b815260206004820152600f60248201526e111d5c1b1a58d85d1948185cdcd95d608a1b60448201526064016106a3565b8061369f81615bf6565b9150506135eb565b50806136b281615bf6565b915050613527565b505050919050565b6136ca6145be565b60405180606001604052806007600301546136e460035490565b6136ee91906159c5565b81526020016136fb613f8f565b815260408051808201909152600f546001600160801b038082168352600160801b9091041660208281019190915290910152905090565b600081613747670de0b6b3a764000085615b14565b610d2e91906159dd565b6001600160a01b0383166137b35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016106a3565b6001600160a01b0382166138145760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016106a3565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60408051606081018252600080825260208201819052918101919091527f000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a56001600160a01b0316826001600160a01b031614156138f9575060408051606081018252600081526001600160a01b0383166020820152600191810191909152611a3c565b6040518060600160405280600160ff168152602001836001600160a01b03168152602001836001600160a01b0316600760050160018154811061394c57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b031614905292915050565b613977614255565b6001600160a01b0316336001600160a01b0316146139d75760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e20657865637574650000000000000060448201526064016106a3565b565b6001600160a01b038316613a3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016106a3565b6001600160a01b038216613a9f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016106a3565b6001600160a01b03831660009081526001602052604090205481811015613b175760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016106a3565b613b218282615b33565b6001600160a01b038086166000908152600160205260408082209390935590851681529081208054849290613b579084906159c5565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613ba391815260200190565b60405180910390a350505050565b613bbd828260126142e8565b5050565b6000600160801b8210613c265760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016106a3565b5090565b801580613cb35750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613c7957600080fd5b505afa158015613c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cb19190614da6565b155b613d1e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016106a3565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052613d70908490614328565b505050565b6000600160401b8210613c265760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016106a3565b600654610100900460ff161580613e085750613df36143fa565b6001600160a01b0316336001600160a01b0316145b6139d75760405162461bcd60e51b8152602060048201526009602482015268556e6865616c74687960b81b60448201526064016106a3565b6001600160a01b038216613ea05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016106a3565b6001600160a01b03821660009081526001602052604090205481811015613f145760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016106a3565b613f1e8282615b33565b6001600160a01b03841660009081526001602052604081209190915560038054849290613f4c908490615b33565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613869565b60408051608081018252600e546001600160401b038082168352600160401b8204811660208401819052600160801b8304821694840194909452600160c01b909104166060820181905260009290428111156140b957825160408401516000806140026001600160401b03841642615b33565b61400c8487615b4a565b6001600160401b031691509150836001600160401b0316866001600160401b0316111561407d57808261403f8689615b4a565b6001600160401b03166140529190615b14565b61405c91906159dd565b61406f906001600160401b0386166159c5565b975050505050505050610859565b80826140898887615b4a565b6001600160401b031661409c9190615b14565b6140a691906159dd565b61406f906001600160401b038616615b33565b506001600160401b031691506108599050565b600082604001511580156140e257508160400151155b156140ef5750600061086d565b82604001518015614101575081604001515b1561410e5750600161086d565b826040015180156141265750826000015160ff166001145b156141335750600161086d565b8160400151801561414b5750816000015160ff166001145b156141585750600161086d565b50600092915050565b6000610d2e8383670de0b6b3a764000061447c565b6001600160a01b0382166141cc5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106a3565b80600360008282546141de91906159c5565b90915550506001600160a01b0382166000908152600160205260408120805483929061420b9084906159c5565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156142b057600080fd5b505afa1580156142c4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db991906147cd565b82516142fb906004906020860190614606565b50815161430f906005906020850190614606565b506006805460ff191660ff929092169190911790555050565b600061437d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661449b9092919063ffffffff16565b805190915015613d70578080602001905181019061439b9190614b53565b613d705760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106a3565b6040516385acd64160e01b81527f39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f60048201526000907f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316906385acd6419060240160206040518083038186803b1580156142b057600080fd5b6000816144898486615b14565b61449391906159dd565b949350505050565b6060614493848460008585843b6144f45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106a3565b600080866001600160a01b031685876040516145109190615174565b60006040518083038185875af1925050503d806000811461454d576040519150601f19603f3d011682016040523d82523d6000602084013e614552565b606091505b50915091506133048282866060831561456c575081610d2e565b82511561457c5782518084602001fd5b8160405162461bcd60e51b81526004016106a391906155c6565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b604051806060016040528060008152602001600081526020016145b9604051806040016040528060006001600160801b0316815260200160006001600160801b031681525090565b82805461461290615bc1565b90600052602060002090601f016020900481019282614634576000855561467a565b82601f1061464d57805160ff191683800117855561467a565b8280016001018555821561467a579182015b8281111561467a57825182559160200191906001019061465f565b50613c269291505b80821115613c265760008155600101614682565b60008083601f8401126146a7578182fd5b5081356001600160401b038111156146bd578182fd5b60208301915083602080830285010111156146d757600080fd5b9250929050565b600082601f8301126146ee578081fd5b815160206147036146fe836159a2565b615972565b828152818101908583018385028701840188101561471f578586fd5b855b8581101561473d57815184529284019290840190600101614721565b5090979650505050505050565b60008083601f84011261475b578182fd5b5081356001600160401b03811115614771578182fd5b6020830191508360208285010111156146d757600080fd5b60006080828403121561479a578081fd5b50919050565b805160ff81168114611a3c57600080fd5b6000602082840312156147c2578081fd5b8135610d2e81615c3d565b6000602082840312156147de578081fd5b8151610d2e81615c3d565b600080604083850312156147fb578081fd5b823561480681615c3d565b9150602083013561481681615c3d565b809150509250929050565b600080600060608486031215614835578081fd5b833561484081615c3d565b9250602084013561485081615c3d565b929592945050506040919091013590565b600080600080600060a08688031215614878578283fd5b853561488381615c3d565b9450602086013561489381615c3d565b9350604086013592506060860135915060808601356148b181615c3d565b809150509295509295909350565b600080604083850312156148d1578182fd5b82356148dc81615c3d565b946020939093013593505050565b600080600080608085870312156148ff578182fd5b843561490a81615c3d565b93506020850135925060408501359150606085013561492881615c3d565b939692955090935050565b600080600060408486031215614947578081fd5b83356001600160401b0381111561495c578182fd5b61496886828701614696565b909450925050602084013561497c81615c3d565b809150509250925092565b6000806000806040858703121561499c578182fd5b84356001600160401b03808211156149b2578384fd5b6149be88838901614696565b909650945060208701359150808211156149d6578384fd5b506149e387828801614696565b95989497509550505050565b60008060008060008060808789031215614a07578384fd5b86356001600160401b0380821115614a1d578586fd5b614a298a838b01614696565b90985096506020890135915080821115614a41578586fd5b50614a4e89828a01614696565b909550935050604087013591506060870135614a6981615c3d565b809150509295509295509295565b60008060408385031215614a89578182fd5b82516001600160401b0380821115614a9f578384fd5b818501915085601f830112614ab2578384fd5b81516020614ac26146fe836159a2565b82815281810190858301838502870184018b1015614ade578889fd5b8896505b84871015614b0757614af3816147a0565b835260019690960195918301918301614ae2565b5091880151919650909350505080821115614b20578283fd5b50614b2d858286016146de565b9150509250929050565b600060208284031215614b48578081fd5b8135610d2e81615c52565b600060208284031215614b64578081fd5b8151610d2e81615c52565b6000806000806000806000806000898b036101c0811215614b8e578788fd5b8a356001600160401b0380821115614ba457898afd5b614bb08e838f0161474a565b909c509a5060208d0135915080821115614bc857898afd5b614bd48e838f0161474a565b909a509850889150614be98e60408f01614789565b9750614bf88e60c08f01614789565b96506101408d0135915080821115614c0e578586fd5b50614c1b8d828e01614696565b909550935050606061015f1982011215614c33578182fd5b614c3d6040615972565b6101608c01358152604061017f1983011215614c57578283fd5b614c616040615972565b91506101808c0135614c7281615c60565b82526101a08c0135614c8381615c60565b8060208401525081602082015280925050509295985092959850929598565b60008082840360c0811215614cb5578283fd5b6080811215614cc2578283fd5b614ccc6080615972565b8451614cd781615c3d565b81526020850151614ce781615c3d565b60208201526040850151614cfa81615c52565b6040820152606085015160088110614d10578485fd5b606082015292506040607f1982011215614d28578182fd5b50614d336040615972565b6080840151614d4181615c60565b815260a0840151614d5181615c60565b6020820152919491935090915050565b60008060408385031215614d73578182fd5b8235614d7e81615c60565b9150602083013561481681615c60565b600060208284031215614d9f578081fd5b5035919050565b600060208284031215614db7578081fd5b5051919050565b600080600060608486031215614dd2578081fd5b835192506020808501516001600160401b0380821115614df0578384fd5b818701915087601f830112614e03578384fd5b8151614e116146fe826159a2565b81815284810190848601868402860187018c1015614e2d578788fd5b8795505b83861015614e58578051614e4481615c3d565b835260019590950194918601918601614e31565b5060408a01519097509450505080831115614e71578384fd5b5050614e7f868287016146de565b9150509250925092565b60008060008060608587031215614e9e578182fd5b8435935060208501356001600160401b03811115614eba578283fd5b614ec687828801614696565b909450925050604085013561492881615c3d565b60008060408385031215614eec578182fd5b50508035926020909101359150565b60008060408385031215614f0d578182fd5b505080516020909101519092909150565b600080600060608486031215614f32578081fd5b505081359360208301359350604090920135919050565b600060208284031215614f5a578081fd5b610d2e826147a0565b60008284526020808501945082825b85811015614fa0578135614f8581615c3d565b6001600160a01b031687529582019590820190600101614f72565b509495945050505050565b6000815180845260208085019450808401835b83811015614fa05781516001600160a01b031687529582019590820190600101614fbe565b6000815480845260208085019450838352808320835b83811015614fa05781546001600160801b038116885260801c8388015260409096019560019182019101614ff9565b81835260006001600160fb1b03831115615040578081fd5b6020830280836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b83811015614fa05781518752958201959082019060010161506f565b6000815180845260208085019450808401835b83811015614fa057815160ff168752958201959082019060010161509e565b600881106150db57634e487b7160e01b600052602160045260246000fd5b9052565b805160ff1682526020808201516001600160a01b0316908301526040908101511515910152565b60018060a01b03808251168352806020830151166020840152506040810151151560408301526060810151613d7060608401826150bd565b80518252602081015160208301526040810151613d70604084018280516001600160801b03908116835260209182015116910152565b60008251615186818460208701615b95565b9190910192915050565b600060018060a01b0386168252846020830152608060408301526151b76080830185614fab565b8281036060840152613304818561505c565b600060018060a01b0388168252866020830152608060408301526151f1608083018688614f63565b8281036060840152615204818587615028565b9998505050505050505050565b600060018060a01b038916825287602083015260a0604083015261523960a083018789614f63565b828103606084015261524c818688615028565b91505082608083015298975050505050505050565b600060018060a01b038716825285602083015260a0604083015261528860a0830186614fab565b828103606084015261529a818661505c565b9150508260808301529695505050505050565b600060e082526152c060e0830188614fe3565b82810360208401526152d2818861508b565b905082810360408401526152e7818688615028565b9150506152f7606083018461513e565b9695505050505050565b600060e0825261531460e0830187614fe3565b602083820381850152615327828861508b565b84810360408601528651808252828801935090820190845b8181101561535b5784518352938301939183019160010161533f565b5050809350505050615370606083018461513e565b95945050505050565b600061012080835261538d8184018a614fe3565b91505060ff8716602083015260ff8616604083015284606083015283608083015261330460a083018461513e565b600060e082526153ce60e0830187614fe3565b905060ff85166020830152836040830152615370606083018461513e565b600060a082526153ff60a0830185614fe3565b9050610d2e602083018461513e565b60408082528351828201819052600091906020906060850190828801855b828110156154525761543f848351615106565b608093909301929084019060010161542c565b50505084810382860152855180825286830191830190855b818110156154a35761549383855180516001600160801b03908116835260209182015116910152565b928401929185019160010161546a565b509098975050505050505050565b84815260606020808301829052908201849052600090859060808401835b878110156154fd5783356154e281615c3d565b6001600160a01b0316825292820192908201906001016154cf565b506001600160a01b039590951660409490940193909352509195945050505050565b600060408083018184528086548083526060925082860191508785526020808620865b8381101561559f5781546001600160a01b03908116865260018301549081168487015260ff60a082901c81161515898801529061558788880160a883901c84166150bd565b50506080949094019360029190910190600101615542565b505095909501959095525092949350505050565b600060208252610d2e602083018461505c565b60006020825282518060208401526155e5816040850160208701615b95565b601f01601f19169190910160400192915050565b6020808252600c908201526b24b73b30b634b2103830b4b960a11b604082015260600190565b602080825260119082015270125b9d985b1a59081c9958da5c1a595b9d607a1b604082015260600190565b60208082526006908201526505174793d3d360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60c081016156af8285615106565b82516001600160801b03908116608084015260208401511660a0830152610d2e565b600060808201905082518252602083015160208301526040830151610a8c604084018280516001600160801b03908116835260209182015116910152565b6000610100888352615724602084018961513e565b8060a08401526157368184018861508b565b905082810360c084015261574b818688615028565b9150508260e0830152979650505050505050565b6000610120898352615774602084018a61513e565b8060a08401526157868184018961508b565b905082810360c084015261579b818789615028565b60e084019590955250506001600160a01b03919091166101009091015295945050505050565b8781526101c081016157d6602083018961513e565b6157e360a08301886150df565b6157f16101008301876150df565b6101608201949094526101808101929092526001600160a01b03166101a090910152949350505050565b8581526101408101615830602083018761513e565b61583d60a08301866150df565b61010082019390935261012001529392505050565b8681526101608101615867602083018861513e565b61587460a08301876150df565b6101008201949094526101208101929092526001600160a01b0316610140909101529392505050565b60006101008883526158b2602084018961513e565b8660a08401528060c08401526158cb8184018688615028565b91505060018060a01b03831660e0830152979650505050505050565b6000610160820190508882528760208301528660408301528560608301528460808301526001600160401b038085511660a08401528060208601511660c08401528060408601511660e0840152806060860151166101008401525061596661012083018480516001600160801b03908116835260209182015116910152565b98975050505050505050565b604051601f8201601f191681016001600160401b038111828210171561599a5761599a615c27565b604052919050565b60006001600160401b038211156159bb576159bb615c27565b5060209081020190565b600082198211156159d8576159d8615c11565b500190565b6000826159f857634e487b7160e01b81526012600452602481fd5b500490565b80825b6001808611615a0f5750615a3a565b818704821115615a2157615a21615c11565b80861615615a2e57918102915b9490941c938002615a00565b94509492505050565b6000610d2e60001960ff851684600082615a5f57506001610d2e565b81615a6c57506000610d2e565b8160018114615a825760028114615a8c57615ab9565b6001915050610d2e565b60ff841115615a9d57615a9d615c11565b6001841b915084821115615ab357615ab3615c11565b50610d2e565b5060208310610133831016604e8410600b8410161715615aec575081810a83811115615ae757615ae7615c11565b610d2e565b615af984848460016159fd565b808604821115615b0b57615b0b615c11565b02949350505050565b6000816000190483118215151615615b2e57615b2e615c11565b500290565b600082821015615b4557615b45615c11565b500390565b60006001600160401b0383811690831681811015615b6a57615b6a615c11565b039392505050565b600060ff821660ff841680821015615b8c57615b8c615c11565b90039392505050565b60005b83811015615bb0578181015183820152602001615b98565b83811115612e3a5750506000910152565b600281046001821680615bd557607f821691505b6020821081141561479a57634e487b7160e01b600052602260045260246000fd5b6000600019821415615c0a57615c0a615c11565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146125e557600080fd5b80151581146125e557600080fd5b6001600160801b03811681146125e557600080fdfea2646970667358221220850dd1f167ac97afe719deef338bad5974094486512a857d3b35961d8341c7f664736f6c63430008020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5
-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3
Arg [1] : _mAsset (address): 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Arg [1] : 000000000000000000000000e2f2a5c287993345a840db3b0845fbc70f5935a5
Libraries Used
FeederManager : 0x90ae544e8cc76d2867987ee4f5456c02c50abd8bFeederLogic : 0x2837c77527c37d61d9763f53005211dacb4125de
Deployed Bytecode Sourcemap
105283:31633:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126686:739;;;;;;:::i;:::-;;:::i;:::-;;;37064:25:1;;;37052:2;37037:18;126686:739:0;;;;;;;;28911:83;;;:::i;:::-;;;;;;;:::i;22467:169::-;;;;;;:::i;:::-;;:::i;:::-;;;36891:14:1;;36884:22;36866:41;;36854:2;36839:18;22467:169:0;36821:92:1;113400:711:0;;;;;;:::i;:::-;;:::i;107069:40::-;;;;;;;;-1:-1:-1;;;;;20896:32:1;;;20878:51;;20866:2;20851:18;107069:40:0;20833:102:1;21420:108:0;21508:12;;21420:108;;134166:214;;;;;;:::i;:::-;;:::i;:::-;;128934:215;;;:::i;:::-;;;;;;;;:::i;23118:422::-;;;;;;:::i;:::-;;:::i;108047:1483::-;;;;;;:::i;:::-;;:::i;29763:83::-;29829:9;;29763:83;;29829:9;;;;59746:36:1;;59734:2;59719:18;29763:83:0;59701:87:1;23949:215:0;;;;;;:::i;:::-;;:::i;128358:378::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;36717:122::-;;;:::i;120560:1157::-;;;;;;:::i;:::-;;:::i;136481:185::-;;;;;;:::i;:::-;;:::i;36326:80::-;;36391:7;;;;;;;;36326:80;136068:218;;;;;;:::i;:::-;;:::i;21591:127::-;;;;;;:::i;:::-;;:::i;117294:1749::-;;;;;;:::i;:::-;;:::i;107144:22::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;107144:22:0;;;;;-1:-1:-1;;;107144:22:0;;;;;;;;;;;;-1:-1:-1;;;107144:22:0;;;;;;;;;-1:-1:-1;;;107144:22:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;107144:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;125623:738::-;;;;;;:::i;:::-;;:::i;132245:913::-;;;:::i;:::-;;;;51303:25:1;;;51359:2;51344:18;;51337:34;;;;51276:18;132245:913:0;51258:119:1;36502:120:0;;;:::i;29113:87::-;;;:::i;127739:157::-;;;:::i;133278:487::-;;;:::i;135350:252::-;;;;;;:::i;:::-;;:::i;32608:29::-;;;;;24667:377;;;;;;:::i;:::-;;:::i;21931:175::-;;;;;;:::i;:::-;;:::i;124075:1228::-;;;;;;:::i;:::-;;:::i;112265:852::-;;;;;;:::i;:::-;;:::i;122256:1147::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;127998:119::-;;;:::i;:::-;;;;;;;:::i;136805:108::-;;;:::i;134682:497::-;;;;;;:::i;:::-;;:::i;115732:1090::-;;;;;;:::i;:::-;;:::i;22169:151::-;;;;;;:::i;:::-;-1:-1:-1;;;;;22285:18:0;;;22258:7;22285:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;22169:151;114487:490;;;;;;:::i;:::-;;:::i;110929:727::-;;;;;;:::i;:::-;;:::i;126686:739::-;126847:23;126897:17;126940:7;;;;;:33;;-1:-1:-1;126951:22:0;;;126940:33;126932:65;;;;-1:-1:-1;;;126932:65:0;;43458:2:1;126932:65:0;;;43440:21:1;43497:2;43477:18;;;43470:30;-1:-1:-1;;;43516:18:1;;;43509:49;43575:18;;126932:65:0;;;;;;;;;127010:22;127035:20;127046:8;;127035:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;127035:10:0;;-1:-1:-1;;;127035:20:0:i;:::-;127010:45;-1:-1:-1;127068:22:0;127106:11;:30;127155:15;127010:45;127215:17;;127251:12;:10;:12::i;:::-;127106:172;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127342:18;;127068:210;;-1:-1:-1;127307:54:0;;127335:25;;:4;:25;:::i;:::-;127307:14;;:27;:54::i;:::-;127289:72;-1:-1:-1;127376:19:0;;127372:45;;127397:20;127416:1;127397:20;;:::i;:::-;;;127372:45;126686:739;;;;;;;;;:::o;28911:83::-;28948:13;28981:5;28974:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28911:83;;:::o;22467:169::-;22550:4;22567:39;18253:10;22590:7;22599:6;22567:8;:39::i;:::-;-1:-1:-1;22624:4:0;22467:169;;;;;:::o;113400:711::-;113531:18;113592:1;113575:14;:18;113567:37;;;;-1:-1:-1;;;113567:37:0;;;;;;;:::i;:::-;113617:18;113638:17;113648:6;113638:9;:17::i;:::-;113617:38;;113672:5;:12;;;113668:436;;;113790:9;;113714:11;;:23;;113756:15;;113818:14;113851:12;:10;:12::i;:::-;113714:164;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113701:177;;113668:436;;;113937:53;;-1:-1:-1;;;113937:53:0;;-1:-1:-1;;;;;22622:32:1;;;113937:53:0;;;22604:51:1;22671:18;;;22664:34;;;113911:23:0;;113945:6;113937:29;;;;;;22577:18:1;;113937:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;113911:79;-1:-1:-1;114018:11:0;:23;114042:15;114059:1;113911:79;114079:12;:10;:12::i;:::-;114018:74;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114005:87;;113668:436;;113400:711;;;;;:::o;134166:214::-;33042:15;:13;:15::i;:::-;134263:4:::1;134249:10;:18;;134241:45;;;::::0;-1:-1:-1;;;134241:45:0;;44898:2:1;134241:45:0::1;::::0;::::1;44880:21:1::0;44937:2;44917:18;;;44910:30;-1:-1:-1;;;44956:18:1;;;44949:44;45010:18;;134241:45:0::1;44870:164:1::0;134241:45:0::1;134299:14:::0;:27;;;134344:28:::1;::::0;37064:25:1;;;134344:28:0::1;::::0;37052:2:1;37037:18;134344:28:0::1;;;;;;;134166:214:::0;:::o;128934:215::-;129024:23;129049:29;129104:4;:19;;129125:4;:15;;129096:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;129096:45:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;129096:45:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;129096:45:0;;;;;;;;;;-1:-1:-1;;;129096:45:0;;;;;;;;;;;;;;;-1:-1:-1;;;129096:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;129096:45:0;;;;;-1:-1:-1;;;129096:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128934:215;;:::o;23118:422::-;23224:4;23241:36;23251:6;23259:9;23270:6;23241:9;:36::i;:::-;-1:-1:-1;;;;;23317:19:0;;23290:24;23317:19;;;:11;:19;;;;;;;;18253:10;23317:33;;;;;;;;23369:26;;;;23361:79;;;;-1:-1:-1;;;23361:79:0;;45648:2:1;23361:79:0;;;45630:21:1;45687:2;45667:18;;;45660:30;45726:34;45706:18;;;45699:62;-1:-1:-1;;;45777:18:1;;;45770:38;45825:19;;23361:79:0;45620:230:1;23361:79:0;23451:57;23460:6;18253:10;23482:25;23501:6;23482:16;:25;:::i;:::-;23451:8;:57::i;:::-;23528:4;23521:11;;;23118:422;;;;;;:::o;108047:1483::-;17024:13;;;;;;;;:30;;-1:-1:-1;17042:12:0;;;;17041:13;17024:30;17016:89;;;;-1:-1:-1;;;17016:89:0;;44483:2:1;17016:89:0;;;44465:21:1;44522:2;44502:18;;;44495:30;44561:34;44541:18;;;44534:62;-1:-1:-1;;;44612:18:1;;;44605:44;44666:19;;17016:89:0;44455:236:1;17016:89:0;17118:19;17141:13;;;;;;17140:14;17165:101;;;;17200:13;:20;;-1:-1:-1;;;;17200:20:0;;;;;17235:19;17216:4;17235:19;;;17165:101;108336:52:::1;108367:8;;108336:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;108336:52:0::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;-1:-1:-1;108377:10:0;;-1:-1:-1;108377:10:0;;;;108336:52;::::1;108377:10:::0;;;;108336:52;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;108336:30:0::1;::::0;-1:-1:-1;;;108336:52:0:i:1;:::-;108401:28;37400:11:::0;:18;;-1:-1:-1;;37400:18:0;;;;;36924:502;108401:28:::1;-1:-1:-1::0;;;;;108466:6:0::1;108450:22;:12;;::::0;::::1;:7:::0;:12:::1;:::i;:::-;-1:-1:-1::0;;;;;108450:22:0::1;;108442:51;;;::::0;-1:-1:-1;;;108442:51:0;;48663:2:1;108442:51:0::1;::::0;::::1;48645:21:1::0;48702:2;48682:18;;;48675:30;-1:-1:-1;;;48721:18:1;;;48714:46;48777:18;;108442:51:0::1;48635:166:1::0;108442:51:0::1;108543:76;::::0;;::::1;::::0;::::1;::::0;;;108504:19;;108543:76;108558:12:::1;;::::0;::::1;:7:::0;:12:::1;:::i;:::-;-1:-1:-1::0;;;;;108543:76:0::1;;;;;108572:7;:18;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;108543:76:0::1;::::0;;108592:5:::1;108543:76;::::0;::::1;::::0;;;;;;108504:126;;::::1;::::0;;::::1;::::0;;-1:-1:-1;108504:126:0;;;::::1;::::0;;;;;;::::1;::::0;;::::1;;::::0;;-1:-1:-1;;;;;108504:126:0;;::::1;-1:-1:-1::0;;;;;;108504:126:0;;::::1;;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;;-1:-1:-1::0;;;108504:126:0::1;-1:-1:-1::0;;;;108504:126:0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;;;;-1:-1:-1;;;;108504:126:0::1;-1:-1:-1::0;;;108504:126:0;::::1;::::0;::::1;;;;-1:-1:-1::0;;;108504:126:0::1;;;;;;;;;;;::::0;;-1:-1:-1;;108662:18:0::1;::::0;;;;::::1;::::0;;108673:3:::1;108662:18:::0;;-1:-1:-1;108662:18:0::1;::::0;;::::1;::::0;;;108641:15;:40;;::::1;::::0;::::1;::::0;;;;;;;;;::::1;::::0;;;;-1:-1:-1;;;;;;108641:40:0;;::::1;-1:-1:-1::0;;;;;108641:40:0;;::::1;;::::0;::::1;-1:-1:-1::0;;;108641:40:0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;108731:87;;::::1;::::0;::::1;::::0;;;108692:19;;-1:-1:-1;108731:87:0;;108746:12:::1;::::0;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;;;108731:87:0::1;;;;;108760:7;:18;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;108731:87:0::1;::::0;;::::1;;108780:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;108731:87;;::::0;;::::1;;108798:19;108731:87:::0;;108692:137;;::::1;::::0;;::::1;::::0;;-1:-1:-1;108692:137:0;;;::::1;::::0;;;;;;::::1;::::0;;::::1;;::::0;;-1:-1:-1;;;;;108692:137:0;;::::1;-1:-1:-1::0;;;;;;108692:137:0;;::::1;;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;;-1:-1:-1::0;;;108692:137:0::1;-1:-1:-1::0;;;;108692:137:0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;;;;-1:-1:-1;;;;108692:137:0::1;-1:-1:-1::0;;;108692:137:0;::::1;::::0;::::1;;;;-1:-1:-1::0;;;108692:137:0::1;;;;;;;;;;;::::0;;-1:-1:-1;;108875:82:0::1;::::0;;;;::::1;::::0;;;108840:15;;-1:-1:-1;108875:82:0;108886:67:::1;108927:12;;::::0;::::1;:7:::0;:12:::1;:::i;:::-;-1:-1:-1::0;;;;;108915:34:0::1;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;108910:41;::::0;:2:::1;:41;:::i;:::-;108905:47;::::0;:2:::1;:47;:::i;:::-;108886:18;:67::i;:::-;-1:-1:-1::0;;;;;108875:82:0;;::::1;::::0;;108955:1:::1;108875:82;::::0;;::::1;::::0;;;108840:128;;::::1;::::0;::::1;::::0;;;;;;;;;;;::::1;::::0;;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;108840:128:0::1;::::0;;::::1;-1:-1:-1::0;;;;;;108840:128:0;;::::1;::::0;;;::::1;;::::0;;;::::1;::::0;;;108979:244:::1;108999:20:::0;;::::1;108979:244;;;109105:12;;::::0;::::1;:7:::0;:12:::1;:::i;:::-;-1:-1:-1::0;;;;;109097:31:0::1;;109129:9;;109139:1;109129:12;;;;;-1:-1:-1::0;;;109129:12:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;109097:45;::::0;-1:-1:-1;;;;;;109097:45:0::1;::::0;;;;;;-1:-1:-1;;;;;20896:32:1;;;109097:45:0::1;::::0;::::1;20878:51:1::0;20851:18;;109097:45:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;109157:54:0::1;::::0;-1:-1:-1;109190:12:0::1;;::::0;::::1;:7:::0;:12:::1;:::i;:::-;-1:-1:-1::0;;;109164:9:0::1;;109174:1;109164:12;;;;;-1:-1:-1::0;;;109164:12:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;109157:32:0::1;::::0;:54;:32:::1;:54::i;:::-;109021:3:::0;::::1;::::0;::::1;:::i;:::-;;;;108979:244;;;;109235:13;109251:42;107059:3;109269:7;:9;;;:23;;;;:::i;:::-;109251:17;:42::i;:::-;109319:29;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;;;;;109319:29:0;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;-1:-1:-1;109319:29:0;;;;;;;;;;;;;;109304:12;:44;;-1:-1:-1;;109304:44:0::1;::::0;::::1;-1:-1:-1::0;;109304:44:0::1;-1:-1:-1::0;;;109304:44:0;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;109304:44:0;;;;;;109379:14;;::::1;::::0;109359:34;;:17;:34;;;;;::::1;::::0;-1:-1:-1;;;;;;109359:34:0;;::::1;::::0;;::::1;;::::0;::::1;-1:-1:-1::0;;;109359:34:0;;;::::1;;;::::0;;-1:-1:-1;109421:4:0::1;109304;109406:19:::0;;;-1:-1:-1;109436:25:0;109489:4:::1;109472:14:::0;:21;;;109504:11;:18;17292:68;;;;17343:5;17327:21;;-1:-1:-1;;17327:21:0;;;17292:68;108047:1483;;;;;;;;;;:::o;23949:215::-;18253:10;24037:4;24086:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;24086:34:0;;;;;;;;;;24037:4;;24054:80;;24077:7;;24086:47;;24123:10;;24086:47;:::i;128358:378::-;128462:30;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;128539:18:0;128560;128570:7;128560:9;:18::i;:::-;128539:39;;128597:5;:12;;;128589:38;;;;-1:-1:-1;;;128589:38:0;;38666:2:1;128589:38:0;;;38648:21:1;38705:2;38685:18;;;38678:30;-1:-1:-1;;;38724:18:1;;;38717:43;38777:18;;128589:38:0;38638:163:1;128589:38:0;128669:9;;128649:19;:30;;:19;;:30;;;;;;;-1:-1:-1;;;128649:30:0;;;;;;;;;;;;;;;;;;128638:41;;;;;;;;128649:30;;;;;;;128638:41;;-1:-1:-1;;;;;128638:41:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;128638:41:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;128638:41:0;;;;;;;;;;-1:-1:-1;;;128638:41:0;;;;;;;;;;;;;;;-1:-1:-1;;;128638:41:0;;;;;;;;;;;;;;;128702:4;:15;;128718:5;:9;;;128702:26;;;;;;;;-1:-1:-1;;;128702:26:0;;;;;;;;;;;;;;;;;;128690:38;;;;;;;;;128702:26;;128690:38;-1:-1:-1;;;;;128690:38:0;;;;;-1:-1:-1;;;128690:38:0;;;;;;;;;;;128358:378;;128690:38;;-1:-1:-1;;;128358:378:0:o;36717:122::-;33042:15;:13;:15::i;:::-;35830:7:::1;::::0;::::1;::::0;::::1;;;35822:40;;;::::0;-1:-1:-1;;;35822:40:0;;38317:2:1;35822:40:0::1;::::0;::::1;38299:21:1::0;38356:2;38336:18;;;38329:30;-1:-1:-1;;;38375:18:1;;;38368:50;38435:18;;35822:40:0::1;38289:170:1::0;35822:40:0::1;36780:7:::2;:15:::0;;-1:-1:-1;;36780:15:0::2;::::0;;36811:20:::2;::::0;36820:10:::2;20878:51:1::0;;36811:20:0::2;::::0;20866:2:1;20851:18;36811:20:0::2;;;;;;;;36717:122::o:0;120560:1157::-;37925:11;;120766:22;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;120809:24:0;::::2;120801:54;;;;-1:-1:-1::0;;;120801:54:0::2;;;;;;;:::i;:::-;120893:1;120874:16;:20;120866:39;;;;-1:-1:-1::0;;;120866:39:0::2;;;;;;;:::i;:::-;120918:19;120940:18;120950:7;120940:9;:18::i;:::-;120918:40;;121036:26;121065:12;:10;:12::i;:::-;121036:41;;121088:35;121094:10;121106:16;121088:5;:35::i;:::-;121192:179;::::0;-1:-1:-1;;;121192:179:0;;121136:16:::2;::::0;121192:11:::2;::::0;:18:::2;::::0;:179:::2;::::0;121225:4:::2;::::0;121244:6;;121265;;121286:16;;121317:18;;121350:10;;121192:179:::2;;;:::i;:::-;;::::0;::::2;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;121401:11:::0;;121163:208;;-1:-1:-1;121163:208:0;-1:-1:-1;121427:10:0;;121423:91:::2;;121497:4;121476:17;121487:6:::0;121476:8;:17:::2;:::i;:::-;121475:26;;;;:::i;:::-;121454:16:::0;:48;;:16:::2;::::0;:48:::2;::::0;;;::::2;:::i;:::-;::::0;;;-1:-1:-1;;121423:91:0::2;121635:11;::::0;;::::2;::::0;121531:178:::2;::::0;;-1:-1:-1;;;;;23476:15:1;;;23458:34;;23508:18;;;23501:34;;;23571:15;;;;23551:18;;;23544:43;23618:2;23603:18;;23596:34;;;23661:3;23646:19;;23639:35;;;121554:10:0::2;::::0;121531:178:::2;::::0;23407:3:1;23392:19;121531:178:0::2;;;;;;;;-1:-1:-1::0;;38230:11:0;:18;;-1:-1:-1;;38230:18:0;;;;;-1:-1:-1;120560:1157:0;;;-1:-1:-1;;;;;120560:1157:0:o;136481:185::-;33042:15;:13;:15::i;:::-;136574:13:::1;:24;136599:12:::0;136613:8;136623:12;136637:7:::1;:5;:7::i;:::-;136574:84;::::0;-1:-1:-1;;;;;;136574:84:0::1;::::0;;;;;;::::1;::::0;::::1;51670:25:1::0;;;;51711:18;;;51704:34;;;;51754:18;;;51747:34;107059:3:0::1;51797:18:1::0;;;51790:34;;;;51840:19;;;51833:35;51642:19;;136574:84:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;136481:185:::0;;:::o;136068:218::-;33042:15;:13;:15::i;:::-;136202:76:::1;::::0;-1:-1:-1;;;136202:76:0;;:13:::1;::::0;:28:::1;::::0;:76:::1;::::0;136231:19;;136252:8;;;;136262:15;;136202:76:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;136068:218:::0;;;:::o;21591:127::-;-1:-1:-1;;;;;21692:18:0;;21665:7;21692:18;;;:9;:18;;;;;;21591:127;;;;:::o;117294:1749::-;117440:18;117489:7;-1:-1:-1;;;;;117479:17:0;:6;-1:-1:-1;;;;;117479:17:0;;;117471:42;;;;-1:-1:-1;;;117471:42:0;;;;;;;:::i;:::-;117549:1;117532:14;:18;117524:37;;;;-1:-1:-1;;;117524:37:0;;;;;;;:::i;:::-;117574:18;117595:17;117605:6;117595:9;:17::i;:::-;117574:38;;117623:19;117645:18;117655:7;117645:9;:18::i;:::-;117623:40;;117682:27;117695:5;117702:6;117682:12;:27::i;:::-;117674:52;;;;-1:-1:-1;;;117674:52:0;;;;;;;:::i;:::-;117795:5;:12;;;:29;;;;;117811:6;:13;;;117795:29;117791:357;;;117934:9;;117962:10;;117858:11;;:23;;117900:15;;117934:9;117991:14;118024:15;;;;:34;;118046:4;:12;118024:34;;;118042:1;118024:34;118077:12;:10;:12::i;:::-;117858:246;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;117841:263:0;-1:-1:-1;118119:17:0;;-1:-1:-1;;118119:17:0;117791:357;118199:5;:12;;;118195:841;;;118300:11;:23;118342:15;118376:1;118396;118416:14;118396:1;118469:12;:10;:12::i;:::-;118300:196;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;118524:52:0;;-1:-1:-1;;;118524:52:0;;-1:-1:-1;;;;;22622:32:1;;;118524:52:0;;;22604:51:1;22671:18;;;22664:34;;;118283:213:0;;-1:-1:-1;118532:6:0;118524:31;;;;;;22577:18:1;;118524:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118511:65;;118195:841;;;118736:53;;-1:-1:-1;;;118736:53:0;;-1:-1:-1;;;;;22622:32:1;;;118736:53:0;;;22604:51:1;22671:18;;;22664:34;;;118744:6:0;118736:29;;;;22577:18:1;;118736:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;118723:66;;118821:11;:23;118863:4;:15;;118897:1;118917;118937:10;118966:4;:12;;;118997;:10;:12::i;:::-;118821:203;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;118804:220:0;-1:-1:-1;118195:841:0;117294:1749;;;;;;;:::o;125623:738::-;125759:20;125824:1;125805:16;:20;125797:39;;;;-1:-1:-1;;;125797:39:0;;;;;;;:::i;:::-;125849:19;125871:18;125881:7;125871:9;:18::i;:::-;125949;;125849:40;;-1:-1:-1;125900:17:0;;125920:48;;:16;;:28;:48::i;:::-;125900:68;;125996:11;:25;126036:4;:15;;126066:6;:13;;;:30;;126095:1;126066:30;;;126082:10;;126066:30;126111:28;126130:9;126111:16;:28;:::i;:::-;126154:12;:10;:12::i;:::-;125996:181;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125981:196;;126239:6;:13;;;126234:120;;126316:11;;;;126284:58;;-1:-1:-1;;;126284:58:0;;-1:-1:-1;;;;;22622:32:1;;;126284:58:0;;;22604:51:1;22671:18;;;22664:34;;;126292:6:0;126284:31;;;;;;22577:18:1;;126284:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126234:120;125623:738;;;;;;:::o;132245:913::-;110044:39;;-1:-1:-1;;;110044:39:0;;31893:66;110044:39;;;37064:25:1;132412:18:0;;;;110087:10;;-1:-1:-1;;;;;110044:5:0;:15;;;;37037:18:1;;110044:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;110044:53:0;;110036:80;;;;-1:-1:-1;;;110036:80:0;;40094:2:1;110036:80:0;;;40076:21:1;40133:2;40113:18;;;40106:30;-1:-1:-1;;;40152:18:1;;;40145:44;40206:18;;110036:80:0;40066:164:1;110036:80:0;109664:16:::1;:14;:16::i;:::-;37925:11:::2;::::0;;;::::2;;;37917:55;;;;-1:-1:-1::0;;;37917:55:0::2;;;;;;;:::i;:::-;38050:11;:19:::0;;-1:-1:-1;;38050:19:0::2;::::0;;132528:77:::3;::::0;-1:-1:-1;;;132528:77:0;;38064:5:::2;::::0;;;132528:13:::3;::::0;:39:::3;::::0;:77:::3;::::0;132568:19;;132589:15;;132528:77:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;::::0;;::::3;-1:-1:-1::0;;132528:77:0::3;::::0;::::3;;::::0;::::3;::::0;;;::::3;::::0;::::3;:::i;:::-;132467:138:::0;;-1:-1:-1;132467:138:0;-1:-1:-1;132723:11:0::3;:28;132752:15:::0;132467:138;;132782:12:::3;:10;:12::i;:::-;132723:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;132834:16:::0;;::::3;21508:12:::0;132710:85;;-1:-1:-1;132710:85:0;;132818:32:::3;;;;:::i;:::-;:45;;;;:::i;:::-;132893:11:::0;;132806:57;;-1:-1:-1;132919:10:0;;132915:93:::3;;132991:4;132968:19;132981:6:::0;132968:10;:19:::3;:::i;:::-;132967:28;;;;:::i;:::-;132946:16:::0;:50;;:16:::3;::::0;:50:::3;::::0;;;::::3;:::i;:::-;::::0;;;-1:-1:-1;;132915:93:0::3;133126:16;::::0;;133123:1:::3;133126:16:::0;;;::::3;::::0;::::3;::::0;;;;133104:4:::3;::::0;133084:66:::3;::::0;::::3;::::0;133111:10:::3;::::0;133123:1;;133126:16;133144:5;;133084:66:::3;:::i;:::-;;;;;;;;-1:-1:-1::0;;38230:11:0::2;:18:::0;;-1:-1:-1;;38230:18:0::2;::::0;::::2;::::0;;-1:-1:-1;132245:913:0;;:::o;36502:120::-;33042:15;:13;:15::i;:::-;35631:7:::1;::::0;::::1;::::0;::::1;;;35630:8;35622:37;;;::::0;-1:-1:-1;;;35622:37:0;;43113:2:1;35622:37:0::1;::::0;::::1;43095:21:1::0;43152:2;43132:18;;;43125:30;-1:-1:-1;;;43171:18:1;;;43164:46;43227:18;;35622:37:0::1;43085:166:1::0;35622:37:0::1;36566:7:::2;:14:::0;;-1:-1:-1;;36566:14:0::2;;;::::0;;36596:18:::2;::::0;36603:10:::2;20878:51:1::0;;36596:18:0::2;::::0;20866:2:1;20851:18;36596::0::2;20833:102:1::0;29113:87:0;29152:13;29185:7;29178:14;;;;;:::i;127739:157::-;127789:13;;127833:11;:24;127858:15;127875:12;:10;:12::i;:::-;127833:55;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;127826:62;;;;127739:157;;:::o;133278:487::-;110044:39;;-1:-1:-1;;;110044:39:0;;31893:66;110044:39;;;37064:25:1;110087:10:0;;-1:-1:-1;;;;;110044:5:0;:15;;;;37037:18:1;;110044:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;110044:53:0;;110036:80;;;;-1:-1:-1;;;110036:80:0;;40094:2:1;110036:80:0;;;40076:21:1;40133:2;40113:18;;;40106:30;-1:-1:-1;;;40152:18:1;;;40145:44;40206:18;;110036:80:0;40066:164:1;110036:80:0;133374:16;;133412:1:::1;133405:8:::0;::::1;133401:357;;;133430:18;133451:8;133458:1;133451:4:::0;:8:::1;:::i;:::-;133493:1;133474:16:::0;:20;133430:29;-1:-1:-1;133511:29:0::1;133517:10;133430:29:::0;133511:5:::1;:29::i;:::-;133598:4;133560:186;133622:10;133651::::0;133694:1:::1;133680:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;133680:16:0::1;-1:-1:-1::0;133715:16:0::1;::::0;;133729:1:::1;133715:16:::0;;::::1;::::0;::::1;::::0;;;;133560:186:::1;::::0;;;;::::1;:::i;:::-;;;;;;;;133401:357;;110127:1;133278:487::o:0;135350:252::-;33042:15;:13;:15::i;:::-;135452:4:::1;135444;-1:-1:-1::0;;;;;135444:12:0::1;;;:28;;;;;135468:4;135460;-1:-1:-1::0;;;;;135460:12:0::1;;;135444:28;135436:52;;;::::0;-1:-1:-1;;;135436:52:0;;43806:2:1;135436:52:0::1;::::0;::::1;43788:21:1::0;43845:2;43825:18;;;43818:30;-1:-1:-1;;;43864:18:1;;;43857:41;43915:18;;135436:52:0::1;43778:161:1::0;135436:52:0::1;135521:24;::::0;;;;::::1;::::0;;-1:-1:-1;;;;;135521:24:0;;::::1;::::0;;;;;::::1;;::::0;;::::1;::::0;;;135501:17;:44;;-1:-1:-1;;;;;;135501:44:0::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;;135501:44:0;::::1;;::::0;;;135563:31;;57748:34:1;;;57798:18;;;57791:43;135563:31:0::1;::::0;57668:18:1;135563:31:0::1;;;;;;;135350:252:::0;;:::o;24667:377::-;18253:10;24760:4;24804:25;;;:11;:25;;;;;;;;-1:-1:-1;;;;;24804:34:0;;;;;;;;;;24857:35;;;;24849:85;;;;-1:-1:-1;;;24849:85:0;;50536:2:1;24849:85:0;;;50518:21:1;50575:2;50555:18;;;50548:30;50614:34;50594:18;;;50587:62;-1:-1:-1;;;50665:18:1;;;50658:35;50710:19;;24849:85:0;50508:227:1;24849:85:0;24945:67;18253:10;24968:7;24977:34;24996:15;24977:16;:34;:::i;24945:67::-;-1:-1:-1;25032:4:0;;24667:377;-1:-1:-1;;;24667:377:0:o;21931:175::-;22017:4;22034:42;18253:10;22058:9;22069:6;22034:9;:42::i;124075:1228::-;37925:11;;124316:23;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;124360:24:0;::::2;124352:54;;;;-1:-1:-1::0;;;124352:54:0::2;;;;;;;:::i;:::-;124431:17:::0;124474:7;;;;;:33:::2;;-1:-1:-1::0;124485:22:0;;::::2;124474:33;124466:65;;;::::0;-1:-1:-1;;;124466:65:0;;43458:2:1;124466:65:0::2;::::0;::::2;43440:21:1::0;43497:2;43477:18;;;43470:30;-1:-1:-1;;;43516:18:1;;;43509:49;43575:18;;124466:65:0::2;43430:169:1::0;124466:65:0::2;124570:1;124550:17;:21;124542:40;;;;-1:-1:-1::0;;;124542:40:0::2;;;;;;;:::i;:::-;124595:22;124620:20;124631:8;;124620:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;124620:10:0::2;::::0;-1:-1:-1;;;124620:20:0:i:2;:::-;124595:45;;124653:16;124710:11;:30;124755:4;124774:12;:10;:12::i;:::-;124801:7;124823:17;;124855;124887:10;124710:198;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;::::0;::::2;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124680:228:::0;;-1:-1:-1;124680:228:0;-1:-1:-1;124921:34:0::2;124927:10;124680:228:::0;124921:5:::2;:34::i;:::-;124983:11:::0;;125009:10;;125005:91:::2;;125079:4;125058:17;125069:6:::0;125058:8;:17:::2;:::i;:::-;125057:26;;;;:::i;:::-;125036:16:::0;:48;;:16:::2;::::0;:48:::2;::::0;;;::::2;:::i;:::-;::::0;;;-1:-1:-1;;125005:91:0::2;125141:10;-1:-1:-1::0;;;;;125113:182:0::2;;125166:10;125191:15;125221:8;;125244:17;;125276:8;125113:182;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;38230:11:0;:18;;-1:-1:-1;;38230:18:0;;;;;-1:-1:-1;124075:1228:0;;;-1:-1:-1;;;;;;;124075:1228:0:o;112265:852::-;37925:11;;112496:18;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;112535:24:0;::::2;112527:54;;;;-1:-1:-1::0;;;112527:54:0::2;;;;;;;:::i;:::-;112606:16:::0;112648:7;;;;;:32:::2;;-1:-1:-1::0;112659:21:0;;::::2;112648:32;112640:65;;;::::0;-1:-1:-1;;;112640:65:0;;41247:2:1;112640:65:0::2;::::0;::::2;41229:21:1::0;41286:2;41266:18;;;41259:30;-1:-1:-1;;;41305:18:1;;;41298:50;41365:18;;112640:65:0::2;41219:170:1::0;112640:65:0::2;112718:22;112743:19;112754:7;;112743:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;112743:10:0::2;::::0;-1:-1:-1;;;112743:19:0:i:2;:::-;112718:44;;112786:11;:21;112822:4;112841:12;:10;:12::i;:::-;112868:7;112890:16;;112921:18;112786:164;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;112773:177;;112990:29;112996:10;113008;112990:5;:29::i;:::-;113047:10;-1:-1:-1::0;;;;;113035:74:0::2;;113059:10;113071;113083:7;;113092:16;;113035:74;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;38230:11:0;:18;;-1:-1:-1;;38230:18:0;;;;;112265:852;;-1:-1:-1;;;;;;112265:852:0:o;122256:1147::-;37925:11;;122462:33;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;122516:24:0;::::2;122508:54;;;;-1:-1:-1::0;;;122508:54:0::2;;;;;;;:::i;:::-;122598:1;122581:14;:18;122573:37;;;;-1:-1:-1::0;;;122573:37:0::2;;;;;;;:::i;:::-;122679:26;122708:12;:10;:12::i;:::-;122679:41;;122731:33;122737:10;122749:14;122731:5;:33::i;:::-;122777:24;122812:17;122881:11;:33;122929:4;122948:6;122969:14;122998:20;;123033:10;122881:173;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;::::0;;::::2;-1:-1:-1::0;;122881:173:0::2;::::0;::::2;;::::0;::::2;::::0;;;::::2;::::0;::::2;:::i;:::-;123084:11:::0;;122840:214;;-1:-1:-1;122840:214:0;;-1:-1:-1;122840:214:0;;-1:-1:-1;123110:10:0;;123106:92:::2;;123181:4;123159:18;123171:6:::0;123159:9;:18:::2;:::i;:::-;123158:27;;;;:::i;:::-;123137:16:::0;:49;;:16:::2;::::0;:49:::2;::::0;;;::::2;:::i;:::-;::::0;;;-1:-1:-1;;123106:92:0::2;123243:10;-1:-1:-1::0;;;;;123215:180:0::2;;123268:10;123293:14;123322:7;123344:16;123375:9;123215:180;;;;;;;;;;:::i;127998:119::-:0;128051:26;;:::i;:::-;128097:12;:10;:12::i;:::-;128090:19;;127998:119;:::o;136805:108::-;33042:15;:13;:15::i;:::-;136859:13:::1;:23;136883:12:::0;136897:7:::1;:5;:7::i;:::-;136859:46;::::0;-1:-1:-1;;;;;;136859:46:0::1;::::0;;;;;;::::1;::::0;::::1;51303:25:1::0;;;;51344:18;;;51337:34;51276:18;;136859:46:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;136805:108::o:0;134682:497::-;33042:15;:13;:15::i;:::-;107009:4:::1;134833:8;:19;;134825:45;;;::::0;-1:-1:-1;;;134825:45:0;;39411:2:1;134825:45:0::1;::::0;::::1;39393:21:1::0;39450:2;39430:18;;;39423:30;-1:-1:-1;;;39469:18:1;;;39462:43;39522:18;;134825:45:0::1;39383:163:1::0;134825:45:0::1;107009:4;134889:14;:25;;134881:57;;;::::0;-1:-1:-1;;;134881:57:0;;42004:2:1;134881:57:0::1;::::0;::::1;41986:21:1::0;42043:2;42023:18;;;42016:30;-1:-1:-1;;;42062:18:1;;;42055:49;42121:18;;134881:57:0::1;41976:169:1::0;134881:57:0::1;134968:4;134957:7;:15;;134949:44;;;::::0;-1:-1:-1;;;134949:44:0;;46403:2:1;134949:44:0::1;::::0;::::1;46385:21:1::0;46442:2;46422:18;;;46415:30;-1:-1:-1;;;46461:18:1;;;46454:46;46517:18;;134949:44:0::1;46375:166:1::0;134949:44:0::1;135006:4;:23:::0;;;135040:18;:35;;;135086:11;:21;;;135125:46:::1;::::0;;58482:25:1;;;58538:2;58523:18;;58516:34;;;58566:18;;;58559:34;;;135125:46:0::1;::::0;58470:2:1;58455:18;135125:46:0::1;;;;;;;134682:497:::0;;;:::o;115732:1090::-;37925:11;;115959:18;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;115998:24:0;::::2;115990:54;;;;-1:-1:-1::0;;;115990:54:0::2;;;;;;;:::i;:::-;116073:7;-1:-1:-1::0;;;;;116063:17:0::2;:6;-1:-1:-1::0;;;;;116063:17:0::2;;;116055:42;;;;-1:-1:-1::0;;;116055:42:0::2;;;;;;;:::i;:::-;116133:1;116116:14;:18;116108:37;;;;-1:-1:-1::0;;;116108:37:0::2;;;;;;;:::i;:::-;116158:18;116179:17;116189:6;116179:9;:17::i;:::-;116158:38;;116207:19;116229:18;116239:7;116229:9;:18::i;:::-;116207:40;;116266:27;116279:5;116286:6;116266:12;:27::i;:::-;116258:52;;;;-1:-1:-1::0;;;116258:52:0::2;;;;;;;:::i;:::-;116323:16;116375:11;:16;116406:4;116425:12;:10;:12::i;:::-;116452:5;116472:6;116493:14;116522:18;116555:10;116375:201;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;::::0;::::2;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116606:11:::0;;116350:226;;-1:-1:-1;116350:226:0;-1:-1:-1;116632:10:0;;116628:91:::2;;116702:4;116681:17;116692:6:::0;116681:8;:17:::2;:::i;:::-;116680:26;;;;:::i;:::-;116659:16:::0;:48;;:16:::2;::::0;:48:::2;::::0;;;::::2;:::i;:::-;::::0;;;-1:-1:-1;;116628:91:0::2;116756:10;::::0;;::::2;::::0;116768:11;;::::2;::::0;116736:78:::2;::::0;;-1:-1:-1;;;;;21564:15:1;;;21546:34;;21616:15;;;21596:18;;;21589:43;;;;21648:18;;;21641:34;;;21706:2;21691:18;;21684:34;;;21755:15;;21749:3;21734:19;;21727:44;116744:10:0::2;::::0;116736:78:::2;::::0;21495:3:1;21480:19;116736:78:0::2;;;;;;;-1:-1:-1::0;;38230:11:0;:18;;-1:-1:-1;;38230:18:0;;;;;-1:-1:-1;115732:1090:0;;;-1:-1:-1;;;;;;115732:1090:0:o;114487:490::-;114648:18;114698:16;114740:7;;;;;:32;;-1:-1:-1;114751:21:0;;;114740:32;114732:65;;;;-1:-1:-1;;;114732:65:0;;41247:2:1;114732:65:0;;;41229:21:1;41286:2;41266:18;;;41259:30;-1:-1:-1;;;41305:18:1;;;41298:50;41365:18;;114732:65:0;41219:170:1;114732:65:0;114808:22;114833:19;114844:7;;114833:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;114833:10:0;;-1:-1:-1;;;114833:19:0:i;:::-;114808:44;-1:-1:-1;114883:11:0;:28;114912:15;114808:44;114938:16;;114956:12;:10;:12::i;:::-;114883:86;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114863:106;114487:490;-1:-1:-1;;;;;;;114487:490:0:o;110929:727::-;37925:11;;111130:18;;37925:11;;;;;37917:55;;;;-1:-1:-1;;;37917:55:0;;;;;;;:::i;:::-;38050:11;:19;;-1:-1:-1;;38050:19:0;;;109664:16:::1;:14;:16::i;:::-;-1:-1:-1::0;;;;;111169:24:0;::::2;111161:54;;;;-1:-1:-1::0;;;111161:54:0::2;;;;;;;:::i;:::-;111251:1;111234:14;:18;111226:37;;;;-1:-1:-1::0;;;111226:37:0::2;;;;;;;:::i;:::-;111276:18;111297:17;111307:6;111297:9;:17::i;:::-;111276:38;;111340:11;:16;111371:4;111390:12;:10;:12::i;:::-;111417:5;111437:14;111466:18;111340:155;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111327:168;;111537:29;111543:10;111555;111537:5;:29::i;:::-;111582:66;::::0;;-1:-1:-1;;;;;22996:15:1;;;22978:34;;23043:2;23028:18;;23021:34;;;23091:15;;23071:18;;;23064:43;23138:2;23123:18;;23116:34;;;111582:66:0;;111589:10:::2;::::0;111582:66:::2;::::0;;;;;22927:3:1;111582:66:0;;::::2;-1:-1:-1::0;38230:11:0;:18;;-1:-1:-1;;38230:18:0;;;;;110929:727;;-1:-1:-1;;;;110929:727:0:o;130018:545::-;130136:14;;130087:22;;130136:14;-1:-1:-1;;;;;130173:16:0;;;;;-1:-1:-1;;;130173:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;130173:16:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;130163:26:0;;-1:-1:-1;130232:324:0;130256:3;130252:1;:7;130232:324;;;130290:21;130300:7;130308:1;130300:10;;;;;;-1:-1:-1;;;130300:10:0;;;;;;;;;;;;;;;130290:9;:21::i;:::-;130281:30;;130339:6;:10;;;130326:7;130334:1;130326:10;;;;;;-1:-1:-1;;;130326:10:0;;;;;;;;;;;;;;:23;;;;;;;;;;;130372:6;:13;;;130364:39;;;;-1:-1:-1;;;130364:39:0;;38666:2:1;130364:39:0;;;38648:21:1;38705:2;38685:18;;;38678:30;-1:-1:-1;;;38724:18:1;;;38717:43;38777:18;;130364:39:0;38638:163:1;130364:39:0;130425:9;130437:5;:1;130441;130437:5;:::i;:::-;130425:17;;130420:125;130448:3;130444:1;:7;130420:125;;;130499:7;130507:1;130499:10;;;;;;-1:-1:-1;;;130499:10:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;130485:24:0;:7;130493:1;130485:10;;;;;;-1:-1:-1;;;130485:10:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;130485:24:0;;;130477:52;;;;-1:-1:-1;;;130477:52:0;;47150:2:1;130477:52:0;;;47132:21:1;47189:2;47169:18;;;47162:30;-1:-1:-1;;;47208:18:1;;;47201:45;47263:18;;130477:52:0;47122:165:1;130477:52:0;130453:3;;;;:::i;:::-;;;;130420:125;;;-1:-1:-1;130261:3:0;;;;:::i;:::-;;;;130232:324;;;;130018:545;;;;;:::o;130662:166::-;130707:19;;:::i;:::-;130746:74;;;;;;;;130775:4;:16;;;130759:13;21508:12;;21420:108;;130759:13;:32;;;;:::i;:::-;130746:74;;;;130793:7;:5;:7::i;:::-;130746:74;;;;;;;;;;;130802:17;130746:74;-1:-1:-1;;;;;130746:74:0;;;;;-1:-1:-1;;;130746:74:0;;;;;;;;;;;;;;;;130739:81;-1:-1:-1;130662:166:0;:::o;51597:195::-;51664:7;51783:1;51765:14;47841:4;51765:1;:14;:::i;:::-;51764:20;;;;:::i;27839:346::-;-1:-1:-1;;;;;27941:19:0;;27933:68;;;;-1:-1:-1;;;27933:68:0;;47900:2:1;27933:68:0;;;47882:21:1;47939:2;47919:18;;;47912:30;47978:34;47958:18;;;47951:62;-1:-1:-1;;;48029:18:1;;;48022:34;48073:19;;27933:68:0;47872:226:1;27933:68:0;-1:-1:-1;;;;;28020:21:0;;28012:68;;;;-1:-1:-1;;;28012:68:0;;40437:2:1;28012:68:0;;;40419:21:1;40476:2;40456:18;;;40449:30;40515:34;40495:18;;;40488:62;-1:-1:-1;;;40566:18:1;;;40559:32;40608:19;;28012:68:0;40409:224:1;28012:68:0;-1:-1:-1;;;;;28093:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;28145:32;;37064:25:1;;;28145:32:0;;37037:18:1;28145:32:0;;;;;;;;27839:346;;;:::o;129471:336::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;129632:6:0;-1:-1:-1;;;;;129622:16:0;:6;-1:-1:-1;;;;;129622:16:0;;129618:51;;;-1:-1:-1;129647:22:0;;;;;;;;-1:-1:-1;129647:22:0;;-1:-1:-1;;;;;129647:22:0;;;;;;129664:4;129647:22;;;;;;;129640:29;;129618:51;129744:55;;;;;;;;129750:1;129744:55;;;;;;129753:6;-1:-1:-1;;;;;129744:55:0;;;;;129792:6;-1:-1:-1;;;;;129761:37:0;:4;:19;;129781:1;129761:22;;;;;;-1:-1:-1;;;129761:22:0;;;;;;;;;;;;;;;;;;;;;;:27;-1:-1:-1;;;;;129761:27:0;:37;129744:55;;129737:62;129471:336;-1:-1:-1;;129471:336:0:o;33085:121::-;33157:11;:9;:11::i;:::-;-1:-1:-1;;;;;33143:25:0;:10;-1:-1:-1;;;;;33143:25:0;;33135:63;;;;-1:-1:-1;;;33135:63:0;;42759:2:1;33135:63:0;;;42741:21:1;42798:2;42778:18;;;42771:30;42837:27;42817:18;;;42810:55;42882:18;;33135:63:0;42731:175:1;33135:63:0;33085:121::o;25534:544::-;-1:-1:-1;;;;;25640:20:0;;25632:70;;;;-1:-1:-1;;;25632:70:0;;47494:2:1;25632:70:0;;;47476:21:1;47533:2;47513:18;;;47506:30;47572:34;47552:18;;;47545:62;-1:-1:-1;;;47623:18:1;;;47616:35;47668:19;;25632:70:0;47466:227:1;25632:70:0;-1:-1:-1;;;;;25721:23:0;;25713:71;;;;-1:-1:-1;;;25713:71:0;;37913:2:1;25713:71:0;;;37895:21:1;37952:2;37932:18;;;37925:30;37991:34;37971:18;;;37964:62;-1:-1:-1;;;38042:18:1;;;38035:33;38085:19;;25713:71:0;37885:225:1;25713:71:0;-1:-1:-1;;;;;25821:17:0;;25797:21;25821:17;;;:9;:17;;;;;;25857:23;;;;25849:74;;;;-1:-1:-1;;;25849:74:0;;40840:2:1;25849:74:0;;;40822:21:1;40879:2;40859:18;;;40852:30;40918:34;40898:18;;;40891:62;-1:-1:-1;;;40969:18:1;;;40962:36;41015:19;;25849:74:0;40812:228:1;25849:74:0;25954:22;25970:6;25954:13;:22;:::i;:::-;-1:-1:-1;;;;;25934:17:0;;;;;;;:9;:17;;;;;;:42;;;;25987:20;;;;;;;;:30;;26011:6;;25934:17;25987:30;;26011:6;;25987:30;:::i;:::-;;;;;;;;26052:9;-1:-1:-1;;;;;26035:35:0;26044:6;-1:-1:-1;;;;;26035:35:0;;26063:6;26035:35;;;;37064:25:1;;37052:2;37037:18;;37019:76;26035:35:0;;;;;;;;25534:544;;;;:::o;30097:163::-;30188:64;30227:8;30237:10;30249:2;30188:38;:64::i;:::-;30097:163;;:::o;38668:184::-;38725:7;-1:-1:-1;;;38753:5:0;:14;38745:67;;;;-1:-1:-1;;;38745:67:0;;41596:2:1;38745:67:0;;;41578:21:1;41635:2;41615:18;;;41608:30;41674:34;41654:18;;;41647:62;-1:-1:-1;;;41725:18:1;;;41718:37;41772:19;;38745:67:0;41568:229:1;38745:67:0;-1:-1:-1;38838:5:0;38668:184::o;45100:622::-;45470:10;;;45469:62;;-1:-1:-1;45486:39:0;;-1:-1:-1;;;45486:39:0;;45510:4;45486:39;;;21152:34:1;-1:-1:-1;;;;;21222:15:1;;;21202:18;;;21195:43;45486:15:0;;;;;21087:18:1;;45486:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;45469:62;45461:152;;;;-1:-1:-1;;;45461:152:0;;50113:2:1;45461:152:0;;;50095:21:1;50152:2;50132:18;;;50125:30;50191:34;50171:18;;;50164:62;-1:-1:-1;;;50242:18:1;;;50235:52;50304:19;;45461:152:0;50085:244:1;45461:152:0;45651:62;;;-1:-1:-1;;;;;22622:32:1;;45651:62:0;;;22604:51:1;22671:18;;;;22664:34;;;45651:62:0;;;;;;;;;;22577:18:1;;;;45651:62:0;;;;;;;;-1:-1:-1;;;;;45651:62:0;-1:-1:-1;;;45651:62:0;;;45624:90;;45644:5;;45624:19;:90::i;:::-;45100:622;;;:::o;39151:179::-;39207:6;-1:-1:-1;;;39234:5:0;:13;39226:65;;;;-1:-1:-1;;;39226:65:0;;45241:2:1;39226:65:0;;;45223:21:1;45280:2;45260:18;;;45253:30;45319:34;45299:18;;;45292:62;-1:-1:-1;;;45370:18:1;;;45363:36;45416:19;;39226:65:0;45213:228:1;109767:126:0;109827:7;;;;;;;109826:8;;:45;;;109852:19;:17;:19::i;:::-;-1:-1:-1;;;;;109838:33:0;:10;-1:-1:-1;;;;;109838:33:0;;109826:45;109818:67;;;;-1:-1:-1;;;109818:67:0;;44146:2:1;109818:67:0;;;44128:21:1;44185:1;44165:18;;;44158:29;-1:-1:-1;;;44203:18:1;;;44196:39;44252:18;;109818:67:0;44118:158:1;26969:432:0;-1:-1:-1;;;;;27053:21:0;;27045:67;;;;-1:-1:-1;;;27045:67:0;;46748:2:1;27045:67:0;;;46730:21:1;46787:2;46767:18;;;46760:30;46826:34;46806:18;;;46799:62;-1:-1:-1;;;46877:18:1;;;46870:31;46918:19;;27045:67:0;46720:223:1;27045:67:0;-1:-1:-1;;;;;27150:18:0;;27125:22;27150:18;;;:9;:18;;;;;;27187:24;;;;27179:71;;;;-1:-1:-1;;;27179:71:0;;39008:2:1;27179:71:0;;;38990:21:1;39047:2;39027:18;;;39020:30;39086:34;39066:18;;;39059:62;-1:-1:-1;;;39137:18:1;;;39130:32;39179:19;;27179:71:0;38980:224:1;27179:71:0;27282:23;27299:6;27282:14;:23;:::i;:::-;-1:-1:-1;;;;;27261:18:0;;;;;;:9;:18;;;;;:44;;;;27316:12;:22;;27332:6;;27261:18;27316:22;;27332:6;;27316:22;:::i;:::-;;;;-1:-1:-1;;27356:37:0;;37064:25:1;;;27382:1:0;;-1:-1:-1;;;;;27356:37:0;;;;;37052:2:1;37037:18;27356:37:0;37019:76:1;130900:831:0;130960:38;;;;;;;;130986:12;130960:38;-1:-1:-1;;;;;130960:38:0;;;;;-1:-1:-1;;;130960:38:0;;;;;;;;;;-1:-1:-1;;;130960:38:0;;;;;;;;;;;-1:-1:-1;;;130960:38:0;;;;;;;;;;130940:7;;130960:38;131173:15;:25;-1:-1:-1;131169:555:0;;;131231:17;;131282:22;;;;131215:13;;131357:27;-1:-1:-1;;;;;131357:27:0;;:15;:27;:::i;:::-;131386:19;131396:9;131386:7;:19;:::i;:::-;-1:-1:-1;;;;;131321:85:0;;;;;131434:6;-1:-1:-1;;;;;131427:13:0;:4;-1:-1:-1;;;;;131427:13:0;;131423:201;;;131508:5;131497:7;131480:13;131487:6;131480:4;:13;:::i;:::-;-1:-1:-1;;;;;131479:25:0;;;;;:::i;:::-;131478:35;;;;:::i;:::-;131468:46;;-1:-1:-1;;;;;131468:46:0;;;:::i;:::-;131461:53;;;;;;;;;;;131423:201;131602:5;131591:7;131574:13;131583:4;131574:6;:13;:::i;:::-;-1:-1:-1;;;;;131573:25:0;;;;;:::i;:::-;131572:35;;;;:::i;:::-;131562:46;;-1:-1:-1;;;;;131562:46:0;;;:::i;131169:555::-;-1:-1:-1;;;;;;131701:11:0;;-1:-1:-1;131701:11:0;;-1:-1:-1;131701:11:0;119179:574;119288:12;119354:3;:10;;;119353:11;:27;;;;;119369:4;:11;;;119368:12;119353:27;119349:45;;;-1:-1:-1;119389:5:0;119382:12;;119349:45;119442:3;:10;;;:25;;;;;119456:4;:11;;;119442:25;119438:42;;;-1:-1:-1;119476:4:0;119469:11;;119438:42;119525:3;:10;;;:26;;;;;119539:3;:7;;;:12;;119550:1;119539:12;119525:26;119521:43;;;-1:-1:-1;119560:4:0;119553:11;;119521:43;119609:4;:11;;;:28;;;;;119624:4;:8;;;:13;;119636:1;119624:13;119609:28;119605:45;;;-1:-1:-1;119646:4:0;119639:11;;119605:45;-1:-1:-1;119740:5:0;119179:574;;;;:::o;49467:135::-;49533:7;49560:34;49577:1;49580;47841:4;49560:16;:34::i;26360:276::-;-1:-1:-1;;;;;26444:21:0;;26436:65;;;;-1:-1:-1;;;26436:65:0;;50942:2:1;26436:65:0;;;50924:21:1;50981:2;50961:18;;;50954:30;51020:33;51000:18;;;50993:61;51071:18;;26436:65:0;50914:181:1;26436:65:0;26530:6;26514:12;;:22;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;26547:18:0;;;;;;:9;:18;;;;;:28;;26569:6;;26547:18;:28;;26569:6;;26547:28;:::i;:::-;;;;-1:-1:-1;;26591:37:0;;37064:25:1;;;-1:-1:-1;;;;;26591:37:0;;;26608:1;;26591:37;;37052:2:1;37037:18;26591:37:0;;;;;;;26360:276;;:::o;33692:95::-;33736:7;33763:5;-1:-1:-1;;;;;33763:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;28612:229::-;28754:15;;;;:5;;:15;;;;;:::i;:::-;-1:-1:-1;28780:19:0;;;;:7;;:19;;;;;:::i;:::-;-1:-1:-1;28810:9:0;:23;;-1:-1:-1;;28810:23:0;;;;;;;;;;;;-1:-1:-1;;28612:229:0:o;46875:761::-;47299:23;47325:69;47353:4;47325:69;;;;;;;;;;;;;;;;;47333:5;-1:-1:-1;;;;;47325:27:0;;;:69;;;;;:::i;:::-;47409:17;;47299:95;;-1:-1:-1;47409:21:0;47405:224;;47551:10;47540:30;;;;;;;;;;;;:::i;:::-;47532:85;;;;-1:-1:-1;;;47532:85:0;;49342:2:1;47532:85:0;;;49324:21:1;49381:2;49361:18;;;49354:30;49420:34;49400:18;;;49393:62;-1:-1:-1;;;49471:18:1;;;49464:40;49521:19;;47532:85:0;49314:232:1;34481:124:0;34560:37;;-1:-1:-1;;;34560:37:0;;31239:66;34560:37;;;37064:25:1;34533:7:0;;34560:5;-1:-1:-1;;;;;34560:15:0;;;;37037:18:1;;34560:37:0;;;;;;;;;;;;;;;;;;50075:286;50195:7;50348:5;50339;50343:1;50339;:5;:::i;:::-;50338:15;;;;:::i;:::-;50331:22;50075:286;-1:-1:-1;;;;50075:286:0:o;12250:195::-;12353:12;12385:52;12407:6;12415:4;12421:1;12424:12;12353;9699:20;;13546:60;;;;-1:-1:-1;;;13546:60:0;;48305:2:1;13546:60:0;;;48287:21:1;48344:2;48324:18;;;48317:30;48383:31;48363:18;;;48356:59;48432:18;;13546:60:0;48277:179:1;13546:60:0;13680:12;13694:23;13721:6;-1:-1:-1;;;;;13721:11:0;13741:5;13749:4;13721:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13679:75;;;;13772:52;13790:7;13799:10;13811:12;15957;15986:7;15982:595;;;-1:-1:-1;16017:10:0;16010:17;;15982:595;16131:17;;:21;16127:439;;16394:10;16388:17;16455:15;16442:10;16438:2;16434:19;16427:44;16342:148;16537:12;16530:20;;-1:-1:-1;;;16530:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:398:1;;;141:3;134:4;126:6;122:17;118:27;108:2;;166:8;156;149:26;108:2;-1:-1:-1;196:20:1;;-1:-1:-1;;;;;228:30:1;;225:2;;;278:8;268;261:26;225:2;322:4;314:6;310:17;298:29;;385:3;378:4;370;362:6;358:17;350:6;346:30;342:41;339:50;336:2;;;402:1;399;392:12;336:2;98:314;;;;;:::o;417:691::-;;535:3;528:4;520:6;516:17;512:27;502:2;;557:5;550;543:20;502:2;590:6;584:13;616:4;640:60;656:43;696:2;656:43;:::i;:::-;640:60;:::i;:::-;734:15;;;765:12;;;;797:15;;;843:11;;;831:24;;827:33;;824:42;-1:-1:-1;821:2:1;;;883:5;876;869:20;821:2;909:5;923:156;937:2;934:1;931:9;923:156;;;994:10;;982:23;;1025:12;;;;1057;;;;955:1;948:9;923:156;;;-1:-1:-1;1097:5:1;;492:616;-1:-1:-1;;;;;;;492:616:1:o;1113:376::-;;;1229:3;1222:4;1214:6;1210:17;1206:27;1196:2;;1254:8;1244;1237:26;1196:2;-1:-1:-1;1284:20:1;;-1:-1:-1;;;;;1316:30:1;;1313:2;;;1366:8;1356;1349:26;1313:2;1410:4;1402:6;1398:17;1386:29;;1462:3;1455:4;1446:6;1438;1434:19;1430:30;1427:39;1424:2;;;1479:1;1476;1469:12;1494:171;;1606:3;1597:6;1592:3;1588:16;1584:26;1581:2;;;1627:5;1620;1613:20;1581:2;-1:-1:-1;1653:6:1;1571:94;-1:-1:-1;1571:94:1:o;1670:160::-;1747:13;;1800:4;1789:16;;1779:27;;1769:2;;1820:1;1817;1810:12;1835:257;;1947:2;1935:9;1926:7;1922:23;1918:32;1915:2;;;1968:6;1960;1953:22;1915:2;2012:9;1999:23;2031:31;2056:5;2031:31;:::i;2097:261::-;;2220:2;2208:9;2199:7;2195:23;2191:32;2188:2;;;2241:6;2233;2226:22;2188:2;2278:9;2272:16;2297:31;2322:5;2297:31;:::i;2363:398::-;;;2492:2;2480:9;2471:7;2467:23;2463:32;2460:2;;;2513:6;2505;2498:22;2460:2;2557:9;2544:23;2576:31;2601:5;2576:31;:::i;:::-;2626:5;-1:-1:-1;2683:2:1;2668:18;;2655:32;2696:33;2655:32;2696:33;:::i;:::-;2748:7;2738:17;;;2450:311;;;;;:::o;2766:466::-;;;;2912:2;2900:9;2891:7;2887:23;2883:32;2880:2;;;2933:6;2925;2918:22;2880:2;2977:9;2964:23;2996:31;3021:5;2996:31;:::i;:::-;3046:5;-1:-1:-1;3103:2:1;3088:18;;3075:32;3116:33;3075:32;3116:33;:::i;:::-;2870:362;;3168:7;;-1:-1:-1;;;3222:2:1;3207:18;;;;3194:32;;2870:362::o;3237:677::-;;;;;;3417:3;3405:9;3396:7;3392:23;3388:33;3385:2;;;3439:6;3431;3424:22;3385:2;3483:9;3470:23;3502:31;3527:5;3502:31;:::i;:::-;3552:5;-1:-1:-1;3609:2:1;3594:18;;3581:32;3622:33;3581:32;3622:33;:::i;:::-;3674:7;-1:-1:-1;3728:2:1;3713:18;;3700:32;;-1:-1:-1;3779:2:1;3764:18;;3751:32;;-1:-1:-1;3835:3:1;3820:19;;3807:33;3849;3807;3849;:::i;:::-;3901:7;3891:17;;;3375:539;;;;;;;;:::o;3919:325::-;;;4048:2;4036:9;4027:7;4023:23;4019:32;4016:2;;;4069:6;4061;4054:22;4016:2;4113:9;4100:23;4132:31;4157:5;4132:31;:::i;:::-;4182:5;4234:2;4219:18;;;;4206:32;;-1:-1:-1;;;4006:238:1:o;4249:535::-;;;;;4412:3;4400:9;4391:7;4387:23;4383:33;4380:2;;;4434:6;4426;4419:22;4380:2;4478:9;4465:23;4497:31;4522:5;4497:31;:::i;:::-;4547:5;-1:-1:-1;4599:2:1;4584:18;;4571:32;;-1:-1:-1;4650:2:1;4635:18;;4622:32;;-1:-1:-1;4706:2:1;4691:18;;4678:32;4719:33;4678:32;4719:33;:::i;:::-;4370:414;;;;-1:-1:-1;4370:414:1;;-1:-1:-1;;4370:414:1:o;4789:592::-;;;;4953:2;4941:9;4932:7;4928:23;4924:32;4921:2;;;4974:6;4966;4959:22;4921:2;5019:9;5006:23;-1:-1:-1;;;;;5044:6:1;5041:30;5038:2;;;5089:6;5081;5074:22;5038:2;5133:70;5195:7;5186:6;5175:9;5171:22;5133:70;:::i;:::-;5222:8;;-1:-1:-1;5107:96:1;-1:-1:-1;;5307:2:1;5292:18;;5279:32;5320:31;5279:32;5320:31;:::i;:::-;5370:5;5360:15;;;4911:470;;;;;:::o;5386:803::-;;;;;5585:2;5573:9;5564:7;5560:23;5556:32;5553:2;;;5606:6;5598;5591:22;5553:2;5651:9;5638:23;-1:-1:-1;;;;;5721:2:1;5713:6;5710:14;5707:2;;;5742:6;5734;5727:22;5707:2;5786:70;5848:7;5839:6;5828:9;5824:22;5786:70;:::i;:::-;5875:8;;-1:-1:-1;5760:96:1;-1:-1:-1;5963:2:1;5948:18;;5935:32;;-1:-1:-1;5979:16:1;;;5976:2;;;6013:6;6005;5998:22;5976:2;;6057:72;6121:7;6110:8;6099:9;6095:24;6057:72;:::i;:::-;5543:646;;;;-1:-1:-1;6148:8:1;-1:-1:-1;;;;5543:646:1:o;6194:1007::-;;;;;;;6427:3;6415:9;6406:7;6402:23;6398:33;6395:2;;;6449:6;6441;6434:22;6395:2;6494:9;6481:23;-1:-1:-1;;;;;6564:2:1;6556:6;6553:14;6550:2;;;6585:6;6577;6570:22;6550:2;6629:70;6691:7;6682:6;6671:9;6667:22;6629:70;:::i;:::-;6718:8;;-1:-1:-1;6603:96:1;-1:-1:-1;6806:2:1;6791:18;;6778:32;;-1:-1:-1;6822:16:1;;;6819:2;;;6856:6;6848;6841:22;6819:2;;6900:72;6964:7;6953:8;6942:9;6938:24;6900:72;:::i;:::-;6991:8;;-1:-1:-1;6874:98:1;-1:-1:-1;;7073:2:1;7058:18;;7045:32;;-1:-1:-1;7127:2:1;7112:18;;7099:32;7140:31;7099:32;7140:31;:::i;:::-;7190:5;7180:15;;;6385:816;;;;;;;;:::o;7206:1221::-;;;7394:2;7382:9;7373:7;7369:23;7365:32;7362:2;;;7415:6;7407;7400:22;7362:2;7453:9;7447:16;-1:-1:-1;;;;;7523:2:1;7515:6;7512:14;7509:2;;;7544:6;7536;7529:22;7509:2;7587:6;7576:9;7572:22;7562:32;;7632:7;7625:4;7621:2;7617:13;7613:27;7603:2;;7659:6;7651;7644:22;7603:2;7693;7687:9;7715:4;7739:60;7755:43;7795:2;7755:43;:::i;7739:60::-;7833:15;;;7864:12;;;;7896:11;;;7934;;;7926:20;;7922:29;;7919:42;-1:-1:-1;7916:2:1;;;7979:6;7971;7964:22;7916:2;8006:6;7997:15;;8021:178;8035:2;8032:1;8029:9;8021:178;;;8092:32;8120:3;8092:32;:::i;:::-;8080:45;;8053:1;8046:9;;;;;8145:12;;;;8177;;8021:178;;;-1:-1:-1;8254:18:1;;;8248:25;8218:5;;-1:-1:-1;8248:25:1;;-1:-1:-1;;;8285:16:1;;;8282:2;;;8319:6;8311;8304:22;8282:2;;8347:74;8413:7;8402:8;8391:9;8387:24;8347:74;:::i;:::-;8337:84;;;7352:1075;;;;;:::o;8432:251::-;;8541:2;8529:9;8520:7;8516:23;8512:32;8509:2;;;8562:6;8554;8547:22;8509:2;8606:9;8593:23;8625:28;8647:5;8625:28;:::i;8688:255::-;;8808:2;8796:9;8787:7;8783:23;8779:32;8776:2;;;8829:6;8821;8814:22;8776:2;8866:9;8860:16;8885:28;8907:5;8885:28;:::i;8948:2031::-;;;;;;;;;;9303:9;9294:7;9290:23;9333:3;9329:2;9325:12;9322:2;;;9355:6;9347;9340:22;9322:2;9400:9;9387:23;-1:-1:-1;;;;;9470:2:1;9462:6;9459:14;9456:2;;;9491:6;9483;9476:22;9456:2;9535:59;9586:7;9577:6;9566:9;9562:22;9535:59;:::i;:::-;9613:8;;-1:-1:-1;9509:85:1;-1:-1:-1;9701:2:1;9686:18;;9673:32;;-1:-1:-1;9717:16:1;;;9714:2;;;9751:6;9743;9736:22;9714:2;9795:61;9848:7;9837:8;9826:9;9822:24;9795:61;:::i;:::-;9875:8;;-1:-1:-1;9769:87:1;-1:-1:-1;9769:87:1;;-1:-1:-1;9929:70:1;9991:7;9986:2;9971:18;;9929:70;:::i;:::-;9919:80;;10018:71;10081:7;10075:3;10064:9;10060:19;10018:71;:::i;:::-;10008:81;;10142:3;10131:9;10127:19;10114:33;10098:49;;10172:2;10162:8;10159:16;10156:2;;;10193:6;10185;10178:22;10156:2;;10237:72;10301:7;10290:8;10279:9;10275:24;10237:72;:::i;:::-;10328:8;;-1:-1:-1;10211:98:1;-1:-1:-1;;10398:4:1;-1:-1:-1;;10379:17:1;;10375:28;10372:2;;;10421:6;10413;10406:22;10372:2;10452:19;10468:2;10452:19;:::i;:::-;10522:3;10507:19;;10494:33;10480:48;;10563:2;-1:-1:-1;;10544:17:1;;10540:26;10537:2;;;10584:6;10576;10569:22;10537:2;10617:19;10633:2;10617:19;:::i;:::-;10602:34;;10688:3;10677:9;10673:19;10660:33;10702;10727:7;10702:33;:::i;:::-;10744:24;;10820:3;10805:19;;10792:33;10834;10792;10834;:::i;:::-;10901:7;10896:2;10887:7;10883:16;10876:33;;10941:7;10936:2;10929:5;10925:14;10918:31;10968:5;10958:15;;;;9270:1709;;;;;;;;;;;:::o;10984:1289::-;;;11171:9;11162:7;11158:23;11201:3;11197:2;11193:12;11190:2;;;11223:6;11215;11208:22;11190:2;11252:4;11248:2;11244:13;11241:2;;;11275:6;11267;11260:22;11241:2;11306:21;11322:4;11306:21;:::i;:::-;11357:9;11351:16;11376:33;11401:7;11376:33;:::i;:::-;11418:22;;11485:2;11470:18;;11464:25;11498:33;11464:25;11498:33;:::i;:::-;11558:2;11547:14;;11540:31;11616:2;11601:18;;11595:25;11629:30;11595:25;11629:30;:::i;:::-;11686:2;11675:14;;11668:31;11744:2;11729:18;;11723:25;11779:1;11767:14;;11757:2;;11800:6;11792;11785:22;11757:2;11836;11825:14;;11818:31;11829:5;-1:-1:-1;11908:2:1;-1:-1:-1;;11889:17:1;;11885:26;11882:2;;;11929:6;11921;11914:22;11882:2;;11962:19;11978:2;11962:19;:::i;:::-;12026:4;12015:9;12011:20;12005:27;12041:33;12066:7;12041:33;:::i;:::-;12083:24;;12152:3;12137:19;;12131:26;12166:33;12131:26;12166:33;:::i;:::-;12228:2;12215:16;;12208:33;11138:1135;;12219:7;;-1:-1:-1;11138:1135:1;;-1:-1:-1;;11138:1135:1:o;12278:398::-;;;12407:2;12395:9;12386:7;12382:23;12378:32;12375:2;;;12428:6;12420;12413:22;12375:2;12472:9;12459:23;12491:31;12516:5;12491:31;:::i;:::-;12541:5;-1:-1:-1;12598:2:1;12583:18;;12570:32;12611:33;12570:32;12611:33;:::i;12681:190::-;;12793:2;12781:9;12772:7;12768:23;12764:32;12761:2;;;12814:6;12806;12799:22;12761:2;-1:-1:-1;12842:23:1;;12751:120;-1:-1:-1;12751:120:1:o;12876:194::-;;12999:2;12987:9;12978:7;12974:23;12970:32;12967:2;;;13020:6;13012;13005:22;12967:2;-1:-1:-1;13048:16:1;;12957:113;-1:-1:-1;12957:113:1:o;13075:1335::-;;;;13282:2;13270:9;13261:7;13257:23;13253:32;13250:2;;;13303:6;13295;13288:22;13250:2;13337:9;13331:16;13321:26;;13366:2;13412;13401:9;13397:18;13391:25;-1:-1:-1;;;;;13476:2:1;13468:6;13465:14;13462:2;;;13497:6;13489;13482:22;13462:2;13540:6;13529:9;13525:22;13515:32;;13585:7;13578:4;13574:2;13570:13;13566:27;13556:2;;13612:6;13604;13597:22;13556:2;13646;13640:9;13669:60;13685:43;13725:2;13685:43;:::i;13669:60::-;13763:15;;;13794:12;;;;13826:11;;;13864;;;13856:20;;13852:29;;13849:42;-1:-1:-1;13846:2:1;;;13909:6;13901;13894:22;13846:2;13936:6;13927:15;;13951:231;13965:2;13962:1;13959:9;13951:231;;;14029:3;14023:10;14046:31;14071:5;14046:31;:::i;:::-;14090:18;;13983:1;13976:9;;;;;14128:12;;;;14160;;13951:231;;;-1:-1:-1;14252:2:1;14237:18;;14231:25;14201:5;;-1:-1:-1;14231:25:1;-1:-1:-1;;;14268:16:1;;;14265:2;;;14302:6;14294;14287:22;14265:2;;;14330:74;14396:7;14385:8;14374:9;14370:24;14330:74;:::i;:::-;14320:84;;;13240:1170;;;;;:::o;14415:660::-;;;;;14596:2;14584:9;14575:7;14571:23;14567:32;14564:2;;;14617:6;14609;14602:22;14564:2;14658:9;14645:23;14635:33;;14719:2;14708:9;14704:18;14691:32;-1:-1:-1;;;;;14738:6:1;14735:30;14732:2;;;14783:6;14775;14768:22;14732:2;14827:70;14889:7;14880:6;14869:9;14865:22;14827:70;:::i;:::-;14916:8;;-1:-1:-1;14801:96:1;-1:-1:-1;;15001:2:1;14986:18;;14973:32;15014:31;14973:32;15014:31;:::i;15080:258::-;;;15209:2;15197:9;15188:7;15184:23;15180:32;15177:2;;;15230:6;15222;15215:22;15177:2;-1:-1:-1;;15258:23:1;;;15328:2;15313:18;;;15300:32;;-1:-1:-1;15167:171:1:o;15343:255::-;;;15483:2;15471:9;15462:7;15458:23;15454:32;15451:2;;;15504:6;15496;15489:22;15451:2;-1:-1:-1;;15532:16:1;;15588:2;15573:18;;;15567:25;15532:16;;15567:25;;-1:-1:-1;15441:157:1:o;15603:326::-;;;;15749:2;15737:9;15728:7;15724:23;15720:32;15717:2;;;15770:6;15762;15755:22;15717:2;-1:-1:-1;;15798:23:1;;;15868:2;15853:18;;15840:32;;-1:-1:-1;15919:2:1;15904:18;;;15891:32;;15707:222;-1:-1:-1;15707:222:1:o;15934:214::-;;16055:2;16043:9;16034:7;16030:23;16026:32;16023:2;;;16076:6;16068;16061:22;16023:2;16104:38;16132:9;16104:38;:::i;16153:524::-;;16253:6;16248:3;16241:19;16279:4;16308:2;16303:3;16299:12;16292:19;;16334:5;16357:3;16369:283;16383:6;16380:1;16377:13;16369:283;;;16460:6;16447:20;16480:33;16505:7;16480:33;:::i;:::-;-1:-1:-1;;;;;16538:33:1;16526:46;;16592:12;;;;16627:15;;;;16568:1;16398:9;16369:283;;;-1:-1:-1;16668:3:1;;16231:446;-1:-1:-1;;;;;16231:446:1:o;16682:463::-;;16773:5;16767:12;16800:6;16795:3;16788:19;16826:4;16855:2;16850:3;16846:12;16839:19;;16892:2;16885:5;16881:14;16913:3;16925:195;16939:6;16936:1;16933:13;16925:195;;;17004:13;;-1:-1:-1;;;;;17000:39:1;16988:52;;17060:12;;;;17095:15;;;;17036:1;16954:9;16925:195;;17150:621;;17259:5;17253:12;17286:6;17281:3;17274:19;17312:4;17341:2;17336:3;17332:12;17325:19;;17365:5;17360:3;17353:18;17409:2;17404:3;17394:18;17430:3;17442:304;17456:6;17453:1;17450:13;17442:304;;;17522:13;;-1:-1:-1;;;;;17560:50:1;;17548:63;;17649:3;17645:19;17631:12;;;17624:41;17694:4;17685:14;;;;17734:1;17722:14;;;;17471:9;17442:304;;17776:363;17864:19;;;17776:363;-1:-1:-1;;;;;17895:31:1;;17892:2;;;17941:3;17936;17929:16;17892:2;17984:4;17976:6;17972:17;18034:8;18027:5;18020:4;18015:3;18011:14;17998:45;18066:18;;;;18086:4;18062:29;18100:15;;;-1:-1:-1;18062:29:1;;17854:285;-1:-1:-1;17854:285:1:o;18144:437::-;;18235:5;18229:12;18262:6;18257:3;18250:19;18288:4;18317:2;18312:3;18308:12;18301:19;;18354:2;18347:5;18343:14;18375:3;18387:169;18401:6;18398:1;18395:13;18387:169;;;18462:13;;18450:26;;18496:12;;;;18531:15;;;;18423:1;18416:9;18387:169;;18586:446;;18675:5;18669:12;18702:6;18697:3;18690:19;18728:4;18757:2;18752:3;18748:12;18741:19;;18794:2;18787:5;18783:14;18815:3;18827:180;18841:6;18838:1;18835:13;18827:180;;;18906:13;;18921:4;18902:24;18890:37;;18947:12;;;;18982:15;;;;18863:1;18856:9;18827:180;;19037:240;19121:1;19114:5;19111:12;19101:2;;19166:10;19161:3;19157:20;19154:1;19147:31;19201:4;19198:1;19191:15;19229:4;19226:1;19219:15;19101:2;19253:18;;19091:186::o;19282:255::-;19357:12;;19371:4;19353:23;19341:36;;19430:4;19419:16;;;19413:23;-1:-1:-1;;;;;19409:49:1;19393:14;;;19386:73;19522:4;19511:16;;;19505:23;19498:31;19491:39;19475:14;;19468:63;19331:206::o;19769:402::-;19864:1;19860;19855:3;19851:11;19847:19;19905:2;19897:5;19891:12;19887:21;19882:3;19875:34;19970:2;19962:4;19955:5;19951:16;19945:23;19941:32;19934:4;19929:3;19925:14;19918:56;;20037:4;20030:5;20026:16;20020:23;20013:31;20006:39;19999:4;19994:3;19990:14;19983:63;20092:4;20085:5;20081:16;20075:23;20107:58;20159:4;20154:3;20150:14;20136:12;20107:58;:::i;20176:272::-;20260:5;20254:12;20249:3;20242:25;20316:4;20309:5;20305:16;20299:23;20292:4;20287:3;20283:14;20276:47;20369:4;20362:5;20358:16;20352:23;20384:58;20436:4;20431:3;20427:14;20413:12;19675;;-1:-1:-1;;;;;19671:21:1;;;19659:34;;19746:4;19735:16;;;19729:23;19725:32;19709:14;;19702:56;19596:168;20453:274;;20620:6;20614:13;20636:53;20682:6;20677:3;20670:4;20662:6;20658:17;20636:53;:::i;:::-;20705:16;;;;;20590:137;-1:-1:-1;;20590:137:1:o;21782:643::-;;22132:1;22128;22123:3;22119:11;22115:19;22107:6;22103:32;22092:9;22085:51;22172:6;22167:2;22156:9;22152:18;22145:34;22215:3;22210:2;22199:9;22195:18;22188:31;22242:57;22294:3;22283:9;22279:19;22271:6;22242:57;:::i;:::-;22347:9;22339:6;22335:22;22330:2;22319:9;22315:18;22308:50;22375:44;22412:6;22404;22375:44;:::i;23685:689::-;;24047:1;24043;24038:3;24034:11;24030:19;24022:6;24018:32;24007:9;24000:51;24087:6;24082:2;24071:9;24067:18;24060:34;24130:3;24125:2;24114:9;24110:18;24103:31;24157:74;24226:3;24215:9;24211:19;24203:6;24195;24157:74;:::i;:::-;24279:9;24271:6;24267:22;24262:2;24251:9;24247:18;24240:50;24307:61;24361:6;24353;24345;24307:61;:::i;:::-;24299:69;23990:384;-1:-1:-1;;;;;;;;;23990:384:1:o;24379:761::-;;24769:1;24765;24760:3;24756:11;24752:19;24744:6;24740:32;24729:9;24722:51;24809:6;24804:2;24793:9;24789:18;24782:34;24852:3;24847:2;24836:9;24832:18;24825:31;24879:74;24948:3;24937:9;24933:19;24925:6;24917;24879:74;:::i;:::-;25001:9;24993:6;24989:22;24984:2;24973:9;24969:18;24962:50;25029:61;25083:6;25075;25067;25029:61;:::i;:::-;25021:69;;;25127:6;25121:3;25110:9;25106:19;25099:35;24712:428;;;;;;;;;;:::o;25785:707::-;;26155:1;26151;26146:3;26142:11;26138:19;26130:6;26126:32;26115:9;26108:51;26195:6;26190:2;26179:9;26175:18;26168:34;26238:3;26233:2;26222:9;26218:18;26211:31;26265:57;26317:3;26306:9;26302:19;26294:6;26265:57;:::i;:::-;26370:9;26362:6;26358:22;26353:2;26342:9;26338:18;26331:50;26398:44;26435:6;26427;26398:44;:::i;:::-;26390:52;;;26479:6;26473:3;26462:9;26458:19;26451:35;26098:394;;;;;;;;:::o;26497:917::-;;26978:3;26967:9;26960:22;27005:75;27075:3;27064:9;27060:19;27052:6;27005:75;:::i;:::-;27128:9;27120:6;27116:22;27111:2;27100:9;27096:18;27089:50;27162:42;27197:6;27189;27162:42;:::i;:::-;27148:56;;27252:9;27244:6;27240:22;27235:2;27224:9;27220:18;27213:50;27280:61;27334:6;27326;27318;27280:61;:::i;:::-;27272:69;;;27350:58;27404:2;27393:9;27389:18;27381:6;27350:58;:::i;:::-;26950:464;;;;;;;;:::o;27419:1232::-;;27890:3;27879:9;27872:22;27917:75;27987:3;27976:9;27972:19;27964:6;27917:75;:::i;:::-;28011:2;28061:9;28053:6;28049:22;28044:2;28033:9;28029:18;28022:50;28095:42;28130:6;28122;28095:42;:::i;:::-;28173:22;;;28168:2;28153:18;;28146:50;28245:13;;28267:22;;;28343:15;;;;-1:-1:-1;28305:15:1;;;;28376:4;28389:169;28403:6;28400:1;28397:13;28389:169;;;28464:13;;28452:26;;28533:15;;;;28498:12;;;;28425:1;28418:9;28389:169;;;28393:3;;28575;28567:11;;;;;28587:58;28641:2;28630:9;28626:18;28618:6;28587:58;:::i;:::-;27862:789;;;;;;;:::o;28656:828::-;;29091:3;29121:2;29110:9;29103:21;29141:74;29211:2;29200:9;29196:18;29188:6;29141:74;:::i;:::-;29133:82;;;29263:4;29255:6;29251:17;29246:2;29235:9;29231:18;29224:45;29317:4;29309:6;29305:17;29300:2;29289:9;29285:18;29278:45;29359:6;29354:2;29343:9;29339:18;29332:34;29403:6;29397:3;29386:9;29382:19;29375:35;29419:59;29473:3;29462:9;29458:19;29450:6;29419:59;:::i;29489:647::-;;29870:3;29859:9;29852:22;29891:75;29961:3;29950:9;29946:19;29938:6;29891:75;:::i;:::-;29883:83;;30014:4;30006:6;30002:17;29997:2;29986:9;29982:18;29975:45;30056:6;30051:2;30040:9;30036:18;30029:34;30072:58;30126:2;30115:9;30111:18;30103:6;30072:58;:::i;30982:488::-;;31301:3;31290:9;31283:22;31322:75;31392:3;31381:9;31377:19;31369:6;31322:75;:::i;:::-;31314:83;;31406:58;31460:2;31449:9;31445:18;31437:6;31406:58;:::i;32930:1341::-;33291:2;33343:21;;;33413:13;;33316:18;;;33435:22;;;32930:1341;;33291:2;33510:4;;33488:2;33473:18;;;33537:15;;;32930:1341;33583:197;33597:6;33594:1;33591:13;33583:197;;;33646:52;33694:3;33685:6;33679:13;33646:52;:::i;:::-;33727:4;33718:14;;;;;33755:15;;;;33619:1;33612:9;33583:197;;;-1:-1:-1;;;33816:19:1;;;33796:18;;;33789:47;33886:13;;33908:21;;;33984:15;;;;33947:12;;;34019:4;34032:211;34048:8;34043:3;34040:17;34032:211;;;34103:52;34149:5;34138:8;34132:15;19675:12;;-1:-1:-1;;;;;19671:21:1;;;19659:34;;19746:4;19735:16;;;19729:23;19725:32;19709:14;;19702:56;19596:168;34103:52;34216:17;;;;34177:14;;;;34076:1;34067:11;34032:211;;;-1:-1:-1;34260:5:1;;33271:1000;-1:-1:-1;;;;;;;;33271:1000:1:o;34276:934::-;34601:25;;;34589:2;34645;34663:18;;;34656:30;;;34574:18;;;34721:22;;;34276:934;;34801:6;;34774:3;34759:19;;34276:934;34838:277;34852:6;34849:1;34846:13;34838:277;;;34927:6;34914:20;34947:31;34972:5;34947:31;:::i;:::-;-1:-1:-1;;;;;35003:31:1;34991:44;;35090:15;;;;35055:12;;;;35031:1;34867:9;34838:277;;;-1:-1:-1;;;;;;35171:32:1;;;;35166:2;35151:18;;;;35144:60;;;;-1:-1:-1;35132:3:1;;34550:660;-1:-1:-1;;;;;34550:660:1:o;35215:1240::-;;35521:2;35561;35550:9;35546:18;35591:2;35580:9;35573:21;35614:6;35649;35643:13;35680:6;35672;35665:22;35706:2;35696:12;;35739:2;35728:9;35724:18;35717:25;;35764:6;35758:4;35751:20;35790:4;35833:2;35827:4;35817:19;35854:4;35867:519;35881:6;35878:1;35875:13;35867:519;;;35988:13;;-1:-1:-1;;;;;35984:22:1;;;35972:35;;35957:1;36043:14;;36037:21;36092:18;;;36078:12;;;36071:40;36134:4;35948:3;36190:19;;;36186:28;;36179:36;36172:44;36158:12;;;36151:66;36134:4;36230:72;36289:12;;;36267:3;36263:19;;;36259:28;;36230:72;:::i;:::-;-1:-1:-1;;36331:4:1;36322:14;;;;;36371:4;36359:17;;;;;35903:1;35896:9;35867:519;;;-1:-1:-1;;36422:18:1;;;;36415:34;;;;-1:-1:-1;36403:3:1;;35501:954;-1:-1:-1;;;;35501:954:1:o;36460:261::-;;36639:2;36628:9;36621:21;36659:56;36711:2;36700:9;36696:18;36688:6;36659:56;:::i;37323:383::-;;37472:2;37461:9;37454:21;37504:6;37498:13;37547:6;37542:2;37531:9;37527:18;37520:34;37563:66;37622:6;37617:2;37606:9;37602:18;37597:2;37589:6;37585:15;37563:66;:::i;:::-;37690:2;37669:15;-1:-1:-1;;37665:29:1;37650:45;;;;37697:2;37646:54;;37444:262;-1:-1:-1;;37444:262:1:o;39551:336::-;39753:2;39735:21;;;39792:2;39772:18;;;39765:30;-1:-1:-1;;;39826:2:1;39811:18;;39804:42;39878:2;39863:18;;39725:162::o;45855:341::-;46057:2;46039:21;;;46096:2;46076:18;;;46069:30;-1:-1:-1;;;46130:2:1;46115:18;;46108:47;46187:2;46172:18;;46029:167::o;48806:329::-;49008:2;48990:21;;;49047:1;49027:18;;;49020:29;-1:-1:-1;;;49080:2:1;49065:18;;49058:36;49126:2;49111:18;;48980:155::o;49551:355::-;49753:2;49735:21;;;49792:2;49772:18;;;49765:30;49831:33;49826:2;49811:18;;49804:61;49897:2;49882:18;;49725:181::o;51879:410::-;52153:3;52138:19;;52166:51;52142:9;52199:6;52166:51;:::i;:::-;19675:12;;-1:-1:-1;;;;;19671:21:1;;;52278:3;52263:19;;19659:34;19746:4;19735:16;;19729:23;19725:32;19709:14;;;19702:56;52226:57;19596:168;52294:432;;52486:3;52475:9;52471:19;52463:27;;52523:6;52517:13;52506:9;52499:32;52587:4;52579:6;52575:17;52569:24;52562:4;52551:9;52547:20;52540:54;52641:4;52633:6;52629:17;52623:24;52656:64;52714:4;52703:9;52699:20;52685:12;19675;;-1:-1:-1;;;;;19671:21:1;;;19659:34;;19746:4;19735:16;;;19729:23;19725:32;19709:14;;19702:56;19596:168;52731:838;;53160:3;53190:6;53179:9;53172:25;53206:58;53260:2;53249:9;53245:18;53237:6;53206:58;:::i;:::-;53301:2;53295:3;53284:9;53280:19;53273:31;53327:54;53377:2;53366:9;53362:18;53354:6;53327:54;:::i;:::-;53313:68;;53430:9;53422:6;53418:22;53412:3;53401:9;53397:19;53390:51;53458:61;53512:6;53504;53496;53458:61;:::i;:::-;53450:69;;;53556:6;53550:3;53539:9;53535:19;53528:35;53140:429;;;;;;;;;:::o;53574:936::-;;54031:3;54061:6;54050:9;54043:25;54077:58;54131:2;54120:9;54116:18;54108:6;54077:58;:::i;:::-;54172:2;54166:3;54155:9;54151:19;54144:31;54198:54;54248:2;54237:9;54233:18;54225:6;54198:54;:::i;:::-;54184:68;;54301:9;54293:6;54289:22;54283:3;54272:9;54268:19;54261:51;54329:61;54383:6;54375;54367;54329:61;:::i;:::-;54421:3;54406:19;;54399:35;;;;-1:-1:-1;;;;;;;54471:32:1;;;;54465:3;54450:19;;;54443:61;54321:69;54011:499;-1:-1:-1;;;;;54011:499:1:o;54515:871::-;55008:25;;;54995:3;54980:19;;55042:58;55096:2;55081:18;;55073:6;55042:58;:::i;:::-;55109:52;55156:3;55145:9;55141:19;55133:6;55109:52;:::i;:::-;55170;55217:3;55206:9;55202:19;55194:6;55170:52;:::i;:::-;55253:3;55238:19;;55231:35;;;;55297:3;55282:19;;55275:35;;;;-1:-1:-1;;;;;55347:32:1;55341:3;55326:19;;;55319:61;54962:424;;-1:-1:-1;;;;54962:424:1:o;55391:640::-;55784:25;;;55771:3;55756:19;;55818:58;55872:2;55857:18;;55849:6;55818:58;:::i;:::-;55885:52;55932:3;55921:9;55917:19;55909:6;55885:52;:::i;:::-;55968:3;55953:19;;55946:35;;;;56012:3;55997:19;55990:35;55738:293;;-1:-1:-1;;;55738:293:1:o;56036:738::-;56457:25;;;56444:3;56429:19;;56491:58;56545:2;56530:18;;56522:6;56491:58;:::i;:::-;56558:52;56605:3;56594:9;56590:19;56582:6;56558:52;:::i;:::-;56641:3;56626:19;;56619:35;;;;56685:3;56670:19;;56663:35;;;;-1:-1:-1;;;;;56735:32:1;56729:3;56714:19;;;56707:61;56411:363;;-1:-1:-1;;;56411:363:1:o;56779:737::-;;57162:3;57192:6;57181:9;57174:25;57208:58;57262:2;57251:9;57247:18;57239:6;57208:58;:::i;:::-;57303:6;57297:3;57286:9;57282:19;57275:35;57347:2;57341:3;57330:9;57326:19;57319:31;57367:73;57436:2;57425:9;57421:18;57413:6;57405;57367:73;:::i;:::-;57359:81;;;57506:1;57502;57497:3;57493:11;57489:19;57481:6;57477:32;57471:3;57460:9;57456:19;57449:61;57142:374;;;;;;;;;:::o;58604:995::-;;59012:3;59001:9;58997:19;58989:27;;59043:6;59032:9;59025:25;59086:6;59081:2;59070:9;59066:18;59059:34;59129:6;59124:2;59113:9;59109:18;59102:34;59172:6;59167:2;59156:9;59152:18;59145:34;59216:6;59210:3;59199:9;59195:19;59188:35;-1:-1:-1;;;;;59316:2:1;59307:6;59301:13;59297:22;59291:3;59280:9;59276:19;59269:51;59385:2;59379;59371:6;59367:15;59361:22;59357:31;59351:3;59340:9;59336:19;59329:60;59454:2;59448;59440:6;59436:15;59430:22;59426:31;59420:3;59409:9;59405:19;59398:60;59523:2;59517;59509:6;59505:15;59499:22;59495:31;59489:3;59478:9;59474:19;59467:60;;59536:57;59588:3;59577:9;59573:19;59565:6;19675:12;;-1:-1:-1;;;;;19671:21:1;;;19659:34;;19746:4;19735:16;;;19729:23;19725:32;19709:14;;19702:56;19596:168;59536:57;58979:620;;;;;;;;;;:::o;59793:275::-;59864:2;59858:9;59929:2;59910:13;;-1:-1:-1;;59906:27:1;59894:40;;-1:-1:-1;;;;;59949:34:1;;59985:22;;;59946:62;59943:2;;;60011:18;;:::i;:::-;60047:2;60040:22;59838:230;;-1:-1:-1;59838:230:1:o;60073:186::-;;-1:-1:-1;;;;;60158:6:1;60155:30;60152:2;;;60188:18;;:::i;:::-;-1:-1:-1;60248:4:1;60229:17;;;60225:28;;60142:117::o;60264:128::-;;60335:1;60331:6;60328:1;60325:13;60322:2;;;60341:18;;:::i;:::-;-1:-1:-1;60377:9:1;;60312:80::o;60397:217::-;;60463:1;60453:2;;-1:-1:-1;;;60488:31:1;;60542:4;60539:1;60532:15;60570:4;60495:1;60560:15;60453:2;-1:-1:-1;60599:9:1;;60443:171::o;60619:453::-;60715:6;60738:5;60752:314;60801:1;60838:2;60828:8;60825:16;60815:2;;60845:5;;;60815:2;60886:4;60881:3;60877:14;60871:4;60868:24;60865:2;;;60895:18;;:::i;:::-;60945:2;60935:8;60931:17;60928:2;;;60960:16;;;;60928:2;61039:17;;;;;60999:15;;60752:314;;;60696:376;;;;;;;:::o;61077:148::-;;61164:55;-1:-1:-1;;61205:4:1;61191:19;;61185:4;61230:922;61314:8;61304:2;;-1:-1:-1;61355:1:1;61369:5;;61304:2;61403:4;61393:2;;-1:-1:-1;61440:1:1;61454:5;;61393:2;61485:4;61503:1;61498:59;;;;61571:1;61566:183;;;;61478:271;;61498:59;61528:1;61519:10;;61542:5;;;61566:183;61603:3;61593:8;61590:17;61587:2;;;61610:18;;:::i;:::-;61666:1;61656:8;61652:16;61643:25;;61694:3;61687:5;61684:14;61681:2;;;61701:18;;:::i;:::-;61734:5;;;61478:271;;61833:2;61823:8;61820:16;61814:3;61808:4;61805:13;61801:36;61795:2;61785:8;61782:16;61777:2;61771:4;61768:12;61764:35;61761:77;61758:2;;;-1:-1:-1;61870:19:1;;;61905:14;;;61902:2;;;61922:18;;:::i;:::-;61955:5;;61758:2;62002:42;62040:3;62030:8;62024:4;62021:1;62002:42;:::i;:::-;62077:6;62072:3;62068:16;62059:7;62056:29;62053:2;;;62088:18;;:::i;:::-;62126:20;;61294:858;-1:-1:-1;;;;61294:858:1:o;62157:168::-;;62263:1;62259;62255:6;62251:14;62248:1;62245:21;62240:1;62233:9;62226:17;62222:45;62219:2;;;62270:18;;:::i;:::-;-1:-1:-1;62310:9:1;;62209:116::o;62330:125::-;;62398:1;62395;62392:8;62389:2;;;62403:18;;:::i;:::-;-1:-1:-1;62440:9:1;;62379:76::o;62460:229::-;;-1:-1:-1;;;;;62596:10:1;;;;62566;;62618:12;;;62615:2;;;62633:18;;:::i;:::-;62670:13;;62508:181;-1:-1:-1;;;62508:181:1:o;62694:195::-;;62769:4;62766:1;62762:12;62801:4;62798:1;62794:12;62826:3;62821;62818:12;62815:2;;;62833:18;;:::i;:::-;62870:13;;;62741:148;-1:-1:-1;;;62741:148:1:o;62894:258::-;62966:1;62976:113;62990:6;62987:1;62984:13;62976:113;;;63066:11;;;63060:18;63047:11;;;63040:39;63012:2;63005:10;62976:113;;;63107:6;63104:1;63101:13;63098:2;;;-1:-1:-1;;63142:1:1;63124:16;;63117:27;62947:205::o;63157:380::-;63242:1;63232:12;;63289:1;63279:12;;;63300:2;;63354:4;63346:6;63342:17;63332:27;;63300:2;63407;63399:6;63396:14;63376:18;63373:38;63370:2;;;63453:10;63448:3;63444:20;63441:1;63434:31;63488:4;63485:1;63478:15;63516:4;63513:1;63506:15;63542:135;;-1:-1:-1;;63602:17:1;;63599:2;;;63622:18;;:::i;:::-;-1:-1:-1;63669:1:1;63658:13;;63589:88::o;63682:127::-;63743:10;63738:3;63734:20;63731:1;63724:31;63774:4;63771:1;63764:15;63798:4;63795:1;63788:15;63814:127;63875:10;63870:3;63866:20;63863:1;63856:31;63906:4;63903:1;63896:15;63930:4;63927:1;63920:15;63946:131;-1:-1:-1;;;;;64021:31:1;;64011:42;;64001:2;;64067:1;64064;64057:12;64082:118;64168:5;64161:13;64154:21;64147:5;64144:32;64134:2;;64190:1;64187;64180:12;64205:146;-1:-1:-1;;;;;64284:5:1;64280:46;64273:5;64270:57;64260:2;;64341:1;64338;64331:12
Swarm Source
ipfs://850dd1f167ac97afe719deef338bad5974094486512a857d3b35961d8341c7f6
Loading...
Loading
Loading...
Loading
OVERVIEW
Logic contract for mStable Alchemix USD (alUSD) Feeder Pool.Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.