More Info
Private Name Tags
ContractCreator
GENESIS at txn GENESIS_2935cd347b79c319a6464fe3b1087170f142418c
Latest 25 from a total of 26,171 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 128842955 | 8 days ago | IN | 0 ETH | 0.000000154269 | ||||
Withdraw | 128650770 | 12 days ago | IN | 0 ETH | 0.000000358283 | ||||
Un Signal Withdr... | 128486515 | 16 days ago | IN | 0 ETH | 0.00000045522 | ||||
Withdraw | 128314981 | 20 days ago | IN | 0 ETH | 0.000000146644 | ||||
Withdraw | 127914968 | 29 days ago | IN | 0 ETH | 0.000001949289 | ||||
End Round | 119092232 | 234 days ago | IN | 0 ETH | 0.000713157317 | ||||
Withdraw | 118465013 | 248 days ago | IN | 0 ETH | 0.000001499283 | ||||
Withdraw | 118465005 | 248 days ago | IN | 0 ETH | 0.000001672456 | ||||
Withdraw | 118442382 | 249 days ago | IN | 0 ETH | 0.000002081074 | ||||
Withdraw | 117453067 | 272 days ago | IN | 0 ETH | 0.000001532962 | ||||
Withdraw | 117453064 | 272 days ago | IN | 0 ETH | 0.000001537874 | ||||
Withdraw | 117453061 | 272 days ago | IN | 0 ETH | 0.000001548058 | ||||
Withdraw | 117453059 | 272 days ago | IN | 0 ETH | 0.000001554687 | ||||
Withdraw | 117453056 | 272 days ago | IN | 0 ETH | 0.000001566063 | ||||
Withdraw | 117453049 | 272 days ago | IN | 0 ETH | 0.000001551932 | ||||
Withdraw | 117453042 | 272 days ago | IN | 0 ETH | 0.000001540154 | ||||
Withdraw | 117453034 | 272 days ago | IN | 0 ETH | 0.000001534501 | ||||
Withdraw | 117453027 | 272 days ago | IN | 0 ETH | 0.000001555597 | ||||
Withdraw | 117453020 | 272 days ago | IN | 0 ETH | 0.000001527091 | ||||
Withdraw | 117453012 | 272 days ago | IN | 0 ETH | 0.000001561008 | ||||
Withdraw | 117453004 | 272 days ago | IN | 0 ETH | 0.000001557824 | ||||
Withdraw | 117452996 | 272 days ago | IN | 0 ETH | 0.000001545156 | ||||
Withdraw | 117452989 | 272 days ago | IN | 0 ETH | 0.000001548671 | ||||
Withdraw | 117452982 | 272 days ago | IN | 0 ETH | 0.00000155029 | ||||
Withdraw | 117452975 | 272 days ago | IN | 0 ETH | 0.000001553458 |
Loading...
Loading
Contract Source Code Verified (Genesis Bytecode Match Only)
Contract Name:
LiquidityPool
Compiler Version
v0.7.6
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; // Libraries import "./synthetix/SafeDecimalMath.sol"; // Interfaces import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IOptionMarket.sol"; import "./interfaces/ILiquidityCertificate.sol"; import "./interfaces/IPoolHedger.sol"; import "./interfaces/IShortCollateral.sol"; /** * @title LiquidityPool * @author Lyra * @dev Holds funds from LPs, which are used for the following purposes: * 1. Collateralizing options sold by the OptionMarket. * 2. Buying options from users. * 3. Delta hedging the LPs. * 4. Storing funds for expired in the money options. */ contract LiquidityPool is ILiquidityPool { using SafeMath for uint; using SafeDecimalMath for uint; //// // Constants //// ILyraGlobals internal globals; IOptionMarket internal optionMarket; ILiquidityCertificate internal liquidityCertificate; IShortCollateral internal shortCollateral; IPoolHedger internal poolHedger; IERC20 internal quoteAsset; IERC20 internal baseAsset; uint internal constant INITIAL_RATE = 1e18; //// // Variables //// mapping(uint => string) internal errorMessages; bool internal initialized = false; /// @dev Amount of collateral locked for outstanding calls and puts sold to users Collateral public override lockedCollateral; /** * @dev Total amount of quoteAsset held to pay out users who have locked/waited for their tokens to be burnable. As * well as keeping track of all settled option's usd value. */ uint internal totalQuoteAmountReserved; /// @dev Total number of tokens that will be removed from the totalTokenSupply at the end of the round. uint internal tokensBurnableForRound; /// @dev Funds entering the pool in the next round. uint public override queuedQuoteFunds; /// @dev Total amount of tokens that represents the total amount of pool shares uint internal totalTokenSupply; /// @dev Counter for reentrancy guard. uint internal counter = 1; /** * @dev Mapping of timestamps to conversion rates of liquidity to tokens. To get the token value of a certificate; * `certificate.liquidity / expiryToTokenValue[certificate.enteredAt]` */ mapping(uint => uint) public override expiryToTokenValue; constructor() {} /** * @dev Initialize the contract. * * @param _optionMarket OptionMarket address * @param _liquidityCertificate LiquidityCertificate address * @param _quoteAsset Quote Asset address * @param _poolHedger PoolHedger address */ function init( ILyraGlobals _globals, IOptionMarket _optionMarket, ILiquidityCertificate _liquidityCertificate, IPoolHedger _poolHedger, IShortCollateral _shortCollateral, IERC20 _quoteAsset, IERC20 _baseAsset, string[] memory _errorMessages ) external { require(!initialized, "already initialized"); globals = _globals; optionMarket = _optionMarket; liquidityCertificate = _liquidityCertificate; shortCollateral = _shortCollateral; poolHedger = _poolHedger; quoteAsset = _quoteAsset; baseAsset = _baseAsset; require(_errorMessages.length == uint(Error.Last), "error msg count"); for (uint i = 0; i < _errorMessages.length; i++) { errorMessages[i] = _errorMessages[i]; } initialized = true; } //////////////////////////////////////////////////////////////// // Dealing with providing liquidity and withdrawing liquidity // //////////////////////////////////////////////////////////////// /** * @dev Deposits liquidity to the pool. This assumes users have authorised access to the quote ERC20 token. Will add * any deposited amount to the queuedQuoteFunds until the next round begins. * * @param beneficiary The account that will receive the liquidity certificate. * @param amount The amount of quoteAsset to deposit. */ function deposit(address beneficiary, uint amount) external override returns (uint) { // Assume we have the allowance to take the amount they are depositing queuedQuoteFunds = queuedQuoteFunds.add(amount); uint certificateId = liquidityCertificate.mint(beneficiary, amount, optionMarket.maxExpiryTimestamp()); emit Deposit(beneficiary, certificateId, amount); _require(quoteAsset.transferFrom(msg.sender, address(this), amount), Error.QuoteTransferFailed); return certificateId; } /** * @notice Signals withdraw of liquidity from the pool. * @dev It is not possible to withdraw during a round, thus a user can signal to withdraw at the time the round ends. * * @param certificateId The id of the LiquidityCertificate. */ function signalWithdrawal(uint certificateId) external override { ILiquidityCertificate.CertificateData memory certificateData = liquidityCertificate.certificateData(certificateId); uint maxExpiryTimestamp = optionMarket.maxExpiryTimestamp(); _require(certificateData.burnableAt == 0, Error.AlreadySignalledWithdrawal); _require( certificateData.enteredAt != maxExpiryTimestamp && expiryToTokenValue[maxExpiryTimestamp] == 0, Error.SignallingBetweenRounds ); if (certificateData.enteredAt == 0) { // Dividing by INITIAL_RATE is redundant as initial rate is 1 unit tokensBurnableForRound = tokensBurnableForRound.add(certificateData.liquidity); } else { tokensBurnableForRound = tokensBurnableForRound.add( certificateData.liquidity.divideDecimal(expiryToTokenValue[certificateData.enteredAt]) ); } liquidityCertificate.setBurnableAt(msg.sender, certificateId, maxExpiryTimestamp); emit WithdrawSignaled(certificateId, tokensBurnableForRound); } /** * @dev Undo a previously signalled withdraw. Certificate owner must have signalled withdraw to call this function, * and cannot unsignal if the token is already burnable or burnt. * * @param certificateId The id of the LiquidityCertificate. */ function unSignalWithdrawal(uint certificateId) external override { ILiquidityCertificate.CertificateData memory certificateData = liquidityCertificate.certificateData(certificateId); // Cannot unsignal withdrawal if the token is burnable/hasn't signalled exit _require(certificateData.burnableAt != 0, Error.UnSignalMustSignalFirst); _require(expiryToTokenValue[certificateData.burnableAt] == 0, Error.UnSignalAlreadyBurnable); liquidityCertificate.setBurnableAt(msg.sender, certificateId, 0); if (certificateData.enteredAt == 0) { // Dividing by INITIAL_RATE is redundant as initial rate is 1 unit tokensBurnableForRound = tokensBurnableForRound.sub(certificateData.liquidity); } else { tokensBurnableForRound = tokensBurnableForRound.sub( certificateData.liquidity.divideDecimal(expiryToTokenValue[certificateData.enteredAt]) ); } emit WithdrawUnSignaled(certificateId, tokensBurnableForRound); } /** * @dev Withdraws liquidity from the pool. * * This requires tokens to have been locked until the round ending at the burnableAt timestamp has been ended. * This will burn the liquidityCertificates and have the quote asset equivalent at the time be reserved for the users. * * @param beneficiary The account that will receive the withdrawn funds. * @param certificateId The id of the LiquidityCertificate. */ function withdraw(address beneficiary, uint certificateId) external override returns (uint value) { ILiquidityCertificate.CertificateData memory certificateData = liquidityCertificate.certificateData(certificateId); uint maxExpiryTimestamp = optionMarket.maxExpiryTimestamp(); // We allow people to withdraw if their funds haven't entered the system if (certificateData.enteredAt == maxExpiryTimestamp) { queuedQuoteFunds = queuedQuoteFunds.sub(certificateData.liquidity); liquidityCertificate.burn(msg.sender, certificateId); emit Withdraw(beneficiary, certificateId, certificateData.liquidity, totalQuoteAmountReserved); _require(quoteAsset.transfer(beneficiary, certificateData.liquidity), Error.QuoteTransferFailed); return certificateData.liquidity; } uint enterValue = certificateData.enteredAt == 0 ? INITIAL_RATE : expiryToTokenValue[certificateData.enteredAt]; // expiryToTokenValue will only be set if the previous round has ended, and the next has not started uint currentRoundValue = expiryToTokenValue[maxExpiryTimestamp]; // If they haven't signaled withdrawal, and it is between rounds if (certificateData.burnableAt == 0 && currentRoundValue != 0) { uint tokenAmt = certificateData.liquidity.divideDecimal(enterValue); totalTokenSupply = totalTokenSupply.sub(tokenAmt); value = tokenAmt.multiplyDecimal(currentRoundValue); liquidityCertificate.burn(msg.sender, certificateId); emit Withdraw(beneficiary, certificateId, value, totalQuoteAmountReserved); _require(quoteAsset.transfer(beneficiary, value), Error.QuoteTransferFailed); return value; } uint exitValue = expiryToTokenValue[certificateData.burnableAt]; _require(certificateData.burnableAt != 0 && exitValue != 0, Error.WithdrawNotBurnable); value = certificateData.liquidity.multiplyDecimal(exitValue).divideDecimal(enterValue); // We can allow a 0 expiry for options created before any boards exist liquidityCertificate.burn(msg.sender, certificateId); totalQuoteAmountReserved = totalQuoteAmountReserved.sub(value); emit Withdraw(beneficiary, certificateId, value, totalQuoteAmountReserved); _require(quoteAsset.transfer(beneficiary, value), Error.QuoteTransferFailed); return value; } ////////////////////////////////////////////// // Dealing with locking and expiry rollover // ////////////////////////////////////////////// /** * @dev Return Token value. * * This token price is only accurate within the period between rounds. */ function tokenPriceQuote() public view override returns (uint) { ILyraGlobals.ExchangeGlobals memory exchangeGlobals = globals.getExchangeGlobals(address(optionMarket), ILyraGlobals.ExchangeType.ALL); if (totalTokenSupply == 0) { return INITIAL_RATE; } uint poolValue = getTotalPoolValueQuote( exchangeGlobals.spotPrice, poolHedger.getValueQuote(exchangeGlobals.short, exchangeGlobals.spotPrice) ); return poolValue.divideDecimal(totalTokenSupply); } /** * @notice Ends a round. * @dev Should only be called after all boards have been liquidated. */ function endRound() external override { // Round can only be ended if all boards have been liquidated, and can only be called once. uint maxExpiryTimestamp = optionMarket.maxExpiryTimestamp(); // We must ensure all boards have been expired _require(optionMarket.getLiveBoards().length == 0, Error.EndRoundWithLiveBoards); // We can only end the round once _require(expiryToTokenValue[maxExpiryTimestamp] == 0, Error.EndRoundAlreadyEnded); // We want to make sure all base collateral has been exchanged _require(baseAsset.balanceOf(address(this)) == 0, Error.EndRoundMustExchangeBase); // We want to make sure there is no outstanding poolHedger balance. If there is collateral left in the poolHedger // it will not affect calculations. _require(poolHedger.getCurrentHedgedNetDelta() == 0, Error.EndRoundMustHedgeDelta); uint pricePerToken = tokenPriceQuote(); // Store the value for the tokens that are burnable for this round expiryToTokenValue[maxExpiryTimestamp] = pricePerToken; // Reserve the amount of quote we need for the tokens that are burnable totalQuoteAmountReserved = totalQuoteAmountReserved.add(tokensBurnableForRound.multiplyDecimal(pricePerToken)); emit QuoteReserved(tokensBurnableForRound.multiplyDecimal(pricePerToken), totalQuoteAmountReserved); totalTokenSupply = totalTokenSupply.sub(tokensBurnableForRound); emit RoundEnded(maxExpiryTimestamp, pricePerToken, totalQuoteAmountReserved, tokensBurnableForRound); tokensBurnableForRound = 0; } /** * @dev Starts a round. Can only be called by optionMarket contract when adding a board. * * @param lastMaxExpiryTimestamp The time at which the previous round ended. * @param newMaxExpiryTimestamp The time which funds will be locked until. */ function startRound(uint lastMaxExpiryTimestamp, uint newMaxExpiryTimestamp) external override onlyOptionMarket { // As the value is never reset, this is when the first board is added if (lastMaxExpiryTimestamp == 0) { totalTokenSupply = queuedQuoteFunds; } else { _require(expiryToTokenValue[lastMaxExpiryTimestamp] != 0, Error.StartRoundMustEndRound); totalTokenSupply = totalTokenSupply.add( queuedQuoteFunds.divideDecimal(expiryToTokenValue[lastMaxExpiryTimestamp]) ); } queuedQuoteFunds = 0; emit RoundStarted( lastMaxExpiryTimestamp, newMaxExpiryTimestamp, totalTokenSupply, lastMaxExpiryTimestamp == 0 ? SafeDecimalMath.UNIT : expiryToTokenValue[lastMaxExpiryTimestamp] ); } ///////////////////////////////////////// // Dealing with collateral for options // ///////////////////////////////////////// /** * @dev external override function that will bring the base balance of this contract to match locked.base. This cannot be done * in the same transaction as locking the base, as exchanging on synthetix is too costly gas-wise. */ function exchangeBase() external override reentrancyGuard { uint currentBaseBalance = baseAsset.balanceOf(address(this)); // Add this additional check to prevent any soft locks at round end, as the base balance must be 0 to end the round. if (optionMarket.getLiveBoards().length == 0) { lockedCollateral.base = 0; } if (currentBaseBalance > lockedCollateral.base) { // Sell excess baseAsset ILyraGlobals.ExchangeGlobals memory exchangeGlobals = globals.getExchangeGlobals(address(optionMarket), ILyraGlobals.ExchangeType.BASE_QUOTE); uint amount = currentBaseBalance - lockedCollateral.base; uint quoteReceived = exchangeGlobals.synthetix.exchange(exchangeGlobals.baseKey, amount, exchangeGlobals.quoteKey); _require(quoteReceived > 0, Error.ReceivedZeroFromBaseQuoteExchange); emit BaseSold(msg.sender, amount, quoteReceived); } else if (lockedCollateral.base > currentBaseBalance) { // Buy required amount of baseAsset ILyraGlobals.ExchangeGlobals memory exchangeGlobals = globals.getExchangeGlobals(address(optionMarket), ILyraGlobals.ExchangeType.QUOTE_BASE); uint quoteToSpend = (lockedCollateral.base - currentBaseBalance) .divideDecimalRound(SafeDecimalMath.UNIT.sub(exchangeGlobals.quoteBaseFeeRate)) .multiplyDecimalRound(exchangeGlobals.spotPrice); uint totalQuoteAvailable = quoteAsset.balanceOf(address(this)).sub(totalQuoteAmountReserved).sub(lockedCollateral.quote).sub( queuedQuoteFunds ); // We want to always buy as much collateral as we can, even if it dips into the delta hedging portion. // But we cannot compromise funds that aren't useable by the pool. quoteToSpend = quoteToSpend > totalQuoteAvailable ? totalQuoteAvailable : quoteToSpend; uint amtReceived = exchangeGlobals.synthetix.exchange(exchangeGlobals.quoteKey, quoteToSpend, exchangeGlobals.baseKey); _require(amtReceived > 0, Error.ReceivedZeroFromQuoteBaseExchange); emit BasePurchased(msg.sender, quoteToSpend, amtReceived); } } /** * @notice Locks quote when the system sells a put option. * * @param amount The amount of quote to lock. * @param freeCollatLiq The amount of free collateral that can be locked. */ function lockQuote(uint amount, uint freeCollatLiq) external override onlyOptionMarket { _require(amount <= freeCollatLiq, Error.LockingMoreQuoteThanIsFree); lockedCollateral.quote = lockedCollateral.quote.add(amount); emit QuoteLocked(amount, lockedCollateral.quote); } /** * @notice Purchases and locks base when the system sells a call option. * * @param amount The amount of baseAsset to purchase and lock. * @param exchangeGlobals The exchangeGlobals. * @param liquidity Free and used liquidity amounts. */ function lockBase( uint amount, ILyraGlobals.ExchangeGlobals memory exchangeGlobals, Liquidity memory liquidity ) external override onlyOptionMarket { uint currentBaseBal = baseAsset.balanceOf(address(this)); uint desiredBase; uint availableQuote = liquidity.freeCollatLiquidity; if (lockedCollateral.base >= currentBaseBal) { uint outstanding = lockedCollateral.base - currentBaseBal; // We need to ignore any base we haven't purchased yet from our availableQuote availableQuote = availableQuote.add(outstanding.multiplyDecimal(exchangeGlobals.spotPrice)); // But we want to make sure we will have enough quote to cover the debt owed on top of new base we want to lock desiredBase = amount.add(outstanding); } else { // We actually need to buy less, or none, if we already have excess balance uint excess = currentBaseBal - lockedCollateral.base; if (excess >= amount) { desiredBase = 0; } else { desiredBase = amount.sub(excess); } } uint quoteToSpend = desiredBase.divideDecimalRound(SafeDecimalMath.UNIT.sub(exchangeGlobals.quoteBaseFeeRate)).multiplyDecimalRound( exchangeGlobals.spotPrice ); _require(availableQuote >= quoteToSpend, Error.LockingMoreBaseThanCanBeExchanged); lockedCollateral.base = lockedCollateral.base.add(amount); emit BaseLocked(amount, lockedCollateral.base); } /** * @notice Frees quote when the system buys back a put from the user. * * @param amount The amount of quote to free. */ function freeQuoteCollateral(uint amount) external override onlyOptionMarket { _freeQuoteCollateral(amount); } /** * @notice Frees quote when the system buys back a put from the user. * * @param amount The amount of quote to free. */ function _freeQuoteCollateral(uint amount) internal { // Handle rounding errors by returning the full amount when the requested amount is greater if (amount > lockedCollateral.quote) { amount = lockedCollateral.quote; } lockedCollateral.quote = lockedCollateral.quote.sub(amount); emit QuoteFreed(amount, lockedCollateral.quote); } /** * @notice Sells base and frees the proceeds of the sale. * * @param amountBase The amount of base to sell. */ function freeBase(uint amountBase) external override onlyOptionMarket { _require(amountBase <= lockedCollateral.base, Error.FreeingMoreBaseThanLocked); lockedCollateral.base = lockedCollateral.base.sub(amountBase); emit BaseFreed(amountBase, lockedCollateral.base); } /** * @notice Sends the premium to a user who is selling an option to the pool. * @dev The caller must be the OptionMarket. * * @param recipient The address of the recipient. * @param amount The amount to transfer. * @param freeCollatLiq The amount of free collateral liquidity. */ function sendPremium( address recipient, uint amount, uint freeCollatLiq ) external override onlyOptionMarket reentrancyGuard { _require(freeCollatLiq >= amount, Error.SendPremiumNotEnoughCollateral); _require(quoteAsset.transfer(recipient, amount), Error.QuoteTransferFailed); emit CollateralQuoteTransferred(recipient, amount); } ////////////////////////////////////////// // Dealing with expired option premiums // ////////////////////////////////////////// /** * @notice Manages collateral at the time of board liquidation, also converting base sent here from the OptionMarket. * * @param amountQuoteFreed Total amount of base to convert to quote, including profits from short calls. * @param amountQuoteReserved Total amount of base to convert to quote, including profits from short calls. * @param amountBaseFreed Total amount of collateral to liquidate. */ function boardLiquidation( uint amountQuoteFreed, uint amountQuoteReserved, uint amountBaseFreed ) external override onlyOptionMarket { _freeQuoteCollateral(amountQuoteFreed); totalQuoteAmountReserved = totalQuoteAmountReserved.add(amountQuoteReserved); emit QuoteReserved(amountQuoteReserved, totalQuoteAmountReserved); lockedCollateral.base = lockedCollateral.base.sub(amountBaseFreed); emit BaseFreed(amountBaseFreed, lockedCollateral.base); } /** * @dev Transfers reserved quote. Sends `amount` of reserved quoteAsset to `user`. * * Requirements: * * - the caller must be `OptionMarket`. * * @param user The address of the user to send the quote. * @param amount The amount of quote to send. */ function sendReservedQuote(address user, uint amount) external override onlyShortCollateral reentrancyGuard { // Should never happen, but added to prevent any potential rounding errors if (amount > totalQuoteAmountReserved) { amount = totalQuoteAmountReserved; } totalQuoteAmountReserved = totalQuoteAmountReserved.sub(amount); _require(quoteAsset.transfer(user, amount), Error.QuoteTransferFailed); emit ReservedQuoteSent(user, amount, totalQuoteAmountReserved); } //////////////////////////// // Getting Pool Liquidity // //////////////////////////// /** * @notice Returns the total pool value in quoteAsset. * * @param basePrice The price of the baseAsset. * @param usedDeltaLiquidity The amout of delta liquidity that has been used for hedging. */ function getTotalPoolValueQuote(uint basePrice, uint usedDeltaLiquidity) public view override returns (uint) { return quoteAsset .balanceOf(address(this)) .add(baseAsset.balanceOf(address(this)).multiplyDecimal(basePrice)) .add(usedDeltaLiquidity) .sub(totalQuoteAmountReserved) .sub(queuedQuoteFunds); } /** * @notice Returns the used and free amounts for collateral and delta liquidity. * * @param basePrice The price of the base asset. * @param short The address of the short contract. */ function getLiquidity(uint basePrice, ICollateralShort short) public view override returns (Liquidity memory) { Liquidity memory liquidity; liquidity.usedDeltaLiquidity = poolHedger.getValueQuote(short, basePrice); liquidity.usedCollatLiquidity = lockedCollateral.quote.add(lockedCollateral.base.multiplyDecimal(basePrice)); uint totalLiquidity = getTotalPoolValueQuote(basePrice, liquidity.usedDeltaLiquidity); uint collatPortion = (totalLiquidity * 2) / 3; uint deltaPortion = totalLiquidity.sub(collatPortion); if (liquidity.usedCollatLiquidity > collatPortion) { collatPortion = liquidity.usedCollatLiquidity; deltaPortion = totalLiquidity.sub(collatPortion); } else if (liquidity.usedDeltaLiquidity > deltaPortion) { deltaPortion = liquidity.usedDeltaLiquidity; collatPortion = totalLiquidity.sub(deltaPortion); } liquidity.freeDeltaLiquidity = deltaPortion.sub(liquidity.usedDeltaLiquidity); liquidity.freeCollatLiquidity = collatPortion.sub(liquidity.usedCollatLiquidity); return liquidity; } ////////// // Misc // ////////// /** * @notice Sends quoteAsset to the PoolHedger. * @dev This function will transfer whatever free delta liquidity is available. * The hedger must determine what to do with the amount received. * * @param exchangeGlobals The exchangeGlobals. * @param amount The amount requested by the PoolHedger. */ function transferQuoteToHedge(ILyraGlobals.ExchangeGlobals memory exchangeGlobals, uint amount) external override onlyPoolHedger reentrancyGuard returns (uint) { Liquidity memory liquidity = getLiquidity(exchangeGlobals.spotPrice, exchangeGlobals.short); uint available = liquidity.freeDeltaLiquidity; if (available < amount) { amount = available; } _require(quoteAsset.transfer(address(poolHedger), amount), Error.QuoteTransferFailed); emit DeltaQuoteTransferredToPoolHedger(amount); return amount; } function _require(bool pass, Error error) internal view { require(pass, errorMessages[uint(error)]); } /////////////// // Modifiers // /////////////// modifier onlyPoolHedger virtual { _require(msg.sender == address(poolHedger), Error.OnlyPoolHedger); _; } modifier onlyOptionMarket virtual { _require(msg.sender == address(optionMarket), Error.OnlyOptionMarket); _; } modifier onlyShortCollateral virtual { _require(msg.sender == address(shortCollateral), Error.OnlyShortCollateral); _; } modifier reentrancyGuard virtual { counter = counter.add(1); // counter adds 1 to the existing 1 so becomes 2 uint guard = counter; // assigns 2 to the "guard" variable _; _require(guard == counter, Error.ReentrancyDetected); } /** * @dev Emitted when liquidity is deposited. */ event Deposit(address indexed beneficiary, uint indexed certificateId, uint amount); /** * @dev Emitted when withdrawal is signaled. */ event WithdrawSignaled(uint indexed certificateId, uint tokensBurnableForRound); /** * @dev Emitted when a withdrawal is unsignaled. */ event WithdrawUnSignaled(uint indexed certificateId, uint tokensBurnableForRound); /** * @dev Emitted when liquidity is withdrawn. */ event Withdraw(address indexed beneficiary, uint indexed certificateId, uint value, uint totalQuoteAmountReserved); /** * @dev Emitted when a round ends. */ event RoundEnded( uint indexed maxExpiryTimestamp, uint pricePerToken, uint totalQuoteAmountReserved, uint tokensBurnableForRound ); /** * @dev Emitted when a round starts. */ event RoundStarted( uint indexed lastMaxExpiryTimestamp, uint indexed newMaxExpiryTimestamp, uint totalTokenSupply, uint tokenValue ); /** * @dev Emitted when quote is locked. */ event QuoteLocked(uint quoteLocked, uint lockedCollateralQuote); /** * @dev Emitted when base is locked. */ event BaseLocked(uint baseLocked, uint lockedCollateralBase); /** * @dev Emitted when quote is freed. */ event QuoteFreed(uint quoteFreed, uint lockedCollateralQuote); /** * @dev Emitted when base is freed. */ event BaseFreed(uint baseFreed, uint lockedCollateralBase); /** * @dev Emitted when base is purchased. */ event BasePurchased(address indexed caller, uint quoteSpent, uint amountPurchased); /** * @dev Emitted when base is sold. */ event BaseSold(address indexed caller, uint amountSold, uint quoteReceived); /** * @dev Emitted when collateral is liquidated. This combines LP profit from short calls and freeing base collateral */ event CollateralLiquidated( uint totalAmountToLiquidate, uint baseFreed, uint quoteReceived, uint lockedCollateralBase ); /** * @dev Emitted when quote is reserved. */ event QuoteReserved(uint amountQuoteReserved, uint totalQuoteAmountReserved); /** * @dev Emitted when reserved quote is sent. */ event ReservedQuoteSent(address indexed user, uint amount, uint totalQuoteAmountReserved); /** * @dev Emitted when collatQuote is transferred. */ event CollateralQuoteTransferred(address indexed recipient, uint amount); /** * @dev Emitted when quote is transferred to hedge. */ event DeltaQuoteTransferredToPoolHedger(uint amount); }
//SPDX-License-Identifier: MIT // //Copyright (c) 2019 Synthetix // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in all //copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE //SOFTWARE. pragma solidity ^0.7.6; // Libraries import "@openzeppelin/contracts/math/SafeMath.sol"; // https://docs.synthetix.io/contracts/source/libraries/SafeDecimalMath/ library SafeDecimalMath { using SafeMath for uint; /* Number of decimal places in the representations. */ uint8 public constant decimals = 18; uint8 public constant highPrecisionDecimals = 27; /* The number representing 1.0. */ uint public constant UNIT = 10**uint(decimals); /* The number representing 1.0 for higher fidelity numbers. */ uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals); uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals); /** * @return Provides an interface to UNIT. */ function unit() external pure returns (uint) { return UNIT; } /** * @return Provides an interface to PRECISE_UNIT. */ function preciseUnit() external pure returns (uint) { return PRECISE_UNIT; } /** * @return The result of multiplying x and y, interpreting the operands as fixed-point * decimals. * * @dev A unit factor is divided out after the product of x and y is evaluated, * so that product must be less than 2**256. As this is an integer division, * the internal division always rounds down. This helps save on gas. Rounding * is more expensive on gas. */ function multiplyDecimal(uint x, uint y) internal pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y) / UNIT; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of the specified precision unit. * * @dev The operands should be in the form of a the specified unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function _multiplyDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ uint quotientTimesTen = x.mul(y) / (precisionUnit / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a precise unit. * * @dev The operands should be in the precise unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, PRECISE_UNIT); } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a standard unit. * * @dev The operands should be in the standard unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is a high * precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and UNIT must be less than 2**256. As * this is an integer division, the result is always rounded down. * This helps save on gas. Rounding is more expensive on gas. */ function divideDecimal(uint x, uint y) internal pure returns (uint) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(UNIT).div(y); } /** * @return The result of safely dividing x and y. The return value is as a rounded * decimal in the precision unit specified in the parameter. * * @dev y is divided after the product of x and the specified precision unit * is evaluated, so the product of x and the specified precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function _divideDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { uint resultTimesTen = x.mul(precisionUnit * 10).div(y); if (resultTimesTen % 10 >= 5) { resultTimesTen += 10; } return resultTimesTen / 10; } /** * @return The result of safely dividing x and y. The return value is as a rounded * standard precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and the standard precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRound(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is as a rounded * high precision decimal. * * @dev y is divided after the product of x and the high precision unit * is evaluated, so the product of x and the high precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, PRECISE_UNIT); } /** * @dev Convert a standard decimal representation to a high precision one. */ function decimalToPreciseDecimal(uint i) internal pure returns (uint) { return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); } /** * @dev Convert a high precision decimal to a standard decimal representation. */ function preciseDecimalToDecimal(uint i) internal pure returns (uint) { uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; import "./ILyraGlobals.sol"; import "./ILiquidityPool.sol"; interface IOptionMarket { struct OptionListing { uint id; uint strike; uint skew; uint longCall; uint shortCall; uint longPut; uint shortPut; uint boardId; } struct OptionBoard { uint id; uint expiry; uint iv; bool frozen; uint[] listingIds; } struct Trade { bool isBuy; uint amount; uint vol; uint expiry; ILiquidityPool.Liquidity liquidity; } enum TradeType {LONG_CALL, SHORT_CALL, LONG_PUT, SHORT_PUT} enum Error { TransferOwnerToZero, InvalidBoardId, InvalidBoardIdOrNotFrozen, InvalidListingIdOrNotFrozen, StrikeSkewLengthMismatch, BoardMaxExpiryReached, CannotStartNewRoundWhenBoardsExist, ZeroAmountOrInvalidTradeType, BoardFrozenOrTradingCutoffReached, QuoteTransferFailed, BaseTransferFailed, BoardNotExpired, BoardAlreadyLiquidated, OnlyOwner, Last } function maxExpiryTimestamp() external view returns (uint); function optionBoards(uint) external view returns ( uint id, uint expiry, uint iv, bool frozen ); function optionListings(uint) external view returns ( uint id, uint strike, uint skew, uint longCall, uint shortCall, uint longPut, uint shortPut, uint boardId ); function boardToPriceAtExpiry(uint) external view returns (uint); function listingToBaseReturnedRatio(uint) external view returns (uint); function transferOwnership(address newOwner) external; function setBoardFrozen(uint boardId, bool frozen) external; function setBoardBaseIv(uint boardId, uint baseIv) external; function setListingSkew(uint listingId, uint skew) external; function createOptionBoard( uint expiry, uint baseIV, uint[] memory strikes, uint[] memory skews ) external returns (uint); function addListingToBoard( uint boardId, uint strike, uint skew ) external; function getLiveBoards() external view returns (uint[] memory _liveBoards); function getBoardListings(uint boardId) external view returns (uint[] memory); function openPosition( uint _listingId, TradeType tradeType, uint amount ) external returns (uint totalCost); function closePosition( uint _listingId, TradeType tradeType, uint amount ) external returns (uint totalCost); function liquidateExpiredBoard(uint boardId) external; function settleOptions(uint listingId, TradeType tradeType) external; }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; interface ILiquidityCertificate { struct CertificateData { uint liquidity; uint enteredAt; uint burnableAt; } function MIN_LIQUIDITY() external view returns (uint); function liquidityPool() external view returns (address); function certificates(address owner) external view returns (uint[] memory); function liquidity(uint certificateId) external view returns (uint); function enteredAt(uint certificateId) external view returns (uint); function burnableAt(uint certificateId) external view returns (uint); function certificateData(uint certificateId) external view returns (CertificateData memory); function mint( address owner, uint liquidityAmount, uint expiryAtCreation ) external returns (uint); function setBurnableAt( address spender, uint certificateId, uint timestamp ) external; function burn(address spender, uint certificateId) external; function split(uint certificateId, uint percentageSplit) external returns (uint); }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; import "./ICollateralShort.sol"; interface IPoolHedger { function shortingInitialized() external view returns (bool); function shortId() external view returns (uint); function shortBuffer() external view returns (uint); function lastInteraction() external view returns (uint); function interactionDelay() external view returns (uint); function setShortBuffer(uint newShortBuffer) external; function setInteractionDelay(uint newInteractionDelay) external; function initShort() external; function reopenShort() external; function hedgeDelta() external; function getShortPosition(ICollateralShort short) external view returns (uint shortBalance, uint collateral); function getCurrentHedgedNetDelta() external view returns (int); function getValueQuote(ICollateralShort short, uint spotPrice) external view returns (uint value); }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; import "./IOptionMarket.sol"; interface IShortCollateral { function sendQuoteCollateral(address recipient, uint amount) external; function sendBaseCollateral(address recipient, uint amount) external; function sendToLP(uint amountBase, uint amountQuote) external; function processSettle( uint listingId, address receiver, IOptionMarket.TradeType tradeType, uint amount, uint strike, uint priceAtExpiry, uint listingToShortCallEthReturned ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; import "./ICollateralShort.sol"; import "./IExchangeRates.sol"; import "./IExchanger.sol"; import "./ISynthetix.sol"; interface ILyraGlobals { enum ExchangeType {BASE_QUOTE, QUOTE_BASE, ALL} /** * @dev Structs to help reduce the number of calls between other contracts and this one * Grouped in usage for a particular contract/use case */ struct ExchangeGlobals { uint spotPrice; bytes32 quoteKey; bytes32 baseKey; ISynthetix synthetix; ICollateralShort short; uint quoteBaseFeeRate; uint baseQuoteFeeRate; } struct GreekCacheGlobals { int rateAndCarry; uint spotPrice; } struct PricingGlobals { uint optionPriceFeeCoefficient; uint spotPriceFeeCoefficient; uint vegaFeeCoefficient; uint vegaNormFactor; uint standardSize; uint skewAdjustmentFactor; int rateAndCarry; int minDelta; uint volatilityCutoff; uint spotPrice; } function synthetix() external view returns (ISynthetix); function exchanger() external view returns (IExchanger); function exchangeRates() external view returns (IExchangeRates); function collateralShort() external view returns (ICollateralShort); function isPaused() external view returns (bool); function tradingCutoff(address) external view returns (uint); function optionPriceFeeCoefficient(address) external view returns (uint); function spotPriceFeeCoefficient(address) external view returns (uint); function vegaFeeCoefficient(address) external view returns (uint); function vegaNormFactor(address) external view returns (uint); function standardSize(address) external view returns (uint); function skewAdjustmentFactor(address) external view returns (uint); function rateAndCarry(address) external view returns (int); function minDelta(address) external view returns (int); function volatilityCutoff(address) external view returns (uint); function quoteKey(address) external view returns (bytes32); function baseKey(address) external view returns (bytes32); function setGlobals( ISynthetix _synthetix, IExchanger _exchanger, IExchangeRates _exchangeRates, ICollateralShort _collateralShort ) external; function setGlobalsForContract( address _contractAddress, uint _tradingCutoff, PricingGlobals memory pricingGlobals, bytes32 _quoteKey, bytes32 _baseKey ) external; function setPaused(bool _isPaused) external; function setTradingCutoff(address _contractAddress, uint _tradingCutoff) external; function setOptionPriceFeeCoefficient(address _contractAddress, uint _optionPriceFeeCoefficient) external; function setSpotPriceFeeCoefficient(address _contractAddress, uint _spotPriceFeeCoefficient) external; function setVegaFeeCoefficient(address _contractAddress, uint _vegaFeeCoefficient) external; function setVegaNormFactor(address _contractAddress, uint _vegaNormFactor) external; function setStandardSize(address _contractAddress, uint _standardSize) external; function setSkewAdjustmentFactor(address _contractAddress, uint _skewAdjustmentFactor) external; function setRateAndCarry(address _contractAddress, int _rateAndCarry) external; function setMinDelta(address _contractAddress, int _minDelta) external; function setVolatilityCutoff(address _contractAddress, uint _volatilityCutoff) external; function setQuoteKey(address _contractAddress, bytes32 _quoteKey) external; function setBaseKey(address _contractAddress, bytes32 _baseKey) external; function getSpotPriceForMarket(address _contractAddress) external view returns (uint); function getSpotPrice(bytes32 to) external view returns (uint); function getPricingGlobals(address _contractAddress) external view returns (PricingGlobals memory); function getGreekCacheGlobals(address _contractAddress) external view returns (GreekCacheGlobals memory); function getExchangeGlobals(address _contractAddress, ExchangeType exchangeType) external view returns (ExchangeGlobals memory exchangeGlobals); function getGlobalsForOptionTrade(address _contractAddress, bool isBuy) external view returns ( PricingGlobals memory pricingGlobals, ExchangeGlobals memory exchangeGlobals, uint tradeCutoff ); }
//SPDX-License-Identifier: ISC pragma solidity 0.7.6; pragma experimental ABIEncoderV2; import "./ILyraGlobals.sol"; interface ILiquidityPool { struct Collateral { uint quote; uint base; } /// @dev These are all in quoteAsset amounts. struct Liquidity { uint freeCollatLiquidity; uint usedCollatLiquidity; uint freeDeltaLiquidity; uint usedDeltaLiquidity; } enum Error { QuoteTransferFailed, AlreadySignalledWithdrawal, SignallingBetweenRounds, UnSignalMustSignalFirst, UnSignalAlreadyBurnable, WithdrawNotBurnable, EndRoundWithLiveBoards, EndRoundAlreadyEnded, EndRoundMustExchangeBase, EndRoundMustHedgeDelta, StartRoundMustEndRound, ReceivedZeroFromBaseQuoteExchange, ReceivedZeroFromQuoteBaseExchange, LockingMoreQuoteThanIsFree, LockingMoreBaseThanCanBeExchanged, FreeingMoreBaseThanLocked, SendPremiumNotEnoughCollateral, OnlyPoolHedger, OnlyOptionMarket, OnlyShortCollateral, ReentrancyDetected, Last } function lockedCollateral() external view returns (uint, uint); function queuedQuoteFunds() external view returns (uint); function expiryToTokenValue(uint) external view returns (uint); function deposit(address beneficiary, uint amount) external returns (uint); function signalWithdrawal(uint certificateId) external; function unSignalWithdrawal(uint certificateId) external; function withdraw(address beneficiary, uint certificateId) external returns (uint value); function tokenPriceQuote() external view returns (uint); function endRound() external; function startRound(uint lastMaxExpiryTimestamp, uint newMaxExpiryTimestamp) external; function exchangeBase() external; function lockQuote(uint amount, uint freeCollatLiq) external; function lockBase( uint amount, ILyraGlobals.ExchangeGlobals memory exchangeGlobals, Liquidity memory liquidity ) external; function freeQuoteCollateral(uint amount) external; function freeBase(uint amountBase) external; function sendPremium( address recipient, uint amount, uint freeCollatLiq ) external; function boardLiquidation( uint amountQuoteFreed, uint amountQuoteReserved, uint amountBaseFreed ) external; function sendReservedQuote(address user, uint amount) external; function getTotalPoolValueQuote(uint basePrice, uint usedDeltaLiquidity) external view returns (uint); function getLiquidity(uint basePrice, ICollateralShort short) external view returns (Liquidity memory); function transferQuoteToHedge(ILyraGlobals.ExchangeGlobals memory exchangeGlobals, uint amount) external returns (uint); }
//SPDX-License-Identifier: ISC pragma solidity >=0.7.6; pragma experimental ABIEncoderV2; interface ICollateralShort { struct Loan { // ID for the loan uint id; // Account that created the loan address account; // Amount of collateral deposited uint collateral; // The synth that was borrowed bytes32 currency; // Amount of synths borrowed uint amount; // Indicates if the position was short sold bool short; // interest amounts accrued uint accruedInterest; // last interest index uint interestIndex; // time of last interaction. uint lastInteraction; } function loans(uint id) external returns ( uint, address, uint, bytes32, uint, bool, uint, uint, uint ); function minCratio() external returns (uint); function minCollateral() external returns (uint); function issueFeeRate() external returns (uint); function open( uint collateral, uint amount, bytes32 currency ) external returns (uint id); function repay( address borrower, uint id, uint amount ) external returns (uint short, uint collateral); function repayWithCollateral(uint id, uint repayAmount) external returns (uint short, uint collateral); function draw(uint id, uint amount) external returns (uint short, uint collateral); // Same as before function deposit( address borrower, uint id, uint amount ) external returns (uint short, uint collateral); // Same as before function withdraw(uint id, uint amount) external returns (uint short, uint collateral); // function to return the loan details in one call, without needing to know about the collateralstate function getShortAndCollateral(address account, uint id) external view returns (uint short, uint collateral); }
//SPDX-License-Identifier:MIT pragma solidity ^0.7.6; // https://docs.synthetix.io/contracts/source/interfaces/iexchangerates interface IExchangeRates { function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid); }
//SPDX-License-Identifier:MIT pragma solidity ^0.7.6; // https://docs.synthetix.io/contracts/source/interfaces/iexchanger interface IExchanger { function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view returns (uint exchangeFeeRate); }
//SPDX-License-Identifier: ISC pragma solidity >=0.7.6; interface ISynthetix { function exchange( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeOnBehalf( address exchangeForAddress, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); }
{ "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "optimizer": { "enabled": false, "runs": 200 }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baseFreed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateralBase","type":"uint256"}],"name":"BaseFreed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"baseLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateralBase","type":"uint256"}],"name":"BaseLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"quoteSpent","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountPurchased","type":"uint256"}],"name":"BasePurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteReceived","type":"uint256"}],"name":"BaseSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalAmountToLiquidate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseFreed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quoteReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateralBase","type":"uint256"}],"name":"CollateralLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralQuoteTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DeltaQuoteTransferredToPoolHedger","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"certificateId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"quoteFreed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateralQuote","type":"uint256"}],"name":"QuoteFreed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"quoteLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedCollateralQuote","type":"uint256"}],"name":"QuoteLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountQuoteReserved","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalQuoteAmountReserved","type":"uint256"}],"name":"QuoteReserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalQuoteAmountReserved","type":"uint256"}],"name":"ReservedQuoteSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"maxExpiryTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalQuoteAmountReserved","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBurnableForRound","type":"uint256"}],"name":"RoundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"lastMaxExpiryTimestamp","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newMaxExpiryTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalTokenSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenValue","type":"uint256"}],"name":"RoundStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"certificateId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalQuoteAmountReserved","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"certificateId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBurnableForRound","type":"uint256"}],"name":"WithdrawSignaled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"certificateId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBurnableForRound","type":"uint256"}],"name":"WithdrawUnSignaled","type":"event"},{"inputs":[{"internalType":"uint256","name":"amountQuoteFreed","type":"uint256"},{"internalType":"uint256","name":"amountQuoteReserved","type":"uint256"},{"internalType":"uint256","name":"amountBaseFreed","type":"uint256"}],"name":"boardLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"expiryToTokenValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountBase","type":"uint256"}],"name":"freeBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"freeQuoteCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"basePrice","type":"uint256"},{"internalType":"contract ICollateralShort","name":"short","type":"address"}],"name":"getLiquidity","outputs":[{"components":[{"internalType":"uint256","name":"freeCollatLiquidity","type":"uint256"},{"internalType":"uint256","name":"usedCollatLiquidity","type":"uint256"},{"internalType":"uint256","name":"freeDeltaLiquidity","type":"uint256"},{"internalType":"uint256","name":"usedDeltaLiquidity","type":"uint256"}],"internalType":"struct ILiquidityPool.Liquidity","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"basePrice","type":"uint256"},{"internalType":"uint256","name":"usedDeltaLiquidity","type":"uint256"}],"name":"getTotalPoolValueQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILyraGlobals","name":"_globals","type":"address"},{"internalType":"contract IOptionMarket","name":"_optionMarket","type":"address"},{"internalType":"contract ILiquidityCertificate","name":"_liquidityCertificate","type":"address"},{"internalType":"contract IPoolHedger","name":"_poolHedger","type":"address"},{"internalType":"contract IShortCollateral","name":"_shortCollateral","type":"address"},{"internalType":"contract IERC20","name":"_quoteAsset","type":"address"},{"internalType":"contract IERC20","name":"_baseAsset","type":"address"},{"internalType":"string[]","name":"_errorMessages","type":"string[]"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint256","name":"spotPrice","type":"uint256"},{"internalType":"bytes32","name":"quoteKey","type":"bytes32"},{"internalType":"bytes32","name":"baseKey","type":"bytes32"},{"internalType":"contract ISynthetix","name":"synthetix","type":"address"},{"internalType":"contract ICollateralShort","name":"short","type":"address"},{"internalType":"uint256","name":"quoteBaseFeeRate","type":"uint256"},{"internalType":"uint256","name":"baseQuoteFeeRate","type":"uint256"}],"internalType":"struct ILyraGlobals.ExchangeGlobals","name":"exchangeGlobals","type":"tuple"},{"components":[{"internalType":"uint256","name":"freeCollatLiquidity","type":"uint256"},{"internalType":"uint256","name":"usedCollatLiquidity","type":"uint256"},{"internalType":"uint256","name":"freeDeltaLiquidity","type":"uint256"},{"internalType":"uint256","name":"usedDeltaLiquidity","type":"uint256"}],"internalType":"struct ILiquidityPool.Liquidity","name":"liquidity","type":"tuple"}],"name":"lockBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"freeCollatLiq","type":"uint256"}],"name":"lockQuote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockedCollateral","outputs":[{"internalType":"uint256","name":"quote","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queuedQuoteFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"freeCollatLiq","type":"uint256"}],"name":"sendPremium","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sendReservedQuote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"certificateId","type":"uint256"}],"name":"signalWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lastMaxExpiryTimestamp","type":"uint256"},{"internalType":"uint256","name":"newMaxExpiryTimestamp","type":"uint256"}],"name":"startRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenPriceQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"spotPrice","type":"uint256"},{"internalType":"bytes32","name":"quoteKey","type":"bytes32"},{"internalType":"bytes32","name":"baseKey","type":"bytes32"},{"internalType":"contract ISynthetix","name":"synthetix","type":"address"},{"internalType":"contract ICollateralShort","name":"short","type":"address"},{"internalType":"uint256","name":"quoteBaseFeeRate","type":"uint256"},{"internalType":"uint256","name":"baseQuoteFeeRate","type":"uint256"}],"internalType":"struct ILyraGlobals.ExchangeGlobals","name":"exchangeGlobals","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferQuoteToHedge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"certificateId","type":"uint256"}],"name":"unSignalWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"certificateId","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526000600860006101000a816200001962000062565b8160ff0219169083151502179062000030620000c7565b5050506001600f62000041620000c7565b50503480156200005b57600080620000586200012e565b50505b506200019e565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b6040811015620000c257600081830152602081019050620000a6565b505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b60005b604081101562000129576000818301526020810190506200010d565b505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b868110156200016b5780860151816040840101526020810190506200014b565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b615c6e80620001ae6000396000f3fe608060405234801561001957600080610016614491565b50505b506004361061014b5760003560e01c8063a00dad22116100c1578063d1201e3111610085578063d1201e311461034c578063db32232f14610368578063dc62c58114610384578063f238ff5c146103a0578063f3fef3a3146103bc578063fc395668146103ec5761014b565b8063a00dad22146102bb578063b952cc4a146102d7578063c3964372146102f6578063c677c58a14610312578063c9061b58146103305761014b565b806347e7ef241161011357806347e7ef241461020f57806354d269af1461023f578063699ba87b1461025b578063749aa2d9146102775780637e8b3f891461028157806390a80ece1461028b5761014b565b8063159317d0146101595780631ebcfe801461017757806321af3525146101935780633f2f757d146101c35780633f6b5019146101f3575b600080610156614491565b50505b61016161041c565b60405161016e91906157b0565b60405180910390f35b610191600480360381019061018c91906151d7565b61065b565b005b6101ad60048036038101906101a89190615191565b6109fd565b6040516101ba91906157b0565b60405180910390f35b6101dd60048036038101906101d8919061523b565b610c36565b6040516101ea9190615795565b60405180910390f35b61020d6004803603810190610208919061531f565b610e4d565b005b61022960048036038101906102249190614efd565b610fa8565b60405161023691906157b0565b60405180910390f35b6102596004803603810190610254919061501f565b611326565b005b610275600480360381019061027091906151d7565b61169d565b005b61027f611964565b005b610289611eba565b005b6102a560048036038101906102a091906151d7565b6127d1565b6040516102b291906157b0565b60405180910390f35b6102d560048036038101906102d09190615280565b6127f0565b005b6102df612b18565b6040516102ed9291906157cb565b60405180910390f35b610310600480360381019061030b91906152da565b612b38565b005b61031a612cdc565b60405161032791906157b0565b60405180910390f35b61034a60048036038101906103459190614f42565b612ce9565b005b61036660048036038101906103619190614efd565b612eeb565b005b610382600480360381019061037d91906151d7565b613132565b005b61039e600480360381019061039991906151d7565b6131a8565b005b6103ba60048036038101906103b591906152da565b6132a5565b005b6103d660048036038101906103d19190614efd565b613397565b6040516103e391906157b0565b60405180910390f35b610406600480360381019061040191906152da565b613d20565b60405161041391906157b0565b60405180910390f35b60008060008061042a6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009061046f6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026040518363ffffffff1660e01b81526004016104ab92919061564a565b60e06040518083038186806104be614562565b1580156104d3576000806104d0614491565b50505b505a6104dd6145c5565b50505050501580156104fc573d6000803e3d60006104f9614491565b50505b505050506040513d601f19601f82011682018060405250810190610520919061515f565b90506000600e61052e6144ff565b141561054557670de0b6b3a7640000915050610658565b60006106358260000151600460009061055c6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d856080015186600001516040518363ffffffff1660e01b81526004016105bb92919061570a565b60206040518083038186806105ce614562565b1580156105e3576000806105e0614491565b50505b505a6105ed6145c5565b505050505015801561060c573d6000803e3d6000610609614491565b50505b505050506040513d601f19601f820116820180604052508101906106309190615209565b613d20565b9050610653600e6106446144ff565b82613ff990919063ffffffff16565b925050505b90565b6000600260009061066a6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b81526004016106bf91906157b0565b60606040518083038186806106d2614562565b1580156106e7576000806106e4614491565b50505b505a6106f16145c5565b5050505050158015610710573d6000803e3d600061070d614491565b50505b505050506040513d601f19601f82011682018060405250810190610734919061512d565b9050600060016000906107456144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806107a2614562565b1580156107b7576000806107b4614491565b50505b505a6107c16145c5565b50505050501580156107e0573d6000803e3d60006107dd614491565b50505b505050506040513d601f19601f820116820180604052508101906108049190615209565b90506108186000836040015114600161402f565b6108508183602001511415801561084957506000601060008481526020019081526020016000206108476144ff565b145b600261402f565b6000826020015114156108915761087d8260000151600c61086f6144ff565b61409d90919063ffffffff16565b600c81906108896146c5565b5050506108f1565b6108e16108c960106000856020015181526020019081526020016000206108b66144ff565b8460000151613ff990919063ffffffff16565b600c6108d36144ff565b61409d90919063ffffffff16565b600c81906108ed6146c5565b5050505b60026000906108fe6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b5a61093f61472a565b85846040518463ffffffff1660e01b815260040161095f93929190615613565b60006040518083038160008780610974614562565b15801561098957600080610986614491565b50505b505a610993614787565b5050505050501580156109b3573d6000803e3d60006109b0614491565b50505b50505050827fa030de897a3fbcd98618ebb6d64981072317ade7083ad8702bbcd0b867a5063e600c6109e36144ff565b6040516109f091906157b0565b60405180910390a2505050565b6000610a696004600090610a0f6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a610a4b61472a565b73ffffffffffffffffffffffffffffffffffffffff1614601161402f565b610a866001600f610a786144ff565b61409d90919063ffffffff16565b600f8190610a926146c5565b5050506000600f610aa16144ff565b90506000610ab785600001518660800151610c36565b905060008160400151905084811015610ace578094505b610bdd6005600090610ade6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6004600090610b236144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518363ffffffff1660e01b8152600401610b5e929190615673565b60206040518083038160008780610b73614562565b158015610b8857600080610b85614491565b50505b505a610b92614787565b505050505050158015610bb2573d6000803e3d6000610baf614491565b50505b505050506040513d601f19601f82011682018060405250810190610bd69190614fed565b600061402f565b7f78139c2f5eabfad75a88b7c1fe1d1e3851b441e2c5a7f792f95d8e1c6b9c636085604051610c0c91906157b0565b60405180910390a18493505050610c2f600f610c266144ff565b8214601461402f565b5092915050565b610c3e614887565b610c46614887565b6004600090610c536144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d84866040518363ffffffff1660e01b8152600401610caa92919061570a565b6020604051808303818680610cbd614562565b158015610cd257600080610ccf614491565b50505b505a610cdc6145c5565b5050505050158015610cfb573d6000803e3d6000610cf8614491565b50505b505050506040513d601f19601f82011682018060405250810190610d1f9190615209565b816060018181525050610d65610d4a856009600101610d3c6144ff565b61412e90919063ffffffff16565b6009600001610d576144ff565b61409d90919063ffffffff16565b8160200181815250506000610d7e858360600151613d20565b9050600060036002830281610d8f57fe5b0490506000610da7828461415b90919063ffffffff16565b90508184602001511115610dd65783602001519150610dcf828461415b90919063ffffffff16565b9050610e00565b8084606001511115610dff5783606001519050610dfc818461415b90919063ffffffff16565b91505b5b610e1784606001518261415b90919063ffffffff16565b846040018181525050610e3784602001518361415b90919063ffffffff16565b8460000181815250508394505050505092915050565b610eb76001600090610e5d6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a610e9961472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b610ec0836141e7565b610edc82600b610ece6144ff565b61409d90919063ffffffff16565b600b8190610ee86146c5565b5050507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b82600b610f176144ff565b604051610f259291906157cb565b60405180910390a1610f4c816009600101610f3e6144ff565b61415b90919063ffffffff16565b60096001018190610f5b6146c5565b5050507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb9816009600101610f8d6144ff565b604051610f9b9291906157cb565b60405180910390a1505050565b6000610fc682600d610fb86144ff565b61409d90919063ffffffff16565b600d8190610fd26146c5565b50505060006002600090610fe46144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663156e29f68585600160009061102b6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b81526004016020604051808303818680611088614562565b15801561109d5760008061109a614491565b50505b505a6110a76145c5565b50505050501580156110c6573d6000803e3d60006110c3614491565b50505b505050506040513d601f19601f820116820180604052508101906110ea9190615209565b6040518463ffffffff1660e01b81526004016111089392919061569c565b6020604051808303816000878061111d614562565b1580156111325760008061112f614491565b50505b505a61113c614787565b50505050505015801561115c573d6000803e3d6000611159614491565b50505b505050506040513d601f19601f820116820180604052508101906111809190615209565b9050808473ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15856040516111c991906157b0565b60405180910390a361131c60056000906111e16144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd5a61122261472a565b5a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b604081101561127b57600081830152602081019050611261565b505050876040518463ffffffff1660e01b815260040161129d9392919061557c565b602060405180830381600087806112b2614562565b1580156112c7576000806112c4614491565b50505b505a6112d1614787565b5050505050501580156112f1573d6000803e3d60006112ee614491565b50505b505050506040513d601f19601f820116820180604052508101906113159190614fed565b600061402f565b8091505092915050565b60086000906113336144ff565b906101000a900460ff1615611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137490615755565b60405180910390611383614491565b50505b876000806101000a816113976144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906113d36146c5565b50505086600160006101000a816113e86144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114246146c5565b50505085600260006101000a816114396144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114756146c5565b50505083600360006101000a8161148a6144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114c66146c5565b50505084600460006101000a816114db6144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906115176146c5565b50505082600560006101000a8161152c6144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906115686146c5565b50505081600660006101000a8161157d6144ff565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906115b96146c5565b5050506015808111156115c857fe5b815114611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160190615775565b60405180910390611610614491565b50505b60005b81518110156116675781818151811061162b57fe5b60200260200101516007600083815260200190815260200160002090805190602001906116599291906148af565b508080600101915050611616565b506001600860006101000a8161167b6144ff565b8160ff021916908315150217906116906146c5565b5050505050505050505050565b600060026000906116ac6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161170191906157b0565b6060604051808303818680611714614562565b15801561172957600080611726614491565b50505b505a6117336145c5565b5050505050158015611752573d6000803e3d600061174f614491565b50505b505050506040513d601f19601f82011682018060405250810190611776919061512d565b905061178b600082604001511415600361402f565b6117b7600060106000846040015181526020019081526020016000206117af6144ff565b14600461402f565b60026000906117c46144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b5a61180561472a565b8460006040518463ffffffff1660e01b8152600401611826939291906155dc565b6000604051808303816000878061183b614562565b1580156118505760008061184d614491565b50505b505a61185a614787565b50505050505015801561187a573d6000803e3d6000611877614491565b50505b505050506000816020015114156118bf576118ab8160000151600c61189d6144ff565b61415b90919063ffffffff16565b600c81906118b76146c5565b50505061191f565b61190f6118f760106000846020015181526020019081526020016000206118e46144ff565b8360000151613ff990919063ffffffff16565b600c6119016144ff565b61415b90919063ffffffff16565b600c819061191b6146c5565b5050505b817f74e46e4569fdcca3333564a0997a08b4607c2af89cd8477813db852c9f364b61600c61194b6144ff565b60405161195891906157b0565b60405180910390a25050565b600060016000906119736144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806119d0614562565b1580156119e5576000806119e2614491565b50505b505a6119ef6145c5565b5050505050158015611a0e573d6000803e3d6000611a0b614491565b50505b505050506040513d601f19601f82011682018060405250810190611a329190615209565b9050611b1360006001600090611a466144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b81526004016000604051808303818680611aa3614562565b158015611ab857600080611ab5614491565b50505b505a611ac26145c5565b5050505050158015611ae1573d6000803e3d6000611ade614491565b50505b505050506040513d6000823e3d601f19601f82011682018060405250810190611b0a9190614f9a565b5114600661402f565b611b3b600060106000848152602001908152602001600020611b336144ff565b14600761402f565b611c7a60006006600090611b4d6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015611bde57600081830152602081019050611bc4565b5050506040518263ffffffff1660e01b8152600401611bfd9190615561565b6020604051808303818680611c10614562565b158015611c2557600080611c22614491565b50505b505a611c2f6145c5565b5050505050158015611c4e573d6000803e3d6000611c4b614491565b50505b505050506040513d601f19601f82011682018060405250810190611c729190615209565b14600861402f565b611d5360006004600090611c8c6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663759d4d596040518163ffffffff1660e01b81526004016020604051808303818680611ce9614562565b158015611cfe57600080611cfb614491565b50505b505a611d086145c5565b5050505050158015611d27573d6000803e3d6000611d24614491565b50505b505050506040513d601f19601f82011682018060405250810190611d4b91906150fb565b14600961402f565b6000611d5d61041c565b905080601060008481526020019081526020016000208190611d7d6146c5565b505050611db7611d9f82600c611d916144ff565b61412e90919063ffffffff16565b600b611da96144ff565b61409d90919063ffffffff16565b600b8190611dc36146c5565b5050507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b611e0382600c611df56144ff565b61412e90919063ffffffff16565b600b611e0d6144ff565b604051611e1b9291906157cb565b60405180910390a1611e48600c611e306144ff565b600e611e3a6144ff565b61415b90919063ffffffff16565b600e8190611e546146c5565b505050817fff9d41e1547acb5eda1e3bac0c795f57760c96016cdd641af6bdd90270a768f382600b611e846144ff565b600c611e8e6144ff565b604051611e9d939291906157f4565b60405180910390a26000600c8190611eb36146c5565b5050505050565b611ed76001600f611ec96144ff565b61409d90919063ffffffff16565b600f8190611ee36146c5565b5050506000600f611ef26144ff565b905060006006600090611f036144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015611f9457600081830152602081019050611f7a565b5050506040518263ffffffff1660e01b8152600401611fb39190615561565b6020604051808303818680611fc6614562565b158015611fdb57600080611fd8614491565b50505b505a611fe56145c5565b5050505050158015612004573d6000803e3d6000612001614491565b50505b505050506040513d601f19601f820116820180604052508101906120289190615209565b9050600060016000906120396144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b81526004016000604051808303818680612096614562565b1580156120ab576000806120a8614491565b50505b505a6120b56145c5565b50505050501580156120d4573d6000803e3d60006120d1614491565b50505b505050506040513d6000823e3d601f19601f820116820180604052508101906120fd9190614f9a565b511415612119576000600960010181906121156146c5565b5050505b60096001016121266144ff565b8111156123795760008060009061213b6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f660016000906121806144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006040518363ffffffff1660e01b81526004016121bc92919061564a565b60e06040518083038186806121cf614562565b1580156121e4576000806121e1614491565b50505b505a6121ee6145c5565b505050505015801561220d573d6000803e3d600061220a614491565b50505b505050506040513d601f19601f82011682018060405250810190612231919061515f565b9050600060096001016122426144ff565b830390506000826060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f384604001518486602001516040518463ffffffff1660e01b8152600401612291939291906156d3565b602060405180830381600087806122a6614562565b1580156122bb576000806122b8614491565b50505b505a6122c5614787565b5050505050501580156122e5573d6000803e3d60006122e2614491565b50505b505050506040513d601f19601f820116820180604052508101906123099190615209565b905061231960008211600b61402f565b5a61232261472a565b73ffffffffffffffffffffffffffffffffffffffff167f0ba93b4b06f63170434e95713b6e4613651536fe0795f417db31ca847d25e0f283836040516123699291906157cb565b60405180910390a25050506127b7565b8060096001016123876144ff565b11156127b65760008060009061239b6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f660016000906123e06144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016040518363ffffffff1660e01b815260040161241c92919061564a565b60e060405180830381868061242f614562565b15801561244457600080612441614491565b50505b505a61244e6145c5565b505050505015801561246d573d6000803e3d600061246a614491565b50505b505050506040513d601f19601f82011682018060405250810190612491919061515f565b905060006124e982600001516124db6124be8560a00151601260ff16600a0a61415b90919063ffffffff16565b8660096001016124cc6144ff565b0361428490919063ffffffff16565b6142a090919063ffffffff16565b90506000612673600d6124fa6144ff565b612665600960000161250a6144ff565b612657600b6125176144ff565b60056000906125246144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b60408110156125b55760008183015260208101905061259b565b5050506040518263ffffffff1660e01b81526004016125d49190615561565b60206040518083038186806125e7614562565b1580156125fc576000806125f9614491565b50505b505a6126066145c5565b5050505050158015612625573d6000803e3d6000612622614491565b50505b505050506040513d601f19601f820116820180604052508101906126499190615209565b61415b90919063ffffffff16565b61415b90919063ffffffff16565b61415b90919063ffffffff16565b90508082116126825781612684565b805b91506000836060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f385602001518587604001516040518463ffffffff1660e01b81526004016126d1939291906156d3565b602060405180830381600087806126e6614562565b1580156126fb576000806126f8614491565b50505b505a612705614787565b505050505050158015612725573d6000803e3d6000612722614491565b50505b505050506040513d601f19601f820116820180604052508101906127499190615209565b905061275960008211600c61402f565b5a61276261472a565b73ffffffffffffffffffffffffffffffffffffffff167ffe644b4d06ffe999b33590d87654491fea7d9ce296e8d305004cf50ca96e6be184836040516127a99291906157cb565b60405180910390a2505050505b5b506127ce600f6127c56144ff565b8214601461402f565b50565b60106020528060005260406000206000915090506127ed6144ff565b81565b61285a60016000906128006144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61283c61472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b600060066000906128696144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b60408110156128fa576000818301526020810190506128e0565b5050506040518263ffffffff1660e01b81526004016129199190615561565b602060405180830381868061292c614562565b1580156129415760008061293e614491565b50505b505a61294b6145c5565b505050505015801561296a573d6000803e3d6000612967614491565b50505b505050506040513d601f19601f8201168201806040525081019061298e9190615209565b9050600080836000015190508260096001016129a86144ff565b10612a065760008360096001016129bd6144ff565b0390506129e96129da87600001518361412e90919063ffffffff16565b8361409d90919063ffffffff16565b91506129fe818861409d90919063ffffffff16565b925050612a41565b60006009600101612a156144ff565b84039050868110612a295760009250612a3f565b612a3c818861415b90919063ffffffff16565b92505b505b6000612a898660000151612a7b612a6c8960a00151601260ff16600a0a61415b90919063ffffffff16565b8661428490919063ffffffff16565b6142a090919063ffffffff16565b9050612a9981831015600e61402f565b612ab8876009600101612aaa6144ff565b61409d90919063ffffffff16565b60096001018190612ac76146c5565b5050507f88cdc2d9dafaa25ef0f861c37488527fa03d0d30cd7ed982e93c2fd8ed44eeaa876009600101612af96144ff565b604051612b079291906157cb565b60405180910390a150505050505050565b600980600001612b266144ff565b9080600101612b336144ff565b905082565b612ba26001600090612b486144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612b8461472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b6000821415612bc957600d612bb56144ff565b600e8190612bc16146c5565b505050612c53565b612bf2600060106000858152602001908152602001600020612be96144ff565b1415600a61402f565b612c43612c2b60106000858152602001908152602001600020612c136144ff565b600d612c1d6144ff565b613ff990919063ffffffff16565b600e612c356144ff565b61409d90919063ffffffff16565b600e8190612c4f6146c5565b5050505b6000600d8190612c616146c5565b50505080827ffd9d17e5565deea3d25918d95fc398673b9445ef0a96d12eaf3ab2b198756c65600e612c916144ff565b60008614612cb95760106000878152602001908152602001600020612cb46144ff565b612cc2565b601260ff16600a0a5b604051612cd09291906157cb565b60405180910390a35050565b600d612ce66144ff565b81565b612d536001600090612cf96144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612d3561472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b612d706001600f612d626144ff565b61409d90919063ffffffff16565b600f8190612d7c6146c5565b5050506000600f612d8b6144ff565b9050612d9b83831015601061402f565b612e816005600090612dab6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86866040518363ffffffff1660e01b8152600401612e02929190615673565b60206040518083038160008780612e17614562565b158015612e2c57600080612e29614491565b50505b505a612e36614787565b505050505050158015612e56573d6000803e3d6000612e53614491565b50505b505050506040513d601f19601f82011682018060405250810190612e7a9190614fed565b600061402f565b8373ffffffffffffffffffffffffffffffffffffffff167f72debe083e16f39475584adf69a588657185fbd31e7627daa95ed7dbd45b3cc184604051612ec791906157b0565b60405180910390a2612ee5600f612edc6144ff565b8214601461402f565b50505050565b612f556003600090612efb6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612f3761472a565b73ffffffffffffffffffffffffffffffffffffffff1614601361402f565b612f726001600f612f646144ff565b61409d90919063ffffffff16565b600f8190612f7e6146c5565b5050506000600f612f8d6144ff565b9050600b612f996144ff565b821115612fad57600b612faa6144ff565b91505b612fc982600b612fbb6144ff565b61415b90919063ffffffff16565b600b8190612fd56146c5565b5050506130be6005600090612fe86144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b815260040161303f929190615673565b60206040518083038160008780613054614562565b15801561306957600080613066614491565b50505b505a613073614787565b505050505050158015613093573d6000803e3d6000613090614491565b50505b505050506040513d601f19601f820116820180604052508101906130b79190614fed565b600061402f565b8273ffffffffffffffffffffffffffffffffffffffff167f10913cbb30d5b8ffef79cb59f0875923e51b1a5a54fb330d0cb2022e6af8d13483600b6131016144ff565b60405161310f9291906157cb565b60405180910390a261312d600f6131246144ff565b8214601461402f565b505050565b61319c60016000906131426144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61317e61472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b6131a5816141e7565b50565b61321260016000906131b86144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6131f461472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b61322c60096001016132226144ff565b821115600f61402f565b61324b81600960010161323d6144ff565b61415b90919063ffffffff16565b6009600101819061325a6146c5565b5050507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb981600960010161328c6144ff565b60405161329a9291906157cb565b60405180910390a150565b61330f60016000906132b56144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6132f161472a565b73ffffffffffffffffffffffffffffffffffffffff1614601261402f565b61331d81831115600d61402f565b61333c82600960000161332e6144ff565b61409d90919063ffffffff16565b6009600001819061334b6146c5565b5050507fa926f60433937c9b276382ddb5204387c2c70104cbe627db98999c7d706c419682600960000161337d6144ff565b60405161338b9291906157cb565b60405180910390a15050565b60008060026000906133a76144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a846040518263ffffffff1660e01b81526004016133fc91906157b0565b606060405180830381868061340f614562565b15801561342457600080613421614491565b50505b505a61342e6145c5565b505050505015801561344d573d6000803e3d600061344a614491565b50505b505050506040513d601f19601f82011682018060405250810190613471919061512d565b9050600060016000906134826144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806134df614562565b1580156134f4576000806134f1614491565b50505b505a6134fe6145c5565b505050505015801561351d573d6000803e3d600061351a614491565b50505b505050506040513d601f19601f820116820180604052508101906135419190615209565b905080826020015114156137985761356f8260000151600d6135616144ff565b61415b90919063ffffffff16565b600d819061357b6146c5565b505050600260009061358b6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a6135cc61472a565b866040518363ffffffff1660e01b81526004016135ea9291906155b3565b600060405180830381600087806135ff614562565b15801561361457600080613611614491565b50505b505a61361e614787565b50505050505015801561363e573d6000803e3d600061363b614491565b50505b50505050838573ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948460000151600b61368a6144ff565b6040516136989291906157cb565b60405180910390a361378a60056000906136b06144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8785600001516040518363ffffffff1660e01b815260040161370b929190615673565b60206040518083038160008780613720614562565b15801561373557600080613732614491565b50505b505a61373f614787565b50505050505015801561375f573d6000803e3d600061375c614491565b50505b505050506040513d601f19601f820116820180604052508101906137839190614fed565b600061402f565b816000015192505050613d1a565b6000808360200151146137c95760106000846020015181526020019081526020016000206137c46144ff565b6137d3565b670de0b6b3a76400005b90506000601060008481526020019081526020016000206137f26144ff565b905060008460400151148015613809575060008114155b15613a77576000613827838660000151613ff990919063ffffffff16565b905061384581600e6138376144ff565b61415b90919063ffffffff16565b600e81906138516146c5565b505050613867828261412e90919063ffffffff16565b955060026000906138766144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a6138b761472a565b896040518363ffffffff1660e01b81526004016138d59291906155b3565b600060405180830381600087806138ea614562565b1580156138ff576000806138fc614491565b50505b505a613909614787565b505050505050158015613929573d6000803e3d6000613926614491565b50505b50505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b6139716144ff565b60405161397f9291906157cb565b60405180910390a3613a6d60056000906139976144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b81526004016139ee929190615673565b60206040518083038160008780613a03614562565b158015613a1857600080613a15614491565b50505b505a613a22614787565b505050505050158015613a42573d6000803e3d6000613a3f614491565b50505b505050506040513d601f19601f82011682018060405250810190613a669190614fed565b600061402f565b5050505050613d1a565b60006010600086604001518152602001908152602001600020613a986144ff565b9050613aba6000866040015114158015613ab3575060008214155b600561402f565b613ae383613ad583886000015161412e90919063ffffffff16565b613ff990919063ffffffff16565b95506002600090613af26144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a613b3361472a565b896040518363ffffffff1660e01b8152600401613b519291906155b3565b60006040518083038160008780613b66614562565b158015613b7b57600080613b78614491565b50505b505a613b85614787565b505050505050158015613ba5573d6000803e3d6000613ba2614491565b50505b50505050613bc586600b613bb76144ff565b61415b90919063ffffffff16565b600b8190613bd16146c5565b505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b613c186144ff565b604051613c269291906157cb565b60405180910390a3613d146005600090613c3e6144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b8152600401613c95929190615673565b60206040518083038160008780613caa614562565b158015613cbf57600080613cbc614491565b50505b505a613cc9614787565b505050505050158015613ce9573d6000803e3d6000613ce6614491565b50505b505050506040513d601f19601f82011682018060405250810190613d0d9190614fed565b600061402f565b50505050505b92915050565b6000613ff1600d613d2f6144ff565b613fe3600b613d3c6144ff565b613fd586613fc7613e878a6006600090613d546144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015613de557600081830152602081019050613dcb565b5050506040518263ffffffff1660e01b8152600401613e049190615561565b6020604051808303818680613e17614562565b158015613e2c57600080613e29614491565b50505b505a613e366145c5565b5050505050158015613e55573d6000803e3d6000613e52614491565b50505b505050506040513d601f19601f82011682018060405250810190613e799190615209565b61412e90919063ffffffff16565b6005600090613e946144ff565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015613f2557600081830152602081019050613f0b565b5050506040518263ffffffff1660e01b8152600401613f449190615561565b6020604051808303818680613f57614562565b158015613f6c57600080613f69614491565b50505b505a613f766145c5565b5050505050158015613f95573d6000803e3d6000613f92614491565b50505b505050506040513d601f19601f82011682018060405250810190613fb99190615209565b61409d90919063ffffffff16565b61409d90919063ffffffff16565b61415b90919063ffffffff16565b61415b90919063ffffffff16565b905092915050565b600061402782614019601260ff16600a0a866142bc90919063ffffffff16565b61434b90919063ffffffff16565b905092915050565b816007600083601581111561404057fe5b815260200190815260200160002090614098576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140869190615733565b60405180910390614095614491565b50505b505050565b600080828401905083811015614124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390614121614491565b50505b8091505092915050565b6000601260ff16600a0a61414b83856142bc90919063ffffffff16565b8161415257fe5b04905092915050565b6000828211156141dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250602001915050604051809103906141d9614491565b50505b818303905092915050565b60096000016141f46144ff565b81111561420b5760096000016142086144ff565b90505b61422a81600960000161421c6144ff565b61415b90919063ffffffff16565b600960000181906142396146c5565b5050507f21035560539b4b4540708d4273620b634b00bda210e30692ec878ef00741cbc181600960000161426b6144ff565b6040516142799291906157cb565b60405180910390a150565b60006142988383601260ff16600a0a6143dd565b905092915050565b60006142b48383601260ff16600a0a614438565b905092915050565b6000808314156142cf5760009050614345565b60008284029050828482816142e057fe5b0414614340576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c4d602191396040019150506040518091039061433d614491565b50505b809150505b92915050565b60008082116143cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250602001915050604051809103906143c8614491565b50505b8183816143d457fe5b04905092915050565b600080614408846143fa600a8602886142bc90919063ffffffff16565b61434b90919063ffffffff16565b90506005600a828161441657fe5b061061442357600a810190505b600a818161442d57fe5b049150509392505050565b600080600a838161444557fe5b0461445985876142bc90919063ffffffff16565b8161446057fe5b0490506005600a828161446f57fe5b061061447c57600a810190505b600a818161448657fe5b049150509392505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b868110156144cc5780860151816040840101526020810190506144ae565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b604081101561455d57600081830152602081019050614543565b505050565b638435035b598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b60408110156145c0576000818301526020810190506145a6565b505050565b638540661f598160e01b8152614604565b6000819050818311156145e7578290505b92915050565b6000819050818310156145fe578290505b92915050565b836004820152846024820152606060448201528660648201526084810160005b8881101561463f578088015181830152602081019050614624565b506060828960a40184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b815160408301513d6000853e8b8b82606087013350600060045af150596146948d3d6145ed565b8c016146a081876145d6565b5b828110156146b857600081526020810190506146a1565b50839d5050505050505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b60005b60408110156147255760008183015260208101905061470b565b505050565b6373509064598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b604081101561478257600081830152602081019050614768565b505050565b6385979f76598160e01b81526147c6565b6000819050818311156147a9578290505b92915050565b6000819050818310156147c0578290505b92915050565b836004820152846024820152606060448201528760648201526084810160005b898110156148015780890151818301526020810190506147e6565b506060828a60a40184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b815160408301513d6000853e8c8c82606087013350600060045af150596148568e3d6147af565b8d016148628187614798565b5b8281101561487a5760008152602081019050614863565b50839e5050505050505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b82806148b96144ff565b600181600116156101000203166002900490600052602060002090601f0160209004810192826148f5576000856148ee6146c5565b5050614957565b82601f1061491757805160ff191683800117856149106146c5565b5050614957565b828001600101856149266146c5565b50508215614957579182015b82811115614956578251826149456146c5565b505091602001919060010190614932565b5b5090506149649190614968565b5090565b5b8082111561498a5760008160009061497f6146c5565b505050600101614969565b5090565b60006149a161499c8461585c565b61582b565b9050808382526020820190508260005b858110156149e157813585016149c78882614c48565b8452602084019350602083019250506001810190506149b1565b5050509392505050565b60006149fe6149f984615888565b61582b565b90508083825260208201905082856020860282011115614a2657600080614a23614491565b50505b60005b85811015614a565781614a3c8882614ee8565b845260208401935060208301925050600181019050614a29565b5050509392505050565b6000614a73614a6e846158b4565b61582b565b905082815260208101848484011115614a9457600080614a91614491565b50505b614a9f848285615a87565b509392505050565b600081359050614ab681615aac565b92915050565b600082601f830112614ad657600080614ad3614491565b50505b8135614ae684826020860161498e565b91505092915050565b600082601f830112614b0957600080614b06614491565b50505b8151614b198482602086016149eb565b91505092915050565b600081519050614b3181615acc565b92915050565b600081359050614b4681615aec565b92915050565b600081519050614b5b81615aec565b92915050565b600081359050614b7081615b0c565b92915050565b600081519050614b8581615b0c565b92915050565b600081359050614b9a81615b2c565b92915050565b600081359050614baf81615b4c565b92915050565b600081359050614bc481615b6c565b92915050565b600081359050614bd981615b8c565b92915050565b600081359050614bee81615bac565b92915050565b600081359050614c0381615bcc565b92915050565b600081359050614c1881615bec565b92915050565b600081519050614c2d81615bec565b92915050565b600081519050614c4281615c0c565b92915050565b600082601f830112614c6257600080614c5f614491565b50505b8135614c72848260208601614a60565b91505092915050565b600060608284031215614c9657600080614c93614491565b50505b614ca0606061582b565b90506000614cb084828501614ee8565b6000830152506020614cc484828501614ee8565b6020830152506040614cd884828501614ee8565b60408301525092915050565b600060e08284031215614cff57600080614cfc614491565b50505b614d0960e061582b565b90506000614d1984828501614ed3565b6000830152506020614d2d84828501614b37565b6020830152506040614d4184828501614b37565b6040830152506060614d5584828501614c09565b6060830152506080614d6984828501614b61565b60808301525060a0614d7d84828501614ed3565b60a08301525060c0614d9184828501614ed3565b60c08301525092915050565b600060e08284031215614db857600080614db5614491565b50505b614dc260e061582b565b90506000614dd284828501614ee8565b6000830152506020614de684828501614b4c565b6020830152506040614dfa84828501614b4c565b6040830152506060614e0e84828501614c1e565b6060830152506080614e2284828501614b76565b60808301525060a0614e3684828501614ee8565b60a08301525060c0614e4a84828501614ee8565b60c08301525092915050565b600060808284031215614e7157600080614e6e614491565b50505b614e7b608061582b565b90506000614e8b84828501614ed3565b6000830152506020614e9f84828501614ed3565b6020830152506040614eb384828501614ed3565b6040830152506060614ec784828501614ed3565b60608301525092915050565b600081359050614ee281615c2c565b92915050565b600081519050614ef781615c2c565b92915050565b60008060408385031215614f1957600080614f16614491565b50505b6000614f2785828601614aa7565b9250506020614f3885828601614ed3565b9150509250929050565b600080600060608486031215614f6057600080614f5d614491565b50505b6000614f6e86828701614aa7565b9350506020614f7f86828701614ed3565b9250506040614f9086828701614ed3565b9150509250925092565b600060208284031215614fb557600080614fb2614491565b50505b600082015167ffffffffffffffff811115614fd857600080614fd5614491565b50505b614fe484828501614aef565b91505092915050565b60006020828403121561500857600080615005614491565b50505b600061501684828501614b22565b91505092915050565b600080600080600080600080610100898b03121561504557600080615042614491565b50505b60006150538b828c01614bb5565b98505060206150648b828c01614bca565b97505060406150758b828c01614ba0565b96505060606150868b828c01614bdf565b95505060806150978b828c01614bf4565b94505060a06150a88b828c01614b8b565b93505060c06150b98b828c01614b8b565b92505060e089013567ffffffffffffffff8111156150df576000806150dc614491565b50505b6150eb8b828c01614abc565b9150509295985092959890939650565b60006020828403121561511657600080615113614491565b50505b600061512484828501614c33565b91505092915050565b60006060828403121561514857600080615145614491565b50505b600061515684828501614c7b565b91505092915050565b600060e0828403121561517a57600080615177614491565b50505b600061518884828501614d9d565b91505092915050565b60008061010083850312156151ae576000806151ab614491565b50505b60006151bc85828601614ce4565b92505060e06151cd85828601614ed3565b9150509250929050565b6000602082840312156151f2576000806151ef614491565b50505b600061520084828501614ed3565b91505092915050565b60006020828403121561522457600080615221614491565b50505b600061523284828501614ee8565b91505092915050565b6000806040838503121561525757600080615254614491565b50505b600061526585828601614ed3565b925050602061527685828601614b61565b9150509250929050565b6000806000610180848603121561529f5760008061529c614491565b50505b60006152ad86828701614ed3565b93505060206152be86828701614ce4565b9250506101006152d086828701614e56565b9150509250925092565b600080604083850312156152f6576000806152f3614491565b50505b600061530485828601614ed3565b925050602061531585828601614ed3565b9150509250929050565b60008060006060848603121561533d5760008061533a614491565b50505b600061534b86828701614ed3565b935050602061535c86828701614ed3565b925050604061536d86828701614ed3565b9150509250925092565b61538081615a09565b82525050565b61538f8161590a565b82525050565b61539e81615928565b82525050565b6153ad81615a1b565b82525050565b6153bc81615a3f565b82525050565b6153cb81615a51565b82525050565b6000816153dc6144ff565b60018116600081146153f5576001811461541b57615466565b607f600283041661540681876158f9565b955060ff198316865260208601935050615466565b6002820461542981876158f9565b9550615434856158e4565b60005b8281101561545d57816154486144ff565b81890152600182019150602081019050615437565b80880195505050505b505092915050565b600061547b6013836158f9565b91507f616c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b60006154bb600f836158f9565b91507f6572726f72206d736720636f756e7400000000000000000000000000000000006000830152602082019050919050565b6080820160008201516155046000850182615543565b5060208201516155176020850182615543565b50604082015161552a6040850182615543565b50606082015161553d6060850182615543565b50505050565b61554c816159ff565b82525050565b61555b816159ff565b82525050565b60006020820190506155766000830184615386565b92915050565b60006060820190506155916000830186615377565b61559e6020830185615386565b6155ab6040830184615552565b949350505050565b60006040820190506155c86000830185615377565b6155d56020830184615552565b9392505050565b60006060820190506155f16000830186615377565b6155fe6020830185615552565b61560b60408301846153c2565b949350505050565b60006060820190506156286000830186615377565b6156356020830185615552565b6156426040830184615552565b949350505050565b600060408201905061565f6000830185615386565b61566c60208301846153b3565b9392505050565b60006040820190506156886000830185615386565b6156956020830184615552565b9392505050565b60006060820190506156b16000830186615386565b6156be6020830185615552565b6156cb6040830184615552565b949350505050565b60006060820190506156e86000830186615395565b6156f56020830185615552565b6157026040830184615395565b949350505050565b600060408201905061571f60008301856153a4565b61572c6020830184615552565b9392505050565b6000602082019050818103600083015261574d81846153d1565b905092915050565b6000602082019050818103600083015261576e8161546e565b9050919050565b6000602082019050818103600083015261578e816154ae565b9050919050565b60006080820190506157aa60008301846154ee565b92915050565b60006020820190506157c56000830184615552565b92915050565b60006040820190506157e06000830185615552565b6157ed6020830184615552565b9392505050565b60006060820190506158096000830186615552565b6158166020830185615552565b6158236040830184615552565b949350505050565b6000604051905081810181811067ffffffffffffffff8211171561585257615851615a96565b5b8060405250919050565b600067ffffffffffffffff82111561587757615876615a96565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156158a3576158a2615a96565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156158cf576158ce615a96565b5b601f19601f8301169050602081019050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b6000615915826159df565b9050919050565b60008115159050919050565b6000819050919050565b600061593d8261590a565b9050919050565b600061594f8261590a565b9050919050565b60006159618261590a565b9050919050565b60006159738261590a565b9050919050565b60006159858261590a565b9050919050565b60006159978261590a565b9050919050565b60006159a98261590a565b9050919050565b60006159bb8261590a565b9050919050565b60008190506159d082615a98565b919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000615a1482615a63565b9050919050565b6000615a2682615a2d565b9050919050565b6000615a38826159df565b9050919050565b6000615a4a826159c2565b9050919050565b6000615a5c826159ff565b9050919050565b6000615a6e82615a75565b9050919050565b6000615a80826159df565b9050919050565b82818337600083830152505050565bfe5b60038110615aa957615aa8615a96565b5b50565b615ab58161590a565b8114615ac957600080615ac6614491565b50505b50565b615ad58161591c565b8114615ae957600080615ae6614491565b50505b50565b615af581615928565b8114615b0957600080615b06614491565b50505b50565b615b1581615932565b8114615b2957600080615b26614491565b50505b50565b615b3581615944565b8114615b4957600080615b46614491565b50505b50565b615b5581615956565b8114615b6957600080615b66614491565b50505b50565b615b7581615968565b8114615b8957600080615b86614491565b50505b50565b615b958161597a565b8114615ba957600080615ba6614491565b50505b50565b615bb58161598c565b8114615bc957600080615bc6614491565b50505b50565b615bd58161599e565b8114615be957600080615be6614491565b50505b50565b615bf5816159b0565b8114615c0957600080615c06614491565b50505b50565b615c15816159d5565b8114615c2957600080615c26614491565b50505b50565b615c35816159ff565b8114615c4957600080615c46614491565b50505b5056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c8063a00dad22116100b8578063d1201e311161007c578063d1201e311461033a578063db32232f14610356578063dc62c58114610372578063f238ff5c1461038e578063f3fef3a3146103aa578063fc395668146103da57610142565b8063a00dad22146102a9578063b952cc4a146102c5578063c3964372146102e4578063c677c58a14610300578063c9061b581461031e57610142565b806347e7ef241161010a57806347e7ef24146101fd57806354d269af1461022d578063699ba87b14610249578063749aa2d9146102655780637e8b3f891461026f57806390a80ece1461027957610142565b8063159317d0146101475780631ebcfe801461016557806321af3525146101815780633f2f757d146101b15780633f6b5019146101e1575b600080fd5b61014f61040a565b60405161015c91906144d1565b60405180910390f35b61017f600480360381019061017a9190613f3c565b6105dc565b005b61019b60048036038101906101969190613eff565b6108bc565b6040516101a891906144d1565b60405180910390f35b6101cb60048036038101906101c69190613f8e565b610a94565b6040516101d891906144b6565b60405180910390f35b6101fb60048036038101906101f69190614057565b610c71565b005b61021760048036038101906102129190613cc5565b610d8f565b60405161022491906144d1565b60405180910390f35b61024760048036038101906102429190613dba565b611014565b005b610263600480360381019061025e9190613f3c565b6112f2565b005b61026d611523565b005b61027761190b565b005b610293600480360381019061028e9190613f3c565b611fce565b6040516102a091906144d1565b60405180910390f35b6102c360048036038101906102be9190613fca565b611fe6565b005b6102cd61224c565b6040516102db9291906144ec565b60405180910390f35b6102fe60048036038101906102f9919061401b565b61225e565b005b6103086123a7565b60405161031591906144d1565b60405180910390f35b61033860048036038101906103339190613d01565b6123ad565b005b610354600480360381019061034f9190613cc5565b612555565b005b610370600480360381019061036b9190613f3c565b61271d565b005b61038c60048036038101906103879190613f3c565b612784565b005b6103a860048036038101906103a3919061401b565b612854565b005b6103c460048036038101906103bf9190613cc5565b612920565b6040516103d191906144d1565b60405180910390f35b6103f460048036038101906103ef919061401b565b6130d1565b60405161040191906144d1565b60405180910390f35b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026040518363ffffffff1660e01b815260040161048b92919061436b565b60e06040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db9190613ed6565b90506000600e5414156104f957670de0b6b3a76400009150506105d9565b60006105bd8260000151600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d856080015186600001516040518363ffffffff1660e01b815260040161056892919061442b565b60206040518083038186803b15801561058057600080fd5b505afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190613f65565b6130d1565b90506105d4600e548261328e90919063ffffffff16565b925050505b90565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161063991906144d1565b60606040518083038186803b15801561065157600080fd5b505afa158015610665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106899190613ead565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f557600080fd5b505afa158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d9190613f65565b9050610741600083604001511460016132c4565b6107728183602001511415801561076b575060006010600084815260200190815260200160002054145b60026132c4565b6000826020015114156107a3576107988260000151600c5461332990919063ffffffff16565b600c819055506107ec565b6107e56107d4601060008560200151815260200190815260200160002054846000015161328e90919063ffffffff16565b600c5461332990919063ffffffff16565b600c819055505b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b3385846040518463ffffffff1660e01b815260040161084b93929190614334565b600060405180830381600087803b15801561086557600080fd5b505af1158015610879573d6000803e3d6000fd5b50505050827fa030de897a3fbcd98618ebb6d64981072317ade7083ad8702bbcd0b867a5063e600c546040516108af91906144d1565b60405180910390a2505050565b6000610919600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460116132c4565b61092f6001600f5461332990919063ffffffff16565b600f819055506000600f549050600061095085600001518660800151610a94565b905060008160400151905084811015610967578094505b610a42600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518363ffffffff1660e01b81526004016109e9929190614394565b602060405180830381600087803b158015610a0357600080fd5b505af1158015610a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3b9190613d91565b60006132c4565b7f78139c2f5eabfad75a88b7c1fe1d1e3851b441e2c5a7f792f95d8e1c6b9c636085604051610a7191906144d1565b60405180910390a18493505050610a8d600f54821460146132c4565b5092915050565b610a9c6136d4565b610aa46136d4565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d84866040518363ffffffff1660e01b8152600401610b0192919061442b565b60206040518083038186803b158015610b1957600080fd5b505afa158015610b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b519190613f65565b816060018181525050610b89610b75856009600101546133b190919063ffffffff16565b60096000015461332990919063ffffffff16565b8160200181815250506000610ba28583606001516130d1565b9050600060036002830281610bb357fe5b0490506000610bcb82846133de90919063ffffffff16565b90508184602001511115610bfa5783602001519150610bf382846133de90919063ffffffff16565b9050610c24565b8084606001511115610c235783606001519050610c2081846133de90919063ffffffff16565b91505b5b610c3b8460600151826133de90919063ffffffff16565b846040018181525050610c5b8460200151836133de90919063ffffffff16565b8460000181815250508394505050505092915050565b610ccc600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b610cd583613461565b610cea82600b5461332990919063ffffffff16565b600b819055507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b82600b54604051610d239291906144ec565b60405180910390a1610d43816009600101546133de90919063ffffffff16565b6009600101819055507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb981600960010154604051610d829291906144ec565b60405180910390a1505050565b6000610da682600d5461332990919063ffffffff16565b600d819055506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663156e29f68585600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5657600080fd5b505afa158015610e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8e9190613f65565b6040518463ffffffff1660e01b8152600401610eac939291906143bd565b602060405180830381600087803b158015610ec657600080fd5b505af1158015610eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efe9190613f65565b9050808473ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1585604051610f4791906144d1565b60405180910390a361100a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330876040518463ffffffff1660e01b8152600401610fb19392919061429d565b602060405180830381600087803b158015610fcb57600080fd5b505af1158015610fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110039190613d91565b60006132c4565b8091505092915050565b600860009054906101000a900460ff1615611064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105b90614476565b60405180910390fd5b876000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060158081111561123657fe5b815114611278576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126f90614496565b60405180910390fd5b60005b81518110156112cc5781818151811061129057fe5b60200260200101516007600083815260200190815260200160002090805190602001906112be9291906136fc565b50808060010191505061127b565b506001600860006101000a81548160ff0219169083151502179055505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161134f91906144d1565b60606040518083038186803b15801561136757600080fd5b505afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190613ead565b90506113b460008260400151141560036132c4565b6113d960006010600084604001518152602001908152602001600020541460046132c4565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b338460006040518463ffffffff1660e01b8152600401611439939291906142fd565b600060405180830381600087803b15801561145357600080fd5b505af1158015611467573d6000803e3d6000fd5b5050505060008160200151141561149c576114918160000151600c546133de90919063ffffffff16565b600c819055506114e5565b6114de6114cd601060008460200151815260200190815260200160002054836000015161328e90919063ffffffff16565b600c546133de90919063ffffffff16565b600c819055505b817f74e46e4569fdcca3333564a0997a08b4607c2af89cd8477813db852c9f364b61600c5460405161151791906144d1565b60405180910390a25050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561158d57600080fd5b505afa1580156115a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c59190613f65565b905061167a6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561163457600080fd5b505afa158015611648573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116719190613d50565b511460066132c4565b61169b600060106000848152602001908152602001600020541460076132c4565b6117536000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116fb9190614282565b60206040518083038186803b15801561171357600080fd5b505afa158015611727573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174b9190613f65565b1460086132c4565b6118006000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663759d4d596040518163ffffffff1660e01b815260040160206040518083038186803b1580156117c057600080fd5b505afa1580156117d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f89190613e84565b1460096132c4565b600061180a61040a565b905080601060008481526020019081526020016000208190555061184d61183c82600c546133b190919063ffffffff16565b600b5461332990919063ffffffff16565b600b819055507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b61188982600c546133b190919063ffffffff16565b600b5460405161189a9291906144ec565b60405180910390a16118b9600c54600e546133de90919063ffffffff16565b600e81905550817fff9d41e1547acb5eda1e3bac0c795f57760c96016cdd641af6bdd90270a768f382600b54600c546040516118f793929190614515565b60405180910390a26000600c819055505050565b6119216001600f5461332990919063ffffffff16565b600f819055506000600f5490506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161198b9190614282565b60206040518083038186803b1580156119a357600080fd5b505afa1580156119b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119db9190613f65565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b815260040160006040518083038186803b158015611a4757600080fd5b505afa158015611a5b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a849190613d50565b511415611a975760006009600101819055505b600960010154811115611c885760008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006040518363ffffffff1660e01b8152600401611b2592919061436b565b60e06040518083038186803b158015611b3d57600080fd5b505afa158015611b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b759190613ed6565b90506000600960010154830390506000826060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f384604001518486602001516040518463ffffffff1660e01b8152600401611bce939291906143f4565b602060405180830381600087803b158015611be857600080fd5b505af1158015611bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c209190613f65565b9050611c3060008211600b6132c4565b3373ffffffffffffffffffffffffffffffffffffffff167f0ba93b4b06f63170434e95713b6e4613651536fe0795f417db31ca847d25e0f28383604051611c789291906144ec565b60405180910390a2505050611fbb565b806009600101541115611fba5760008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016040518363ffffffff1660e01b8152600401611d1692919061436b565b60e06040518083038186803b158015611d2e57600080fd5b505afa158015611d42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d669190613ed6565b90506000611db78260000151611da9611d938560a00151601260ff16600a0a6133de90919063ffffffff16565b86600960010154036134d990919063ffffffff16565b6134f590919063ffffffff16565b90506000611ea5600d54611e97600960000154611e89600b54600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611e2b9190614282565b60206040518083038186803b158015611e4357600080fd5b505afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190613f65565b6133de90919063ffffffff16565b6133de90919063ffffffff16565b6133de90919063ffffffff16565b9050808211611eb45781611eb6565b805b91506000836060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f385602001518587604001516040518463ffffffff1660e01b8152600401611f03939291906143f4565b602060405180830381600087803b158015611f1d57600080fd5b505af1158015611f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f559190613f65565b9050611f6560008211600c6132c4565b3373ffffffffffffffffffffffffffffffffffffffff167ffe644b4d06ffe999b33590d87654491fea7d9ce296e8d305004cf50ca96e6be18483604051611fad9291906144ec565b60405180910390a2505050505b5b50611fcb600f54821460146132c4565b50565b60106020528060005260406000206000915090505481565b612041600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161209e9190614282565b60206040518083038186803b1580156120b657600080fd5b505afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee9190613f65565b90506000808360000151905082600960010154106121585760008360096001015403905061213b61212c8760000151836133b190919063ffffffff16565b8361332990919063ffffffff16565b9150612150818861332990919063ffffffff16565b92505061218c565b600060096001015484039050868110612174576000925061218a565b61218781886133de90919063ffffffff16565b92505b505b60006121d486600001516121c66121b78960a00151601260ff16600a0a6133de90919063ffffffff16565b866134d990919063ffffffff16565b6134f590919063ffffffff16565b90506121e481831015600e6132c4565b6121fc8760096001015461332990919063ffffffff16565b6009600101819055507f88cdc2d9dafaa25ef0f861c37488527fa03d0d30cd7ed982e93c2fd8ed44eeaa8760096001015460405161223b9291906144ec565b60405180910390a150505050505050565b60098060000154908060010154905082565b6122b9600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b60008214156122d057600d54600e81905550612335565b6122f2600060106000858152602001908152602001600020541415600a6132c4565b61232e61231d6010600085815260200190815260200160002054600d5461328e90919063ffffffff16565b600e5461332990919063ffffffff16565b600e819055505b6000600d8190555080827ffd9d17e5565deea3d25918d95fc398673b9445ef0a96d12eaf3ab2b198756c65600e546000861461238457601060008781526020019081526020016000205461238d565b601260ff16600a0a5b60405161239b9291906144ec565b60405180910390a35050565b600d5481565b612408600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b61241e6001600f5461332990919063ffffffff16565b600f819055506000600f5490506124398383101560106132c4565b6124f2600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86866040518363ffffffff1660e01b8152600401612499929190614394565b602060405180830381600087803b1580156124b357600080fd5b505af11580156124c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124eb9190613d91565b60006132c4565b8373ffffffffffffffffffffffffffffffffffffffff167f72debe083e16f39475584adf69a588657185fbd31e7627daa95ed7dbd45b3cc18460405161253891906144d1565b60405180910390a261254f600f54821460146132c4565b50505050565b6125b0600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460136132c4565b6125c66001600f5461332990919063ffffffff16565b600f819055506000600f549050600b548211156125e357600b5491505b6125f882600b546133de90919063ffffffff16565b600b819055506126b7600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b815260040161265e929190614394565b602060405180830381600087803b15801561267857600080fd5b505af115801561268c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b09190613d91565b60006132c4565b8273ffffffffffffffffffffffffffffffffffffffff167f10913cbb30d5b8ffef79cb59f0875923e51b1a5a54fb330d0cb2022e6af8d13483600b546040516127019291906144ec565b60405180910390a2612718600f54821460146132c4565b505050565b612778600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b61278181613461565b50565b6127df600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b6127f2600960010154821115600f6132c4565b61280a816009600101546133de90919063ffffffff16565b6009600101819055507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb9816009600101546040516128499291906144ec565b60405180910390a150565b6128af600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c4565b6128bd81831115600d6132c4565b6128d58260096000015461332990919063ffffffff16565b6009600001819055507fa926f60433937c9b276382ddb5204387c2c70104cbe627db98999c7d706c4196826009600001546040516129149291906144ec565b60405180910390a15050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a846040518263ffffffff1660e01b815260040161297e91906144d1565b60606040518083038186803b15801561299657600080fd5b505afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613ead565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3a57600080fd5b505afa158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a729190613f65565b90508082602001511415612c5057612a998260000151600d546133de90919063ffffffff16565b600d81905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33866040518363ffffffff1660e01b8152600401612afc9291906142d4565b600060405180830381600087803b158015612b1657600080fd5b505af1158015612b2a573d6000803e3d6000fd5b50505050838573ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948460000151600b54604051612b7d9291906144ec565b60405180910390a3612c42600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8785600001516040518363ffffffff1660e01b8152600401612be9929190614394565b602060405180830381600087803b158015612c0357600080fd5b505af1158015612c17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3b9190613d91565b60006132c4565b8160000151925050506130cb565b600080836020015114612c7a57601060008460200151815260200190815260200160002054612c84565b670de0b6b3a76400005b905060006010600084815260200190815260200160002054905060008460400151148015612cb3575060008114155b15612ea8576000612cd183866000015161328e90919063ffffffff16565b9050612ce881600e546133de90919063ffffffff16565b600e81905550612d0182826133b190919063ffffffff16565b9550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33896040518363ffffffff1660e01b8152600401612d609291906142d4565b600060405180830381600087803b158015612d7a57600080fd5b505af1158015612d8e573d6000803e3d6000fd5b50505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b54604051612ddd9291906144ec565b60405180910390a3612e9e600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b8152600401612e45929190614394565b602060405180830381600087803b158015612e5f57600080fd5b505af1158015612e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e979190613d91565b60006132c4565b50505050506130cb565b60006010600086604001518152602001908152602001600020549050612ee46000866040015114158015612edd575060008214155b60056132c4565b612f0d83612eff8388600001516133b190919063ffffffff16565b61328e90919063ffffffff16565b9550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33896040518363ffffffff1660e01b8152600401612f6c9291906142d4565b600060405180830381600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b50505050612fb386600b546133de90919063ffffffff16565b600b81905550868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b546040516130049291906144ec565b60405180910390a36130c5600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b815260040161306c929190614394565b602060405180830381600087803b15801561308657600080fd5b505af115801561309a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130be9190613d91565b60006132c4565b50505050505b92915050565b6000613286600d54613278600b5461326a8661325c6131a38a600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016131459190614282565b60206040518083038186803b15801561315d57600080fd5b505afa158015613171573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131959190613f65565b6133b190919063ffffffff16565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016131fe9190614282565b60206040518083038186803b15801561321657600080fd5b505afa15801561322a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061324e9190613f65565b61332990919063ffffffff16565b61332990919063ffffffff16565b6133de90919063ffffffff16565b6133de90919063ffffffff16565b905092915050565b60006132bc826132ae601260ff16600a0a8661351190919063ffffffff16565b61359790919063ffffffff16565b905092915050565b81600760008360158111156132d557fe5b815260200190815260200160002090613324576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161331b9190614454565b60405180910390fd5b505050565b6000808284019050838110156133a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000601260ff16600a0a6133ce838561351190919063ffffffff16565b816133d557fe5b04905092915050565b600082821115613456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b6009600001548111156134775760096000015490505b61348f816009600001546133de90919063ffffffff16565b6009600001819055507f21035560539b4b4540708d4273620b634b00bda210e30692ec878ef00741cbc1816009600001546040516134ce9291906144ec565b60405180910390a150565b60006134ed8383601260ff16600a0a613620565b905092915050565b60006135098383601260ff16600a0a61367b565b905092915050565b6000808314156135245760009050613591565b600082840290508284828161353557fe5b041461358c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806148f96021913960400191505060405180910390fd5b809150505b92915050565b600080821161360e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b81838161361757fe5b04905092915050565b60008061364b8461363d600a86028861351190919063ffffffff16565b61359790919063ffffffff16565b90506005600a828161365957fe5b061061366657600a810190505b600a818161367057fe5b049150509392505050565b600080600a838161368857fe5b0461369c858761351190919063ffffffff16565b816136a357fe5b0490506005600a82816136b257fe5b06106136bf57600a810190505b600a81816136c957fe5b049150509392505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826137325760008555613779565b82601f1061374b57805160ff1916838001178555613779565b82800160010185558215613779579182015b8281111561377857825182559160200191906001019061375d565b5b509050613786919061378a565b5090565b5b808211156137a357600081600090555060010161378b565b5090565b60006137ba6137b58461457d565b61454c565b9050808382526020820190508260005b858110156137fa57813585016137e08882613a3d565b8452602084019350602083019250506001810190506137ca565b5050509392505050565b6000613817613812846145a9565b61454c565b9050808382526020820190508285602086028201111561383657600080fd5b60005b85811015613866578161384c8882613cb0565b845260208401935060208301925050600181019050613839565b5050509392505050565b600061388361387e846145d5565b61454c565b90508281526020810184848401111561389b57600080fd5b6138a68482856147a8565b509392505050565b6000813590506138bd816147cd565b92915050565b600082601f8301126138d457600080fd5b81356138e48482602086016137a7565b91505092915050565b600082601f8301126138fe57600080fd5b815161390e848260208601613804565b91505092915050565b600081519050613926816147e4565b92915050565b60008135905061393b816147fb565b92915050565b600081519050613950816147fb565b92915050565b60008135905061396581614812565b92915050565b60008151905061397a81614812565b92915050565b60008135905061398f81614829565b92915050565b6000813590506139a481614840565b92915050565b6000813590506139b981614857565b92915050565b6000813590506139ce8161486e565b92915050565b6000813590506139e381614885565b92915050565b6000813590506139f88161489c565b92915050565b600081359050613a0d816148b3565b92915050565b600081519050613a22816148b3565b92915050565b600081519050613a37816148ca565b92915050565b600082601f830112613a4e57600080fd5b8135613a5e848260208601613870565b91505092915050565b600060608284031215613a7957600080fd5b613a83606061454c565b90506000613a9384828501613cb0565b6000830152506020613aa784828501613cb0565b6020830152506040613abb84828501613cb0565b60408301525092915050565b600060e08284031215613ad957600080fd5b613ae360e061454c565b90506000613af384828501613c9b565b6000830152506020613b078482850161392c565b6020830152506040613b1b8482850161392c565b6040830152506060613b2f848285016139fe565b6060830152506080613b4384828501613956565b60808301525060a0613b5784828501613c9b565b60a08301525060c0613b6b84828501613c9b565b60c08301525092915050565b600060e08284031215613b8957600080fd5b613b9360e061454c565b90506000613ba384828501613cb0565b6000830152506020613bb784828501613941565b6020830152506040613bcb84828501613941565b6040830152506060613bdf84828501613a13565b6060830152506080613bf38482850161396b565b60808301525060a0613c0784828501613cb0565b60a08301525060c0613c1b84828501613cb0565b60c08301525092915050565b600060808284031215613c3957600080fd5b613c43608061454c565b90506000613c5384828501613c9b565b6000830152506020613c6784828501613c9b565b6020830152506040613c7b84828501613c9b565b6040830152506060613c8f84828501613c9b565b60608301525092915050565b600081359050613caa816148e1565b92915050565b600081519050613cbf816148e1565b92915050565b60008060408385031215613cd857600080fd5b6000613ce6858286016138ae565b9250506020613cf785828601613c9b565b9150509250929050565b600080600060608486031215613d1657600080fd5b6000613d24868287016138ae565b9350506020613d3586828701613c9b565b9250506040613d4686828701613c9b565b9150509250925092565b600060208284031215613d6257600080fd5b600082015167ffffffffffffffff811115613d7c57600080fd5b613d88848285016138ed565b91505092915050565b600060208284031215613da357600080fd5b6000613db184828501613917565b91505092915050565b600080600080600080600080610100898b031215613dd757600080fd5b6000613de58b828c016139aa565b9850506020613df68b828c016139bf565b9750506040613e078b828c01613995565b9650506060613e188b828c016139d4565b9550506080613e298b828c016139e9565b94505060a0613e3a8b828c01613980565b93505060c0613e4b8b828c01613980565b92505060e089013567ffffffffffffffff811115613e6857600080fd5b613e748b828c016138c3565b9150509295985092959890939650565b600060208284031215613e9657600080fd5b6000613ea484828501613a28565b91505092915050565b600060608284031215613ebf57600080fd5b6000613ecd84828501613a67565b91505092915050565b600060e08284031215613ee857600080fd5b6000613ef684828501613b77565b91505092915050565b6000806101008385031215613f1357600080fd5b6000613f2185828601613ac7565b92505060e0613f3285828601613c9b565b9150509250929050565b600060208284031215613f4e57600080fd5b6000613f5c84828501613c9b565b91505092915050565b600060208284031215613f7757600080fd5b6000613f8584828501613cb0565b91505092915050565b60008060408385031215613fa157600080fd5b6000613faf85828601613c9b565b9250506020613fc085828601613956565b9150509250929050565b60008060006101808486031215613fe057600080fd5b6000613fee86828701613c9b565b9350506020613fff86828701613ac7565b92505061010061401186828701613c27565b9150509250925092565b6000806040838503121561402e57600080fd5b600061403c85828601613c9b565b925050602061404d85828601613c9b565b9150509250929050565b60008060006060848603121561406c57600080fd5b600061407a86828701613c9b565b935050602061408b86828701613c9b565b925050604061409c86828701613c9b565b9150509250925092565b6140af8161472a565b82525050565b6140be8161462b565b82525050565b6140cd81614649565b82525050565b6140dc8161473c565b82525050565b6140eb81614760565b82525050565b6140fa81614772565b82525050565b60008154600181166000811461411d576001811461414357614187565b607f600283041661412e818761461a565b955060ff198316865260208601935050614187565b60028204614151818761461a565b955061415c85614605565b60005b8281101561417e5781548189015260018201915060208101905061415f565b80880195505050505b505092915050565b600061419c60138361461a565b91507f616c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b60006141dc600f8361461a565b91507f6572726f72206d736720636f756e7400000000000000000000000000000000006000830152602082019050919050565b6080820160008201516142256000850182614264565b5060208201516142386020850182614264565b50604082015161424b6040850182614264565b50606082015161425e6060850182614264565b50505050565b61426d81614720565b82525050565b61427c81614720565b82525050565b600060208201905061429760008301846140b5565b92915050565b60006060820190506142b260008301866140a6565b6142bf60208301856140b5565b6142cc6040830184614273565b949350505050565b60006040820190506142e960008301856140a6565b6142f66020830184614273565b9392505050565b600060608201905061431260008301866140a6565b61431f6020830185614273565b61432c60408301846140f1565b949350505050565b600060608201905061434960008301866140a6565b6143566020830185614273565b6143636040830184614273565b949350505050565b600060408201905061438060008301856140b5565b61438d60208301846140e2565b9392505050565b60006040820190506143a960008301856140b5565b6143b66020830184614273565b9392505050565b60006060820190506143d260008301866140b5565b6143df6020830185614273565b6143ec6040830184614273565b949350505050565b600060608201905061440960008301866140c4565b6144166020830185614273565b61442360408301846140c4565b949350505050565b600060408201905061444060008301856140d3565b61444d6020830184614273565b9392505050565b6000602082019050818103600083015261446e8184614100565b905092915050565b6000602082019050818103600083015261448f8161418f565b9050919050565b600060208201905081810360008301526144af816141cf565b9050919050565b60006080820190506144cb600083018461420f565b92915050565b60006020820190506144e66000830184614273565b92915050565b60006040820190506145016000830185614273565b61450e6020830184614273565b9392505050565b600060608201905061452a6000830186614273565b6145376020830185614273565b6145446040830184614273565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715614573576145726147b7565b5b8060405250919050565b600067ffffffffffffffff821115614598576145976147b7565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156145c4576145c36147b7565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156145f0576145ef6147b7565b5b601f19601f8301169050602081019050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600061463682614700565b9050919050565b60008115159050919050565b6000819050919050565b600061465e8261462b565b9050919050565b60006146708261462b565b9050919050565b60006146828261462b565b9050919050565b60006146948261462b565b9050919050565b60006146a68261462b565b9050919050565b60006146b88261462b565b9050919050565b60006146ca8261462b565b9050919050565b60006146dc8261462b565b9050919050565b60008190506146f1826147b9565b919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061473582614784565b9050919050565b60006147478261474e565b9050919050565b600061475982614700565b9050919050565b600061476b826146e3565b9050919050565b600061477d82614720565b9050919050565b600061478f82614796565b9050919050565b60006147a182614700565b9050919050565b82818337600083830152505050565bfe5b600381106147ca576147c96147b7565b5b50565b6147d68161462b565b81146147e157600080fd5b50565b6147ed8161463d565b81146147f857600080fd5b50565b61480481614649565b811461480f57600080fd5b50565b61481b81614653565b811461482657600080fd5b50565b61483281614665565b811461483d57600080fd5b50565b61484981614677565b811461485457600080fd5b50565b61486081614689565b811461486b57600080fd5b50565b6148778161469b565b811461488257600080fd5b50565b61488e816146ad565b811461489957600080fd5b50565b6148a5816146bf565b81146148b057600080fd5b50565b6148bc816146d1565b81146148c757600080fd5b50565b6148d3816146f6565b81146148de57600080fd5b50565b6148ea81614720565b81146148f557600080fd5b5056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220e301030e340c9f644c9049bacad162f446183648286340d7c3e31a1b8388646164736f6c63430007060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
OP | 100.00% | $0.995044 | 592,102.9298 | $589,168.26 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.