More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 75 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 8241485 | 857 days ago | IN | 0 ETH | 0.000183903333 | ||||
Withdraw | 7052580 | 867 days ago | IN | 0 ETH | 0.000220802924 | ||||
Withdraw | 7050149 | 867 days ago | IN | 0 ETH | 0.000241459295 | ||||
Withdraw | 6745573 | 872 days ago | IN | 0 ETH | 0.000332206968 | ||||
Withdraw | 6745439 | 872 days ago | IN | 0 ETH | 0.000332224068 | ||||
Withdraw | 6745244 | 872 days ago | IN | 0 ETH | 0.000310928854 | ||||
Withdraw | 6745111 | 872 days ago | IN | 0 ETH | 0.000334504314 | ||||
Withdraw | 6744922 | 872 days ago | IN | 0 ETH | 0.000295509683 | ||||
Withdraw | 6744766 | 872 days ago | IN | 0 ETH | 0.000332039349 | ||||
Withdraw | 6744621 | 872 days ago | IN | 0 ETH | 0.000298380709 | ||||
Withdraw | 6744417 | 872 days ago | IN | 0 ETH | 0.000375311381 | ||||
Withdraw | 6744265 | 872 days ago | IN | 0 ETH | 0.00033889761 | ||||
Withdraw | 6743915 | 872 days ago | IN | 0 ETH | 0.000275148896 | ||||
Withdraw | 6743616 | 872 days ago | IN | 0 ETH | 0.000206721508 | ||||
Withdraw | 6743384 | 872 days ago | IN | 0 ETH | 0.000206142044 | ||||
Withdraw | 6743112 | 872 days ago | IN | 0 ETH | 0.000236875022 | ||||
Withdraw | 6742726 | 872 days ago | IN | 0 ETH | 0.000348135981 | ||||
Withdraw | 6742242 | 872 days ago | IN | 0 ETH | 0.000258373362 | ||||
Withdraw | 6741958 | 872 days ago | IN | 0 ETH | 0.000297304916 | ||||
Withdraw | 6741777 | 872 days ago | IN | 0 ETH | 0.000252618019 | ||||
Withdraw | 6741307 | 872 days ago | IN | 0 ETH | 0.000393925924 | ||||
Withdraw | 6741122 | 872 days ago | IN | 0 ETH | 0.000488184704 | ||||
Withdraw | 6740929 | 872 days ago | IN | 0 ETH | 0.000356046966 | ||||
Withdraw | 6740755 | 872 days ago | IN | 0 ETH | 0.000587127122 | ||||
Withdraw | 6740626 | 872 days ago | IN | 0 ETH | 0.000532277349 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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. Collateralising 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[certificateData.burnableAt] == 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); tokensBurnableForRound = 0; emit RoundEnded(maxExpiryTimestamp, pricePerToken, totalQuoteAmountReserved, totalTokenSupply); } /** * @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, totalTokenSupply.multiplyDecimalRound(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 totalTokenSupply ); /** * @dev Emitted when a round starts. */ event RoundStarted( uint indexed lastMaxExpiryTimestmp, uint indexed newMaxExpiryTimestmp, uint totalTokenSupply, uint totalPoolValueQuote ); /** * @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":"totalTokenSupply","type":"uint256"}],"name":"RoundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"lastMaxExpiryTimestmp","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newMaxExpiryTimestmp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalTokenSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPoolValueQuote","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
60806040526000600860006101000a816200001962000062565b8160ff0219169083151502179062000030620000c7565b5050506001600f62000041620000c7565b50503480156200005b57600080620000586200012e565b50505b506200019e565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b6040811015620000c257600081830152602081019050620000a6565b505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b60005b604081101562000129576000818301526020810190506200010d565b505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b868110156200016b5780860151816040840101526020810190506200014b565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b615c7780620001ae6000396000f3fe60806040523480156100195760008061001661449a565b50505b506004361061014b5760003560e01c8063a00dad22116100c1578063d1201e3111610085578063d1201e311461034c578063db32232f14610368578063dc62c58114610384578063f238ff5c146103a0578063f3fef3a3146103bc578063fc395668146103ec5761014b565b8063a00dad22146102bb578063b952cc4a146102d7578063c3964372146102f6578063c677c58a14610312578063c9061b58146103305761014b565b806347e7ef241161011357806347e7ef241461020f57806354d269af1461023f578063699ba87b1461025b578063749aa2d9146102775780637e8b3f891461028157806390a80ece1461028b5761014b565b8063159317d0146101595780631ebcfe801461017757806321af3525146101935780633f2f757d146101c35780633f6b5019146101f3575b60008061015661449a565b50505b61016161041c565b60405161016e91906157b9565b60405180910390f35b610191600480360381019061018c91906151e0565b61065b565b005b6101ad60048036038101906101a8919061519a565b610a01565b6040516101ba91906157b9565b60405180910390f35b6101dd60048036038101906101d89190615244565b610c3a565b6040516101ea919061579e565b60405180910390f35b61020d60048036038101906102089190615328565b610e51565b005b61022960048036038101906102249190614f06565b610fac565b60405161023691906157b9565b60405180910390f35b61025960048036038101906102549190615028565b61132a565b005b610275600480360381019061027091906151e0565b6116a1565b005b61027f611968565b005b610289611ebe565b005b6102a560048036038101906102a091906151e0565b6127d5565b6040516102b291906157b9565b60405180910390f35b6102d560048036038101906102d09190615289565b6127f4565b005b6102df612b1c565b6040516102ed9291906157d4565b60405180910390f35b610310600480360381019061030b91906152e3565b612b3c565b005b61031a612ce5565b60405161032791906157b9565b60405180910390f35b61034a60048036038101906103459190614f4b565b612cf2565b005b61036660048036038101906103619190614f06565b612ef4565b005b610382600480360381019061037d91906151e0565b61313b565b005b61039e600480360381019061039991906151e0565b6131b1565b005b6103ba60048036038101906103b591906152e3565b6132ae565b005b6103d660048036038101906103d19190614f06565b6133a0565b6040516103e391906157b9565b60405180910390f35b610406600480360381019061040191906152e3565b613d29565b60405161041391906157b9565b60405180910390f35b60008060008061042a614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009061046f614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026040518363ffffffff1660e01b81526004016104ab929190615653565b60e06040518083038186806104be61456b565b1580156104d3576000806104d061449a565b50505b505a6104dd6145ce565b50505050501580156104fc573d6000803e3d60006104f961449a565b50505b505050506040513d601f19601f820116820180604052508101906105209190615168565b90506000600e61052e614508565b141561054557670de0b6b3a7640000915050610658565b60006106358260000151600460009061055c614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d856080015186600001516040518363ffffffff1660e01b81526004016105bb929190615713565b60206040518083038186806105ce61456b565b1580156105e3576000806105e061449a565b50505b505a6105ed6145ce565b505050505015801561060c573d6000803e3d600061060961449a565b50505b505050506040513d601f19601f820116820180604052508101906106309190615212565b613d29565b9050610653600e610644614508565b8261400290919063ffffffff16565b925050505b90565b6000600260009061066a614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b81526004016106bf91906157b9565b60606040518083038186806106d261456b565b1580156106e7576000806106e461449a565b50505b505a6106f16145ce565b5050505050158015610710573d6000803e3d600061070d61449a565b50505b505050506040513d601f19601f820116820180604052508101906107349190615136565b905060006001600090610745614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806107a261456b565b1580156107b7576000806107b461449a565b50505b505a6107c16145ce565b50505050501580156107e0573d6000803e3d60006107dd61449a565b50505b505050506040513d601f19601f820116820180604052508101906108049190615212565b905061081860008360400151146001614038565b6108548183602001511415801561084d57506000601060008560400151815260200190815260200160002061084b614508565b145b6002614038565b600082602001511415610895576108818260000151600c610873614508565b6140a690919063ffffffff16565b600c819061088d6146ce565b5050506108f5565b6108e56108cd60106000856020015181526020019081526020016000206108ba614508565b846000015161400290919063ffffffff16565b600c6108d7614508565b6140a690919063ffffffff16565b600c81906108f16146ce565b5050505b6002600090610902614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b5a610943614733565b85846040518463ffffffff1660e01b81526004016109639392919061561c565b6000604051808303816000878061097861456b565b15801561098d5760008061098a61449a565b50505b505a610997614790565b5050505050501580156109b7573d6000803e3d60006109b461449a565b50505b50505050827fa030de897a3fbcd98618ebb6d64981072317ade7083ad8702bbcd0b867a5063e600c6109e7614508565b6040516109f491906157b9565b60405180910390a2505050565b6000610a6d6004600090610a13614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a610a4f614733565b73ffffffffffffffffffffffffffffffffffffffff16146011614038565b610a8a6001600f610a7c614508565b6140a690919063ffffffff16565b600f8190610a966146ce565b5050506000600f610aa5614508565b90506000610abb85600001518660800151610c3a565b905060008160400151905084811015610ad2578094505b610be16005600090610ae2614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6004600090610b27614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518363ffffffff1660e01b8152600401610b6292919061567c565b60206040518083038160008780610b7761456b565b158015610b8c57600080610b8961449a565b50505b505a610b96614790565b505050505050158015610bb6573d6000803e3d6000610bb361449a565b50505b505050506040513d601f19601f82011682018060405250810190610bda9190614ff6565b6000614038565b7f78139c2f5eabfad75a88b7c1fe1d1e3851b441e2c5a7f792f95d8e1c6b9c636085604051610c1091906157b9565b60405180910390a18493505050610c33600f610c2a614508565b82146014614038565b5092915050565b610c42614890565b610c4a614890565b6004600090610c57614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d84866040518363ffffffff1660e01b8152600401610cae929190615713565b6020604051808303818680610cc161456b565b158015610cd657600080610cd361449a565b50505b505a610ce06145ce565b5050505050158015610cff573d6000803e3d6000610cfc61449a565b50505b505050506040513d601f19601f82011682018060405250810190610d239190615212565b816060018181525050610d69610d4e856009600101610d40614508565b61413790919063ffffffff16565b6009600001610d5b614508565b6140a690919063ffffffff16565b8160200181815250506000610d82858360600151613d29565b9050600060036002830281610d9357fe5b0490506000610dab828461416490919063ffffffff16565b90508184602001511115610dda5783602001519150610dd3828461416490919063ffffffff16565b9050610e04565b8084606001511115610e035783606001519050610e00818461416490919063ffffffff16565b91505b5b610e1b84606001518261416490919063ffffffff16565b846040018181525050610e3b84602001518361416490919063ffffffff16565b8460000181815250508394505050505092915050565b610ebb6001600090610e61614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a610e9d614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b610ec4836141f0565b610ee082600b610ed2614508565b6140a690919063ffffffff16565b600b8190610eec6146ce565b5050507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b82600b610f1b614508565b604051610f299291906157d4565b60405180910390a1610f50816009600101610f42614508565b61416490919063ffffffff16565b60096001018190610f5f6146ce565b5050507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb9816009600101610f91614508565b604051610f9f9291906157d4565b60405180910390a1505050565b6000610fca82600d610fbc614508565b6140a690919063ffffffff16565b600d8190610fd66146ce565b50505060006002600090610fe8614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663156e29f68585600160009061102f614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b8152600401602060405180830381868061108c61456b565b1580156110a15760008061109e61449a565b50505b505a6110ab6145ce565b50505050501580156110ca573d6000803e3d60006110c761449a565b50505b505050506040513d601f19601f820116820180604052508101906110ee9190615212565b6040518463ffffffff1660e01b815260040161110c939291906156a5565b6020604051808303816000878061112161456b565b1580156111365760008061113361449a565b50505b505a611140614790565b505050505050158015611160573d6000803e3d600061115d61449a565b50505b505050506040513d601f19601f820116820180604052508101906111849190615212565b9050808473ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15856040516111cd91906157b9565b60405180910390a361132060056000906111e5614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd5a611226614733565b5a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b604081101561127f57600081830152602081019050611265565b505050876040518463ffffffff1660e01b81526004016112a193929190615585565b602060405180830381600087806112b661456b565b1580156112cb576000806112c861449a565b50505b505a6112d5614790565b5050505050501580156112f5573d6000803e3d60006112f261449a565b50505b505050506040513d601f19601f820116820180604052508101906113199190614ff6565b6000614038565b8091505092915050565b6008600090611337614508565b906101000a900460ff161561138a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113789061575e565b6040518091039061138761449a565b50505b876000806101000a8161139b614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906113d76146ce565b50505086600160006101000a816113ec614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114286146ce565b50505085600260006101000a8161143d614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114796146ce565b50505083600360006101000a8161148e614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906114ca6146ce565b50505084600460006101000a816114df614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061151b6146ce565b50505082600560006101000a81611530614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061156c6146ce565b50505081600660006101000a81611581614508565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906115bd6146ce565b5050506015808111156115cc57fe5b815114611617576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116059061577e565b6040518091039061161461449a565b50505b60005b815181101561166b5781818151811061162f57fe5b602002602001015160076000838152602001908152602001600020908051906020019061165d9291906148b8565b50808060010191505061161a565b506001600860006101000a8161167f614508565b8160ff021916908315150217906116946146ce565b5050505050505050505050565b600060026000906116b0614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161170591906157b9565b606060405180830381868061171861456b565b15801561172d5760008061172a61449a565b50505b505a6117376145ce565b5050505050158015611756573d6000803e3d600061175361449a565b50505b505050506040513d601f19601f8201168201806040525081019061177a9190615136565b905061178f6000826040015114156003614038565b6117bb600060106000846040015181526020019081526020016000206117b3614508565b146004614038565b60026000906117c8614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b5a611809614733565b8460006040518463ffffffff1660e01b815260040161182a939291906155e5565b6000604051808303816000878061183f61456b565b1580156118545760008061185161449a565b50505b505a61185e614790565b50505050505015801561187e573d6000803e3d600061187b61449a565b50505b505050506000816020015114156118c3576118af8160000151600c6118a1614508565b61416490919063ffffffff16565b600c81906118bb6146ce565b505050611923565b6119136118fb60106000846020015181526020019081526020016000206118e8614508565b836000015161400290919063ffffffff16565b600c611905614508565b61416490919063ffffffff16565b600c819061191f6146ce565b5050505b817f74e46e4569fdcca3333564a0997a08b4607c2af89cd8477813db852c9f364b61600c61194f614508565b60405161195c91906157b9565b60405180910390a25050565b60006001600090611977614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806119d461456b565b1580156119e9576000806119e661449a565b50505b505a6119f36145ce565b5050505050158015611a12573d6000803e3d6000611a0f61449a565b50505b505050506040513d601f19601f82011682018060405250810190611a369190615212565b9050611b1760006001600090611a4a614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b81526004016000604051808303818680611aa761456b565b158015611abc57600080611ab961449a565b50505b505a611ac66145ce565b5050505050158015611ae5573d6000803e3d6000611ae261449a565b50505b505050506040513d6000823e3d601f19601f82011682018060405250810190611b0e9190614fa3565b51146006614038565b611b3f600060106000848152602001908152602001600020611b37614508565b146007614038565b611c7e60006006600090611b51614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015611be257600081830152602081019050611bc8565b5050506040518263ffffffff1660e01b8152600401611c01919061556a565b6020604051808303818680611c1461456b565b158015611c2957600080611c2661449a565b50505b505a611c336145ce565b5050505050158015611c52573d6000803e3d6000611c4f61449a565b50505b505050506040513d601f19601f82011682018060405250810190611c769190615212565b146008614038565b611d5760006004600090611c90614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663759d4d596040518163ffffffff1660e01b81526004016020604051808303818680611ced61456b565b158015611d0257600080611cff61449a565b50505b505a611d0c6145ce565b5050505050158015611d2b573d6000803e3d6000611d2861449a565b50505b505050506040513d601f19601f82011682018060405250810190611d4f9190615104565b146009614038565b6000611d6161041c565b905080601060008481526020019081526020016000208190611d816146ce565b505050611dbb611da382600c611d95614508565b61413790919063ffffffff16565b600b611dad614508565b6140a690919063ffffffff16565b600b8190611dc76146ce565b5050507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b611e0782600c611df9614508565b61413790919063ffffffff16565b600b611e11614508565b604051611e1f9291906157d4565b60405180910390a1611e4c600c611e34614508565b600e611e3e614508565b61416490919063ffffffff16565b600e8190611e586146ce565b5050506000600c8190611e696146ce565b505050817fff9d41e1547acb5eda1e3bac0c795f57760c96016cdd641af6bdd90270a768f382600b611e99614508565b600e611ea3614508565b604051611eb2939291906157fd565b60405180910390a25050565b611edb6001600f611ecd614508565b6140a690919063ffffffff16565b600f8190611ee76146ce565b5050506000600f611ef6614508565b905060006006600090611f07614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015611f9857600081830152602081019050611f7e565b5050506040518263ffffffff1660e01b8152600401611fb7919061556a565b6020604051808303818680611fca61456b565b158015611fdf57600080611fdc61449a565b50505b505a611fe96145ce565b5050505050158015612008573d6000803e3d600061200561449a565b50505b505050506040513d601f19601f8201168201806040525081019061202c9190615212565b90506000600160009061203d614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b8152600401600060405180830381868061209a61456b565b1580156120af576000806120ac61449a565b50505b505a6120b96145ce565b50505050501580156120d8573d6000803e3d60006120d561449a565b50505b505050506040513d6000823e3d601f19601f820116820180604052508101906121019190614fa3565b51141561211d576000600960010181906121196146ce565b5050505b600960010161212a614508565b81111561237d5760008060009061213f614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f66001600090612184614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006040518363ffffffff1660e01b81526004016121c0929190615653565b60e06040518083038186806121d361456b565b1580156121e8576000806121e561449a565b50505b505a6121f26145ce565b5050505050158015612211573d6000803e3d600061220e61449a565b50505b505050506040513d601f19601f820116820180604052508101906122359190615168565b905060006009600101612246614508565b830390506000826060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f384604001518486602001516040518463ffffffff1660e01b8152600401612295939291906156dc565b602060405180830381600087806122aa61456b565b1580156122bf576000806122bc61449a565b50505b505a6122c9614790565b5050505050501580156122e9573d6000803e3d60006122e661449a565b50505b505050506040513d601f19601f8201168201806040525081019061230d9190615212565b905061231d60008211600b614038565b5a612326614733565b73ffffffffffffffffffffffffffffffffffffffff167f0ba93b4b06f63170434e95713b6e4613651536fe0795f417db31ca847d25e0f2838360405161236d9291906157d4565b60405180910390a25050506127bb565b80600960010161238b614508565b11156127ba5760008060009061239f614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f660016000906123e4614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016040518363ffffffff1660e01b8152600401612420929190615653565b60e060405180830381868061243361456b565b1580156124485760008061244561449a565b50505b505a6124526145ce565b5050505050158015612471573d6000803e3d600061246e61449a565b50505b505050506040513d601f19601f820116820180604052508101906124959190615168565b905060006124ed82600001516124df6124c28560a00151601260ff16600a0a61416490919063ffffffff16565b8660096001016124d0614508565b0361428d90919063ffffffff16565b6142a990919063ffffffff16565b90506000612677600d6124fe614508565b612669600960000161250e614508565b61265b600b61251b614508565b6005600090612528614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b60408110156125b95760008183015260208101905061259f565b5050506040518263ffffffff1660e01b81526004016125d8919061556a565b60206040518083038186806125eb61456b565b158015612600576000806125fd61449a565b50505b505a61260a6145ce565b5050505050158015612629573d6000803e3d600061262661449a565b50505b505050506040513d601f19601f8201168201806040525081019061264d9190615212565b61416490919063ffffffff16565b61416490919063ffffffff16565b61416490919063ffffffff16565b90508082116126865781612688565b805b91506000836060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f385602001518587604001516040518463ffffffff1660e01b81526004016126d5939291906156dc565b602060405180830381600087806126ea61456b565b1580156126ff576000806126fc61449a565b50505b505a612709614790565b505050505050158015612729573d6000803e3d600061272661449a565b50505b505050506040513d601f19601f8201168201806040525081019061274d9190615212565b905061275d60008211600c614038565b5a612766614733565b73ffffffffffffffffffffffffffffffffffffffff167ffe644b4d06ffe999b33590d87654491fea7d9ce296e8d305004cf50ca96e6be184836040516127ad9291906157d4565b60405180910390a2505050505b5b506127d2600f6127c9614508565b82146014614038565b50565b60106020528060005260406000206000915090506127f1614508565b81565b61285e6001600090612804614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612840614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b6000600660009061286d614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b60408110156128fe576000818301526020810190506128e4565b5050506040518263ffffffff1660e01b815260040161291d919061556a565b602060405180830381868061293061456b565b1580156129455760008061294261449a565b50505b505a61294f6145ce565b505050505015801561296e573d6000803e3d600061296b61449a565b50505b505050506040513d601f19601f820116820180604052508101906129929190615212565b9050600080836000015190508260096001016129ac614508565b10612a0a5760008360096001016129c1614508565b0390506129ed6129de87600001518361413790919063ffffffff16565b836140a690919063ffffffff16565b9150612a0281886140a690919063ffffffff16565b925050612a45565b60006009600101612a19614508565b84039050868110612a2d5760009250612a43565b612a40818861416490919063ffffffff16565b92505b505b6000612a8d8660000151612a7f612a708960a00151601260ff16600a0a61416490919063ffffffff16565b8661428d90919063ffffffff16565b6142a990919063ffffffff16565b9050612a9d81831015600e614038565b612abc876009600101612aae614508565b6140a690919063ffffffff16565b60096001018190612acb6146ce565b5050507f88cdc2d9dafaa25ef0f861c37488527fa03d0d30cd7ed982e93c2fd8ed44eeaa876009600101612afd614508565b604051612b0b9291906157d4565b60405180910390a150505050505050565b600980600001612b2a614508565b9080600101612b37614508565b905082565b612ba66001600090612b4c614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612b88614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b6000821415612bcd57600d612bb9614508565b600e8190612bc56146ce565b505050612c57565b612bf6600060106000858152602001908152602001600020612bed614508565b1415600a614038565b612c47612c2f60106000858152602001908152602001600020612c17614508565b600d612c21614508565b61400290919063ffffffff16565b600e612c39614508565b6140a690919063ffffffff16565b600e8190612c536146ce565b5050505b6000600d8190612c656146ce565b50505080827ffd9d17e5565deea3d25918d95fc398673b9445ef0a96d12eaf3ab2b198756c65600e612c95614508565b612ccb60106000888152602001908152602001600020612cb3614508565b600e612cbd614508565b6142a990919063ffffffff16565b604051612cd99291906157d4565b60405180910390a35050565b600d612cef614508565b81565b612d5c6001600090612d02614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612d3e614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b612d796001600f612d6b614508565b6140a690919063ffffffff16565b600f8190612d856146ce565b5050506000600f612d94614508565b9050612da4838310156010614038565b612e8a6005600090612db4614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86866040518363ffffffff1660e01b8152600401612e0b92919061567c565b60206040518083038160008780612e2061456b565b158015612e3557600080612e3261449a565b50505b505a612e3f614790565b505050505050158015612e5f573d6000803e3d6000612e5c61449a565b50505b505050506040513d601f19601f82011682018060405250810190612e839190614ff6565b6000614038565b8373ffffffffffffffffffffffffffffffffffffffff167f72debe083e16f39475584adf69a588657185fbd31e7627daa95ed7dbd45b3cc184604051612ed091906157b9565b60405180910390a2612eee600f612ee5614508565b82146014614038565b50505050565b612f5e6003600090612f04614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a612f40614733565b73ffffffffffffffffffffffffffffffffffffffff16146013614038565b612f7b6001600f612f6d614508565b6140a690919063ffffffff16565b600f8190612f876146ce565b5050506000600f612f96614508565b9050600b612fa2614508565b821115612fb657600b612fb3614508565b91505b612fd282600b612fc4614508565b61416490919063ffffffff16565b600b8190612fde6146ce565b5050506130c76005600090612ff1614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b815260040161304892919061567c565b6020604051808303816000878061305d61456b565b1580156130725760008061306f61449a565b50505b505a61307c614790565b50505050505015801561309c573d6000803e3d600061309961449a565b50505b505050506040513d601f19601f820116820180604052508101906130c09190614ff6565b6000614038565b8273ffffffffffffffffffffffffffffffffffffffff167f10913cbb30d5b8ffef79cb59f0875923e51b1a5a54fb330d0cb2022e6af8d13483600b61310a614508565b6040516131189291906157d4565b60405180910390a2613136600f61312d614508565b82146014614038565b505050565b6131a5600160009061314b614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a613187614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b6131ae816141f0565b50565b61321b60016000906131c1614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6131fd614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b613235600960010161322b614508565b821115600f614038565b613254816009600101613246614508565b61416490919063ffffffff16565b600960010181906132636146ce565b5050507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb9816009600101613295614508565b6040516132a39291906157d4565b60405180910390a150565b61331860016000906132be614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6132fa614733565b73ffffffffffffffffffffffffffffffffffffffff16146012614038565b61332681831115600d614038565b613345826009600001613337614508565b6140a690919063ffffffff16565b600960000181906133546146ce565b5050507fa926f60433937c9b276382ddb5204387c2c70104cbe627db98999c7d706c4196826009600001613386614508565b6040516133949291906157d4565b60405180910390a15050565b60008060026000906133b0614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a846040518263ffffffff1660e01b815260040161340591906157b9565b606060405180830381868061341861456b565b15801561342d5760008061342a61449a565b50505b505a6134376145ce565b5050505050158015613456573d6000803e3d600061345361449a565b50505b505050506040513d601f19601f8201168201806040525081019061347a9190615136565b90506000600160009061348b614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186806134e861456b565b1580156134fd576000806134fa61449a565b50505b505a6135076145ce565b5050505050158015613526573d6000803e3d600061352361449a565b50505b505050506040513d601f19601f8201168201806040525081019061354a9190615212565b905080826020015114156137a1576135788260000151600d61356a614508565b61416490919063ffffffff16565b600d81906135846146ce565b5050506002600090613594614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a6135d5614733565b866040518363ffffffff1660e01b81526004016135f39291906155bc565b6000604051808303816000878061360861456b565b15801561361d5760008061361a61449a565b50505b505a613627614790565b505050505050158015613647573d6000803e3d600061364461449a565b50505b50505050838573ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948460000151600b613693614508565b6040516136a19291906157d4565b60405180910390a361379360056000906136b9614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8785600001516040518363ffffffff1660e01b815260040161371492919061567c565b6020604051808303816000878061372961456b565b15801561373e5760008061373b61449a565b50505b505a613748614790565b505050505050158015613768573d6000803e3d600061376561449a565b50505b505050506040513d601f19601f8201168201806040525081019061378c9190614ff6565b6000614038565b816000015192505050613d23565b6000808360200151146137d25760106000846020015181526020019081526020016000206137cd614508565b6137dc565b670de0b6b3a76400005b90506000601060008481526020019081526020016000206137fb614508565b905060008460400151148015613812575060008114155b15613a8057600061383083866000015161400290919063ffffffff16565b905061384e81600e613840614508565b61416490919063ffffffff16565b600e819061385a6146ce565b505050613870828261413790919063ffffffff16565b9550600260009061387f614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a6138c0614733565b896040518363ffffffff1660e01b81526004016138de9291906155bc565b600060405180830381600087806138f361456b565b1580156139085760008061390561449a565b50505b505a613912614790565b505050505050158015613932573d6000803e3d600061392f61449a565b50505b50505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b61397a614508565b6040516139889291906157d4565b60405180910390a3613a7660056000906139a0614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b81526004016139f792919061567c565b60206040518083038160008780613a0c61456b565b158015613a2157600080613a1e61449a565b50505b505a613a2b614790565b505050505050158015613a4b573d6000803e3d6000613a4861449a565b50505b505050506040513d601f19601f82011682018060405250810190613a6f9190614ff6565b6000614038565b5050505050613d23565b60006010600086604001518152602001908152602001600020613aa1614508565b9050613ac36000866040015114158015613abc575060008214155b6005614038565b613aec83613ade83886000015161413790919063ffffffff16565b61400290919063ffffffff16565b95506002600090613afb614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac5a613b3c614733565b896040518363ffffffff1660e01b8152600401613b5a9291906155bc565b60006040518083038160008780613b6f61456b565b158015613b8457600080613b8161449a565b50505b505a613b8e614790565b505050505050158015613bae573d6000803e3d6000613bab61449a565b50505b50505050613bce86600b613bc0614508565b61416490919063ffffffff16565b600b8190613bda6146ce565b505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b613c21614508565b604051613c2f9291906157d4565b60405180910390a3613d1d6005600090613c47614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b8152600401613c9e92919061567c565b60206040518083038160008780613cb361456b565b158015613cc857600080613cc561449a565b50505b505a613cd2614790565b505050505050158015613cf2573d6000803e3d6000613cef61449a565b50505b505050506040513d601f19601f82011682018060405250810190613d169190614ff6565b6000614038565b50505050505b92915050565b6000613ffa600d613d38614508565b613fec600b613d45614508565b613fde86613fd0613e908a6006600090613d5d614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015613dee57600081830152602081019050613dd4565b5050506040518263ffffffff1660e01b8152600401613e0d919061556a565b6020604051808303818680613e2061456b565b158015613e3557600080613e3261449a565b50505b505a613e3f6145ce565b5050505050158015613e5e573d6000803e3d6000613e5b61449a565b50505b505050506040513d601f19601f82011682018060405250810190613e829190615212565b61413790919063ffffffff16565b6005600090613e9d614508565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a082315a63996d79a5598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051925060005b6040811015613f2e57600081830152602081019050613f14565b5050506040518263ffffffff1660e01b8152600401613f4d919061556a565b6020604051808303818680613f6061456b565b158015613f7557600080613f7261449a565b50505b505a613f7f6145ce565b5050505050158015613f9e573d6000803e3d6000613f9b61449a565b50505b505050506040513d601f19601f82011682018060405250810190613fc29190615212565b6140a690919063ffffffff16565b6140a690919063ffffffff16565b61416490919063ffffffff16565b61416490919063ffffffff16565b905092915050565b600061403082614022601260ff16600a0a866142c590919063ffffffff16565b61435490919063ffffffff16565b905092915050565b816007600083601581111561404957fe5b8152602001908152602001600020906140a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408f919061573c565b6040518091039061409e61449a565b50505b505050565b60008082840190508381101561412d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f7700000000008152506020019150506040518091039061412a61449a565b50505b8091505092915050565b6000601260ff16600a0a61415483856142c590919063ffffffff16565b8161415b57fe5b04905092915050565b6000828211156141e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250602001915050604051809103906141e261449a565b50505b818303905092915050565b60096000016141fd614508565b811115614214576009600001614211614508565b90505b614233816009600001614225614508565b61416490919063ffffffff16565b600960000181906142426146ce565b5050507f21035560539b4b4540708d4273620b634b00bda210e30692ec878ef00741cbc1816009600001614274614508565b6040516142829291906157d4565b60405180910390a150565b60006142a18383601260ff16600a0a6143e6565b905092915050565b60006142bd8383601260ff16600a0a614441565b905092915050565b6000808314156142d8576000905061434e565b60008284029050828482816142e957fe5b0414614349576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c56602191396040019150506040518091039061434661449a565b50505b809150505b92915050565b60008082116143d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250602001915050604051809103906143d161449a565b50505b8183816143dd57fe5b04905092915050565b60008061441184614403600a8602886142c590919063ffffffff16565b61435490919063ffffffff16565b90506005600a828161441f57fe5b061061442c57600a810190505b600a818161443657fe5b049150509392505050565b600080600a838161444e57fe5b0461446285876142c590919063ffffffff16565b8161446957fe5b0490506005600a828161447857fe5b061061448557600a810190505b600a818161448f57fe5b049150509392505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b868110156144d55780860151816040840101526020810190506144b7565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b60408110156145665760008183015260208101905061454c565b505050565b638435035b598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b60408110156145c9576000818301526020810190506145af565b505050565b638540661f598160e01b815261460d565b6000819050818311156145f0578290505b92915050565b600081905081831015614607578290505b92915050565b836004820152846024820152606060448201528660648201526084810160005b8881101561464857808801518183015260208101905061462d565b506060828960a40184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b815160408301513d6000853e8b8b82606087013350600060045af1505961469d8d3d6145f6565b8c016146a981876145df565b5b828110156146c157600081526020810190506146aa565b50839d5050505050505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b60005b604081101561472e57600081830152602081019050614714565b505050565b6373509064598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b604081101561478b57600081830152602081019050614771565b505050565b6385979f76598160e01b81526147cf565b6000819050818311156147b2578290505b92915050565b6000819050818310156147c9578290505b92915050565b836004820152846024820152606060448201528760648201526084810160005b8981101561480a5780890151818301526020810190506147ef565b506060828a60a40184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b815160408301513d6000853e8c8c82606087013350600060045af1505961485f8e3d6147b8565b8d0161486b81876147a1565b5b82811015614883576000815260208101905061486c565b50839e5050505050505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b82806148c2614508565b600181600116156101000203166002900490600052602060002090601f0160209004810192826148fe576000856148f76146ce565b5050614960565b82601f1061492057805160ff191683800117856149196146ce565b5050614960565b8280016001018561492f6146ce565b50508215614960579182015b8281111561495f5782518261494e6146ce565b50509160200191906001019061493b565b5b50905061496d9190614971565b5090565b5b80821115614993576000816000906149886146ce565b505050600101614972565b5090565b60006149aa6149a584615865565b615834565b9050808382526020820190508260005b858110156149ea57813585016149d08882614c51565b8452602084019350602083019250506001810190506149ba565b5050509392505050565b6000614a07614a0284615891565b615834565b90508083825260208201905082856020860282011115614a2f57600080614a2c61449a565b50505b60005b85811015614a5f5781614a458882614ef1565b845260208401935060208301925050600181019050614a32565b5050509392505050565b6000614a7c614a77846158bd565b615834565b905082815260208101848484011115614a9d57600080614a9a61449a565b50505b614aa8848285615a90565b509392505050565b600081359050614abf81615ab5565b92915050565b600082601f830112614adf57600080614adc61449a565b50505b8135614aef848260208601614997565b91505092915050565b600082601f830112614b1257600080614b0f61449a565b50505b8151614b228482602086016149f4565b91505092915050565b600081519050614b3a81615ad5565b92915050565b600081359050614b4f81615af5565b92915050565b600081519050614b6481615af5565b92915050565b600081359050614b7981615b15565b92915050565b600081519050614b8e81615b15565b92915050565b600081359050614ba381615b35565b92915050565b600081359050614bb881615b55565b92915050565b600081359050614bcd81615b75565b92915050565b600081359050614be281615b95565b92915050565b600081359050614bf781615bb5565b92915050565b600081359050614c0c81615bd5565b92915050565b600081359050614c2181615bf5565b92915050565b600081519050614c3681615bf5565b92915050565b600081519050614c4b81615c15565b92915050565b600082601f830112614c6b57600080614c6861449a565b50505b8135614c7b848260208601614a69565b91505092915050565b600060608284031215614c9f57600080614c9c61449a565b50505b614ca96060615834565b90506000614cb984828501614ef1565b6000830152506020614ccd84828501614ef1565b6020830152506040614ce184828501614ef1565b60408301525092915050565b600060e08284031215614d0857600080614d0561449a565b50505b614d1260e0615834565b90506000614d2284828501614edc565b6000830152506020614d3684828501614b40565b6020830152506040614d4a84828501614b40565b6040830152506060614d5e84828501614c12565b6060830152506080614d7284828501614b6a565b60808301525060a0614d8684828501614edc565b60a08301525060c0614d9a84828501614edc565b60c08301525092915050565b600060e08284031215614dc157600080614dbe61449a565b50505b614dcb60e0615834565b90506000614ddb84828501614ef1565b6000830152506020614def84828501614b55565b6020830152506040614e0384828501614b55565b6040830152506060614e1784828501614c27565b6060830152506080614e2b84828501614b7f565b60808301525060a0614e3f84828501614ef1565b60a08301525060c0614e5384828501614ef1565b60c08301525092915050565b600060808284031215614e7a57600080614e7761449a565b50505b614e846080615834565b90506000614e9484828501614edc565b6000830152506020614ea884828501614edc565b6020830152506040614ebc84828501614edc565b6040830152506060614ed084828501614edc565b60608301525092915050565b600081359050614eeb81615c35565b92915050565b600081519050614f0081615c35565b92915050565b60008060408385031215614f2257600080614f1f61449a565b50505b6000614f3085828601614ab0565b9250506020614f4185828601614edc565b9150509250929050565b600080600060608486031215614f6957600080614f6661449a565b50505b6000614f7786828701614ab0565b9350506020614f8886828701614edc565b9250506040614f9986828701614edc565b9150509250925092565b600060208284031215614fbe57600080614fbb61449a565b50505b600082015167ffffffffffffffff811115614fe157600080614fde61449a565b50505b614fed84828501614af8565b91505092915050565b6000602082840312156150115760008061500e61449a565b50505b600061501f84828501614b2b565b91505092915050565b600080600080600080600080610100898b03121561504e5760008061504b61449a565b50505b600061505c8b828c01614bbe565b985050602061506d8b828c01614bd3565b975050604061507e8b828c01614ba9565b965050606061508f8b828c01614be8565b95505060806150a08b828c01614bfd565b94505060a06150b18b828c01614b94565b93505060c06150c28b828c01614b94565b92505060e089013567ffffffffffffffff8111156150e8576000806150e561449a565b50505b6150f48b828c01614ac5565b9150509295985092959890939650565b60006020828403121561511f5760008061511c61449a565b50505b600061512d84828501614c3c565b91505092915050565b6000606082840312156151515760008061514e61449a565b50505b600061515f84828501614c84565b91505092915050565b600060e082840312156151835760008061518061449a565b50505b600061519184828501614da6565b91505092915050565b60008061010083850312156151b7576000806151b461449a565b50505b60006151c585828601614ced565b92505060e06151d685828601614edc565b9150509250929050565b6000602082840312156151fb576000806151f861449a565b50505b600061520984828501614edc565b91505092915050565b60006020828403121561522d5760008061522a61449a565b50505b600061523b84828501614ef1565b91505092915050565b600080604083850312156152605760008061525d61449a565b50505b600061526e85828601614edc565b925050602061527f85828601614b6a565b9150509250929050565b600080600061018084860312156152a8576000806152a561449a565b50505b60006152b686828701614edc565b93505060206152c786828701614ced565b9250506101006152d986828701614e5f565b9150509250925092565b600080604083850312156152ff576000806152fc61449a565b50505b600061530d85828601614edc565b925050602061531e85828601614edc565b9150509250929050565b6000806000606084860312156153465760008061534361449a565b50505b600061535486828701614edc565b935050602061536586828701614edc565b925050604061537686828701614edc565b9150509250925092565b61538981615a12565b82525050565b61539881615913565b82525050565b6153a781615931565b82525050565b6153b681615a24565b82525050565b6153c581615a48565b82525050565b6153d481615a5a565b82525050565b6000816153e5614508565b60018116600081146153fe57600181146154245761546f565b607f600283041661540f8187615902565b955060ff19831686526020860193505061546f565b600282046154328187615902565b955061543d856158ed565b60005b828110156154665781615451614508565b81890152600182019150602081019050615440565b80880195505050505b505092915050565b6000615484601383615902565b91507f616c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b60006154c4600f83615902565b91507f6572726f72206d736720636f756e7400000000000000000000000000000000006000830152602082019050919050565b60808201600082015161550d600085018261554c565b506020820151615520602085018261554c565b506040820151615533604085018261554c565b506060820151615546606085018261554c565b50505050565b61555581615a08565b82525050565b61556481615a08565b82525050565b600060208201905061557f600083018461538f565b92915050565b600060608201905061559a6000830186615380565b6155a7602083018561538f565b6155b4604083018461555b565b949350505050565b60006040820190506155d16000830185615380565b6155de602083018461555b565b9392505050565b60006060820190506155fa6000830186615380565b615607602083018561555b565b61561460408301846153cb565b949350505050565b60006060820190506156316000830186615380565b61563e602083018561555b565b61564b604083018461555b565b949350505050565b6000604082019050615668600083018561538f565b61567560208301846153bc565b9392505050565b6000604082019050615691600083018561538f565b61569e602083018461555b565b9392505050565b60006060820190506156ba600083018661538f565b6156c7602083018561555b565b6156d4604083018461555b565b949350505050565b60006060820190506156f1600083018661539e565b6156fe602083018561555b565b61570b604083018461539e565b949350505050565b600060408201905061572860008301856153ad565b615735602083018461555b565b9392505050565b6000602082019050818103600083015261575681846153da565b905092915050565b6000602082019050818103600083015261577781615477565b9050919050565b60006020820190508181036000830152615797816154b7565b9050919050565b60006080820190506157b360008301846154f7565b92915050565b60006020820190506157ce600083018461555b565b92915050565b60006040820190506157e9600083018561555b565b6157f6602083018461555b565b9392505050565b6000606082019050615812600083018661555b565b61581f602083018561555b565b61582c604083018461555b565b949350505050565b6000604051905081810181811067ffffffffffffffff8211171561585b5761585a615a9f565b5b8060405250919050565b600067ffffffffffffffff8211156158805761587f615a9f565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156158ac576158ab615a9f565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156158d8576158d7615a9f565b5b601f19601f8301169050602081019050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600061591e826159e8565b9050919050565b60008115159050919050565b6000819050919050565b600061594682615913565b9050919050565b600061595882615913565b9050919050565b600061596a82615913565b9050919050565b600061597c82615913565b9050919050565b600061598e82615913565b9050919050565b60006159a082615913565b9050919050565b60006159b282615913565b9050919050565b60006159c482615913565b9050919050565b60008190506159d982615aa1565b919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000615a1d82615a6c565b9050919050565b6000615a2f82615a36565b9050919050565b6000615a41826159e8565b9050919050565b6000615a53826159cb565b9050919050565b6000615a6582615a08565b9050919050565b6000615a7782615a7e565b9050919050565b6000615a89826159e8565b9050919050565b82818337600083830152505050565bfe5b60038110615ab257615ab1615a9f565b5b50565b615abe81615913565b8114615ad257600080615acf61449a565b50505b50565b615ade81615925565b8114615af257600080615aef61449a565b50505b50565b615afe81615931565b8114615b1257600080615b0f61449a565b50505b50565b615b1e8161593b565b8114615b3257600080615b2f61449a565b50505b50565b615b3e8161594d565b8114615b5257600080615b4f61449a565b50505b50565b615b5e8161595f565b8114615b7257600080615b6f61449a565b50505b50565b615b7e81615971565b8114615b9257600080615b8f61449a565b50505b50565b615b9e81615983565b8114615bb257600080615baf61449a565b50505b50565b615bbe81615995565b8114615bd257600080615bcf61449a565b50505b50565b615bde816159a7565b8114615bf257600080615bef61449a565b50505b50565b615bfe816159b9565b8114615c1257600080615c0f61449a565b50505b50565b615c1e816159de565b8114615c3257600080615c2f61449a565b50505b50565b615c3e81615a08565b8114615c5257600080615c4f61449a565b50505b5056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c8063a00dad22116100b8578063d1201e311161007c578063d1201e311461033a578063db32232f14610356578063dc62c58114610372578063f238ff5c1461038e578063f3fef3a3146103aa578063fc395668146103da57610142565b8063a00dad22146102a9578063b952cc4a146102c5578063c3964372146102e4578063c677c58a14610300578063c9061b581461031e57610142565b806347e7ef241161010a57806347e7ef24146101fd57806354d269af1461022d578063699ba87b14610249578063749aa2d9146102655780637e8b3f891461026f57806390a80ece1461027957610142565b8063159317d0146101475780631ebcfe801461016557806321af3525146101815780633f2f757d146101b15780633f6b5019146101e1575b600080fd5b61014f61040a565b60405161015c91906144d3565b60405180910390f35b61017f600480360381019061017a9190613f3e565b6105dc565b005b61019b60048036038101906101969190613f01565b6108c0565b6040516101a891906144d3565b60405180910390f35b6101cb60048036038101906101c69190613f90565b610a98565b6040516101d891906144b8565b60405180910390f35b6101fb60048036038101906101f69190614059565b610c75565b005b61021760048036038101906102129190613cc7565b610d93565b60405161022491906144d3565b60405180910390f35b61024760048036038101906102429190613dbc565b611018565b005b610263600480360381019061025e9190613f3e565b6112f6565b005b61026d611527565b005b61027761190f565b005b610293600480360381019061028e9190613f3e565b611fd2565b6040516102a091906144d3565b60405180910390f35b6102c360048036038101906102be9190613fcc565b611fea565b005b6102cd612250565b6040516102db9291906144ee565b60405180910390f35b6102fe60048036038101906102f9919061401d565b612262565b005b6103086123a9565b60405161031591906144d3565b60405180910390f35b61033860048036038101906103339190613d03565b6123af565b005b610354600480360381019061034f9190613cc7565b612557565b005b610370600480360381019061036b9190613f3e565b61271f565b005b61038c60048036038101906103879190613f3e565b612786565b005b6103a860048036038101906103a3919061401d565b612856565b005b6103c460048036038101906103bf9190613cc7565b612922565b6040516103d191906144d3565b60405180910390f35b6103f460048036038101906103ef919061401d565b6130d3565b60405161040191906144d3565b60405180910390f35b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026040518363ffffffff1660e01b815260040161048b92919061436d565b60e06040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db9190613ed8565b90506000600e5414156104f957670de0b6b3a76400009150506105d9565b60006105bd8260000151600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d856080015186600001516040518363ffffffff1660e01b815260040161056892919061442d565b60206040518083038186803b15801561058057600080fd5b505afa158015610594573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b89190613f67565b6130d3565b90506105d4600e548261329090919063ffffffff16565b925050505b90565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161063991906144d3565b60606040518083038186803b15801561065157600080fd5b505afa158015610665573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106899190613eaf565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f557600080fd5b505afa158015610709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072d9190613f67565b9050610741600083604001511460016132c6565b6107768183602001511415801561076f57506000601060008560400151815260200190815260200160002054145b60026132c6565b6000826020015114156107a75761079c8260000151600c5461332b90919063ffffffff16565b600c819055506107f0565b6107e96107d8601060008560200151815260200190815260200160002054846000015161329090919063ffffffff16565b600c5461332b90919063ffffffff16565b600c819055505b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b3385846040518463ffffffff1660e01b815260040161084f93929190614336565b600060405180830381600087803b15801561086957600080fd5b505af115801561087d573d6000803e3d6000fd5b50505050827fa030de897a3fbcd98618ebb6d64981072317ade7083ad8702bbcd0b867a5063e600c546040516108b391906144d3565b60405180910390a2505050565b600061091d600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460116132c6565b6109336001600f5461332b90919063ffffffff16565b600f819055506000600f549050600061095485600001518660800151610a98565b90506000816040015190508481101561096b578094505b610a46600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886040518363ffffffff1660e01b81526004016109ed929190614396565b602060405180830381600087803b158015610a0757600080fd5b505af1158015610a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3f9190613d93565b60006132c6565b7f78139c2f5eabfad75a88b7c1fe1d1e3851b441e2c5a7f792f95d8e1c6b9c636085604051610a7591906144d3565b60405180910390a18493505050610a91600f54821460146132c6565b5092915050565b610aa06136d6565b610aa86136d6565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cbb7429d84866040518363ffffffff1660e01b8152600401610b0592919061442d565b60206040518083038186803b158015610b1d57600080fd5b505afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613f67565b816060018181525050610b8d610b79856009600101546133b390919063ffffffff16565b60096000015461332b90919063ffffffff16565b8160200181815250506000610ba68583606001516130d3565b9050600060036002830281610bb757fe5b0490506000610bcf82846133e090919063ffffffff16565b90508184602001511115610bfe5783602001519150610bf782846133e090919063ffffffff16565b9050610c28565b8084606001511115610c275783606001519050610c2481846133e090919063ffffffff16565b91505b5b610c3f8460600151826133e090919063ffffffff16565b846040018181525050610c5f8460200151836133e090919063ffffffff16565b8460000181815250508394505050505092915050565b610cd0600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b610cd983613463565b610cee82600b5461332b90919063ffffffff16565b600b819055507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b82600b54604051610d279291906144ee565b60405180910390a1610d47816009600101546133e090919063ffffffff16565b6009600101819055507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb981600960010154604051610d869291906144ee565b60405180910390a1505050565b6000610daa82600d5461332b90919063ffffffff16565b600d819055506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663156e29f68585600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5a57600080fd5b505afa158015610e6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e929190613f67565b6040518463ffffffff1660e01b8152600401610eb0939291906143bf565b602060405180830381600087803b158015610eca57600080fd5b505af1158015610ede573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f029190613f67565b9050808473ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a1585604051610f4b91906144d3565b60405180910390a361100e600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330876040518463ffffffff1660e01b8152600401610fb59392919061429f565b602060405180830381600087803b158015610fcf57600080fd5b505af1158015610fe3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110079190613d93565b60006132c6565b8091505092915050565b600860009054906101000a900460ff1615611068576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105f90614478565b60405180910390fd5b876000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060158081111561123a57fe5b81511461127c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127390614498565b60405180910390fd5b60005b81518110156112d05781818151811061129457fe5b60200260200101516007600083815260200190815260200160002090805190602001906112c29291906136fe565b50808060010191505061127f565b506001600860006101000a81548160ff0219169083151502179055505050505050505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a836040518263ffffffff1660e01b815260040161135391906144d3565b60606040518083038186803b15801561136b57600080fd5b505afa15801561137f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a39190613eaf565b90506113b860008260400151141560036132c6565b6113dd60006010600084604001518152602001908152602001600020541460046132c6565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638fbf3f4b338460006040518463ffffffff1660e01b815260040161143d939291906142ff565b600060405180830381600087803b15801561145757600080fd5b505af115801561146b573d6000803e3d6000fd5b505050506000816020015114156114a0576114958160000151600c546133e090919063ffffffff16565b600c819055506114e9565b6114e26114d1601060008460200151815260200190815260200160002054836000015161329090919063ffffffff16565b600c546133e090919063ffffffff16565b600c819055505b817f74e46e4569fdcca3333564a0997a08b4607c2af89cd8477813db852c9f364b61600c5460405161151b91906144d3565b60405180910390a25050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561159157600080fd5b505afa1580156115a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c99190613f67565b905061167e6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561163857600080fd5b505afa15801561164c573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116759190613d52565b511460066132c6565b61169f600060106000848152602001908152602001600020541460076132c6565b6117576000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016116ff9190614284565b60206040518083038186803b15801561171757600080fd5b505afa15801561172b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061174f9190613f67565b1460086132c6565b6118046000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663759d4d596040518163ffffffff1660e01b815260040160206040518083038186803b1580156117c457600080fd5b505afa1580156117d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fc9190613e86565b1460096132c6565b600061180e61040a565b905080601060008481526020019081526020016000208190555061185161184082600c546133b390919063ffffffff16565b600b5461332b90919063ffffffff16565b600b819055507f26fdd62e661c6437a27feaa8bcd05f1567dba4aa031bc1c15e5243d472969d9b61188d82600c546133b390919063ffffffff16565b600b5460405161189e9291906144ee565b60405180910390a16118bd600c54600e546133e090919063ffffffff16565b600e819055506000600c81905550817fff9d41e1547acb5eda1e3bac0c795f57760c96016cdd641af6bdd90270a768f382600b54600e5460405161190393929190614517565b60405180910390a25050565b6119256001600f5461332b90919063ffffffff16565b600f819055506000600f5490506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161198f9190614284565b60206040518083038186803b1580156119a757600080fd5b505afa1580156119bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119df9190613f67565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637e7088eb6040518163ffffffff1660e01b815260040160006040518083038186803b158015611a4b57600080fd5b505afa158015611a5f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a889190613d52565b511415611a9b5760006009600101819055505b600960010154811115611c8c5760008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660006040518363ffffffff1660e01b8152600401611b2992919061436d565b60e06040518083038186803b158015611b4157600080fd5b505afa158015611b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b799190613ed8565b90506000600960010154830390506000826060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f384604001518486602001516040518463ffffffff1660e01b8152600401611bd2939291906143f6565b602060405180830381600087803b158015611bec57600080fd5b505af1158015611c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c249190613f67565b9050611c3460008211600b6132c6565b3373ffffffffffffffffffffffffffffffffffffffff167f0ba93b4b06f63170434e95713b6e4613651536fe0795f417db31ca847d25e0f28383604051611c7c9291906144ee565b60405180910390a2505050611fbf565b806009600101541115611fbe5760008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166305b7f2f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016040518363ffffffff1660e01b8152600401611d1a92919061436d565b60e06040518083038186803b158015611d3257600080fd5b505afa158015611d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6a9190613ed8565b90506000611dbb8260000151611dad611d978560a00151601260ff16600a0a6133e090919063ffffffff16565b86600960010154036134db90919063ffffffff16565b6134f790919063ffffffff16565b90506000611ea9600d54611e9b600960000154611e8d600b54600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611e2f9190614284565b60206040518083038186803b158015611e4757600080fd5b505afa158015611e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7f9190613f67565b6133e090919063ffffffff16565b6133e090919063ffffffff16565b6133e090919063ffffffff16565b9050808211611eb85781611eba565b805b91506000836060015173ffffffffffffffffffffffffffffffffffffffff1663ee52a2f385602001518587604001516040518463ffffffff1660e01b8152600401611f07939291906143f6565b602060405180830381600087803b158015611f2157600080fd5b505af1158015611f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f599190613f67565b9050611f6960008211600c6132c6565b3373ffffffffffffffffffffffffffffffffffffffff167ffe644b4d06ffe999b33590d87654491fea7d9ce296e8d305004cf50ca96e6be18483604051611fb19291906144ee565b60405180910390a2505050505b5b50611fcf600f54821460146132c6565b50565b60106020528060005260406000206000915090505481565b612045600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016120a29190614284565b60206040518083038186803b1580156120ba57600080fd5b505afa1580156120ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120f29190613f67565b905060008083600001519050826009600101541061215c5760008360096001015403905061213f6121308760000151836133b390919063ffffffff16565b8361332b90919063ffffffff16565b9150612154818861332b90919063ffffffff16565b925050612190565b600060096001015484039050868110612178576000925061218e565b61218b81886133e090919063ffffffff16565b92505b505b60006121d886600001516121ca6121bb8960a00151601260ff16600a0a6133e090919063ffffffff16565b866134db90919063ffffffff16565b6134f790919063ffffffff16565b90506121e881831015600e6132c6565b6122008760096001015461332b90919063ffffffff16565b6009600101819055507f88cdc2d9dafaa25ef0f861c37488527fa03d0d30cd7ed982e93c2fd8ed44eeaa8760096001015460405161223f9291906144ee565b60405180910390a150505050505050565b60098060000154908060010154905082565b6122bd600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b60008214156122d457600d54600e81905550612339565b6122f6600060106000858152602001908152602001600020541415600a6132c6565b6123326123216010600085815260200190815260200160002054600d5461329090919063ffffffff16565b600e5461332b90919063ffffffff16565b600e819055505b6000600d8190555080827ffd9d17e5565deea3d25918d95fc398673b9445ef0a96d12eaf3ab2b198756c65600e5461238f6010600088815260200190815260200160002054600e546134f790919063ffffffff16565b60405161239d9291906144ee565b60405180910390a35050565b600d5481565b61240a600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b6124206001600f5461332b90919063ffffffff16565b600f819055506000600f54905061243b8383101560106132c6565b6124f4600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb86866040518363ffffffff1660e01b815260040161249b929190614396565b602060405180830381600087803b1580156124b557600080fd5b505af11580156124c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ed9190613d93565b60006132c6565b8373ffffffffffffffffffffffffffffffffffffffff167f72debe083e16f39475584adf69a588657185fbd31e7627daa95ed7dbd45b3cc18460405161253a91906144d3565b60405180910390a2612551600f54821460146132c6565b50505050565b6125b2600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460136132c6565b6125c86001600f5461332b90919063ffffffff16565b600f819055506000600f549050600b548211156125e557600b5491505b6125fa82600b546133e090919063ffffffff16565b600b819055506126b9600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040518363ffffffff1660e01b8152600401612660929190614396565b602060405180830381600087803b15801561267a57600080fd5b505af115801561268e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b29190613d93565b60006132c6565b8273ffffffffffffffffffffffffffffffffffffffff167f10913cbb30d5b8ffef79cb59f0875923e51b1a5a54fb330d0cb2022e6af8d13483600b546040516127039291906144ee565b60405180910390a261271a600f54821460146132c6565b505050565b61277a600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b61278381613463565b50565b6127e1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b6127f4600960010154821115600f6132c6565b61280c816009600101546133e090919063ffffffff16565b6009600101819055507f5b5eb4c315d078b7384bec63e32d19bebdac730f44483dc358bd9085aa20ffb98160096001015460405161284b9291906144ee565b60405180910390a150565b6128b1600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161460126132c6565b6128bf81831115600d6132c6565b6128d78260096000015461332b90919063ffffffff16565b6009600001819055507fa926f60433937c9b276382ddb5204387c2c70104cbe627db98999c7d706c4196826009600001546040516129169291906144ee565b60405180910390a15050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638024818a846040518263ffffffff1660e01b815260040161298091906144d3565b60606040518083038186803b15801561299857600080fd5b505afa1580156129ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129d09190613eaf565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb6534f6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3c57600080fd5b505afa158015612a50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a749190613f67565b90508082602001511415612c5257612a9b8260000151600d546133e090919063ffffffff16565b600d81905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33866040518363ffffffff1660e01b8152600401612afe9291906142d6565b600060405180830381600087803b158015612b1857600080fd5b505af1158015612b2c573d6000803e3d6000fd5b50505050838573ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca948460000151600b54604051612b7f9291906144ee565b60405180910390a3612c44600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8785600001516040518363ffffffff1660e01b8152600401612beb929190614396565b602060405180830381600087803b158015612c0557600080fd5b505af1158015612c19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3d9190613d93565b60006132c6565b8160000151925050506130cd565b600080836020015114612c7c57601060008460200151815260200190815260200160002054612c86565b670de0b6b3a76400005b905060006010600084815260200190815260200160002054905060008460400151148015612cb5575060008114155b15612eaa576000612cd383866000015161329090919063ffffffff16565b9050612cea81600e546133e090919063ffffffff16565b600e81905550612d0382826133b390919063ffffffff16565b9550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33896040518363ffffffff1660e01b8152600401612d629291906142d6565b600060405180830381600087803b158015612d7c57600080fd5b505af1158015612d90573d6000803e3d6000fd5b50505050868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b54604051612ddf9291906144ee565b60405180910390a3612ea0600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b8152600401612e47929190614396565b602060405180830381600087803b158015612e6157600080fd5b505af1158015612e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e999190613d93565b60006132c6565b50505050506130cd565b60006010600086604001518152602001908152602001600020549050612ee66000866040015114158015612edf575060008214155b60056132c6565b612f0f83612f018388600001516133b390919063ffffffff16565b61329090919063ffffffff16565b9550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639dc29fac33896040518363ffffffff1660e01b8152600401612f6e9291906142d6565b600060405180830381600087803b158015612f8857600080fd5b505af1158015612f9c573d6000803e3d6000fd5b50505050612fb586600b546133e090919063ffffffff16565b600b81905550868873ffffffffffffffffffffffffffffffffffffffff167f02f25270a4d87bea75db541cdfe559334a275b4a233520ed6c0a2429667cca9488600b546040516130069291906144ee565b60405180910390a36130c7600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff1660e01b815260040161306e929190614396565b602060405180830381600087803b15801561308857600080fd5b505af115801561309c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c09190613d93565b60006132c6565b50505050505b92915050565b6000613288600d5461327a600b5461326c8661325e6131a58a600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016131479190614284565b60206040518083038186803b15801561315f57600080fd5b505afa158015613173573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131979190613f67565b6133b390919063ffffffff16565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016132009190614284565b60206040518083038186803b15801561321857600080fd5b505afa15801561322c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132509190613f67565b61332b90919063ffffffff16565b61332b90919063ffffffff16565b6133e090919063ffffffff16565b6133e090919063ffffffff16565b905092915050565b60006132be826132b0601260ff16600a0a8661351390919063ffffffff16565b61359990919063ffffffff16565b905092915050565b81600760008360158111156132d757fe5b815260200190815260200160002090613326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161331d9190614456565b60405180910390fd5b505050565b6000808284019050838110156133a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000601260ff16600a0a6133d0838561351390919063ffffffff16565b816133d757fe5b04905092915050565b600082821115613458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b6009600001548111156134795760096000015490505b613491816009600001546133e090919063ffffffff16565b6009600001819055507f21035560539b4b4540708d4273620b634b00bda210e30692ec878ef00741cbc1816009600001546040516134d09291906144ee565b60405180910390a150565b60006134ef8383601260ff16600a0a613622565b905092915050565b600061350b8383601260ff16600a0a61367d565b905092915050565b6000808314156135265760009050613593565b600082840290508284828161353757fe5b041461358e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806148fb6021913960400191505060405180910390fd5b809150505b92915050565b6000808211613610576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b81838161361957fe5b04905092915050565b60008061364d8461363f600a86028861351390919063ffffffff16565b61359990919063ffffffff16565b90506005600a828161365b57fe5b061061366857600a810190505b600a818161367257fe5b049150509392505050565b600080600a838161368a57fe5b0461369e858761351390919063ffffffff16565b816136a557fe5b0490506005600a82816136b457fe5b06106136c157600a810190505b600a81816136cb57fe5b049150509392505050565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282613734576000855561377b565b82601f1061374d57805160ff191683800117855561377b565b8280016001018555821561377b579182015b8281111561377a57825182559160200191906001019061375f565b5b509050613788919061378c565b5090565b5b808211156137a557600081600090555060010161378d565b5090565b60006137bc6137b78461457f565b61454e565b9050808382526020820190508260005b858110156137fc57813585016137e28882613a3f565b8452602084019350602083019250506001810190506137cc565b5050509392505050565b6000613819613814846145ab565b61454e565b9050808382526020820190508285602086028201111561383857600080fd5b60005b85811015613868578161384e8882613cb2565b84526020840193506020830192505060018101905061383b565b5050509392505050565b6000613885613880846145d7565b61454e565b90508281526020810184848401111561389d57600080fd5b6138a88482856147aa565b509392505050565b6000813590506138bf816147cf565b92915050565b600082601f8301126138d657600080fd5b81356138e68482602086016137a9565b91505092915050565b600082601f83011261390057600080fd5b8151613910848260208601613806565b91505092915050565b600081519050613928816147e6565b92915050565b60008135905061393d816147fd565b92915050565b600081519050613952816147fd565b92915050565b60008135905061396781614814565b92915050565b60008151905061397c81614814565b92915050565b6000813590506139918161482b565b92915050565b6000813590506139a681614842565b92915050565b6000813590506139bb81614859565b92915050565b6000813590506139d081614870565b92915050565b6000813590506139e581614887565b92915050565b6000813590506139fa8161489e565b92915050565b600081359050613a0f816148b5565b92915050565b600081519050613a24816148b5565b92915050565b600081519050613a39816148cc565b92915050565b600082601f830112613a5057600080fd5b8135613a60848260208601613872565b91505092915050565b600060608284031215613a7b57600080fd5b613a85606061454e565b90506000613a9584828501613cb2565b6000830152506020613aa984828501613cb2565b6020830152506040613abd84828501613cb2565b60408301525092915050565b600060e08284031215613adb57600080fd5b613ae560e061454e565b90506000613af584828501613c9d565b6000830152506020613b098482850161392e565b6020830152506040613b1d8482850161392e565b6040830152506060613b3184828501613a00565b6060830152506080613b4584828501613958565b60808301525060a0613b5984828501613c9d565b60a08301525060c0613b6d84828501613c9d565b60c08301525092915050565b600060e08284031215613b8b57600080fd5b613b9560e061454e565b90506000613ba584828501613cb2565b6000830152506020613bb984828501613943565b6020830152506040613bcd84828501613943565b6040830152506060613be184828501613a15565b6060830152506080613bf58482850161396d565b60808301525060a0613c0984828501613cb2565b60a08301525060c0613c1d84828501613cb2565b60c08301525092915050565b600060808284031215613c3b57600080fd5b613c45608061454e565b90506000613c5584828501613c9d565b6000830152506020613c6984828501613c9d565b6020830152506040613c7d84828501613c9d565b6040830152506060613c9184828501613c9d565b60608301525092915050565b600081359050613cac816148e3565b92915050565b600081519050613cc1816148e3565b92915050565b60008060408385031215613cda57600080fd5b6000613ce8858286016138b0565b9250506020613cf985828601613c9d565b9150509250929050565b600080600060608486031215613d1857600080fd5b6000613d26868287016138b0565b9350506020613d3786828701613c9d565b9250506040613d4886828701613c9d565b9150509250925092565b600060208284031215613d6457600080fd5b600082015167ffffffffffffffff811115613d7e57600080fd5b613d8a848285016138ef565b91505092915050565b600060208284031215613da557600080fd5b6000613db384828501613919565b91505092915050565b600080600080600080600080610100898b031215613dd957600080fd5b6000613de78b828c016139ac565b9850506020613df88b828c016139c1565b9750506040613e098b828c01613997565b9650506060613e1a8b828c016139d6565b9550506080613e2b8b828c016139eb565b94505060a0613e3c8b828c01613982565b93505060c0613e4d8b828c01613982565b92505060e089013567ffffffffffffffff811115613e6a57600080fd5b613e768b828c016138c5565b9150509295985092959890939650565b600060208284031215613e9857600080fd5b6000613ea684828501613a2a565b91505092915050565b600060608284031215613ec157600080fd5b6000613ecf84828501613a69565b91505092915050565b600060e08284031215613eea57600080fd5b6000613ef884828501613b79565b91505092915050565b6000806101008385031215613f1557600080fd5b6000613f2385828601613ac9565b92505060e0613f3485828601613c9d565b9150509250929050565b600060208284031215613f5057600080fd5b6000613f5e84828501613c9d565b91505092915050565b600060208284031215613f7957600080fd5b6000613f8784828501613cb2565b91505092915050565b60008060408385031215613fa357600080fd5b6000613fb185828601613c9d565b9250506020613fc285828601613958565b9150509250929050565b60008060006101808486031215613fe257600080fd5b6000613ff086828701613c9d565b935050602061400186828701613ac9565b92505061010061401386828701613c29565b9150509250925092565b6000806040838503121561403057600080fd5b600061403e85828601613c9d565b925050602061404f85828601613c9d565b9150509250929050565b60008060006060848603121561406e57600080fd5b600061407c86828701613c9d565b935050602061408d86828701613c9d565b925050604061409e86828701613c9d565b9150509250925092565b6140b18161472c565b82525050565b6140c08161462d565b82525050565b6140cf8161464b565b82525050565b6140de8161473e565b82525050565b6140ed81614762565b82525050565b6140fc81614774565b82525050565b60008154600181166000811461411f576001811461414557614189565b607f6002830416614130818761461c565b955060ff198316865260208601935050614189565b60028204614153818761461c565b955061415e85614607565b60005b8281101561418057815481890152600182019150602081019050614161565b80880195505050505b505092915050565b600061419e60138361461c565b91507f616c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b60006141de600f8361461c565b91507f6572726f72206d736720636f756e7400000000000000000000000000000000006000830152602082019050919050565b6080820160008201516142276000850182614266565b50602082015161423a6020850182614266565b50604082015161424d6040850182614266565b5060608201516142606060850182614266565b50505050565b61426f81614722565b82525050565b61427e81614722565b82525050565b600060208201905061429960008301846140b7565b92915050565b60006060820190506142b460008301866140a8565b6142c160208301856140b7565b6142ce6040830184614275565b949350505050565b60006040820190506142eb60008301856140a8565b6142f86020830184614275565b9392505050565b600060608201905061431460008301866140a8565b6143216020830185614275565b61432e60408301846140f3565b949350505050565b600060608201905061434b60008301866140a8565b6143586020830185614275565b6143656040830184614275565b949350505050565b600060408201905061438260008301856140b7565b61438f60208301846140e4565b9392505050565b60006040820190506143ab60008301856140b7565b6143b86020830184614275565b9392505050565b60006060820190506143d460008301866140b7565b6143e16020830185614275565b6143ee6040830184614275565b949350505050565b600060608201905061440b60008301866140c6565b6144186020830185614275565b61442560408301846140c6565b949350505050565b600060408201905061444260008301856140d5565b61444f6020830184614275565b9392505050565b600060208201905081810360008301526144708184614102565b905092915050565b6000602082019050818103600083015261449181614191565b9050919050565b600060208201905081810360008301526144b1816141d1565b9050919050565b60006080820190506144cd6000830184614211565b92915050565b60006020820190506144e86000830184614275565b92915050565b60006040820190506145036000830185614275565b6145106020830184614275565b9392505050565b600060608201905061452c6000830186614275565b6145396020830185614275565b6145466040830184614275565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715614575576145746147b9565b5b8060405250919050565b600067ffffffffffffffff82111561459a576145996147b9565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156145c6576145c56147b9565b5b602082029050602081019050919050565b600067ffffffffffffffff8211156145f2576145f16147b9565b5b601f19601f8301169050602081019050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600061463882614702565b9050919050565b60008115159050919050565b6000819050919050565b60006146608261462d565b9050919050565b60006146728261462d565b9050919050565b60006146848261462d565b9050919050565b60006146968261462d565b9050919050565b60006146a88261462d565b9050919050565b60006146ba8261462d565b9050919050565b60006146cc8261462d565b9050919050565b60006146de8261462d565b9050919050565b60008190506146f3826147bb565b919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061473782614786565b9050919050565b600061474982614750565b9050919050565b600061475b82614702565b9050919050565b600061476d826146e5565b9050919050565b600061477f82614722565b9050919050565b600061479182614798565b9050919050565b60006147a382614702565b9050919050565b82818337600083830152505050565bfe5b600381106147cc576147cb6147b9565b5b50565b6147d88161462d565b81146147e357600080fd5b50565b6147ef8161463f565b81146147fa57600080fd5b50565b6148068161464b565b811461481157600080fd5b50565b61481d81614655565b811461482857600080fd5b50565b61483481614667565b811461483f57600080fd5b50565b61484b81614679565b811461485657600080fd5b50565b6148628161468b565b811461486d57600080fd5b50565b6148798161469d565b811461488457600080fd5b50565b614890816146af565b811461489b57600080fd5b50565b6148a7816146c1565b81146148b257600080fd5b50565b6148be816146d3565b81146148c957600080fd5b50565b6148d5816146f8565b81146148e057600080fd5b50565b6148ec81614722565b81146148f757600080fd5b5056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212204a6d5e7b23cc7b2b6756dbe08454f0b61080244e2f1ca5c64d92267ef5ccb53964736f6c63430007060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
OP | 100.00% | $0.985693 | 39,599.0368 | $39,032.48 |
[ 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.