More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 75 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 8241485 | 884 days ago | IN | 0 ETH | 0.000183903333 | ||||
Withdraw | 7052580 | 894 days ago | IN | 0 ETH | 0.000220802924 | ||||
Withdraw | 7050149 | 894 days ago | IN | 0 ETH | 0.000241459295 | ||||
Withdraw | 6745573 | 899 days ago | IN | 0 ETH | 0.000332206968 | ||||
Withdraw | 6745439 | 899 days ago | IN | 0 ETH | 0.000332224068 | ||||
Withdraw | 6745244 | 899 days ago | IN | 0 ETH | 0.000310928854 | ||||
Withdraw | 6745111 | 899 days ago | IN | 0 ETH | 0.000334504314 | ||||
Withdraw | 6744922 | 899 days ago | IN | 0 ETH | 0.000295509683 | ||||
Withdraw | 6744766 | 899 days ago | IN | 0 ETH | 0.000332039349 | ||||
Withdraw | 6744621 | 899 days ago | IN | 0 ETH | 0.000298380709 | ||||
Withdraw | 6744417 | 899 days ago | IN | 0 ETH | 0.000375311381 | ||||
Withdraw | 6744265 | 899 days ago | IN | 0 ETH | 0.00033889761 | ||||
Withdraw | 6743915 | 899 days ago | IN | 0 ETH | 0.000275148896 | ||||
Withdraw | 6743616 | 899 days ago | IN | 0 ETH | 0.000206721508 | ||||
Withdraw | 6743384 | 899 days ago | IN | 0 ETH | 0.000206142044 | ||||
Withdraw | 6743112 | 899 days ago | IN | 0 ETH | 0.000236875022 | ||||
Withdraw | 6742726 | 899 days ago | IN | 0 ETH | 0.000348135981 | ||||
Withdraw | 6742242 | 899 days ago | IN | 0 ETH | 0.000258373362 | ||||
Withdraw | 6741958 | 899 days ago | IN | 0 ETH | 0.000297304916 | ||||
Withdraw | 6741777 | 899 days ago | IN | 0 ETH | 0.000252618019 | ||||
Withdraw | 6741307 | 899 days ago | IN | 0 ETH | 0.000393925924 | ||||
Withdraw | 6741122 | 899 days ago | IN | 0 ETH | 0.000488184704 | ||||
Withdraw | 6740929 | 899 days ago | IN | 0 ETH | 0.000356046966 | ||||
Withdraw | 6740755 | 899 days ago | IN | 0 ETH | 0.000587127122 | ||||
Withdraw | 6740626 | 899 days ago | IN | 0 ETH | 0.000532277349 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | ||||
---|---|---|---|---|---|---|---|
8241485 | 884 days ago | 0 ETH | |||||
8241485 | 884 days ago | 0 ETH | |||||
8241485 | 884 days ago | 0 ETH | |||||
8241485 | 884 days ago | 0 ETH | |||||
7052580 | 894 days ago | 0 ETH | |||||
7052580 | 894 days ago | 0 ETH | |||||
7052580 | 894 days ago | 0 ETH | |||||
7052580 | 894 days ago | 0 ETH | |||||
7050149 | 894 days ago | 0 ETH | |||||
6745573 | 899 days ago | 0 ETH | |||||
6745573 | 899 days ago | 0 ETH | |||||
6745573 | 899 days ago | 0 ETH | |||||
6745573 | 899 days ago | 0 ETH | |||||
6745439 | 899 days ago | 0 ETH | |||||
6745439 | 899 days ago | 0 ETH | |||||
6745439 | 899 days ago | 0 ETH | |||||
6745439 | 899 days ago | 0 ETH | |||||
6745244 | 899 days ago | 0 ETH | |||||
6745244 | 899 days ago | 0 ETH | |||||
6745244 | 899 days ago | 0 ETH | |||||
6745244 | 899 days ago | 0 ETH | |||||
6745111 | 899 days ago | 0 ETH | |||||
6745111 | 899 days ago | 0 ETH | |||||
6745111 | 899 days ago | 0 ETH | |||||
6745111 | 899 days ago | 0 ETH |
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.998814 | 39,599.0368 | $39,552.06 |
[ 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.