Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ACOToken
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity Multiple files format)
pragma solidity ^0.6.6; import "./ERC20.sol"; import "./Address.sol"; import "./ACONameFormatter.sol"; /** * @title ACOToken * @dev The implementation of the ACO token. * The token is ERC20 compliant. */ contract ACOToken is ERC20 { using Address for address; /** * @dev Struct to store the accounts that generated tokens with a collateral deposit. */ struct TokenCollateralized { /** * @dev Current amount of tokens. */ uint256 amount; /** * @dev Index on the collateral owners array. */ uint256 index; } /** * @dev Emitted when collateral is deposited on the contract. * @param account Address of the collateral owner. * @param amount Amount of collateral deposited. */ event CollateralDeposit(address indexed account, uint256 amount); /** * @dev Emitted when collateral is withdrawn from the contract. * @param account Address of the account. * @param recipient Address of the collateral destination. * @param amount Amount of collateral withdrawn. * @param fee The fee amount charged on the withdrawal. */ event CollateralWithdraw(address indexed account, address indexed recipient, uint256 amount, uint256 fee); /** * @dev Emitted when the collateral is used on an assignment. * @param from Address of the account of the collateral owner. * @param to Address of the account that exercises tokens to get the collateral. * @param paidAmount Amount paid to the collateral owner. * @param tokenAmount Amount of tokens used to exercise. */ event Assigned(address indexed from, address indexed to, uint256 paidAmount, uint256 tokenAmount); /** * @dev Emitted when the collateralized token is transferred. * @param from Address of the account of the collateral owner. * @param to Address of the account to get the collateralized tokens. * @param tokenCollateralizedAmount Amount of collateralized tokens transferred. */ event TransferCollateralOwnership(address indexed from, address indexed to, uint256 tokenCollateralizedAmount); /** * @dev The ERC20 token address for the underlying asset (0x0 for Ethereum). */ address public underlying; /** * @dev The ERC20 token address for the strike asset (0x0 for Ethereum). */ address public strikeAsset; /** * @dev Address of the fee destination charged on the exercise. */ address payable public feeDestination; /** * @dev True if the type is CALL, false for PUT. */ bool public isCall; /** * @dev The strike price for the token with the strike asset precision. */ uint256 public strikePrice; /** * @dev The UNIX time for the token expiration. */ uint256 public expiryTime; /** * @dev The total amount of collateral on the contract. */ uint256 public totalCollateral; /** * @dev The fee value. It is a percentage value (100000 is 100%). */ uint256 public acoFee; /** * @dev Symbol of the underlying asset. */ string public underlyingSymbol; /** * @dev Symbol of the strike asset. */ string public strikeAssetSymbol; /** * @dev Decimals for the underlying asset. */ uint8 public underlyingDecimals; /** * @dev Decimals for the strike asset. */ uint8 public strikeAssetDecimals; /** * @dev The maximum number of accounts that can be exercised by transaction. */ uint256 public maxExercisedAccounts; /** * @dev Underlying precision. (10 ^ underlyingDecimals) */ uint256 internal underlyingPrecision; /** * @dev Accounts that generated tokens with a collateral deposit. */ mapping(address => TokenCollateralized) internal tokenData; /** * @dev Array with all accounts with collateral deposited. */ address[] internal _collateralOwners; /** * @dev Internal data to control the reentrancy. */ bool internal _notEntered; /** * @dev Selector for ERC20 transfer function. */ bytes4 internal _transferSelector; /** * @dev Selector for ERC20 transfer from function. */ bytes4 internal _transferFromSelector; /** * @dev Modifier to check if the token is not expired. * It is executed only while the token is not expired. */ modifier notExpired() { require(_notExpired(), "ACOToken::Expired"); _; } /** * @dev Modifier to prevent a contract from calling itself during the function execution. */ modifier nonReentrant() { require(_notEntered, "ACOToken::Reentry"); _notEntered = false; _; _notEntered = true; } /** * @dev Function to initialize the contract. * It should be called when creating the token. * It must be called only once. The first `require` is to guarantee that behavior. * @param _underlying Address of the underlying asset (0x0 for Ethereum). * @param _strikeAsset Address of the strike asset (0x0 for Ethereum). * @param _isCall True if the type is CALL, false for PUT. * @param _strikePrice The strike price with the strike asset precision. * @param _expiryTime The UNIX time for the token expiration. * @param _acoFee Value of the ACO fee. It is a percentage value (100000 is 100%). * @param _feeDestination Address of the fee destination charged on the exercise. * @param _maxExercisedAccounts The maximum number of accounts that can be exercised by transaction. */ function init( address _underlying, address _strikeAsset, bool _isCall, uint256 _strikePrice, uint256 _expiryTime, uint256 _acoFee, address payable _feeDestination, uint256 _maxExercisedAccounts ) public { require(underlying == address(0) && strikeAsset == address(0) && strikePrice == 0, "ACOToken::init: Already initialized"); require(_expiryTime > now, "ACOToken::init: Invalid expiry"); require(_strikePrice > 0, "ACOToken::init: Invalid strike price"); require(_underlying != _strikeAsset, "ACOToken::init: Same assets"); require(_acoFee <= 500, "ACOToken::init: Invalid ACO fee"); // Maximum is 0.5% require(_isEther(_underlying) || _underlying.isContract(), "ACOToken::init: Invalid underlying"); require(_isEther(_strikeAsset) || _strikeAsset.isContract(), "ACOToken::init: Invalid strike asset"); require(_maxExercisedAccounts >= 25 && _maxExercisedAccounts <= 150, "ACOToken::init: Invalid number to max exercised accounts"); underlying = _underlying; strikeAsset = _strikeAsset; isCall = _isCall; strikePrice = _strikePrice; expiryTime = _expiryTime; acoFee = _acoFee; feeDestination = _feeDestination; maxExercisedAccounts = _maxExercisedAccounts; underlyingDecimals = _getAssetDecimals(_underlying); require(underlyingDecimals < 78, "ACOToken::init: Invalid underlying decimals"); strikeAssetDecimals = _getAssetDecimals(_strikeAsset); underlyingSymbol = _getAssetSymbol(_underlying); strikeAssetSymbol = _getAssetSymbol(_strikeAsset); underlyingPrecision = 10 ** uint256(underlyingDecimals); _transferSelector = bytes4(keccak256(bytes("transfer(address,uint256)"))); _transferFromSelector = bytes4(keccak256(bytes("transferFrom(address,address,uint256)"))); _notEntered = true; } /** * @dev Function to guarantee that the contract will not receive ether directly. */ receive() external payable { revert(); } /** * @dev Function to get the token name. */ function name() public view override returns(string memory) { return _name(); } /** * @dev Function to get the token symbol, that it is equal to the name. */ function symbol() public view override returns(string memory) { return _name(); } /** * @dev Function to get the token decimals, that it is equal to the underlying asset decimals. */ function decimals() public view override returns(uint8) { return underlyingDecimals; } /** * @dev Function to get the current amount of collateral for an account. * @param account Address of the account. * @return The current amount of collateral. */ function currentCollateral(address account) public view returns(uint256) { return getCollateralAmount(currentCollateralizedTokens(account)); } /** * @dev Function to get the current amount of unassignable collateral for an account. * After expiration, the unassignable collateral is equal to the account's collateral balance. * @param account Address of the account. * @return The respective amount of unassignable collateral. */ function unassignableCollateral(address account) public view returns(uint256) { return getCollateralAmount(unassignableTokens(account)); } /** * @dev Function to get the current amount of assignable collateral for an account. * After expiration, the assignable collateral is zero. * @param account Address of the account. * @return The respective amount of assignable collateral. */ function assignableCollateral(address account) public view returns(uint256) { return getCollateralAmount(assignableTokens(account)); } /** * @dev Function to get the current amount of collateralized tokens for an account. * @param account Address of the account. * @return The current amount of collateralized tokens. */ function currentCollateralizedTokens(address account) public view returns(uint256) { return tokenData[account].amount; } /** * @dev Function to get the current amount of unassignable tokens for an account. * After expiration, the unassignable tokens is equal to the account's collateralized tokens. * @param account Address of the account. * @return The respective amount of unassignable tokens. */ function unassignableTokens(address account) public view returns(uint256) { if (balanceOf(account) > tokenData[account].amount || !_notExpired()) { return tokenData[account].amount; } else { return balanceOf(account); } } /** * @dev Function to get the current amount of assignable tokens for an account. * After expiration, the assignable tokens is zero. * @param account Address of the account. * @return The respective amount of assignable tokens. */ function assignableTokens(address account) public view returns(uint256) { if (_notExpired()) { return _getAssignableAmount(account); } else { return 0; } } /** * @dev Function to get the equivalent collateral amount for a token amount. * @param tokenAmount Amount of tokens. * @return The respective amount of collateral. */ function getCollateralAmount(uint256 tokenAmount) public view returns(uint256) { if (isCall) { return tokenAmount; } else if (tokenAmount > 0) { return _getTokenStrikePriceRelation(tokenAmount); } else { return 0; } } /** * @dev Function to get the equivalent token amount for a collateral amount. * @param collateralAmount Amount of collateral. * @return The respective amount of tokens. */ function getTokenAmount(uint256 collateralAmount) public view returns(uint256) { if (isCall) { return collateralAmount; } else if (collateralAmount > 0) { return collateralAmount.mul(underlyingPrecision).div(strikePrice); } else { return 0; } } /** * @dev Function to get the number of addresses that have collateral deposited. * @return The number of addresses. */ function numberOfAccountsWithCollateral() public view returns(uint256) { return _collateralOwners.length; } /** * @dev Function to get the base data for exercise of an amount of token. * To call the exercise the value returned must be added by the number of accounts that could be exercised: * - using the ´exercise´ or ´exerciseFrom´ functions it will be equal to `maxExercisedAccounts`. * - using the ´exerciseAccounts´ or `exerciseAccountsFrom` functions it will be equal to the number of accounts sent as function argument. * @param tokenAmount Amount of tokens. * @return The asset and the respective base amount that should be sent to get the collateral. */ function getBaseExerciseData(uint256 tokenAmount) public view returns(address, uint256) { if (isCall) { return (strikeAsset, _getTokenStrikePriceRelation(tokenAmount)); } else { return (underlying, tokenAmount); } } /** * @dev Function to get the collateral to be received on an exercise and the respective fee. * @param tokenAmount Amount of tokens. * @return The collateral to be received and the respective fee. */ function getCollateralOnExercise(uint256 tokenAmount) public view returns(uint256, uint256) { uint256 collateralAmount = getCollateralAmount(tokenAmount); uint256 fee = collateralAmount.mul(acoFee).div(100000); collateralAmount = collateralAmount.sub(fee); return (collateralAmount, fee); } /** * @dev Function to get the collateral asset. * @return The address of the collateral asset. */ function collateral() public view returns(address) { if (isCall) { return underlying; } else { return strikeAsset; } } /** * @dev Function to mint tokens with Ether deposited as collateral. * NOTE: The function only works when the token is NOT expired yet. * @return The amount of tokens minted. */ function mintPayable() external payable returns(uint256) { require(_isEther(collateral()), "ACOToken::mintPayable: Invalid call"); return _mintToken(msg.sender, msg.value); } /** * @dev Function to mint tokens with Ether deposited as collateral to an informed account. * However, the minted tokens are assigned to the transaction sender. * NOTE: The function only works when the token is NOT expired yet. * @param account Address of the account that will be the collateral owner. * @return The amount of tokens minted. */ function mintToPayable(address account) external payable returns(uint256) { require(_isEther(collateral()), "ACOToken::mintToPayable: Invalid call"); return _mintToken(account, msg.value); } /** * @dev Function to mint tokens with ERC20 deposited as collateral. * NOTE: The function only works when the token is NOT expired yet. * @param collateralAmount Amount of collateral deposited. * @return The amount of tokens minted. */ function mint(uint256 collateralAmount) external returns(uint256) { address _collateral = collateral(); require(!_isEther(_collateral), "ACOToken::mint: Invalid call"); _transferFromERC20(_collateral, msg.sender, address(this), collateralAmount); return _mintToken(msg.sender, collateralAmount); } /** * @dev Function to mint tokens with ERC20 deposited as collateral to an informed account. * However, the minted tokens are assigned to the transaction sender. * NOTE: The function only works when the token is NOT expired yet. * @param account Address of the account that will be the collateral owner. * @param collateralAmount Amount of collateral deposited. * @return The amount of tokens minted. */ function mintTo(address account, uint256 collateralAmount) external returns(uint256) { address _collateral = collateral(); require(!_isEther(_collateral), "ACOToken::mintTo: Invalid call"); _transferFromERC20(_collateral, msg.sender, address(this), collateralAmount); return _mintToken(account, collateralAmount); } /** * @dev Function to burn tokens and get the collateral, not assigned, back. * NOTE: The function only works when the token is NOT expired yet. * @param tokenAmount Amount of tokens to be burned. * @return The amount of collateral transferred. */ function burn(uint256 tokenAmount) external returns(uint256) { return _burn(msg.sender, tokenAmount); } /** * @dev Function to burn tokens from a specific account and send the collateral to its address. * The token allowance must be respected. * The collateral is sent to the transaction sender. * NOTE: The function only works when the token is NOT expired yet. * @param account Address of the account. * @param tokenAmount Amount of tokens to be burned. * @return The amount of collateral transferred. */ function burnFrom(address account, uint256 tokenAmount) external returns(uint256) { return _burn(account, tokenAmount); } /** * @dev Function to get the collateral, not assigned, back. * NOTE: The function only works when the token IS expired. * @return The amount of collateral transferred. */ function redeem() external returns(uint256) { return _redeem(msg.sender); } /** * @dev Function to get the collateral from a specific account sent back to its address . * The token allowance must be respected. * The collateral is sent to the transaction sender. * NOTE: The function only works when the token IS expired. * @param account Address of the account. * @return The amount of collateral transferred. */ function redeemFrom(address account) external returns(uint256) { require(tokenData[account].amount <= allowance(account, msg.sender), "ACOToken::redeemFrom: Allowance too low"); return _redeem(account); } /** * @dev Function to exercise the tokens, paying to get the equivalent collateral. * The paid amount is sent to the collateral owners that were assigned. * NOTE: The function only works when the token is NOT expired. * @param tokenAmount Amount of tokens. * @param salt Random number to calculate the start index of the array of accounts to be exercised. * @return The amount of collateral transferred. */ function exercise(uint256 tokenAmount, uint256 salt) external payable returns(uint256) { return _exercise(msg.sender, tokenAmount, salt); } /** * @dev Function to exercise the tokens from an account, paying to get the equivalent collateral. * The token allowance must be respected. * The paid amount is sent to the collateral owners that were assigned. * The collateral is transferred to the transaction sender. * NOTE: The function only works when the token is NOT expired. * @param account Address of the account. * @param tokenAmount Amount of tokens. * @param salt Random number to calculate the start index of the array of accounts to be exercised. * @return The amount of collateral transferred. */ function exerciseFrom(address account, uint256 tokenAmount, uint256 salt) external payable returns(uint256) { return _exercise(account, tokenAmount, salt); } /** * @dev Function to exercise the tokens, paying to get the equivalent collateral. * The paid amount is sent to the collateral owners (on accounts list) that were assigned. * NOTE: The function only works when the token is NOT expired. * @param tokenAmount Amount of tokens. * @param accounts The array of addresses to get collateral from. * @return The amount of collateral transferred. */ function exerciseAccounts(uint256 tokenAmount, address[] calldata accounts) external payable returns(uint256) { return _exerciseFromAccounts(msg.sender, tokenAmount, accounts); } /** * @dev Function to transfer collateralized tokens. * @param recipient Address of the destination. * @param tokenCollateralizedAmount Amount of collateralized tokens to be transferred. */ function transferCollateralOwnership(address recipient, uint256 tokenCollateralizedAmount) external { require(recipient != address(0), "ACOToken::transferCollateralOwnership: Invalid recipient"); require(tokenCollateralizedAmount > 0, "ACOToken::transferCollateralOwnership: Invalid amount"); TokenCollateralized storage senderData = tokenData[msg.sender]; senderData.amount = senderData.amount.sub(tokenCollateralizedAmount); _removeCollateralDataIfNecessary(msg.sender); TokenCollateralized storage recipientData = tokenData[recipient]; if (_hasCollateral(recipientData)) { recipientData.amount = recipientData.amount.add(tokenCollateralizedAmount); } else { tokenData[recipient] = TokenCollateralized(tokenCollateralizedAmount, _collateralOwners.length); _collateralOwners.push(recipient); } emit TransferCollateralOwnership(msg.sender, recipient, tokenCollateralizedAmount); } /** * @dev Function to exercise the tokens from a specific account, paying to get the equivalent collateral sent to its address. * The token allowance must be respected. * The paid amount is sent to the collateral owners (on accounts list) that were assigned. * The collateral is transferred to the transaction sender. * NOTE: The function only works when the token is NOT expired. * @param account Address of the account. * @param tokenAmount Amount of tokens. * @param accounts The array of addresses to get the deposited collateral. * @return The amount of collateral transferred. */ function exerciseAccountsFrom(address account, uint256 tokenAmount, address[] calldata accounts) external payable returns(uint256) { return _exerciseFromAccounts(account, tokenAmount, accounts); } /** * @dev Internal function to redeem respective collateral from an account. * @param account Address of the account. * @param tokenAmount Amount of tokens. * @return The amount of collateral transferred. */ function _redeemCollateral(address account, uint256 tokenAmount) internal returns(uint256) { require(_accountHasCollateral(account), "ACOToken::_redeemCollateral: No collateral available"); require(tokenAmount > 0, "ACOToken::_redeemCollateral: Invalid token amount"); TokenCollateralized storage data = tokenData[account]; data.amount = data.amount.sub(tokenAmount); _removeCollateralDataIfNecessary(account); return _transferCollateral(account, getCollateralAmount(tokenAmount), 0); } /** * @dev Internal function to mint tokens. * The tokens are minted for the transaction sender. * @param account Address of the account. * @param collateralAmount Amount of collateral deposited. * @return The amount of tokens minted. */ function _mintToken(address account, uint256 collateralAmount) nonReentrant notExpired internal returns(uint256) { require(collateralAmount > 0, "ACOToken::_mintToken: Invalid collateral amount"); if (!_accountHasCollateral(account)) { tokenData[account].index = _collateralOwners.length; _collateralOwners.push(account); } uint256 tokenAmount = getTokenAmount(collateralAmount); require(tokenAmount != 0, "ACOToken::_mintToken: Invalid token amount"); tokenData[account].amount = tokenData[account].amount.add(tokenAmount); totalCollateral = totalCollateral.add(collateralAmount); emit CollateralDeposit(account, collateralAmount); super._mintAction(msg.sender, tokenAmount); return tokenAmount; } /** * @dev Internal function to transfer collateral. * When there is a fee, the calculated fee is also transferred to the destination fee address. * The collateral destination is always the transaction sender address. * @param account Address of the account. * @param collateralAmount Amount of collateral to be transferred. * @param fee Amount of fee charged. * @return The amount of collateral transferred. */ function _transferCollateral(address account, uint256 collateralAmount, uint256 fee) internal returns(uint256) { totalCollateral = totalCollateral.sub(collateralAmount.add(fee)); address _collateral = collateral(); if (_isEther(_collateral)) { payable(msg.sender).transfer(collateralAmount); if (fee > 0) { feeDestination.transfer(fee); } } else { _transferERC20(_collateral, msg.sender, collateralAmount); if (fee > 0) { _transferERC20(_collateral, feeDestination, fee); } } emit CollateralWithdraw(account, msg.sender, collateralAmount, fee); return collateralAmount; } /** * @dev Internal function to exercise the tokens from an account. * @param account Address of the account that is exercising. * @param tokenAmount Amount of tokens. * @param salt Random number to calculate the start index of the array of accounts to be exercised. * @return The amount of collateral transferred. */ function _exercise(address account, uint256 tokenAmount, uint256 salt) nonReentrant internal returns(uint256) { _validateAndBurn(account, tokenAmount, maxExercisedAccounts); _exerciseOwners(account, tokenAmount, salt); (uint256 collateralAmount, uint256 fee) = getCollateralOnExercise(tokenAmount); return _transferCollateral(account, collateralAmount, fee); } /** * @dev Internal function to exercise the tokens from an account. * @param account Address of the account that is exercising. * @param tokenAmount Amount of tokens. * @param accounts The array of addresses to get the collateral from. * @return The amount of collateral transferred. */ function _exerciseFromAccounts(address account, uint256 tokenAmount, address[] memory accounts) nonReentrant internal returns(uint256) { _validateAndBurn(account, tokenAmount, accounts.length); _exerciseAccounts(account, tokenAmount, accounts); (uint256 collateralAmount, uint256 fee) = getCollateralOnExercise(tokenAmount); return _transferCollateral(account, collateralAmount, fee); } /** * @dev Internal function to exercise the assignable tokens from the stored list of collateral owners. * @param exerciseAccount Address of the account that is exercising. * @param tokenAmount Amount of tokens. * @param salt Random number to calculate the start index of the array of accounts to be exercised. */ function _exerciseOwners(address exerciseAccount, uint256 tokenAmount, uint256 salt) internal { uint256 accountsExercised = 0; uint256 start = salt.mod(_collateralOwners.length); uint256 index = start; uint256 count = 0; while (tokenAmount > 0 && count < _collateralOwners.length) { uint256 remainingAmount = _exerciseAccount(_collateralOwners[index], tokenAmount, exerciseAccount); if (remainingAmount < tokenAmount) { accountsExercised++; require(accountsExercised < maxExercisedAccounts || remainingAmount == 0, "ACOToken::_exerciseOwners: Too many accounts to exercise"); } tokenAmount = remainingAmount; ++index; if (index == _collateralOwners.length) { index = 0; } ++count; } require(tokenAmount == 0, "ACOToken::_exerciseOwners: Invalid remaining amount"); uint256 indexOnModifyIteration; bool shouldModifyIteration = false; if (index == 0) { index = _collateralOwners.length; } else if (index <= start) { indexOnModifyIteration = index - 1; shouldModifyIteration = true; index = _collateralOwners.length; } for (uint256 i = 0; i < count; ++i) { --index; if (shouldModifyIteration && index < start) { index = indexOnModifyIteration; shouldModifyIteration = false; } _removeCollateralDataIfNecessary(_collateralOwners[index]); } } /** * @dev Internal function to exercise the assignable tokens from an accounts list. * @param exerciseAccount Address of the account that is exercising. * @param tokenAmount Amount of tokens. * @param accounts The array of addresses to get the collateral from. */ function _exerciseAccounts(address exerciseAccount, uint256 tokenAmount, address[] memory accounts) internal { for (uint256 i = 0; i < accounts.length; ++i) { if (tokenAmount == 0) { break; } tokenAmount = _exerciseAccount(accounts[i], tokenAmount, exerciseAccount); _removeCollateralDataIfNecessary(accounts[i]); } require(tokenAmount == 0, "ACOToken::_exerciseAccounts: Invalid remaining amount"); } /** * @dev Internal function to exercise the assignable tokens from an account and transfer to its address the respective payment. * @param account Address of the account. * @param tokenAmount Amount of tokens. * @param exerciseAccount Address of the account that is exercising. * @return Remaining amount of tokens. */ function _exerciseAccount(address account, uint256 tokenAmount, address exerciseAccount) internal returns(uint256) { uint256 available = _getAssignableAmount(account); if (available > 0) { TokenCollateralized storage data = tokenData[account]; uint256 valueToTransfer; if (available < tokenAmount) { valueToTransfer = available; tokenAmount = tokenAmount.sub(available); } else { valueToTransfer = tokenAmount; tokenAmount = 0; } (address exerciseAsset, uint256 amount) = getBaseExerciseData(valueToTransfer); // To guarantee that the minter will be paid. amount = amount.add(1); data.amount = data.amount.sub(valueToTransfer); if (_isEther(exerciseAsset)) { payable(account).transfer(amount); } else { _transferERC20(exerciseAsset, account, amount); } emit Assigned(account, exerciseAccount, amount, valueToTransfer); } return tokenAmount; } /** * @dev Internal function to validate the exercise operation and burn the respective tokens. * @param account Address of the account that is exercising. * @param tokenAmount Amount of tokens. * @param maximumNumberOfAccounts The maximum number of accounts that can be exercised. */ function _validateAndBurn(address account, uint256 tokenAmount, uint256 maximumNumberOfAccounts) notExpired internal { require(tokenAmount > 0, "ACOToken::_validateAndBurn: Invalid token amount"); // Whether an account has deposited collateral it only can exercise the extra amount of unassignable tokens. if (_accountHasCollateral(account)) { require(tokenAmount <= balanceOf(account).sub(tokenData[account].amount), "ACOToken::_validateAndBurn: Token amount not available"); } _callBurn(account, tokenAmount); (address exerciseAsset, uint256 expectedAmount) = getBaseExerciseData(tokenAmount); expectedAmount = expectedAmount.add(maximumNumberOfAccounts); if (_isEther(exerciseAsset)) { require(msg.value == expectedAmount, "ACOToken::_validateAndBurn: Invalid ether amount"); } else { require(msg.value == 0, "ACOToken::_validateAndBurn: No ether expected"); _transferFromERC20(exerciseAsset, msg.sender, address(this), expectedAmount); } } /** * @dev Internal function to calculate the token strike price relation. * @param tokenAmount Amount of tokens. * @return Calculated value with strike asset precision. */ function _getTokenStrikePriceRelation(uint256 tokenAmount) internal view returns(uint256) { return tokenAmount.mul(strikePrice).div(underlyingPrecision); } /** * @dev Internal function to get the collateral sent back from an account. * Function to be called when the token IS expired. * @param account Address of the account. * @return The amount of collateral transferred. */ function _redeem(address account) nonReentrant internal returns(uint256) { require(!_notExpired(), "ACOToken::_redeem: Token not expired yet"); uint256 collateralAmount = _redeemCollateral(account, tokenData[account].amount); super._burnAction(account, balanceOf(account)); return collateralAmount; } /** * @dev Internal function to burn tokens from an account and get the collateral, not assigned, back. * @param account Address of the account. * @param tokenAmount Amount of tokens to be burned. * @return The amount of collateral transferred. */ function _burn(address account, uint256 tokenAmount) nonReentrant notExpired internal returns(uint256) { uint256 collateralAmount = _redeemCollateral(account, tokenAmount); _callBurn(account, tokenAmount); return collateralAmount; } /** * @dev Internal function to burn tokens. * @param account Address of the account. * @param tokenAmount Amount of tokens to be burned. */ function _callBurn(address account, uint256 tokenAmount) internal { if (account == msg.sender) { super._burnAction(account, tokenAmount); } else { super._burnFrom(account, tokenAmount); } } /** * @dev Internal function to get the amount of assignable token from an account. * @param account Address of the account. * @return The assignable amount of tokens. */ function _getAssignableAmount(address account) internal view returns(uint256) { if (tokenData[account].amount > balanceOf(account)) { return tokenData[account].amount.sub(balanceOf(account)); } else { return 0; } } /** * @dev Internal function to remove the token data with collateral if its total amount was assigned. * @param account Address of account. */ function _removeCollateralDataIfNecessary(address account) internal { TokenCollateralized storage data = tokenData[account]; if (!_hasCollateral(data)) { uint256 lastIndex = _collateralOwners.length - 1; if (lastIndex != data.index) { address last = _collateralOwners[lastIndex]; tokenData[last].index = data.index; _collateralOwners[data.index] = last; } _collateralOwners.pop(); delete tokenData[account]; } } /** * @dev Internal function to get if the token is not expired. * @return Whether the token is NOT expired. */ function _notExpired() internal view returns(bool) { return now < expiryTime; } /** * @dev Internal function to get if an account has collateral deposited. * @param account Address of the account. * @return Whether the account has collateral deposited. */ function _accountHasCollateral(address account) internal view returns(bool) { return _hasCollateral(tokenData[account]); } /** * @dev Internal function to get if an account has collateral deposited. * @param data Token data from an account. * @return Whether the account has collateral deposited. */ function _hasCollateral(TokenCollateralized storage data) internal view returns(bool) { return data.amount > 0; } /** * @dev Internal function to get if the address is for Ethereum (0x0). * @param _address Address to be checked. * @return Whether the address is for Ethereum. */ function _isEther(address _address) internal pure returns(bool) { return _address == address(0); } /** * @dev Internal function to get the token name. * The token name is assembled with the token data: * ACO UNDERLYING_SYMBOL-STRIKE_PRICE_STRIKE_ASSET_SYMBOL-TYPE-EXPIRYTIME * @return The token name. */ function _name() internal view returns(string memory) { return string(abi.encodePacked( "ACO ", underlyingSymbol, "-", ACONameFormatter.formatNumber(strikePrice, strikeAssetDecimals), strikeAssetSymbol, "-", ACONameFormatter.formatType(isCall), "-", ACONameFormatter.formatTime(expiryTime) )); } /** * @dev Internal function to the asset decimals. * @param asset Address of the asset. * @return The asset decimals. */ function _getAssetDecimals(address asset) internal view returns(uint8) { if (_isEther(asset)) { return uint8(18); } else { (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSignature("decimals()")); require(success, "ACOToken::_getAssetDecimals: Invalid asset decimals"); return abi.decode(returndata, (uint8)); } } /** * @dev Internal function to the asset symbol. * @param asset Address of the asset. * @return The asset symbol. */ function _getAssetSymbol(address asset) internal view returns(string memory) { if (_isEther(asset)) { return "ETH"; } else { (bool success, bytes memory returndata) = asset.staticcall(abi.encodeWithSignature("symbol()")); require(success, "ACOToken::_getAssetSymbol: Invalid asset symbol"); return abi.decode(returndata, (string)); } } /** * @dev Internal function to transfer ERC20 tokens. * @param token Address of the token. * @param recipient Address of the transfer destination. * @param amount Amount to transfer. */ function _transferERC20(address token, address recipient, uint256 amount) internal { (bool success, bytes memory returndata) = token.call(abi.encodeWithSelector(_transferSelector, recipient, amount)); require(success && (returndata.length == 0 || abi.decode(returndata, (bool))), "ACOToken::_transferERC20"); } /** * @dev Internal function to call transferFrom on ERC20 tokens. * @param token Address of the token. * @param sender Address of the sender. * @param recipient Address of the transfer destination. * @param amount Amount to transfer. */ function _transferFromERC20(address token, address sender, address recipient, uint256 amount) internal { (bool success, bytes memory returndata) = token.call(abi.encodeWithSelector(_transferFromSelector, sender, recipient, amount)); require(success && (returndata.length == 0 || abi.decode(returndata, (bool))), "ACOToken::_transferFromERC20"); } }
pragma solidity ^0.6.6; import './BokkyPooBahsDateTimeLibrary.sol'; import './Strings.sol'; library ACONameFormatter { /** * @dev Function to get the `value` formatted. * The function returns a string for the `value` with a point (character '.') in the proper position considering the `decimals`. * Beyond that, the string returned presents only representative digits. * For example, a `value` with 18 decimals: * - For 100000000000000000000 the return is "100" * - For 100100000000000000000 the return is "100.1" * - For 100000000000000000 the return is "0.1" * - For 100000000000000 the return is "0.0001" * - For 100000000000000000001 the return is "100.000000000000000001" * @param value The number to be formatted. * @param decimals The respective number decimals. * @return The value formatted on a string. */ function formatNumber(uint256 value, uint8 decimals) internal pure returns(string memory) { uint256 digits; uint256 count; bool foundRepresentativeDigit = false; uint256 addPointAt = 0; uint256 temp = value; uint256 number = value; while (temp != 0) { if (!foundRepresentativeDigit && (temp % 10 != 0 || count == uint256(decimals))) { foundRepresentativeDigit = true; number = temp; } if (foundRepresentativeDigit) { if (count == uint256(decimals)) { addPointAt = digits; } digits++; } temp /= 10; count++; } if (count <= uint256(decimals)) { digits = digits + 2 + uint256(decimals) - count; addPointAt = digits - 2; } else if (addPointAt > 0) { digits++; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = number; for (uint256 i = 0; i < digits; ++i) { if (i > 0 && i == addPointAt) { buffer[index--] = byte("."); } else if (number == 0) { buffer[index--] = byte("0"); } else { buffer[index--] = byte(uint8(48 + number % 10)); number /= 10; } } return string(buffer); } /** * @dev Function to get the `unixTime` formatted. * @param unixTime The UNIX time to be formatted. * @return The unix time formatted on a string. */ function formatTime(uint256 unixTime) internal pure returns(string memory) { (uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute,) = BokkyPooBahsDateTimeLibrary.timestampToDateTime(unixTime); return string(abi.encodePacked( _getDateNumberWithTwoCharacters(day), _getMonthFormatted(month), _getYearFormatted(year), "-", _getDateNumberWithTwoCharacters(hour), _getDateNumberWithTwoCharacters(minute), "UTC" )); } /** * @dev Function to get the token type description. * @return The token type description. */ function formatType(bool isCall) internal pure returns(string memory) { if (isCall) { return "C"; } else { return "P"; } } /** * @dev Function to get the year formatted with 2 characters. * @return The year formatted. */ function _getYearFormatted(uint256 year) private pure returns(string memory) { bytes memory yearBytes = bytes(Strings.toString(year)); bytes memory result = new bytes(2); uint256 startIndex = yearBytes.length - 2; for (uint256 i = startIndex; i < yearBytes.length; i++) { result[i - startIndex] = yearBytes[i]; } return string(result); } /** * @dev Function to get the month abbreviation. * @return The month abbreviation. */ function _getMonthFormatted(uint256 month) private pure returns(string memory) { if (month == 1) { return "JAN"; } else if (month == 2) { return "FEB"; } else if (month == 3) { return "MAR"; } else if (month == 4) { return "APR"; } else if (month == 5) { return "MAY"; } else if (month == 6) { return "JUN"; } else if (month == 7) { return "JUL"; } else if (month == 8) { return "AUG"; } else if (month == 9) { return "SEP"; } else if (month == 10) { return "OCT"; } else if (month == 11) { return "NOV"; } else if (month == 12) { return "DEC"; } else { return "INVALID"; } } /** * @dev Function to get the date number with 2 characters. * @return The 2 characters for the number. */ function _getDateNumberWithTwoCharacters(uint256 number) private pure returns(string memory) { string memory _string = Strings.toString(number); if (number < 10) { return string(abi.encodePacked("0", _string)); } else { return _string; } } }
pragma solidity ^0.6.6; // Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } }
pragma solidity ^0.6.6; // ---------------------------------------------------------------------------- // BokkyPooBah's DateTime Library v1.01 // // A gas-efficient Solidity date and time library // // https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary // // Tested date range 1970/01/01 to 2345/12/31 // // Conventions: // Unit | Range | Notes // :-------- |:-------------:|:----- // timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC // year | 1970 ... 2345 | // month | 1 ... 12 | // day | 1 ... 31 | // hour | 0 ... 23 | // minute | 0 ... 59 | // second | 0 ... 59 | // dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday // // // Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence. // ---------------------------------------------------------------------------- library BokkyPooBahsDateTimeLibrary { uint constant SECONDS_PER_DAY = 24 * 60 * 60; uint constant SECONDS_PER_HOUR = 60 * 60; uint constant SECONDS_PER_MINUTE = 60; int constant OFFSET19700101 = 2440588; uint constant DOW_MON = 1; uint constant DOW_TUE = 2; uint constant DOW_WED = 3; uint constant DOW_THU = 4; uint constant DOW_FRI = 5; uint constant DOW_SAT = 6; uint constant DOW_SUN = 7; // ------------------------------------------------------------------------ // Calculate the number of days from 1970/01/01 to year/month/day using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and subtracting the offset 2440588 so that 1970/01/01 is day 0 // // days = day // - 32075 // + 1461 * (year + 4800 + (month - 14) / 12) / 4 // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 // - offset // ------------------------------------------------------------------------ function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { require(year >= 1970); int _year = int(year); int _month = int(month); int _day = int(day); int __days = _day - 32075 + 1461 * (_year + 4800 + (_month - 14) / 12) / 4 + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12 - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4 - OFFSET19700101; _days = uint(__days); } // ------------------------------------------------------------------------ // Calculate year/month/day from the number of days since 1970/01/01 using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and adding the offset 2440588 so that 1970/01/01 is day 0 // // int L = days + 68569 + offset // int N = 4 * L / 146097 // L = L - (146097 * N + 3) / 4 // year = 4000 * (L + 1) / 1461001 // L = L - 1461 * year / 4 + 31 // month = 80 * L / 2447 // dd = L - 2447 * month / 80 // L = month / 11 // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { int __days = int(_days); int L = __days + 68569 + OFFSET19700101; int N = 4 * L / 146097; L = L - (146097 * N + 3) / 4; int _year = 4000 * (L + 1) / 1461001; L = L - 1461 * _year / 4 + 31; int _month = 80 * L / 2447; int _day = L - 2447 * _month / 80; L = _month / 11; _month = _month + 2 - 12 * L; _year = 100 * (N - 49) + _year + L; year = uint(_year); month = uint(_month); day = uint(_day); } function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) { timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY; } function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) { timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second; } function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); } function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint secs = timestamp % SECONDS_PER_DAY; hour = secs / SECONDS_PER_HOUR; secs = secs % SECONDS_PER_HOUR; minute = secs / SECONDS_PER_MINUTE; second = secs % SECONDS_PER_MINUTE; } function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) { if (year >= 1970 && month > 0 && month <= 12) { uint daysInMonth = _getDaysInMonth(year, month); if (day > 0 && day <= daysInMonth) { valid = true; } } } function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) { if (isValidDate(year, month, day)) { if (hour < 24 && minute < 60 && second < 60) { valid = true; } } } function isLeapYear(uint timestamp) internal pure returns (bool leapYear) { (uint year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); leapYear = _isLeapYear(year); } function _isLeapYear(uint year) internal pure returns (bool leapYear) { leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); } function isWeekDay(uint timestamp) internal pure returns (bool weekDay) { weekDay = getDayOfWeek(timestamp) <= DOW_FRI; } function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) { weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; } function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) { (uint year, uint month,) = _daysToDate(timestamp / SECONDS_PER_DAY); daysInMonth = _getDaysInMonth(year, month); } function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) { if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { daysInMonth = 31; } else if (month != 2) { daysInMonth = 30; } else { daysInMonth = _isLeapYear(year) ? 29 : 28; } } // 1 = Monday, 7 = Sunday function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) { uint _days = timestamp / SECONDS_PER_DAY; dayOfWeek = (_days + 3) % 7 + 1; } function getYear(uint timestamp) internal pure returns (uint year) { (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getMonth(uint timestamp) internal pure returns (uint month) { (,month,) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getDay(uint timestamp) internal pure returns (uint day) { (,,day) = _daysToDate(timestamp / SECONDS_PER_DAY); } function getHour(uint timestamp) internal pure returns (uint hour) { uint secs = timestamp % SECONDS_PER_DAY; hour = secs / SECONDS_PER_HOUR; } function getMinute(uint timestamp) internal pure returns (uint minute) { uint secs = timestamp % SECONDS_PER_HOUR; minute = secs / SECONDS_PER_MINUTE; } function getSecond(uint timestamp) internal pure returns (uint second) { second = timestamp % SECONDS_PER_MINUTE; } function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY); year += _years; uint daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; require(newTimestamp >= timestamp); } function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY); month += _months; year += (month - 1) / 12; month = (month - 1) % 12 + 1; uint daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; require(newTimestamp >= timestamp); } function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { newTimestamp = timestamp + _days * SECONDS_PER_DAY; require(newTimestamp >= timestamp); } function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { newTimestamp = timestamp + _hours * SECONDS_PER_HOUR; require(newTimestamp >= timestamp); } function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE; require(newTimestamp >= timestamp); } function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { newTimestamp = timestamp + _seconds; require(newTimestamp >= timestamp); } function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY); year -= _years; uint daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; require(newTimestamp <= timestamp); } function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) { (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint yearMonth = year * 12 + (month - 1) - _months; year = yearMonth / 12; month = yearMonth % 12 + 1; uint daysInMonth = _getDaysInMonth(year, month); if (day > daysInMonth) { day = daysInMonth; } newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY; require(newTimestamp <= timestamp); } function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) { newTimestamp = timestamp - _days * SECONDS_PER_DAY; require(newTimestamp <= timestamp); } function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) { newTimestamp = timestamp - _hours * SECONDS_PER_HOUR; require(newTimestamp <= timestamp); } function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) { newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE; require(newTimestamp <= timestamp); } function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) { newTimestamp = timestamp - _seconds; require(newTimestamp <= timestamp); } function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) { require(fromTimestamp <= toTimestamp); (uint fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); (uint toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); _years = toYear - fromYear; } function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) { require(fromTimestamp <= toTimestamp); (uint fromYear, uint fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY); (uint toYear, uint toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY); _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth; } function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) { require(fromTimestamp <= toTimestamp); _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY; } function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) { require(fromTimestamp <= toTimestamp); _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR; } function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) { require(fromTimestamp <= toTimestamp); _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE; } function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) { require(fromTimestamp <= toTimestamp); _seconds = toTimestamp - fromTimestamp; } }
pragma solidity ^0.6.6; import "./SafeMath.sol"; import "./IERC20.sol"; /** * @title ERC20 * @dev Base implementation of ERC20 token. */ abstract contract ERC20 is IERC20 { using SafeMath for uint256; uint256 private _totalSupply; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; function name() public view virtual returns(string memory); function symbol() public view virtual returns(string memory); function decimals() public view virtual returns(uint8); function totalSupply() public view override returns(uint256) { return _totalSupply; } function balanceOf(address account) public view override returns(uint256) { return _balances[account]; } function allowance(address owner, address spender) public view override returns(uint256) { return _allowances[owner][spender]; } function transfer(address recipient, uint256 amount) public override returns(bool) { _transfer(msg.sender, recipient, amount); return true; } function transferFrom(address sender, address recipient, uint256 amount) public override returns(bool) { _approveAction(sender, msg.sender, _allowances[sender][msg.sender].sub(amount)); _transfer(sender, recipient, amount); return true; } function approve(address spender, uint256 amount) public override returns(bool) { _approve(msg.sender, spender, amount); return true; } function increaseAllowance(address spender, uint256 amount) public returns(bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].add(amount)); return true; } function decreaseAllowance(address spender, uint256 amount) public returns(bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(amount)); return true; } function _transfer(address sender, address recipient, uint256 amount) internal virtual { _transferAction(sender, recipient, amount); } function _approve(address owner, address spender, uint256 amount) internal virtual { _approveAction(owner, spender, amount); } function _burnFrom(address account, uint256 amount) internal { _approveAction(account, msg.sender, _allowances[account][msg.sender].sub(amount)); _burnAction(account, amount); } function _transferAction(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20::_transferAction: Invalid sender"); require(recipient != address(0), "ERC20::_transferAction: Invalid recipient"); _balances[sender] = _balances[sender].sub(amount); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } function _approveAction(address owner, address spender, uint256 amount) internal { require(owner != address(0), "ERC20::_approveAction: Invalid owner"); require(spender != address(0), "ERC20::_approveAction: Invalid spender"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _mintAction(address account, uint256 amount) internal { require(account != address(0), "ERC20::_mintAction: Invalid account"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } function _burnAction(address account, uint256 amount) internal { require(account != address(0), "ERC20::_burnAction: Invalid account"); _balances[account] = _balances[account].sub(amount); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } }
pragma solidity ^0.6.6; // Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts /** * @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); }
pragma solidity ^0.6.6; // Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts /** * @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, 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) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * 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); uint256 c = a - b; return c; } /** * @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) { // 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 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts 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) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts 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) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.6.6; // Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts /** * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = value; while (temp != 0) { buffer[index--] = byte(uint8(48 + temp % 10)); temp /= 10; } return string(buffer); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"paidAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"Assigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"CollateralWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenCollateralizedAmount","type":"uint256"}],"name":"TransferCollateralOwnership","type":"event"},{"inputs":[],"name":"acoFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"assignableCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"assignableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"burnFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"currentCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"currentCollateralizedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"}],"name":"exercise","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"exerciseAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"exerciseAccountsFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"}],"name":"exerciseFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"expiryTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDestination","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getBaseExerciseData","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getCollateralAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"getCollateralOnExercise","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"getTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"address","name":"_strikeAsset","type":"address"},{"internalType":"bool","name":"_isCall","type":"bool"},{"internalType":"uint256","name":"_strikePrice","type":"uint256"},{"internalType":"uint256","name":"_expiryTime","type":"uint256"},{"internalType":"uint256","name":"_acoFee","type":"uint256"},{"internalType":"address payable","name":"_feeDestination","type":"address"},{"internalType":"uint256","name":"_maxExercisedAccounts","type":"uint256"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxExercisedAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintPayable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"mintTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"mintToPayable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfAccountsWithCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"redeemFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strikeAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strikeAssetDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strikeAssetSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strikePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"tokenCollateralizedAmount","type":"uint256"}],"name":"transferCollateralOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unassignableCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unassignableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b50614751806100206000396000f3fe6080604052600436106102cd5760003560e01c806379cc679011610175578063a95ad147116100dc578063c52987cf11610095578063d90a730e1161006f578063d90a730e14610b62578063dd62ed3e14610b77578063de53fcd514610bb2578063e503d23914610bc7576102d7565b8063c52987cf14610b05578063c54e486214610b1a578063d8dfeb4514610b4d576102d7565b8063a95ad147146109ea578063b0df1cc714610a61578063bdc7c12b14610a87578063be040fb014610ab1578063c132566114610ac6578063c2507ac114610adb576102d7565b806399bc0aea1161012e57806399bc0aea146108e35780639c83c847146108f8578063a0712d681461092b578063a457c2d714610955578063a86265bb1461098e578063a9059cbb146109b1576102d7565b806379cc67901461075b5780637c974fc41461079457806387ab4a18146108195780638ff1516b1461084c5780639152cb591461087f57806395d89b41146102dc576102d7565b8063449a52f8116102345780634dd662ee116101ed5780636f012b8d116101c75780636f012b8d146106c85780636f307dc31461070b57806370a0823114610720578063732a950d14610753576102d7565b80634dd662ee146106515780635d97d3e2146106665780636d636478146106b3576102d7565b8063449a52f81461054e57806345f79d1b14610587578063464673c6146105ba5780634701eaa8146105f5578063477130981461060a5780634ac8eb5f1461063c576102d7565b806325a760c21161028657806325a760c214610463578063313a9b4e1461048e578063313ce567146104a357806339509351146104b85780633acc3af2146104f157806342966c6814610524576102d7565b806306fdde03146102dc578063095ea7b31461036657806311b7bda7146103b357806317d69bc8146103c857806318160ddd146103f957806323b872dd14610420576102d7565b366102d757600080fd5b600080fd5b3480156102e857600080fd5b506102f1610bfa565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561032b578181015183820152602001610313565b50505050905090810190601f1680156103585780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037257600080fd5b5061039f6004803603604081101561038957600080fd5b506001600160a01b038135169060200135610c0a565b604080519115158252519081900360200190f35b3480156103bf57600080fd5b506102f1610c21565b3480156103d457600080fd5b506103dd610caf565b604080516001600160a01b039092168252519081900360200190f35b34801561040557600080fd5b5061040e610cbe565b60408051918252519081900360200190f35b34801561042c57600080fd5b5061039f6004803603606081101561044357600080fd5b506001600160a01b03813581169160208101359091169060400135610cc4565b34801561046f57600080fd5b50610478610d18565b6040805160ff9092168252519081900360200190f35b34801561049a57600080fd5b5061040e610d21565b3480156104af57600080fd5b50610478610d27565b3480156104c457600080fd5b5061039f600480360360408110156104db57600080fd5b506001600160a01b038135169060200135610d30565b3480156104fd57600080fd5b5061040e6004803603602081101561051457600080fd5b50356001600160a01b0316610d71565b34801561053057600080fd5b5061040e6004803603602081101561054757600080fd5b5035610d8c565b34801561055a57600080fd5b5061040e6004803603604081101561057157600080fd5b506001600160a01b038135169060200135610d98565b34801561059357600080fd5b5061040e600480360360208110156105aa57600080fd5b50356001600160a01b0316610e1e565b3480156105c657600080fd5b506105f3600480360360408110156105dd57600080fd5b506001600160a01b038135169060200135610e39565b005b34801561060157600080fd5b5061040e610fe5565b61040e6004803603606081101561062057600080fd5b506001600160a01b038135169060208101359060400135610feb565b34801561064857600080fd5b5061040e610ff8565b34801561065d57600080fd5b5061040e610ffe565b34801561067257600080fd5b506106906004803603602081101561068957600080fd5b5035611004565b604080516001600160a01b03909316835260208301919091528051918290030190f35b3480156106bf57600080fd5b5061039f61104e565b3480156106d457600080fd5b506106f2600480360360208110156106eb57600080fd5b503561105e565b6040805192835260208301919091528051918290030190f35b34801561071757600080fd5b506103dd6110b4565b34801561072c57600080fd5b5061040e6004803603602081101561074357600080fd5b50356001600160a01b03166110c3565b61040e6110de565b34801561076757600080fd5b5061040e6004803603604081101561077e57600080fd5b506001600160a01b038135169060200135611135565b61040e600480360360608110156107aa57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156107da57600080fd5b8201836020820111156107ec57600080fd5b8035906020019184602083028401116401000000008311171561080e57600080fd5b509092509050611148565b34801561082557600080fd5b5061040e6004803603602081101561083c57600080fd5b50356001600160a01b0316611191565b34801561085857600080fd5b5061040e6004803603602081101561086f57600080fd5b50356001600160a01b03166111b8565b34801561088b57600080fd5b506105f360048036036101008110156108a357600080fd5b506001600160a01b0381358116916020810135821691604082013515159160608101359160808201359160a08101359160c0820135169060e001356111c6565b3480156108ef57600080fd5b5061040e61164c565b34801561090457600080fd5b5061040e6004803603602081101561091b57600080fd5b50356001600160a01b0316611652565b34801561093757600080fd5b5061040e6004803603602081101561094e57600080fd5b5035611660565b34801561096157600080fd5b5061039f6004803603604081101561097857600080fd5b506001600160a01b0381351690602001356116de565b61040e600480360360408110156109a457600080fd5b508035906020013561171a565b3480156109bd57600080fd5b5061039f600480360360408110156109d457600080fd5b506001600160a01b038135169060200135611727565b61040e60048036036040811015610a0057600080fd5b81359190810190604081016020820135640100000000811115610a2257600080fd5b820183602082011115610a3457600080fd5b80359060200191846020830284011164010000000083111715610a5657600080fd5b509092509050611734565b61040e60048036036020811015610a7757600080fd5b50356001600160a01b0316611774565b348015610a9357600080fd5b5061040e60048036036020811015610aaa57600080fd5b50356117c6565b348015610abd57600080fd5b5061040e6117f1565b348015610ad257600080fd5b506104786117fc565b348015610ae757600080fd5b5061040e60048036036020811015610afe57600080fd5b503561180a565b348015610b1157600080fd5b5061040e611847565b348015610b2657600080fd5b5061040e60048036036020811015610b3d57600080fd5b50356001600160a01b031661184d565b348015610b5957600080fd5b506103dd6118b8565b348015610b6e57600080fd5b506102f16118f1565b348015610b8357600080fd5b5061040e60048036036040811015610b9a57600080fd5b506001600160a01b038135811691602001351661194c565b348015610bbe57600080fd5b506103dd611977565b348015610bd357600080fd5b5061040e60048036036020811015610bea57600080fd5b50356001600160a01b0316611986565b6060610c046119e6565b90505b90565b6000610c17338484611c17565b5060015b92915050565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ca75780601f10610c7c57610100808354040283529160200191610ca7565b820191906000526020600020905b815481529060010190602001808311610c8a57829003601f168201915b505050505081565b6004546001600160a01b031681565b60005490565b6001600160a01b0383166000908152600260209081526040808320338085529252822054610d03918691610cfe908663ffffffff611c2716565b611c69565b610d0e848484611d55565b5060019392505050565b600c5460ff1681565b600d5481565b600c5460ff1690565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610c17918590610d6c908663ffffffff611d6016565b611c17565b6000610d84610d7f83611191565b6117c6565b90505b919050565b6000610d843383611dba565b600080610da36118b8565b9050610dae81611e8c565b15610e00576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a6d696e74546f3a20496e76616c69642063616c6c0000604482015290519081900360640190fd5b610e0c81333086611e99565b610e168484612022565b949350505050565b6001600160a01b03166000908152600f602052604090205490565b6001600160a01b038216610e7e5760405162461bcd60e51b81526004018080602001828103825260388152602001806143426038913960400191505060405180910390fd5b60008111610ebd5760405162461bcd60e51b81526004018080602001828103825260358152602001806144a96035913960400191505060405180910390fd5b336000908152600f602052604090208054610ede908363ffffffff611c2716565b8155610ee93361225d565b6001600160a01b0383166000908152600f60205260409020610f0a8161236d565b15610f28578054610f21908463ffffffff611d6016565b8155610f9f565b6040805180820182528481526010805460208084019182526001600160a01b0389166000818152600f90925294812093518455905160019384015581549283018255527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b6040805184815290516001600160a01b0386169133917ff268b386023666001c794e23f1bc2285c15f9ae8db3025abbc16bf45edc6d08d9181900360200190a350505050565b60095481565b6000610e16848484612373565b60085481565b60105490565b6005546000908190600160a01b900460ff1615611039576004546001600160a01b031661103084612419565b91509150611049565b50506003546001600160a01b0316815b915091565b600554600160a01b900460ff1681565b600080600061106c846117c6565b90506000611098620186a061108c6009548561243690919063ffffffff16565b9063ffffffff61248f16565b90506110aa828263ffffffff611c2716565b9350915050915091565b6003546001600160a01b031681565b6001600160a01b031660009081526001602052604090205490565b60006110f06110eb6118b8565b611e8c565b61112b5760405162461bcd60e51b81526004018080602001828103825260238152602001806145d36023913960400191505060405180910390fd5b610c043334612022565b60006111418383611dba565b9392505050565b600061118885858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506124d192505050565b95945050505050565b600061119b612543565b156111b0576111a98261254b565b9050610d87565b506000610d87565b6000610d84610d7f83610e1e565b6003546001600160a01b03161580156111e857506004546001600160a01b0316155b80156111f45750600654155b61122f5760405162461bcd60e51b815260040180806020018281038252602381526020018061464f6023913960400191505060405180910390fd5b428411611283576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a696e69743a20496e76616c6964206578706972790000604482015290519081900360640190fd5b600085116112c25760405162461bcd60e51b815260040180806020018281038252602481526020018061439d6024913960400191505060405180910390fd5b866001600160a01b0316886001600160a01b03161415611329576040805162461bcd60e51b815260206004820152601b60248201527f41434f546f6b656e3a3a696e69743a2053616d65206173736574730000000000604482015290519081900360640190fd5b6101f4831115611380576040805162461bcd60e51b815260206004820152601f60248201527f41434f546f6b656e3a3a696e69743a20496e76616c69642041434f2066656500604482015290519081900360640190fd5b61138988611e8c565b806113a157506113a1886001600160a01b03166125a6565b6113dc5760405162461bcd60e51b81526004018080602001828103825260228152602001806141e66022913960400191505060405180910390fd5b6113e587611e8c565b806113fd57506113fd876001600160a01b03166125a6565b6114385760405162461bcd60e51b81526004018080602001828103825260248152602001806145f66024913960400191505060405180910390fd5b6019811015801561144a575060968111155b6114855760405162461bcd60e51b815260040180806020018281038252603881526020018061430a6038913960400191505060405180910390fd5b600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a84161790556005805460068990556007889055600987905560ff60a01b1916600160a01b8a15150217909116918416919091179055600d8190556114f1886125df565b600c805460ff191660ff9283161790819055604e9116106115435760405162461bcd60e51b815260040180806020018281038252602b815260200180614237602b913960400191505060405180910390fd5b61154c876125df565b600c60016101000a81548160ff021916908360ff16021790555061156f88612724565b805161158391600a916020909101906140e7565b5061158d87612724565b80516115a191600b916020909101906140e7565b50600c5460ff16600a0a600e55604080518082018252601981527f7472616e7366657228616464726573732c75696e7432353629000000000000006020918201526011805464ffffffff00191664a9059cbb001790558151606081019092526025808352906142629083013980516020909101206011805460ff1960e09390931c650100000000000268ffffffff000000000019909116179190911660011790555050505050505050565b60075481565b6000610d84610d7f83611986565b60008061166b6118b8565b905061167681611e8c565b156116c8576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a6d696e743a20496e76616c69642063616c6c00000000604482015290519081900360640190fd5b6116d481333086611e99565b6111413384612022565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610c17918590610d6c908663ffffffff611c2716565b6000611141338484612373565b6000610c17338484611d55565b6000610e1633858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506124d192505050565b60006117816110eb6118b8565b6117bc5760405162461bcd60e51b81526004018080602001828103825260258152602001806142bb6025913960400191505060405180910390fd5b610d848234612022565b600554600090600160a01b900460ff16156117e2575080610d87565b81156111b0576111a982612419565b6000610c043361292e565b600c54610100900460ff1681565b600554600090600160a01b900460ff1615611826575080610d87565b81156111b0576111a960065461108c600e548561243690919063ffffffff16565b60065481565b6000611859823361194c565b6001600160a01b0383166000908152600f602052604090205411156118af5760405162461bcd60e51b81526004018080602001828103825260278152602001806145ac6027913960400191505060405180910390fd5b610d848261292e565b600554600090600160a01b900460ff16156118df57506003546001600160a01b0316610c07565b506004546001600160a01b0316610c07565b600a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ca75780601f10610c7c57610100808354040283529160200191610ca7565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6005546001600160a01b031681565b6001600160a01b0381166000908152600f60205260408120546119a8836110c3565b11806119b957506119b7612543565b155b156119dd57506001600160a01b0381166000908152600f6020526040902054610d87565b6111a9826110c3565b6060600a611a05600654600c60019054906101000a900460ff16612a16565b600554600b90611a1e90600160a01b900460ff16612bbe565b611a29600754612c02565b604051602001808063020a1a7960e51b81525060040186805460018160011615610100020316600290048015611a965780601f10611a74576101008083540402835291820191611a96565b820191906000526020600020905b815481529060010190602001808311611a82575b505080602d60f81b81525060010185805190602001908083835b60208310611acf5780518252601f199092019160209182019101611ab0565b6001836020036101000a03801982511681845116808217855250505050505090500184805460018160011615610100020316600290048015611b485780601f10611b26576101008083540402835291820191611b48565b820191906000526020600020905b815481529060010190602001808311611b34575b505080602d60f81b81525060010183805190602001908083835b60208310611b815780518252601f199092019160209182019101611b62565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010182805190602001908083835b60208310611bda5780518252601f199092019160209182019101611bbb565b6001836020036101000a03801982511681845116808217855250505050505090500195505050505050604051602081830303815290604052905090565b611c22838383611c69565b505050565b600061114183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e00565b6001600160a01b038316611cae5760405162461bcd60e51b81526004018080602001828103825260248152602001806146c76024913960400191505060405180910390fd5b6001600160a01b038216611cf35760405162461bcd60e51b81526004018080602001828103825260268152602001806145566026913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b611c22838383612e97565b600082820183811015611141576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60115460009060ff16611e08576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611e1a612543565b611e5f576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000611e6b8484612fdb565b9050611e7784846130a9565b90506011805460ff1916600117905592915050565b6001600160a01b03161590565b601154604080516001600160a01b0386811660248301528581166044830152606480830186905283518084039091018152608490920183526020820180516501000000000090950460e01b6001600160e01b0319166001600160e01b03909516949094178452915181516000946060948a169392918291908083835b60208310611f345780518252601f199092019160209182019101611f15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611f96576040519150601f19603f3d011682016040523d82523d6000602084013e611f9b565b606091505b5091509150818015611fc9575080511580611fc95750808060200190516020811015611fc657600080fd5b50515b61201a576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a5f7472616e7366657246726f6d455243323000000000604482015290519081900360640190fd5b505050505050565b60115460009060ff16612070576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055612082612543565b6120c7576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b600082116121065760405162461bcd60e51b815260040180806020018281038252602f815260200180614208602f913960400191505060405180910390fd5b61210f836130d3565b61217357601080546001600160a01b0385166000818152600f60205260408120600190810184905583018455929092527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b600061217e8361180a565b9050806121bc5760405162461bcd60e51b815260040180806020018281038252602a8152602001806142e0602a913960400191505060405180910390fd5b6001600160a01b0384166000908152600f60205260409020546121e5908263ffffffff611d6016565b6001600160a01b0385166000908152600f6020526040902055600854612211908463ffffffff611d6016565b6008556040805184815290516001600160a01b038616917ff645c19720906ca336d36d26058a9489c6c757fe35843b75a74e3b8aa972ecf5919081900360200190a2611e7733826130f4565b6001600160a01b0381166000908152600f6020526040902061227e8161236d565b61236957601054600182015460001990910190811461231b576000601082815481106122a657fe5b60009182526020808320909101546001868101546001600160a01b03909216808552600f9093526040909320909201829055601080549193508392909181106122eb57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b601080548061232657fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600f90526040812081815560010155505b5050565b54151590565b60115460009060ff166123c1576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055600d546123db90859085906131cf565b6123e68484846133a7565b6000806123f28561105e565b91509150612401868383613552565b925050506011805460ff191660011790559392505050565b6000610d84600e5461108c6006548561243690919063ffffffff16565b60008261244557506000610c1b565b8282028284828161245257fe5b04146111415760405162461bcd60e51b81526004018080602001828103825260218152602001806144586021913960400191505060405180910390fd5b600061114183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613682565b60115460009060ff1661251f576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055815161253890859085906131cf565b6123e68484846136e7565b600754421090565b6000612556826110c3565b6001600160a01b0383166000908152600f602052604090205411156111b0576111a9612581836110c3565b6001600160a01b0384166000908152600f60205260409020549063ffffffff611c2716565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610e16575050151592915050565b60006125ea82611e8c565b156125f757506012610d87565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b178152915181516000936060936001600160a01b038816939092909182918083835b6020831061265d5780518252601f19909201916020918201910161263e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146126bd576040519150601f19603f3d011682016040523d82523d6000602084013e6126c2565b606091505b5091509150816127035760405162461bcd60e51b81526004018080602001828103825260338152602001806141b36033913960400191505060405180910390fd5b80806020019051602081101561271857600080fd5b50519250610d87915050565b606061272f82611e8c565b15612754575060408051808201909152600381526208aa8960eb1b6020820152610d87565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106127ba5780518252601f19909201916020918201910161279b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461281a576040519150601f19603f3d011682016040523d82523d6000602084013e61281f565b606091505b5091509150816128605760405162461bcd60e51b815260040180806020018281038252602f815260200180614672602f913960400191505060405180910390fd5b80806020019051602081101561287557600080fd5b810190808051604051939291908464010000000082111561289557600080fd5b9083019060208201858111156128aa57600080fd5b82516401000000008111828201881017156128c457600080fd5b82525081516020918201929091019080838360005b838110156128f15781810151838201526020016128d9565b50505050905090810190601f16801561291e5780820380516001836020036101000a031916815260200191505b5060405250505092505050610d87565b60115460009060ff1661297c576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905561298e612543565b156129ca5760405162461bcd60e51b815260040180806020018281038252602881526020018061452e6028913960400191505060405180910390fd5b6001600160a01b0382166000908152600f60205260408120546129ee908490612fdb565b9050612a02836129fd856110c3565b61377f565b90506011805460ff19166001179055919050565b6060600080808086805b8115612a7b5783158015612a425750600a8206151580612a4257508760ff1685145b15612a4e575060019250805b8315612a6a578760ff16851415612a63578592505b6001909501945b600a82600190960195049150612a20565b8760ff168511612a9d57848860ff168760020101039550600286039250612aaa565b8215612aaa576001909501945b60608667ffffffffffffffff81118015612ac357600080fd5b506040519080825280601f01601f191660200182016040528015612aee576020820181803683370190505b5091925082919050600019870160005b88811015612bae57600081118015612b1557508581145b15612b4e57601760f91b83838060019003945081518110612b3257fe5b60200101906001600160f81b031916908160001a905350612ba6565b83612b6b57600360fc1b83838060019003945081518110612b3257fe5b600a840660300160f81b83838060019003945081518110612b8857fe5b60200101906001600160f81b031916908160001a905350600a840493505b600101612afe565b50909a9950505050505050505050565b60608115612be457506040805180820190915260018152604360f81b6020820152610d87565b506040805180820190915260018152600560fc1b6020820152610d87565b60606000806000806000612c1587613862565b5094509450945094509450612c29836138a2565b612c3285613934565b612c3b87613b46565b612c44856138a2565b612c4d856138a2565b6040516020018086805190602001908083835b60208310612c7f5780518252601f199092019160209182019101612c60565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b60208310612cc75780518252601f199092019160209182019101612ca8565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b60208310612d0f5780518252601f199092019160209182019101612cf0565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010183805190602001908083835b60208310612d685780518252601f199092019160209182019101612d49565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612db05780518252601f199092019160209182019101612d91565b5181516020939093036101000a60001901801990911692169190911790526255544360e81b92019182525060408051808303601c19018152600390920190529d9c50505050505050505050505050565b60008184841115612e8f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e54578181015183820152602001612e3c565b50505050905090810190601f168015612e815780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316612edc5760405162461bcd60e51b81526004018080602001828103825260268152602001806146a16026913960400191505060405180910390fd5b6001600160a01b038216612f215760405162461bcd60e51b81526004018080602001828103825260298152602001806143f96029913960400191505060405180910390fd5b6001600160a01b038316600090815260016020526040902054612f4a908263ffffffff611c2716565b6001600160a01b038085166000908152600160205260408082209390935590841681522054612f7f908263ffffffff611d6016565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000612fe6836130d3565b6130215760405162461bcd60e51b81526004018080602001828103825260348152602001806142876034913960400191505060405180910390fd5b600082116130605760405162461bcd60e51b81526004018080602001828103825260318152602001806146eb6031913960400191505060405180910390fd5b6001600160a01b0383166000908152600f60205260409020805461308a908463ffffffff611c2716565b81556130958461225d565b610e16846130a2856117c6565b6000613552565b6001600160a01b0382163314156130c9576130c4828261377f565b612369565b6123698282613bd6565b6001600160a01b0381166000908152600f60205260408120610d849061236d565b6001600160a01b0382166131395760405162461bcd60e51b81526004018080602001828103825260238152602001806144de6023913960400191505060405180910390fd5b60005461314c908263ffffffff611d6016565b60009081556001600160a01b038316815260016020526040902054613177908263ffffffff611d6016565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6131d7612543565b61321c576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000821161325b5760405162461bcd60e51b81526004018080602001828103825260308152602001806144796030913960400191505060405180910390fd5b613264836130d3565b156132d9576001600160a01b0383166000908152600f602052604090205461329b9061328f856110c3565b9063ffffffff611c2716565b8211156132d95760405162461bcd60e51b81526004018080602001828103825260368152602001806144226036913960400191505060405180910390fd5b6132e383836130a9565b6000806132ef84611004565b9092509050613304818463ffffffff611d6016565b905061330f82611e8c565b15613357578034146133525760405162461bcd60e51b815260040180806020018281038252603081526020018061457c6030913960400191505060405180910390fd5b6133a0565b34156133945760405162461bcd60e51b815260040180806020018281038252602d815260200180614501602d913960400191505060405180910390fd5b6133a082333084611e99565b5050505050565b60105460009081906133c090849063ffffffff613c1b16565b90508060005b6000861180156133d7575060105481105b1561348657600061340a601084815481106133ee57fe5b6000918252602090912001546001600160a01b0316888a613c5d565b90508681101561346357600d54600190950194851080613428575080155b6134635760405162461bcd60e51b81526004018080602001828103825260388152602001806143c16038913960400191505060405180910390fd5b601054909650600190920191869083141561347d57600092505b506001016133c6565b85156134c35760405162461bcd60e51b81526004018080602001828103825260338152602001806141806033913960400191505060405180910390fd5b600080836134d55760105493506134e9565b8484116134e9575050601054916000190160015b60005b83811015613546576000199094019381801561350757508585105b1561351457829450600091505b61353e6010868154811061352457fe5b6000918252602090912001546001600160a01b031661225d565b6001016134ec565b50505050505050505050565b6000613576613567848463ffffffff611d6016565b6008549063ffffffff611c2716565b60085560006135836118b8565b905061358e81611e8c565b1561360857604051339085156108fc029086906000818181858888f193505050501580156135c0573d6000803e3d6000fd5b508215613603576005546040516001600160a01b039091169084156108fc029085906000818181858888f19350505050158015613601573d6000803e3d6000fd5b505b613631565b613613813386613d9f565b8215613631576005546136319082906001600160a01b031685613d9f565b6040805185815260208101859052815133926001600160a01b038916927fd3506bcc260407a7f95f487dd7c600bc45888cce58989ceadbe8c0bbf9257b28929081900390910190a350919392505050565b600081836136d15760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e54578181015183820152602001612e3c565b5060008385816136dd57fe5b0495945050505050565b60005b815181101561374157826136fd57613741565b61371b82828151811061370c57fe5b60200260200101518486613c5d565b925061373982828151811061372c57fe5b602002602001015161225d565b6001016136ea565b508115611c225760405162461bcd60e51b815260040180806020018281038252603581526020018061461a6035913960400191505060405180910390fd5b6001600160a01b0382166137c45760405162461bcd60e51b815260040180806020018281038252602381526020018061437a6023913960400191505060405180910390fd5b6001600160a01b0382166000908152600160205260409020546137ed908263ffffffff611c2716565b6001600160a01b0383166000908152600160205260408120919091555461381a908263ffffffff611c2716565b60009081556040805183815290516001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b60008080808080613877620151808804613f14565b91999098919750610e10620151809092068281049750603c9290068281049650919091069350915050565b6060806138ae83613faa565b9050600a8310156111a957806040516020018080600360fc1b81525060010182805190602001908083835b602083106138f85780518252601f1990920191602091820191016138d9565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052915050610d87565b6060816001141561395f57506040805180820190915260038152622520a760e91b6020820152610d87565b816002141561398857506040805180820190915260038152622322a160e91b6020820152610d87565b81600314156139b1575060408051808201909152600381526226a0a960e91b6020820152610d87565b81600414156139da575060408051808201909152600381526220a82960e91b6020820152610d87565b8160051415613a0357506040805180820190915260038152624d415960e81b6020820152610d87565b8160061415613a2c5750604080518082019091526003815262252aa760e91b6020820152610d87565b8160071415613a55575060408051808201909152600381526212955360ea1b6020820152610d87565b8160081415613a7e575060408051808201909152600381526241554760e81b6020820152610d87565b8160091415613aa7575060408051808201909152600381526205345560ec1b6020820152610d87565b81600a1415613ad0575060408051808201909152600381526213d0d560ea1b6020820152610d87565b81600b1415613af957506040805180820190915260038152622727ab60e91b6020820152610d87565b81600c1415613b22575060408051808201909152600381526244454360e81b6020820152610d87565b506040805180820190915260078152661253959053125160ca1b6020820152610d87565b606080613b5283613faa565b60408051600280825281830190925291925060609190602082018180368337505083519192505060011901805b8351811015613bcc57838181518110613b9457fe5b602001015160f81c60f81b8383830381518110613bad57fe5b60200101906001600160f81b031916908160001a905350600101613b7f565b5090949350505050565b6001600160a01b038216600090815260026020908152604080832033808552925290912054613c11918491610cfe908563ffffffff611c2716565b612369828261377f565b600061114183836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250614085565b600080613c698561254b565b90508015613d96576001600160a01b0385166000908152600f602052604081209085831015613cab575081613ca4868263ffffffff611c2716565b9550613cb0565b506000945b600080613cbc83611004565b9092509050613cd281600163ffffffff611d6016565b8454909150613ce7908463ffffffff611c2716565b8455613cf282611e8c565b15613d33576040516001600160a01b038a169082156108fc029083906000818181858888f19350505050158015613d2d573d6000803e3d6000fd5b50613d3e565b613d3e828a83613d9f565b866001600160a01b0316896001600160a01b03167f5f283076724262032199f54be27a9364634b895b3a37c1e66bfe47d5d05347698386604051808381526020018281526020019250505060405180910390a3505050505b50919392505050565b601154604080516001600160a01b0385811660248301526044808301869052835180840390910181526064909201835260208201805161010090950460e01b6001600160e01b0319166001600160e01b039095169490941784529151815160009460609489169392918291908083835b60208310613e2e5780518252601f199092019160209182019101613e0f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613e90576040519150601f19603f3d011682016040523d82523d6000602084013e613e95565b606091505b5091509150818015613ec3575080511580613ec35750808060200190516020811015613ec057600080fd5b50515b6133a0576040805162461bcd60e51b815260206004820152601860248201527f41434f546f6b656e3a3a5f7472616e7366657245524332300000000000000000604482015290519081900360640190fd5b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f8460500281613f6b57fe5b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b606081613fcf57506040805180820190915260018152600360fc1b6020820152610d87565b8160005b8115613fe757600101600a82049150613fd3565b60608167ffffffffffffffff8111801561400057600080fd5b506040519080825280601f01601f19166020018201604052801561402b576020820181803683370190505b50859350905060001982015b831561407c57600a840660300160f81b8282806001900393508151811061405a57fe5b60200101906001600160f81b031916908160001a905350600a84049350614037565b50949350505050565b600081836140d45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e54578181015183820152602001612e3c565b508284816140de57fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061412857805160ff1916838001178555614155565b82800160010185558215614155579182015b8281111561415557825182559160200191906001019061413a565b50614161929150614165565b5090565b610c0791905b80821115614161576000815560010161416b56fe41434f546f6b656e3a3a5f65786572636973654f776e6572733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a5f6765744173736574446563696d616c733a20496e76616c696420617373657420646563696d616c7341434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6741434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420636f6c6c61746572616c20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6720646563696d616c737472616e7366657246726f6d28616464726573732c616464726573732c75696e743235362941434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a204e6f20636f6c6c61746572616c20617661696c61626c6541434f546f6b656e3a3a6d696e74546f50617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c6964206e756d62657220746f206d617820657865726369736564206163636f756e747341434f546f6b656e3a3a7472616e73666572436f6c6c61746572616c4f776e6572736869703a20496e76616c696420726563697069656e7445524332303a3a5f6275726e416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520707269636541434f546f6b656e3a3a5f65786572636973654f776e6572733a20546f6f206d616e79206163636f756e747320746f20657865726369736545524332303a3a5f7472616e73666572416374696f6e3a20496e76616c696420726563697069656e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20546f6b656e20616d6f756e74206e6f7420617661696c61626c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7741434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a7472616e73666572436f6c6c61746572616c4f776e6572736869703a20496e76616c696420616d6f756e7445524332303a3a5f6d696e74416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a204e6f20657468657220657870656374656441434f546f6b656e3a3a5f72656465656d3a20546f6b656e206e6f7420657870697265642079657445524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964207370656e64657241434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420657468657220616d6f756e7441434f546f6b656e3a3a72656465656d46726f6d3a20416c6c6f77616e636520746f6f206c6f7741434f546f6b656e3a3a6d696e7450617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520617373657441434f546f6b656e3a3a5f65786572636973654163636f756e74733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a696e69743a20416c726561647920696e697469616c697a656441434f546f6b656e3a3a5f676574417373657453796d626f6c3a20496e76616c69642061737365742073796d626f6c45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c69642073656e64657245524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964206f776e657241434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a20496e76616c696420746f6b656e20616d6f756e74a2646970667358221220cb30ae80319463574ff120f520633d68378fa215960c0dd60da4052df64ca49164736f6c63430006060033
Deployed Bytecode
0x6080604052600436106102cd5760003560e01c806379cc679011610175578063a95ad147116100dc578063c52987cf11610095578063d90a730e1161006f578063d90a730e14610b62578063dd62ed3e14610b77578063de53fcd514610bb2578063e503d23914610bc7576102d7565b8063c52987cf14610b05578063c54e486214610b1a578063d8dfeb4514610b4d576102d7565b8063a95ad147146109ea578063b0df1cc714610a61578063bdc7c12b14610a87578063be040fb014610ab1578063c132566114610ac6578063c2507ac114610adb576102d7565b806399bc0aea1161012e57806399bc0aea146108e35780639c83c847146108f8578063a0712d681461092b578063a457c2d714610955578063a86265bb1461098e578063a9059cbb146109b1576102d7565b806379cc67901461075b5780637c974fc41461079457806387ab4a18146108195780638ff1516b1461084c5780639152cb591461087f57806395d89b41146102dc576102d7565b8063449a52f8116102345780634dd662ee116101ed5780636f012b8d116101c75780636f012b8d146106c85780636f307dc31461070b57806370a0823114610720578063732a950d14610753576102d7565b80634dd662ee146106515780635d97d3e2146106665780636d636478146106b3576102d7565b8063449a52f81461054e57806345f79d1b14610587578063464673c6146105ba5780634701eaa8146105f5578063477130981461060a5780634ac8eb5f1461063c576102d7565b806325a760c21161028657806325a760c214610463578063313a9b4e1461048e578063313ce567146104a357806339509351146104b85780633acc3af2146104f157806342966c6814610524576102d7565b806306fdde03146102dc578063095ea7b31461036657806311b7bda7146103b357806317d69bc8146103c857806318160ddd146103f957806323b872dd14610420576102d7565b366102d757600080fd5b600080fd5b3480156102e857600080fd5b506102f1610bfa565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561032b578181015183820152602001610313565b50505050905090810190601f1680156103585780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561037257600080fd5b5061039f6004803603604081101561038957600080fd5b506001600160a01b038135169060200135610c0a565b604080519115158252519081900360200190f35b3480156103bf57600080fd5b506102f1610c21565b3480156103d457600080fd5b506103dd610caf565b604080516001600160a01b039092168252519081900360200190f35b34801561040557600080fd5b5061040e610cbe565b60408051918252519081900360200190f35b34801561042c57600080fd5b5061039f6004803603606081101561044357600080fd5b506001600160a01b03813581169160208101359091169060400135610cc4565b34801561046f57600080fd5b50610478610d18565b6040805160ff9092168252519081900360200190f35b34801561049a57600080fd5b5061040e610d21565b3480156104af57600080fd5b50610478610d27565b3480156104c457600080fd5b5061039f600480360360408110156104db57600080fd5b506001600160a01b038135169060200135610d30565b3480156104fd57600080fd5b5061040e6004803603602081101561051457600080fd5b50356001600160a01b0316610d71565b34801561053057600080fd5b5061040e6004803603602081101561054757600080fd5b5035610d8c565b34801561055a57600080fd5b5061040e6004803603604081101561057157600080fd5b506001600160a01b038135169060200135610d98565b34801561059357600080fd5b5061040e600480360360208110156105aa57600080fd5b50356001600160a01b0316610e1e565b3480156105c657600080fd5b506105f3600480360360408110156105dd57600080fd5b506001600160a01b038135169060200135610e39565b005b34801561060157600080fd5b5061040e610fe5565b61040e6004803603606081101561062057600080fd5b506001600160a01b038135169060208101359060400135610feb565b34801561064857600080fd5b5061040e610ff8565b34801561065d57600080fd5b5061040e610ffe565b34801561067257600080fd5b506106906004803603602081101561068957600080fd5b5035611004565b604080516001600160a01b03909316835260208301919091528051918290030190f35b3480156106bf57600080fd5b5061039f61104e565b3480156106d457600080fd5b506106f2600480360360208110156106eb57600080fd5b503561105e565b6040805192835260208301919091528051918290030190f35b34801561071757600080fd5b506103dd6110b4565b34801561072c57600080fd5b5061040e6004803603602081101561074357600080fd5b50356001600160a01b03166110c3565b61040e6110de565b34801561076757600080fd5b5061040e6004803603604081101561077e57600080fd5b506001600160a01b038135169060200135611135565b61040e600480360360608110156107aa57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156107da57600080fd5b8201836020820111156107ec57600080fd5b8035906020019184602083028401116401000000008311171561080e57600080fd5b509092509050611148565b34801561082557600080fd5b5061040e6004803603602081101561083c57600080fd5b50356001600160a01b0316611191565b34801561085857600080fd5b5061040e6004803603602081101561086f57600080fd5b50356001600160a01b03166111b8565b34801561088b57600080fd5b506105f360048036036101008110156108a357600080fd5b506001600160a01b0381358116916020810135821691604082013515159160608101359160808201359160a08101359160c0820135169060e001356111c6565b3480156108ef57600080fd5b5061040e61164c565b34801561090457600080fd5b5061040e6004803603602081101561091b57600080fd5b50356001600160a01b0316611652565b34801561093757600080fd5b5061040e6004803603602081101561094e57600080fd5b5035611660565b34801561096157600080fd5b5061039f6004803603604081101561097857600080fd5b506001600160a01b0381351690602001356116de565b61040e600480360360408110156109a457600080fd5b508035906020013561171a565b3480156109bd57600080fd5b5061039f600480360360408110156109d457600080fd5b506001600160a01b038135169060200135611727565b61040e60048036036040811015610a0057600080fd5b81359190810190604081016020820135640100000000811115610a2257600080fd5b820183602082011115610a3457600080fd5b80359060200191846020830284011164010000000083111715610a5657600080fd5b509092509050611734565b61040e60048036036020811015610a7757600080fd5b50356001600160a01b0316611774565b348015610a9357600080fd5b5061040e60048036036020811015610aaa57600080fd5b50356117c6565b348015610abd57600080fd5b5061040e6117f1565b348015610ad257600080fd5b506104786117fc565b348015610ae757600080fd5b5061040e60048036036020811015610afe57600080fd5b503561180a565b348015610b1157600080fd5b5061040e611847565b348015610b2657600080fd5b5061040e60048036036020811015610b3d57600080fd5b50356001600160a01b031661184d565b348015610b5957600080fd5b506103dd6118b8565b348015610b6e57600080fd5b506102f16118f1565b348015610b8357600080fd5b5061040e60048036036040811015610b9a57600080fd5b506001600160a01b038135811691602001351661194c565b348015610bbe57600080fd5b506103dd611977565b348015610bd357600080fd5b5061040e60048036036020811015610bea57600080fd5b50356001600160a01b0316611986565b6060610c046119e6565b90505b90565b6000610c17338484611c17565b5060015b92915050565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ca75780601f10610c7c57610100808354040283529160200191610ca7565b820191906000526020600020905b815481529060010190602001808311610c8a57829003601f168201915b505050505081565b6004546001600160a01b031681565b60005490565b6001600160a01b0383166000908152600260209081526040808320338085529252822054610d03918691610cfe908663ffffffff611c2716565b611c69565b610d0e848484611d55565b5060019392505050565b600c5460ff1681565b600d5481565b600c5460ff1690565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610c17918590610d6c908663ffffffff611d6016565b611c17565b6000610d84610d7f83611191565b6117c6565b90505b919050565b6000610d843383611dba565b600080610da36118b8565b9050610dae81611e8c565b15610e00576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a6d696e74546f3a20496e76616c69642063616c6c0000604482015290519081900360640190fd5b610e0c81333086611e99565b610e168484612022565b949350505050565b6001600160a01b03166000908152600f602052604090205490565b6001600160a01b038216610e7e5760405162461bcd60e51b81526004018080602001828103825260388152602001806143426038913960400191505060405180910390fd5b60008111610ebd5760405162461bcd60e51b81526004018080602001828103825260358152602001806144a96035913960400191505060405180910390fd5b336000908152600f602052604090208054610ede908363ffffffff611c2716565b8155610ee93361225d565b6001600160a01b0383166000908152600f60205260409020610f0a8161236d565b15610f28578054610f21908463ffffffff611d6016565b8155610f9f565b6040805180820182528481526010805460208084019182526001600160a01b0389166000818152600f90925294812093518455905160019384015581549283018255527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b6040805184815290516001600160a01b0386169133917ff268b386023666001c794e23f1bc2285c15f9ae8db3025abbc16bf45edc6d08d9181900360200190a350505050565b60095481565b6000610e16848484612373565b60085481565b60105490565b6005546000908190600160a01b900460ff1615611039576004546001600160a01b031661103084612419565b91509150611049565b50506003546001600160a01b0316815b915091565b600554600160a01b900460ff1681565b600080600061106c846117c6565b90506000611098620186a061108c6009548561243690919063ffffffff16565b9063ffffffff61248f16565b90506110aa828263ffffffff611c2716565b9350915050915091565b6003546001600160a01b031681565b6001600160a01b031660009081526001602052604090205490565b60006110f06110eb6118b8565b611e8c565b61112b5760405162461bcd60e51b81526004018080602001828103825260238152602001806145d36023913960400191505060405180910390fd5b610c043334612022565b60006111418383611dba565b9392505050565b600061118885858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506124d192505050565b95945050505050565b600061119b612543565b156111b0576111a98261254b565b9050610d87565b506000610d87565b6000610d84610d7f83610e1e565b6003546001600160a01b03161580156111e857506004546001600160a01b0316155b80156111f45750600654155b61122f5760405162461bcd60e51b815260040180806020018281038252602381526020018061464f6023913960400191505060405180910390fd5b428411611283576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a696e69743a20496e76616c6964206578706972790000604482015290519081900360640190fd5b600085116112c25760405162461bcd60e51b815260040180806020018281038252602481526020018061439d6024913960400191505060405180910390fd5b866001600160a01b0316886001600160a01b03161415611329576040805162461bcd60e51b815260206004820152601b60248201527f41434f546f6b656e3a3a696e69743a2053616d65206173736574730000000000604482015290519081900360640190fd5b6101f4831115611380576040805162461bcd60e51b815260206004820152601f60248201527f41434f546f6b656e3a3a696e69743a20496e76616c69642041434f2066656500604482015290519081900360640190fd5b61138988611e8c565b806113a157506113a1886001600160a01b03166125a6565b6113dc5760405162461bcd60e51b81526004018080602001828103825260228152602001806141e66022913960400191505060405180910390fd5b6113e587611e8c565b806113fd57506113fd876001600160a01b03166125a6565b6114385760405162461bcd60e51b81526004018080602001828103825260248152602001806145f66024913960400191505060405180910390fd5b6019811015801561144a575060968111155b6114855760405162461bcd60e51b815260040180806020018281038252603881526020018061430a6038913960400191505060405180910390fd5b600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a84161790556005805460068990556007889055600987905560ff60a01b1916600160a01b8a15150217909116918416919091179055600d8190556114f1886125df565b600c805460ff191660ff9283161790819055604e9116106115435760405162461bcd60e51b815260040180806020018281038252602b815260200180614237602b913960400191505060405180910390fd5b61154c876125df565b600c60016101000a81548160ff021916908360ff16021790555061156f88612724565b805161158391600a916020909101906140e7565b5061158d87612724565b80516115a191600b916020909101906140e7565b50600c5460ff16600a0a600e55604080518082018252601981527f7472616e7366657228616464726573732c75696e7432353629000000000000006020918201526011805464ffffffff00191664a9059cbb001790558151606081019092526025808352906142629083013980516020909101206011805460ff1960e09390931c650100000000000268ffffffff000000000019909116179190911660011790555050505050505050565b60075481565b6000610d84610d7f83611986565b60008061166b6118b8565b905061167681611e8c565b156116c8576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a6d696e743a20496e76616c69642063616c6c00000000604482015290519081900360640190fd5b6116d481333086611e99565b6111413384612022565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610c17918590610d6c908663ffffffff611c2716565b6000611141338484612373565b6000610c17338484611d55565b6000610e1633858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506124d192505050565b60006117816110eb6118b8565b6117bc5760405162461bcd60e51b81526004018080602001828103825260258152602001806142bb6025913960400191505060405180910390fd5b610d848234612022565b600554600090600160a01b900460ff16156117e2575080610d87565b81156111b0576111a982612419565b6000610c043361292e565b600c54610100900460ff1681565b600554600090600160a01b900460ff1615611826575080610d87565b81156111b0576111a960065461108c600e548561243690919063ffffffff16565b60065481565b6000611859823361194c565b6001600160a01b0383166000908152600f602052604090205411156118af5760405162461bcd60e51b81526004018080602001828103825260278152602001806145ac6027913960400191505060405180910390fd5b610d848261292e565b600554600090600160a01b900460ff16156118df57506003546001600160a01b0316610c07565b506004546001600160a01b0316610c07565b600a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ca75780601f10610c7c57610100808354040283529160200191610ca7565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6005546001600160a01b031681565b6001600160a01b0381166000908152600f60205260408120546119a8836110c3565b11806119b957506119b7612543565b155b156119dd57506001600160a01b0381166000908152600f6020526040902054610d87565b6111a9826110c3565b6060600a611a05600654600c60019054906101000a900460ff16612a16565b600554600b90611a1e90600160a01b900460ff16612bbe565b611a29600754612c02565b604051602001808063020a1a7960e51b81525060040186805460018160011615610100020316600290048015611a965780601f10611a74576101008083540402835291820191611a96565b820191906000526020600020905b815481529060010190602001808311611a82575b505080602d60f81b81525060010185805190602001908083835b60208310611acf5780518252601f199092019160209182019101611ab0565b6001836020036101000a03801982511681845116808217855250505050505090500184805460018160011615610100020316600290048015611b485780601f10611b26576101008083540402835291820191611b48565b820191906000526020600020905b815481529060010190602001808311611b34575b505080602d60f81b81525060010183805190602001908083835b60208310611b815780518252601f199092019160209182019101611b62565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010182805190602001908083835b60208310611bda5780518252601f199092019160209182019101611bbb565b6001836020036101000a03801982511681845116808217855250505050505090500195505050505050604051602081830303815290604052905090565b611c22838383611c69565b505050565b600061114183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612e00565b6001600160a01b038316611cae5760405162461bcd60e51b81526004018080602001828103825260248152602001806146c76024913960400191505060405180910390fd5b6001600160a01b038216611cf35760405162461bcd60e51b81526004018080602001828103825260268152602001806145566026913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b611c22838383612e97565b600082820183811015611141576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60115460009060ff16611e08576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611e1a612543565b611e5f576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000611e6b8484612fdb565b9050611e7784846130a9565b90506011805460ff1916600117905592915050565b6001600160a01b03161590565b601154604080516001600160a01b0386811660248301528581166044830152606480830186905283518084039091018152608490920183526020820180516501000000000090950460e01b6001600160e01b0319166001600160e01b03909516949094178452915181516000946060948a169392918291908083835b60208310611f345780518252601f199092019160209182019101611f15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611f96576040519150601f19603f3d011682016040523d82523d6000602084013e611f9b565b606091505b5091509150818015611fc9575080511580611fc95750808060200190516020811015611fc657600080fd5b50515b61201a576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a5f7472616e7366657246726f6d455243323000000000604482015290519081900360640190fd5b505050505050565b60115460009060ff16612070576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055612082612543565b6120c7576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b600082116121065760405162461bcd60e51b815260040180806020018281038252602f815260200180614208602f913960400191505060405180910390fd5b61210f836130d3565b61217357601080546001600160a01b0385166000818152600f60205260408120600190810184905583018455929092527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b600061217e8361180a565b9050806121bc5760405162461bcd60e51b815260040180806020018281038252602a8152602001806142e0602a913960400191505060405180910390fd5b6001600160a01b0384166000908152600f60205260409020546121e5908263ffffffff611d6016565b6001600160a01b0385166000908152600f6020526040902055600854612211908463ffffffff611d6016565b6008556040805184815290516001600160a01b038616917ff645c19720906ca336d36d26058a9489c6c757fe35843b75a74e3b8aa972ecf5919081900360200190a2611e7733826130f4565b6001600160a01b0381166000908152600f6020526040902061227e8161236d565b61236957601054600182015460001990910190811461231b576000601082815481106122a657fe5b60009182526020808320909101546001868101546001600160a01b03909216808552600f9093526040909320909201829055601080549193508392909181106122eb57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b601080548061232657fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600f90526040812081815560010155505b5050565b54151590565b60115460009060ff166123c1576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055600d546123db90859085906131cf565b6123e68484846133a7565b6000806123f28561105e565b91509150612401868383613552565b925050506011805460ff191660011790559392505050565b6000610d84600e5461108c6006548561243690919063ffffffff16565b60008261244557506000610c1b565b8282028284828161245257fe5b04146111415760405162461bcd60e51b81526004018080602001828103825260218152602001806144586021913960400191505060405180910390fd5b600061114183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613682565b60115460009060ff1661251f576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055815161253890859085906131cf565b6123e68484846136e7565b600754421090565b6000612556826110c3565b6001600160a01b0383166000908152600f602052604090205411156111b0576111a9612581836110c3565b6001600160a01b0384166000908152600f60205260409020549063ffffffff611c2716565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610e16575050151592915050565b60006125ea82611e8c565b156125f757506012610d87565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b178152915181516000936060936001600160a01b038816939092909182918083835b6020831061265d5780518252601f19909201916020918201910161263e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146126bd576040519150601f19603f3d011682016040523d82523d6000602084013e6126c2565b606091505b5091509150816127035760405162461bcd60e51b81526004018080602001828103825260338152602001806141b36033913960400191505060405180910390fd5b80806020019051602081101561271857600080fd5b50519250610d87915050565b606061272f82611e8c565b15612754575060408051808201909152600381526208aa8960eb1b6020820152610d87565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106127ba5780518252601f19909201916020918201910161279b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461281a576040519150601f19603f3d011682016040523d82523d6000602084013e61281f565b606091505b5091509150816128605760405162461bcd60e51b815260040180806020018281038252602f815260200180614672602f913960400191505060405180910390fd5b80806020019051602081101561287557600080fd5b810190808051604051939291908464010000000082111561289557600080fd5b9083019060208201858111156128aa57600080fd5b82516401000000008111828201881017156128c457600080fd5b82525081516020918201929091019080838360005b838110156128f15781810151838201526020016128d9565b50505050905090810190601f16801561291e5780820380516001836020036101000a031916815260200191505b5060405250505092505050610d87565b60115460009060ff1661297c576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905561298e612543565b156129ca5760405162461bcd60e51b815260040180806020018281038252602881526020018061452e6028913960400191505060405180910390fd5b6001600160a01b0382166000908152600f60205260408120546129ee908490612fdb565b9050612a02836129fd856110c3565b61377f565b90506011805460ff19166001179055919050565b6060600080808086805b8115612a7b5783158015612a425750600a8206151580612a4257508760ff1685145b15612a4e575060019250805b8315612a6a578760ff16851415612a63578592505b6001909501945b600a82600190960195049150612a20565b8760ff168511612a9d57848860ff168760020101039550600286039250612aaa565b8215612aaa576001909501945b60608667ffffffffffffffff81118015612ac357600080fd5b506040519080825280601f01601f191660200182016040528015612aee576020820181803683370190505b5091925082919050600019870160005b88811015612bae57600081118015612b1557508581145b15612b4e57601760f91b83838060019003945081518110612b3257fe5b60200101906001600160f81b031916908160001a905350612ba6565b83612b6b57600360fc1b83838060019003945081518110612b3257fe5b600a840660300160f81b83838060019003945081518110612b8857fe5b60200101906001600160f81b031916908160001a905350600a840493505b600101612afe565b50909a9950505050505050505050565b60608115612be457506040805180820190915260018152604360f81b6020820152610d87565b506040805180820190915260018152600560fc1b6020820152610d87565b60606000806000806000612c1587613862565b5094509450945094509450612c29836138a2565b612c3285613934565b612c3b87613b46565b612c44856138a2565b612c4d856138a2565b6040516020018086805190602001908083835b60208310612c7f5780518252601f199092019160209182019101612c60565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b60208310612cc75780518252601f199092019160209182019101612ca8565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b60208310612d0f5780518252601f199092019160209182019101612cf0565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010183805190602001908083835b60208310612d685780518252601f199092019160209182019101612d49565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612db05780518252601f199092019160209182019101612d91565b5181516020939093036101000a60001901801990911692169190911790526255544360e81b92019182525060408051808303601c19018152600390920190529d9c50505050505050505050505050565b60008184841115612e8f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612e54578181015183820152602001612e3c565b50505050905090810190601f168015612e815780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316612edc5760405162461bcd60e51b81526004018080602001828103825260268152602001806146a16026913960400191505060405180910390fd5b6001600160a01b038216612f215760405162461bcd60e51b81526004018080602001828103825260298152602001806143f96029913960400191505060405180910390fd5b6001600160a01b038316600090815260016020526040902054612f4a908263ffffffff611c2716565b6001600160a01b038085166000908152600160205260408082209390935590841681522054612f7f908263ffffffff611d6016565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000612fe6836130d3565b6130215760405162461bcd60e51b81526004018080602001828103825260348152602001806142876034913960400191505060405180910390fd5b600082116130605760405162461bcd60e51b81526004018080602001828103825260318152602001806146eb6031913960400191505060405180910390fd5b6001600160a01b0383166000908152600f60205260409020805461308a908463ffffffff611c2716565b81556130958461225d565b610e16846130a2856117c6565b6000613552565b6001600160a01b0382163314156130c9576130c4828261377f565b612369565b6123698282613bd6565b6001600160a01b0381166000908152600f60205260408120610d849061236d565b6001600160a01b0382166131395760405162461bcd60e51b81526004018080602001828103825260238152602001806144de6023913960400191505060405180910390fd5b60005461314c908263ffffffff611d6016565b60009081556001600160a01b038316815260016020526040902054613177908263ffffffff611d6016565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6131d7612543565b61321c576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000821161325b5760405162461bcd60e51b81526004018080602001828103825260308152602001806144796030913960400191505060405180910390fd5b613264836130d3565b156132d9576001600160a01b0383166000908152600f602052604090205461329b9061328f856110c3565b9063ffffffff611c2716565b8211156132d95760405162461bcd60e51b81526004018080602001828103825260368152602001806144226036913960400191505060405180910390fd5b6132e383836130a9565b6000806132ef84611004565b9092509050613304818463ffffffff611d6016565b905061330f82611e8c565b15613357578034146133525760405162461bcd60e51b815260040180806020018281038252603081526020018061457c6030913960400191505060405180910390fd5b6133a0565b34156133945760405162461bcd60e51b815260040180806020018281038252602d815260200180614501602d913960400191505060405180910390fd5b6133a082333084611e99565b5050505050565b60105460009081906133c090849063ffffffff613c1b16565b90508060005b6000861180156133d7575060105481105b1561348657600061340a601084815481106133ee57fe5b6000918252602090912001546001600160a01b0316888a613c5d565b90508681101561346357600d54600190950194851080613428575080155b6134635760405162461bcd60e51b81526004018080602001828103825260388152602001806143c16038913960400191505060405180910390fd5b601054909650600190920191869083141561347d57600092505b506001016133c6565b85156134c35760405162461bcd60e51b81526004018080602001828103825260338152602001806141806033913960400191505060405180910390fd5b600080836134d55760105493506134e9565b8484116134e9575050601054916000190160015b60005b83811015613546576000199094019381801561350757508585105b1561351457829450600091505b61353e6010868154811061352457fe5b6000918252602090912001546001600160a01b031661225d565b6001016134ec565b50505050505050505050565b6000613576613567848463ffffffff611d6016565b6008549063ffffffff611c2716565b60085560006135836118b8565b905061358e81611e8c565b1561360857604051339085156108fc029086906000818181858888f193505050501580156135c0573d6000803e3d6000fd5b508215613603576005546040516001600160a01b039091169084156108fc029085906000818181858888f19350505050158015613601573d6000803e3d6000fd5b505b613631565b613613813386613d9f565b8215613631576005546136319082906001600160a01b031685613d9f565b6040805185815260208101859052815133926001600160a01b038916927fd3506bcc260407a7f95f487dd7c600bc45888cce58989ceadbe8c0bbf9257b28929081900390910190a350919392505050565b600081836136d15760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e54578181015183820152602001612e3c565b5060008385816136dd57fe5b0495945050505050565b60005b815181101561374157826136fd57613741565b61371b82828151811061370c57fe5b60200260200101518486613c5d565b925061373982828151811061372c57fe5b602002602001015161225d565b6001016136ea565b508115611c225760405162461bcd60e51b815260040180806020018281038252603581526020018061461a6035913960400191505060405180910390fd5b6001600160a01b0382166137c45760405162461bcd60e51b815260040180806020018281038252602381526020018061437a6023913960400191505060405180910390fd5b6001600160a01b0382166000908152600160205260409020546137ed908263ffffffff611c2716565b6001600160a01b0383166000908152600160205260408120919091555461381a908263ffffffff611c2716565b60009081556040805183815290516001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b60008080808080613877620151808804613f14565b91999098919750610e10620151809092068281049750603c9290068281049650919091069350915050565b6060806138ae83613faa565b9050600a8310156111a957806040516020018080600360fc1b81525060010182805190602001908083835b602083106138f85780518252601f1990920191602091820191016138d9565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052915050610d87565b6060816001141561395f57506040805180820190915260038152622520a760e91b6020820152610d87565b816002141561398857506040805180820190915260038152622322a160e91b6020820152610d87565b81600314156139b1575060408051808201909152600381526226a0a960e91b6020820152610d87565b81600414156139da575060408051808201909152600381526220a82960e91b6020820152610d87565b8160051415613a0357506040805180820190915260038152624d415960e81b6020820152610d87565b8160061415613a2c5750604080518082019091526003815262252aa760e91b6020820152610d87565b8160071415613a55575060408051808201909152600381526212955360ea1b6020820152610d87565b8160081415613a7e575060408051808201909152600381526241554760e81b6020820152610d87565b8160091415613aa7575060408051808201909152600381526205345560ec1b6020820152610d87565b81600a1415613ad0575060408051808201909152600381526213d0d560ea1b6020820152610d87565b81600b1415613af957506040805180820190915260038152622727ab60e91b6020820152610d87565b81600c1415613b22575060408051808201909152600381526244454360e81b6020820152610d87565b506040805180820190915260078152661253959053125160ca1b6020820152610d87565b606080613b5283613faa565b60408051600280825281830190925291925060609190602082018180368337505083519192505060011901805b8351811015613bcc57838181518110613b9457fe5b602001015160f81c60f81b8383830381518110613bad57fe5b60200101906001600160f81b031916908160001a905350600101613b7f565b5090949350505050565b6001600160a01b038216600090815260026020908152604080832033808552925290912054613c11918491610cfe908563ffffffff611c2716565b612369828261377f565b600061114183836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250614085565b600080613c698561254b565b90508015613d96576001600160a01b0385166000908152600f602052604081209085831015613cab575081613ca4868263ffffffff611c2716565b9550613cb0565b506000945b600080613cbc83611004565b9092509050613cd281600163ffffffff611d6016565b8454909150613ce7908463ffffffff611c2716565b8455613cf282611e8c565b15613d33576040516001600160a01b038a169082156108fc029083906000818181858888f19350505050158015613d2d573d6000803e3d6000fd5b50613d3e565b613d3e828a83613d9f565b866001600160a01b0316896001600160a01b03167f5f283076724262032199f54be27a9364634b895b3a37c1e66bfe47d5d05347698386604051808381526020018281526020019250505060405180910390a3505050505b50919392505050565b601154604080516001600160a01b0385811660248301526044808301869052835180840390910181526064909201835260208201805161010090950460e01b6001600160e01b0319166001600160e01b039095169490941784529151815160009460609489169392918291908083835b60208310613e2e5780518252601f199092019160209182019101613e0f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613e90576040519150601f19603f3d011682016040523d82523d6000602084013e613e95565b606091505b5091509150818015613ec3575080511580613ec35750808060200190516020811015613ec057600080fd5b50515b6133a0576040805162461bcd60e51b815260206004820152601860248201527f41434f546f6b656e3a3a5f7472616e7366657245524332300000000000000000604482015290519081900360640190fd5b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f8460500281613f6b57fe5b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b606081613fcf57506040805180820190915260018152600360fc1b6020820152610d87565b8160005b8115613fe757600101600a82049150613fd3565b60608167ffffffffffffffff8111801561400057600080fd5b506040519080825280601f01601f19166020018201604052801561402b576020820181803683370190505b50859350905060001982015b831561407c57600a840660300160f81b8282806001900393508151811061405a57fe5b60200101906001600160f81b031916908160001a905350600a84049350614037565b50949350505050565b600081836140d45760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612e54578181015183820152602001612e3c565b508284816140de57fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061412857805160ff1916838001178555614155565b82800160010185558215614155579182015b8281111561415557825182559160200191906001019061413a565b50614161929150614165565b5090565b610c0791905b80821115614161576000815560010161416b56fe41434f546f6b656e3a3a5f65786572636973654f776e6572733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a5f6765744173736574446563696d616c733a20496e76616c696420617373657420646563696d616c7341434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6741434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420636f6c6c61746572616c20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6720646563696d616c737472616e7366657246726f6d28616464726573732c616464726573732c75696e743235362941434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a204e6f20636f6c6c61746572616c20617661696c61626c6541434f546f6b656e3a3a6d696e74546f50617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c6964206e756d62657220746f206d617820657865726369736564206163636f756e747341434f546f6b656e3a3a7472616e73666572436f6c6c61746572616c4f776e6572736869703a20496e76616c696420726563697069656e7445524332303a3a5f6275726e416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520707269636541434f546f6b656e3a3a5f65786572636973654f776e6572733a20546f6f206d616e79206163636f756e747320746f20657865726369736545524332303a3a5f7472616e73666572416374696f6e3a20496e76616c696420726563697069656e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20546f6b656e20616d6f756e74206e6f7420617661696c61626c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7741434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a7472616e73666572436f6c6c61746572616c4f776e6572736869703a20496e76616c696420616d6f756e7445524332303a3a5f6d696e74416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a204e6f20657468657220657870656374656441434f546f6b656e3a3a5f72656465656d3a20546f6b656e206e6f7420657870697265642079657445524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964207370656e64657241434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420657468657220616d6f756e7441434f546f6b656e3a3a72656465656d46726f6d3a20416c6c6f77616e636520746f6f206c6f7741434f546f6b656e3a3a6d696e7450617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520617373657441434f546f6b656e3a3a5f65786572636973654163636f756e74733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a696e69743a20416c726561647920696e697469616c697a656441434f546f6b656e3a3a5f676574417373657453796d626f6c3a20496e76616c69642061737365742073796d626f6c45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c69642073656e64657245524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964206f776e657241434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a20496e76616c696420746f6b656e20616d6f756e74a2646970667358221220cb30ae80319463574ff120f520633d68378fa215960c0dd60da4052df64ca49164736f6c63430006060033
Deployed Bytecode Sourcemap
221:41335:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;221:41335:1;12:1:-1;9;2:12;8256:93:1;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8256:93:1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;8256:93:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1425:158:4;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1425:158:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;1425:158:4;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;3432:31:1;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3432:31:1;;;:::i;2500:26::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2500:26:1;;;:::i;:::-;;;;-1:-1:-1;;;;;2500:26:1;;;;;;;;;;;;;;592:99:4;;5:9:-1;2:2;;;27:1;24;17:12;2:2;592:99:4;;;:::i;:::-;;;;;;;;;;;;;;;;1147:270;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1147:270:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;1147:270:4;;;;;;;;;;;;;;;;;:::i;3542:31:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3542:31:1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3793:35;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3793:35:1;;;:::i;8681:100::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8681:100:1;;;:::i;1591:197:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1591:197:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;1591:197:4;;;;;;;;:::i;9920:148:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9920:148:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;9920:148:1;-1:-1:-1;;;;;9920:148:1;;:::i;17418:117::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17418:117:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;17418:117:1;;:::i;16755:366::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;16755:366:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;16755:366:1;;;;;;;;:::i;10295:134::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10295:134:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;10295:134:1;-1:-1:-1;;;;;10295:134:1;;:::i;21375:1022::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;21375:1022:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;21375:1022:1;;;;;;;;:::i;:::-;;3233:21;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3233:21:1;;;:::i;20331:171::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;20331:171:1;;;;;;;;;;;;;:::i;3101:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3101:30:1;;;:::i;12724:121::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12724:121:1;;;:::i;13466:274::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;13466:274:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;13466:274:1;;:::i;:::-;;;;-1:-1:-1;;;;;13466:274:1;;;;;;;;;;;;;;;;;;;;;2748:18;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2748:18:1;;;:::i;13983:331::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;13983:331:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;13983:331:1;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;2365:25;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2365:25:1;;;:::i;699:118:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;699:118:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;699:118:4;-1:-1:-1;;;;;699:118:4;;:::i;14846:197:1:-;;;:::i;18004:135::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18004:135:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;18004:135:1;;;;;;;;:::i;23062:210::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;23062:210:1;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;23062:210:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;23062:210:1;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;23062:210:1;;-1:-1:-1;23062:210:1;-1:-1:-1;23062:210:1;:::i;11313:213::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11313:213:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;11313:213:1;-1:-1:-1;;;;;11313:213:1;;:::i;8986:156::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8986:156:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8986:156:1;-1:-1:-1;;;;;8986:156:1;;:::i;5989:2022::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5989:2022:1;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;5989:2022:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2984:25::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2984:25:1;;;:::i;9476:152::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9476:152:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;9476:152:1;-1:-1:-1;;;;;9476:152:1;;:::i;15942:348::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;15942:348:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15942:348:1;;:::i;1796:197:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1796:197:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;1796:197:4;;;;;;;;:::i;19535:153:1:-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;19535:153:1;;;;;;;:::i;975:164:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;975:164:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;975:164:4;;;;;;;;:::i;20955:192:1:-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;20955:192:1;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;20955:192:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;20955:192:1;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;20955:192:1;;-1:-1:-1;20955:192:1;-1:-1:-1;20955:192:1;:::i;15444:212::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15444:212:1;-1:-1:-1;;;;;15444:212:1;;:::i;11736:297::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11736:297:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;11736:297:1;;:::i;18354:89::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18354:89:1;;;:::i;3648:32::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3648:32:1;;;:::i;12248:324::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12248:324:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;12248:324:1;;:::i;2874:26::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2874:26:1;;;:::i;18840:227::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18840:227:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;18840:227:1;-1:-1:-1;;;;;18840:227:1;;:::i;14448:176::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;14448:176:1;;;:::i;3330:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3330:30:1;;;:::i;825:142:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;825:142:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;825:142:4;;;;;;;;;;:::i;2626:37:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2626:37:1;;;:::i;10754:279::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10754:279:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;10754:279:1;-1:-1:-1;;;;;10754:279:1;;:::i;8256:93::-;8301:13;8334:7;:5;:7::i;:::-;8327:14;;8256:93;;:::o;1425:158:4:-;1499:4;1516:37;1525:10;1537:7;1546:6;1516:8;:37::i;:::-;-1:-1:-1;1571:4:4;1425:158;;;;;:::o;3432:31:1:-;;;;;;;;;;;;;;;-1:-1:-1;;3432:31:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2500:26::-;;;-1:-1:-1;;;;;2500:26:1;;:::o;592:99:4:-;644:7;671:12;592:99;:::o;1147:270::-;-1:-1:-1;;;;;1296:19:4;;1244:4;1296:19;;;:11;:19;;;;;;;;1284:10;1296:31;;;;;;;;1261:79;;1276:6;;1296:43;;1332:6;1296:43;:35;:43;:::i;:::-;1261:14;:79::i;:::-;1351:36;1361:6;1369:9;1380:6;1351:9;:36::i;:::-;-1:-1:-1;1405:4:4;1147:270;;;;;:::o;3542:31:1:-;;;;;;:::o;3793:35::-;;;;:::o;8681:100::-;8755:18;;;;8681:100;:::o;1591:197:4:-;1692:10;1666:4;1713:23;;;:11;:23;;;;;;;;-1:-1:-1;;;;;1713:32:4;;;;;;;;;;1666:4;;1683:75;;1704:7;;1713:44;;1750:6;1713:44;:36;:44;:::i;:::-;1683:8;:75::i;9920:148:1:-;9987:7;10014:46;10034:25;10051:7;10034:16;:25::i;:::-;10014:19;:46::i;:::-;10007:53;;9920:148;;;;:::o;17418:117::-;17470:7;17497:30;17503:10;17515:11;17497:5;:30::i;16755:366::-;16831:7;16851:19;16873:12;:10;:12::i;:::-;16851:34;;16905:21;16914:11;16905:8;:21::i;:::-;16904:22;16896:65;;;;;-1:-1:-1;;;16896:65:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;16982:76;17001:11;17014:10;17034:4;17041:16;16982:18;:76::i;:::-;17076:37;17087:7;17096:16;17076:10;:37::i;:::-;17069:44;16755:366;-1:-1:-1;;;;16755:366:1:o;10295:134::-;-1:-1:-1;;;;;10396:18:1;10369:7;10396:18;;;:9;:18;;;;;:25;;10295:134::o;21375:1022::-;-1:-1:-1;;;;;21494:23:1;;21486:92;;;;-1:-1:-1;;;21486:92:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21625:1;21597:25;:29;21589:95;;;;-1:-1:-1;;;21589:95:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21748:10;21697:38;21738:21;;;:9;:21;;;;;21790:17;;:48;;21812:25;21790:48;:21;:48;:::i;:::-;21770:68;;21851:44;21884:10;21851:32;:44::i;:::-;-1:-1:-1;;;;;21952:20:1;;21908:41;21952:20;;;:9;:20;;;;;21987:29;21952:20;21987:14;:29::i;:::-;21983:312;;;22056:20;;:51;;22081:25;22056:51;:24;:51;:::i;:::-;22033:74;;21983:312;;;22163:72;;;;;;;;;;;22210:17;:24;;22163:72;;;;;;;-1:-1:-1;;;;;22140:20:1;;-1:-1:-1;22140:20:1;;;:9;:20;;;;;;:95;;;;;;;;;;;27:10:-1;;23:18;;;45:23;;22250:33:1;;;;;-1:-1:-1;;;;;;22250:33:1;;;;;;21983:312;22312:77;;;;;;;;-1:-1:-1;;;;;22312:77:1;;;22340:10;;22312:77;;;;;;;;;21375:1022;;;;:::o;3233:21::-;;;;:::o;20331:171::-;20430:7;20457:37;20467:7;20476:11;20489:4;20457:9;:37::i;3101:30::-;;;;:::o;12724:121::-;12813:17;:24;12724:121;:::o;13466:274::-;13569:6;;13536:7;;;;-1:-1:-1;;;13569:6:1;;;;13565:168;;;13600:11;;-1:-1:-1;;;;;13600:11:1;13613:41;13642:11;13613:28;:41::i;:::-;13592:63;;;;;;13565:168;-1:-1:-1;;13697:10:1;;-1:-1:-1;;;;;13697:10:1;13709:11;13565:168;13466:274;;;:::o;2748:18::-;;;-1:-1:-1;;;2748:18:1;;;;;:::o;13983:331::-;14057:7;14066;14086:24;14113:32;14133:11;14113:19;:32::i;:::-;14086:59;;14156:11;14170:40;14203:6;14170:28;14191:6;;14170:16;:20;;:28;;;;:::i;:::-;:32;:40;:32;:40;:::i;:::-;14156:54;-1:-1:-1;14240:25:1;:16;14156:54;14240:25;:20;:25;:::i;:::-;14221:44;-1:-1:-1;14302:3:1;-1:-1:-1;;13983:331:1;;;:::o;2365:25::-;;;-1:-1:-1;;;;;2365:25:1;;:::o;699:118:4:-;-1:-1:-1;;;;;791:18:4;764:7;791:18;;;:9;:18;;;;;;;699:118::o;14846:197:1:-;14894:7;14922:22;14931:12;:10;:12::i;:::-;14922:8;:22::i;:::-;14914:70;;;;-1:-1:-1;;;14914:70:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15002:33;15013:10;15025:9;15002:10;:33::i;18004:135::-;18077:7;18104:27;18110:7;18119:11;18104:5;:27::i;:::-;18097:34;18004:135;-1:-1:-1;;;18004:135:1:o;23062:210::-;23184:7;23211:53;23233:7;23242:11;23255:8;;23211:53;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;23211:21:1;;-1:-1:-1;;;23211:53:1:i;:::-;23204:60;23062:210;-1:-1:-1;;;;;23062:210:1:o;11313:213::-;11376:7;11400:13;:11;:13::i;:::-;11396:123;;;11437:29;11458:7;11437:20;:29::i;:::-;11430:36;;;;11396:123;-1:-1:-1;11506:1:1;11499:8;;8986:156;9050:7;9077:57;9097:36;9125:7;9097:27;:36::i;5989:2022::-;6289:10;;-1:-1:-1;;;;;6289:10:1;:24;:53;;;;-1:-1:-1;6317:11:1;;-1:-1:-1;;;;;6317:11:1;:25;6289:53;:73;;;;-1:-1:-1;6346:11:1;;:16;6289:73;6281:121;;;;-1:-1:-1;;;6281:121:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6445:3;6431:11;:17;6423:60;;;;;-1:-1:-1;;;6423:60:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6517:1;6502:12;:16;6494:65;;;;-1:-1:-1;;;6494:65:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6593:12;-1:-1:-1;;;;;6578:27:1;:11;-1:-1:-1;;;;;6578:27:1;;;6570:67;;;;;-1:-1:-1;;;6570:67:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6667:3;6656:7;:14;;6648:58;;;;;-1:-1:-1;;;6648:58:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6744:21;6753:11;6744:8;:21::i;:::-;:49;;;;6769:24;:11;-1:-1:-1;;;;;6769:22:1;;:24::i;:::-;6736:96;;;;-1:-1:-1;;;6736:96:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6851:22;6860:12;6851:8;:22::i;:::-;:51;;;;6877:25;:12;-1:-1:-1;;;;;6877:23:1;;:25::i;:::-;6843:100;;;;-1:-1:-1;;;6843:100:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6987:2;6962:21;:27;;:59;;;;;7018:3;6993:21;:28;;6962:59;6954:128;;;;-1:-1:-1;;;6954:128:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7103:10;:24;;-1:-1:-1;;;;;;7103:24:1;;;-1:-1:-1;;;;;7103:24:1;;;;;;;;;;7138:11;:26;;;;;;;;;;7175:6;:16;;7202:11;:26;;;7239:10;:24;;;7274:6;:16;;;-1:-1:-1;;;;7175:16:1;-1:-1:-1;;;7175:16:1;;;;;7301:32;;;;;;;;;;;;7344:20;:44;;;7420:30;7103:24;7420:17;:30::i;:::-;7399:18;:51;;-1:-1:-1;;7399:51:1;;;;;;;;;;7490:2;7469:18;;:23;7461:79;;;;-1:-1:-1;;;7461:79:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7573:31;7591:12;7573:17;:31::i;:::-;7551:19;;:53;;;;;;;;;;;;;;;;;;7634:28;7650:11;7634:15;:28::i;:::-;7615:47;;;;:16;;:47;;;;;;:::i;:::-;;7693:29;7709:12;7693:15;:29::i;:::-;7673:49;;;;:17;;:49;;;;;;:::i;:::-;-1:-1:-1;7769:18:1;;;;7755:2;:33;7733:19;:55;7838:34;;;;;;;;;;;;;;;;;7801:17;:73;;-1:-1:-1;;7801:73:1;;;;;7926:46;;;;;;;;;;;;;;;;;;7916:57;;;;;;;7885:21;:89;;-1:-1:-1;;7885:89:1;;;;;;;-1:-1:-1;;7885:89:1;;;;7985:18;;;;-1:-1:-1;7985:18:1;;;-1:-1:-1;;;;;;;;5989:2022:1:o;2984:25::-;;;;:::o;9476:152::-;9545:7;9572:48;9592:27;9611:7;9592:18;:27::i;15942:348::-;15999:7;16019:19;16041:12;:10;:12::i;:::-;16019:34;;16073:21;16082:11;16073:8;:21::i;:::-;16072:22;16064:63;;;;;-1:-1:-1;;;16064:63:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;16148:76;16167:11;16180:10;16200:4;16207:16;16148:18;:76::i;:::-;16242:40;16253:10;16265:16;16242:10;:40::i;1796:197:4:-;1897:10;1871:4;1918:23;;;:11;:23;;;;;;;;-1:-1:-1;;;;;1918:32:4;;;;;;;;;;1871:4;;1888:75;;1909:7;;1918:44;;1955:6;1918:44;:36;:44;:::i;19535:153:1:-;19613:7;19640:40;19650:10;19662:11;19675:4;19640:9;:40::i;975:164:4:-;1052:4;1069:40;1079:10;1091:9;1102:6;1069:9;:40::i;20955:192:1:-;21056:7;21083:56;21105:10;21117:11;21130:8;;21083:56;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;21083:21:1;;-1:-1:-1;;;21083:56:1:i;15444:212::-;15509:7;15537:22;15546:12;:10;:12::i;15537:22::-;15529:72;;;;-1:-1:-1;;;15529:72:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15618:30;15629:7;15638:9;15618:10;:30::i;11736:297::-;11830:6;;11806:7;;-1:-1:-1;;;11830:6:1;;;;11826:200;;;-1:-1:-1;11860:11:1;11853:18;;11826:200;11893:15;;11889:137;;11932:41;11961:11;11932:28;:41::i;18354:89::-;18389:7;18416:19;18424:10;18416:7;:19::i;3648:32::-;;;;;;;;;:::o;12248:324::-;12342:6;;12318:7;;-1:-1:-1;;;12342:6:1;;;;12338:227;;;-1:-1:-1;12372:16:1;12365:23;;12338:227;12410:20;;12406:159;;12454:58;12500:11;;12454:41;12475:19;;12454:16;:20;;:41;;;;:::i;2874:26::-;;;;:::o;18840:227::-;18894:7;18951:30;18961:7;18970:10;18951:9;:30::i;:::-;-1:-1:-1;;;;;18922:18:1;;;;;;:9;:18;;;;;:25;:59;;18914:111;;;;-1:-1:-1;;;18914:111:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19043:16;19051:7;19043;:16::i;14448:176::-;14514:6;;14490:7;;-1:-1:-1;;;14514:6:1;;;;14510:107;;;-1:-1:-1;14544:10:1;;-1:-1:-1;;;;;14544:10:1;14537:17;;14510:107;-1:-1:-1;14594:11:1;;-1:-1:-1;;;;;14594:11:1;14587:18;;3330:30;;;;;;;;;;;;;;;-1:-1:-1;;3330:30:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;825:142:4;-1:-1:-1;;;;;932:18:4;;;905:7;932:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;825:142::o;2626:37:1:-;;;-1:-1:-1;;;;;2626:37:1;;:::o;10754:279::-;-1:-1:-1;;;;;10864:18:1;;10819:7;10864:18;;;:9;:18;;;;;:25;10843:18;10874:7;10843:9;:18::i;:::-;:46;:64;;;;10894:13;:11;:13::i;:::-;10893:14;10843:64;10839:187;;;-1:-1:-1;;;;;;10931:18:1;;;;;;:9;:18;;;;;:25;10924:32;;10839:187;10996:18;11006:7;10996:9;:18::i;38726:435::-;38765:13;38857:16;38906:63;38936:11;;38949:19;;;;;;;;;;;38906:29;:63::i;:::-;39062:6;;38984:17;;39034:35;;-1:-1:-1;;;39062:6:1;;;;39034:27;:35::i;:::-;39102:39;39130:10;;39102:27;:39::i;:::-;38805:347;;;;;;-1:-1:-1;;;38805:347:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;38805:347:1;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;38805:347:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;38805:347:1;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;38805:347:1;;;;;;;-1:-1:-1;;;38805:347:1;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;38805:347:1;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;38805:347:1;;;38791:362;;38726:435;:::o;2161:140:4:-;2255:38;2270:5;2277:7;2286:6;2255:14;:38::i;:::-;2161:140;;;:::o;1410:136:6:-;1468:7;1495:43;1499:1;1502;1495:43;;;;;;;;;;;;;;;;;:3;:43::i;2985:358:4:-;-1:-1:-1;;;;;3085:19:4;;3077:68;;;;-1:-1:-1;;;3077:68:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3164:21:4;;3156:72;;;;-1:-1:-1;;;3156:72:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3241:18:4;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;3303:32;;;;;;;;;;;;;;;;;2985:358;;;:::o;2005:148::-;2103:42;2119:6;2127:9;2138:6;2103:15;:42::i;954:181:6:-;1012:7;1044:5;;;1068:6;;;;1060:46;;;;;-1:-1:-1;;;1060:46:6;;;;;;;;;;;;;;;;;;;;;;;;;;;35296:264:1;5011:11;;35390:7;;5011:11;;5003:41;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;;;;5055:11;:19;;-1:-1:-1;;5055:19:1;;;4788:13:::1;:11;:13::i;:::-;4780:43;;;::::0;;-1:-1:-1;;;4780:43:1;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4780:43:1;;;;;;;;;;;;;::::1;;35410:24:::2;35437:39;35455:7;35464:11;35437:17;:39::i;:::-;35410:66;;35487:31;35497:7;35506:11;35487:9;:31::i;:::-;35536:16:::0;-1:-1:-1;5097:11:1;:18;;-1:-1:-1;;5097:18:1;5111:4;5097:18;;;35296:264;;-1:-1:-1;;35296:264:1:o;38360:112::-;-1:-1:-1;;;;;38442:22:1;;;38360:112::o;41184:369::-;41374:21;;41351:72;;;-1:-1:-1;;;;;41351:72:1;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;41351:72:1;;;;;;;25:18:-1;;61:17;;41374:21:1;;;;;;-1:-1:-1;;;;;;41351:72:1;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;41340:84:1;;;;-1:-1:-1;;41313:23:1;;41340:10;;;41351:72;41340:84;;;25:18:-1;41340:84:1;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;41340:84:1;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;41298:126:1;;;;41443:7;:69;;;;-1:-1:-1;41455:17:1;;:22;;:56;;;41492:10;41481:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;41481:30:1;41455:56;41435:110;;;;;-1:-1:-1;;;41435:110:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;41184:369;;;;;;:::o;24394:869::-;5011:11;;24498:7;;5011:11;;5003:41;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;;;;5055:11;:19;;-1:-1:-1;;5055:19:1;;;4788:13:::1;:11;:13::i;:::-;4780:43;;;::::0;;-1:-1:-1;;;4780:43:1;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4780:43:1;;;;;;;;;;;;;::::1;;24545:1:::2;24526:16;:20;24518:80;;;;-1:-1:-1::0;;;24518:80:1::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24624:30;24646:7;24624:21;:30::i;:::-;24619:161;;24698:17;:24:::0;;-1:-1:-1;;;;;24671:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:24:::2;::::0;;::::2;:51:::0;;;23:18:-1;::::2;45:23:::0;;24737:31:1;;;;;::::2;::::0;;-1:-1:-1;;;;;;24737:31:1::2;::::0;;::::2;::::0;;24619:161:::2;24800:19;24822:32;24837:16;24822:14;:32::i;:::-;24800:54:::0;-1:-1:-1;24873:16:1;24865:71:::2;;;;-1:-1:-1::0;;;24865:71:1::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;24975:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:25;:42:::2;::::0;25005:11;24975:42:::2;:29;:42;:::i;:::-;-1:-1:-1::0;;;;;24947:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:70;25056:15:::2;::::0;:37:::2;::::0;25076:16;25056:37:::2;:19;:37;:::i;:::-;25038:15;:55:::0;25119:44:::2;::::0;;;;;;;-1:-1:-1;;;;;25119:44:1;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;::::2;25184:42;25202:10;25214:11;25184:17;:42::i;36652:559::-:0;-1:-1:-1;;;;;36766:18:1;;36731:32;36766:18;;;:9;:18;;;;;36800:20;36766:18;36800:14;:20::i;:::-;36795:409;;36857:17;:24;36884:1;36917:10;;;-1:-1:-1;;36857:28:1;;;;36904:23;;36900:215;;36948:12;36963:17;36981:9;36963:28;;;;;;;;;;;;;;;;;;;;;37034:10;;;;-1:-1:-1;;;;;36963:28:1;;;37010:15;;;:9;:15;;;;;;;:21;;;:34;;;37063:17;:29;;36963:28;;-1:-1:-1;36963:28:1;;37063:17;;:29;;;;;;;;;;;;;;:36;;;;;-1:-1:-1;;;;;37063:36:1;;;;;-1:-1:-1;;;;;37063:36:1;;;;;;36900:215;;37129:17;:23;;;;;;;;;;;;;;;;;-1:-1:-1;;37129:23:1;;;;;-1:-1:-1;;;;;;37129:23:1;;;;;;;;;-1:-1:-1;;;;;37174:18:1;;;;:9;:18;;;;;37167:25;;;37129:23;37167:25;;-1:-1:-1;36795:409:1;36652:559;;:::o;38026:127::-;38130:11;:15;;;38026:127::o;26897:402::-;5011:11;;26998:7;;5011:11;;5003:41;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;;;;5055:11;:19;;-1:-1:-1;;5055:19:1;;;27057:20:::1;::::0;27018:60:::1;::::0;27035:7;;27044:11;;27018:16:::1;:60::i;:::-;27090:43;27106:7;27115:11;27128:4;27090:15;:43::i;:::-;27145:24;27171:11:::0;27186:36:::1;27210:11;27186:23;:36::i;:::-;27144:78;;;;27240:51;27260:7;27269:16;27287:3;27240:19;:51::i;:::-;27233:58;;;;5097:11:::0;:18;;-1:-1:-1;;5097:18:1;5111:4;5097:18;;;26897:402;;-1:-1:-1;;;26897:402:1:o;34213:169::-;34294:7;34321:53;34354:19;;34321:28;34337:11;;34321;:15;;:28;;;;:::i;2284:471:6:-;2342:7;2587:6;2583:47;;-1:-1:-1;2617:1:6;2610:8;;2583:47;2654:5;;;2658:1;2654;:5;:1;2678:5;;;;;:10;2670:56;;;;-1:-1:-1;;;2670:56:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3223:132;3281:7;3308:39;3312:1;3315;3308:39;;;;;;;;;;;;;;;;;:3;:39::i;27641:427:1:-;5011:11;;27767:7;;5011:11;;5003:41;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;;;;5055:11;:19;;-1:-1:-1;;5055:19:1;;;27826:15;;27787:55:::1;::::0;27804:7;;27813:11;;27787:16:::1;:55::i;:::-;27853:49;27871:7;27880:11;27893:8;27853:17;:49::i;37358:93::-:0;37433:10;;37427:3;:16;37358:93;:::o;36201:272::-;36270:7;36322:18;36332:7;36322:9;:18::i;:::-;-1:-1:-1;;;;;36294:18:1;;;;;;:9;:18;;;;;:25;:46;36290:176;;;36364:49;36394:18;36404:7;36394:9;:18::i;:::-;-1:-1:-1;;;;;36364:18:1;;;;;;:9;:18;;;;;:25;;:49;:29;:49;:::i;803:619:2:-;863:4;1331:20;;1174:66;1371:23;;;;;;:42;;-1:-1:-1;;1398:15:2;;;1363:51;-1:-1:-1;;803:619:2:o;39324:422:1:-;39388:5;39410:15;39419:5;39410:8;:15::i;:::-;39406:333;;;-1:-1:-1;39455:2:1;39442:16;;39406:333;39550:37;;;22:32:-1;6:49;;39550:37:1;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;39533:55:1;;;;39492:12;;39506:23;;-1:-1:-1;;;;;39533:16:1;;;39550:37;;39533:55;;;;;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;39533:55:1;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;39491:97:1;;;;39611:7;39603:71;;;;-1:-1:-1;;;39603:71:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39707:10;39696:31;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;39696:31:1;;-1:-1:-1;39689:38:1;;-1:-1:-1;;39689:38:1;39905:419;39967:13;39997:15;40006:5;39997:8;:15::i;:::-;39993:324;;;-1:-1:-1;40029:12:1;;;;;;;;;;;;-1:-1:-1;;;40029:12:1;;;;;;39993:324;40133:35;;;22:32:-1;6:49;;40133:35:1;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;40116:53:1;;;;40075:12;;40089:23;;-1:-1:-1;;;;;40116:16:1;;;40133:35;;40116:53;;;;;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;40116:53:1;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;40074:95:1;;;;40192:7;40184:67;;;;-1:-1:-1;;;40184:67:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40284:10;40273:32;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;40273:32:1;;;;;;;;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;261:11;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;372:25;;-1:-1;40273:32:1;;420:4:-1;411:14;;;;40273:32:1;;;;;411:14:-1;40273:32:1;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;40273:32:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40266:39;;;;;;34650:351;5011:11;;34714:7;;5011:11;;5003:41;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;-1:-1:-1;;;5003:41:1;;;;;;;;;;;;;;;5055:11;:19;;-1:-1:-1;;5055:19:1;;;34743:13:::1;:11;:13::i;:::-;34742:14;34734:67;;;;-1:-1:-1::0;;;34734:67:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;34876:18:1;::::1;34822:24;34876:18:::0;;;:9:::1;:18;::::0;;;;:25;34849:53:::1;::::0;34867:7;;34849:17:::1;:53::i;:::-;34822:80;;34913:46;34931:7;34940:18;34950:7;34940:9;:18::i;:::-;34913:17;:46::i;:::-;34977:16:::0;-1:-1:-1;5097:11:1;:18;;-1:-1:-1;;5097:18:1;5111:4;5097:18;;;34650:351;;-1:-1:-1;34650:351:1:o;892:1498:0:-;967:13;993:14;;;;1138:5;;1187:469;1194:9;;1187:469;;1225:24;1224:25;:75;;;;-1:-1:-1;1261:2:0;1254:4;:9;:14;;;:44;;;1289:8;1281:17;;1272:5;:26;1254:44;1220:179;;;-1:-1:-1;1347:4:0;;-1:-1:-1;1379:4:0;1220:179;1417:24;1413:185;;;1483:8;1475:17;;1466:5;:26;1462:94;;;1530:6;1517:19;;1462:94;1574:8;;;;;1413:185;1620:2;1612:10;1637:7;;;;;1612:10;;-1:-1:-1;1187:469:0;;;1687:8;1679:17;;1670:5;:26;1666:205;;1755:5;1743:8;1735:17;;1722:6;1731:1;1722:10;:30;:38;1713:47;;1797:1;1788:6;:10;1775:23;;1666:205;;;1820:14;;1816:55;;1851:8;;;;;1816:55;1881:19;1913:6;1903:17;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1903:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;1903:17:0;87:42:-1;143:17;;-1:-1;1903:17:0;-1:-1:-1;1975:6:0;;-1:-1:-1;1975:6:0;;1881:39;-1:-1:-1;;;1947:10:0;;1931:13;1992:359;2016:6;2012:1;:10;1992:359;;;2052:1;2048;:5;:24;;;;;2062:10;2057:1;:15;2048:24;2044:296;;;-1:-1:-1;;;2093:6:0;2100:7;;;;;;;2093:15;;;;;;;;;;;:27;-1:-1:-1;;;;;2093:27:0;;;;;;;;;2044:296;;;2146:11;2142:198;;-1:-1:-1;;;2178:6:0;2185:7;;;;;;;2178:15;;;;;;;2142:198;2289:2;2280:6;:11;2275:2;:16;2264:29;;2246:6;2253:7;;;;;;;2246:15;;;;;;;;;;;:47;-1:-1:-1;;;;;2246:47:0;;;;;;;;-1:-1:-1;2322:2:0;2312:12;;;;2142:198;2024:3;;1992:359;;;-1:-1:-1;2375:6:0;;892:1498;-1:-1:-1;;;;;;;;;;892:1498:0:o;3273:180::-;3328:13;3358:6;3354:92;;;-1:-1:-1;3381:10:0;;;;;;;;;;;;-1:-1:-1;;;3381:10:0;;;;;;3354:92;-1:-1:-1;3424:10:0;;;;;;;;;;;;-1:-1:-1;;;3424:10:0;;;;;;2583:559;2643:13;2670:12;2684:13;2699:11;2712:12;2726:14;2745:57;2793:8;2745:47;:57::i;:::-;2669:133;;;;;;;;;;;2859:36;2891:3;2859:31;:36::i;:::-;2910:25;2929:5;2910:18;:25::i;:::-;2950:23;2968:4;2950:17;:23::i;:::-;3006:37;3038:4;3006:31;:37::i;:::-;3058:39;3090:6;3058:31;:39::i;:::-;2828:304;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;2828:304:0;;;;;;;;;;-1:-1:-1;2828:304:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;2828:304:0;;;;;;;;;;-1:-1:-1;2828:304:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;2828:304:0;;;;;;;-1:-1:-1;;;2828:304:0;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;2828:304:0;;;;;;;;;;-1:-1:-1;2828:304:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;;;;365:33;;-1:-1;;;2828:304:0;;;;;-1:-1:-1;2828:304:0;;;26:21:-1;;;-1:-1;;22:32;6:49;;2828:304:0;;;;;;;;-1:-1:-1;;;;;;;;;;;;;2583:559:0:o;1841:192:6:-;1927:7;1963:12;1955:6;;;;1947:29;;;;-1:-1:-1;;;1947:29:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1947:29:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1999:5:6;;;1841:192::o;2521:452:4:-;-1:-1:-1;;;;;2625:20:4;;2617:71;;;;-1:-1:-1;;;2617:71:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2707:23:4;;2699:77;;;;-1:-1:-1;;;2699:77:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2809:17:4;;;;;;:9;:17;;;;;;:29;;2831:6;2809:29;:21;:29;:::i;:::-;-1:-1:-1;;;;;2789:17:4;;;;;;;:9;:17;;;;;;:49;;;;2872:20;;;;;;;:32;;2897:6;2872:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;2849:20:4;;;;;;;:9;:20;;;;;;;;;:55;;;;2930:35;;;;;;;2849:20;;2930:35;;;;;;;;;;;;;2521:452;;;:::o;23528:575:1:-;23610:7;23638:30;23660:7;23638:21;:30::i;:::-;23630:95;;;;-1:-1:-1;;;23630:95:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23758:1;23744:11;:15;23736:77;;;;-1:-1:-1;;;23736:77:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;23869:18:1;;23834:32;23869:18;;;:9;:18;;;;;23912:11;;:28;;23928:11;23912:28;:15;:28;:::i;:::-;23898:42;;23961:41;23994:7;23961:32;:41::i;:::-;24030:65;24050:7;24059:32;24079:11;24059:19;:32::i;:::-;24093:1;24030:19;:65::i;35742:247::-;-1:-1:-1;;;;;35823:21:1;;35834:10;35823:21;35819:163;;;35861:39;35879:7;35888:11;35861:17;:39::i;:::-;35819:163;;;35933:37;35949:7;35958:11;35933:15;:37::i;37668:136::-;-1:-1:-1;;;;;37777:18:1;;37738:4;37777:18;;;:9;:18;;;;;37762:34;;:14;:34::i;3355:328:4:-;-1:-1:-1;;;;;3437:21:4;;3429:69;;;;-1:-1:-1;;;3429:69:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3526:12;;:24;;3543:6;3526:24;:16;:24;:::i;:::-;3511:12;:39;;;-1:-1:-1;;;;;3582:18:4;;;;:9;:18;;;;;;:30;;3605:6;3582:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;3561:18:4;;;;;;:9;:18;;;;;;;;:51;;;;3638:37;;;;;;;3561:18;;;;3638:37;;;;;;;;;;3355:328;;:::o;32876:1123:1:-;4788:13;:11;:13::i;:::-;4780:43;;;;;-1:-1:-1;;;4780:43:1;;;;;;;;;;;;-1:-1:-1;;;4780:43:1;;;;;;;;;;;;;;;33026:1:::1;33012:11;:15;33004:76;;;;-1:-1:-1::0;;;33004:76:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33223:30;33245:7;33223:21;:30::i;:::-;33219:195;;;-1:-1:-1::0;;;;;33316:18:1;::::1;;::::0;;;:9:::1;:18;::::0;;;;:25;33293:49:::1;::::0;:18:::1;33326:7:::0;33293:9:::1;:18::i;:::-;:22:::0;:49:::1;:22;:49;:::i;:::-;33278:11;:64;;33270:131;;;;-1:-1:-1::0;;;33270:131:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33434:31;33444:7;33453:11;33434:9;:31::i;:::-;33487:21;33510:22:::0;33536:32:::1;33556:11;33536:19;:32::i;:::-;33486:82:::0;;-1:-1:-1;33486:82:1;-1:-1:-1;33596:43:1::1;33486:82:::0;33615:23;33596:43:::1;:18;:43;:::i;:::-;33579:60;;33656:23;33665:13;33656:8;:23::i;:::-;33652:340;;;33717:14;33704:9;:27;33696:88;;;;-1:-1:-1::0;;;33696:88:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33652:340;;;33825:9;:14:::0;33817:72:::1;;;;-1:-1:-1::0;;;33817:72:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33904:76;33923:13;33938:10;33958:4;33965:14;33904:18;:76::i;:::-;4834:1;;32876:1123:::0;;;:::o;28431:1713::-;28601:17;:24;28536:25;;;;28592:34;;:4;;:34;:8;:34;:::i;:::-;28576:50;-1:-1:-1;28576:50:1;28637:13;28697:653;28718:1;28704:11;:15;:51;;;;-1:-1:-1;28731:17:1;:24;28723:32;;28704:51;28697:653;;;28786:23;28812:72;28829:17;28847:5;28829:24;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28829:24:1;28855:11;28868:15;28812:16;:72::i;:::-;28786:98;;28921:11;28903:15;:29;28899:241;;;29019:20;;28953:19;;;;;28999:40;;;:64;;-1:-1:-1;29043:20:1;;28999:64;28991:133;;;;-1:-1:-1;;;28991:133:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29247:17;:24;29168:15;;-1:-1:-1;29212:7:1;;;;;29168:15;;29238:33;;29234:83;;;29300:1;29292:9;;29234:83;-1:-1:-1;29331:7:1;;28697:653;;;29368:16;;29360:80;;;;-1:-1:-1;;;29360:80:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29461:30;;29551:10;29547:252;;29586:17;:24;;-1:-1:-1;29547:252:1;;;29641:5;29632;:14;29628:171;;-1:-1:-1;;29763:17:1;:24;;-1:-1:-1;;29688:9:1;29696:1;29628:171;29828:9;29823:314;29847:5;29843:1;:9;29823:314;;;-1:-1:-1;;29874:7:1;;;;29900:21;:38;;;;;29933:5;29925;:13;29900:38;29896:157;;;29967:22;29959:30;;30032:5;30008:29;;29896:157;30067:58;30100:17;30118:5;30100:24;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30100:24:1;30067:32;:58::i;:::-;29854:3;;29823:314;;;;28431:1713;;;;;;;;;:::o;25741:784::-;25843:7;25891:46;25911:25;:16;25932:3;25911:25;:20;:25;:::i;:::-;25891:15;;;:46;:19;:46;:::i;:::-;25873:15;:64;25958:19;25980:12;:10;:12::i;:::-;25958:34;;26007:21;26016:11;26007:8;:21::i;:::-;26003:393;;;26045:46;;26053:10;;26045:46;;;;;26074:16;;26045:46;;;;26074:16;26053:10;26045:46;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;26110:7:1;;26106:79;;26138:14;;:28;;-1:-1:-1;;;;;26138:14:1;;;;:28;;;;;26162:3;;26138:14;:28;:14;:28;26162:3;26138:14;:28;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;26138:28:1;26106:79;26003:393;;;26217:57;26232:11;26245:10;26257:16;26217:14;:57::i;:::-;26293:7;;26289:96;;26349:14;;26321:48;;26336:11;;-1:-1:-1;;;;;26349:14:1;26365:3;26321:14;:48::i;:::-;26421:62;;;;;;;;;;;;;;26449:10;;-1:-1:-1;;;;;26421:62:1;;;;;;;;;;;;;;-1:-1:-1;26501:16:1;;25741:784;-1:-1:-1;;;25741:784:1:o;3843:278:6:-;3929:7;3964:12;3957:5;3949:28;;;;-1:-1:-1;;;3949:28:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;3949:28:6;;3988:9;4004:1;4000;:5;;;;;;;3843:278;-1:-1:-1;;;;;3843:278:6:o;30457:502:1:-;30582:9;30577:282;30601:8;:15;30597:1;:19;30577:282;;;30642:16;30638:62;;30679:5;;30638:62;30728:59;30745:8;30754:1;30745:11;;;;;;;;;;;;;;30758;30771:15;30728:16;:59::i;:::-;30714:73;;30802:45;30835:8;30844:1;30835:11;;;;;;;;;;;;;;30802:32;:45::i;:::-;30618:3;;30577:282;;;-1:-1:-1;30877:16:1;;30869:82;;;;-1:-1:-1;;;30869:82:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3691:328:4;-1:-1:-1;;;;;3773:21:4;;3765:69;;;;-1:-1:-1;;;3765:69:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3868:18:4;;;;;;:9;:18;;;;;;:30;;3891:6;3868:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;3847:18:4;;;;;;:9;:18;;;;;:51;;;;3924:12;:24;;3941:6;3924:24;:16;:24;:::i;:::-;3909:12;:39;;;3974:37;;;;;;;;-1:-1:-1;;;;;3974:37:4;;;;;;;;;;;;;3691:328;;:::o;4652:440:3:-;4720:9;;;;;;4822:40;1015:12;4834:9;:27;4822:11;:40::i;:::-;4801:61;;;;;;-1:-1:-1;1067:7:3;1015:12;4885:27;;;4930:23;;;;-1:-1:-1;1116:2:3;4971:23;;;5014:25;;;;-1:-1:-1;5059:25:3;;;;;-1:-1:-1;4652:440:3;-1:-1:-1;;4652:440:3:o;5136:306:0:-;5214:13;5240:21;5264:24;5281:6;5264:16;:24::i;:::-;5240:48;;5312:2;5303:6;:11;5299:136;;;5367:7;5345:30;;;;;;-1:-1:-1;;;5345:30:0;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;5345:30:0;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;5345:30:0;;;5331:45;;;;;4118:875;4182:13;4212:5;4221:1;4212:10;4208:778;;;-1:-1:-1;4239:12:0;;;;;;;;;;;;-1:-1:-1;;;4239:12:0;;;;;;4208:778;4273:5;4282:1;4273:10;4269:717;;;-1:-1:-1;4300:12:0;;;;;;;;;;;;-1:-1:-1;;;4300:12:0;;;;;;4269:717;4334:5;4343:1;4334:10;4330:656;;;-1:-1:-1;4361:12:0;;;;;;;;;;;;-1:-1:-1;;;4361:12:0;;;;;;4330:656;4395:5;4404:1;4395:10;4391:595;;;-1:-1:-1;4422:12:0;;;;;;;;;;;;-1:-1:-1;;;4422:12:0;;;;;;4391:595;4456:5;4465:1;4456:10;4452:534;;;-1:-1:-1;4483:12:0;;;;;;;;;;;;-1:-1:-1;;;4483:12:0;;;;;;4452:534;4517:5;4526:1;4517:10;4513:473;;;-1:-1:-1;4544:12:0;;;;;;;;;;;;-1:-1:-1;;;4544:12:0;;;;;;4513:473;4578:5;4587:1;4578:10;4574:412;;;-1:-1:-1;4605:12:0;;;;;;;;;;;;-1:-1:-1;;;4605:12:0;;;;;;4574:412;4639:5;4648:1;4639:10;4635:351;;;-1:-1:-1;4666:12:0;;;;;;;;;;;;-1:-1:-1;;;4666:12:0;;;;;;4635:351;4700:5;4709:1;4700:10;4696:290;;;-1:-1:-1;4727:12:0;;;;;;;;;;;;-1:-1:-1;;;4727:12:0;;;;;;4696:290;4761:5;4770:2;4761:11;4757:229;;;-1:-1:-1;4789:12:0;;;;;;;;;;;;-1:-1:-1;;;4789:12:0;;;;;;4757:229;4823:5;4832:2;4823:11;4819:167;;;-1:-1:-1;4851:12:0;;;;;;;;;;;;-1:-1:-1;;;4851:12:0;;;;;;4819:167;4885:5;4894:2;4885:11;4881:105;;;-1:-1:-1;4913:12:0;;;;;;;;;;;;-1:-1:-1;;;4913:12:0;;;;;;4881:105;-1:-1:-1;4958:16:0;;;;;;;;;;;;-1:-1:-1;;;4958:16:0;;;;;;3586:409;3648:13;3674:22;3705;3722:4;3705:16;:22::i;:::-;3761:12;;;3771:1;3761:12;;;;;;;;;3674:54;;-1:-1:-1;3739:19:0;;3761:12;;;;21:6:-1;;108:14;3761:12:0;87:42:-1;-1:-1;;3805:16:0;;3739:34;;-1:-1:-1;;;;3805:20:0;;3836:120;3869:9;:16;3865:1;:20;3836:120;;;3932:9;3942:1;3932:12;;;;;;;;;;;;;;;;3907:6;3918:10;3914:1;:14;3907:22;;;;;;;;;;;:37;-1:-1:-1;;;;;3907:37:0;;;;;;;;-1:-1:-1;3887:3:0;;3836:120;;;-1:-1:-1;3980:6:0;;3586:409;-1:-1:-1;;;;3586:409:0:o;2313:200:4:-;-1:-1:-1;;;;;2421:20:4;;;;;;:11;:20;;;;;;;;2409:10;2421:32;;;;;;;;;2385:81;;2400:7;;2421:44;;2458:6;2421:44;:36;:44;:::i;2385:81::-;2477:28;2489:7;2498:6;2477:11;:28::i;4578:130:6:-;4636:7;4663:37;4667:1;4670;4663:37;;;;;;;;;;;;;;;;;:3;:37::i;31333:1211:1:-;31439:7;31459:17;31479:29;31500:7;31479:20;:29::i;:::-;31459:49;-1:-1:-1;31523:13:1;;31519:989;;-1:-1:-1;;;;;31602:18:1;;31567:32;31602:18;;;:9;:18;;;;;;31677:23;;;31673:254;;;-1:-1:-1;31739:9:1;31781:26;:11;31739:9;31781:26;:15;:26;:::i;:::-;31767:40;;31673:254;;;-1:-1:-1;31910:1:1;;31673:254;31956:21;31979:14;31997:36;32017:15;31997:19;:36::i;:::-;31955:78;;-1:-1:-1;31955:78:1;-1:-1:-1;32116:13:1;31955:78;32127:1;32116:13;:10;:13;:::i;:::-;32172:11;;32107:22;;-1:-1:-1;32172:32:1;;32188:15;32172:32;:15;:32;:::i;:::-;32158:46;;32238:23;32247:13;32238:8;:23::i;:::-;32234:184;;;32282:33;;-1:-1:-1;;;;;32282:25:1;;;:33;;;;;32308:6;;32282:33;;;;32308:6;32282:25;:33;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32282:33:1;32234:184;;;32356:46;32371:13;32386:7;32395:6;32356:14;:46::i;:::-;32455:15;-1:-1:-1;;;;;32437:59:1;32446:7;-1:-1:-1;;;;;32437:59:1;;32472:6;32480:15;32437:59;;;;;;;;;;;;;;;;;;;;;;;;31519:989;;;;;-1:-1:-1;32525:11:1;;31333:1211;-1:-1:-1;;;31333:1211:1:o;40559:333::-;40729:17;;40706:60;;;-1:-1:-1;;;;;40706:60:1;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;40706:60:1;;;;;;;25:18:-1;;61:17;;40729::1;;;;;;-1:-1:-1;;;;;;40706:60:1;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;40695:72:1;;;;-1:-1:-1;;40668:23:1;;40695:10;;;40706:60;40695:72;;;25:18:-1;40695:72:1;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;40695:72:1;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;40653:114:1;;;;40786:7;:69;;;;-1:-1:-1;40798:17:1;;:22;;:56;;;40835:10;40824:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;40824:30:1;40798:56;40778:106;;;;;-1:-1:-1;;;40778:106:1;;;;;;;;;;;;;;;;;;;;;;;;;;;3363:622:3;3419:9;;;3480:5;3507:31;;;3419:9;3565:6;3557:1;:5;;:14;;-1:-1:-1;3609:1:3;3604;3591:6;:10;;:14;3590:20;3586:24;;;;3621:9;3650:7;3633:4;3645:1;3641:5;;3633:14;:24;;-1:-1:-1;3691:1:3;3676:4;:12;;:16;3672:1;:20;3695:2;3672:25;3668:29;;3708:10;3730:4;3726:1;3721:2;:6;:13;;;;;;;-1:-1:-1;3745:8:3;3776:2;3760:4;:13;;:18;3756:22;;;-1:-1:-1;3802:2:3;3793:6;:11;-1:-1:-1;;3869:6:3;;;;3862:3;:14;:22;;;;:26;;;3833:1;3837:2;:6;;;3824:19;;;;;;;;-1:-1:-1;3793:11:3;-1:-1:-1;3862:26:3;-1:-1:-1;;;;3363:622:3:o;273:744:7:-;329:13;550:10;546:53;;-1:-1:-1;577:10:7;;;;;;;;;;;;-1:-1:-1;;;577:10:7;;;;;;546:53;624:5;609:12;665:78;672:9;;665:78;;698:8;;729:2;721:10;;;;665:78;;;753:19;785:6;775:17;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;775:17:7;;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;775:17:7;87:42:-1;143:17;;-1:-1;775:17:7;-1:-1:-1;847:5:7;;-1:-1:-1;753:39:7;-1:-1:-1;;;819:10:7;;863:115;870:9;;863:115;;937:2;930:4;:9;925:2;:14;914:27;;896:6;903:7;;;;;;;896:15;;;;;;;;;;;:45;-1:-1:-1;;;;;896:45:7;;;;;;;;-1:-1:-1;964:2:7;956:10;;;;863:115;;;-1:-1:-1;1002:6:7;273:744;-1:-1:-1;;;;273:744:7:o;5185:166:6:-;5271:7;5307:12;5299:6;5291:29;;;;-1:-1:-1;;;5291:29:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;5291:29:6;;5342:1;5338;:5;;;;;;;5185:166;-1:-1:-1;;;;5185:166:6:o;221:41335:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;221:41335:1;;;-1:-1:-1;221:41335:1;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
ipfs://cb30ae80319463574ff120f520633d68378fa215960c0dd60da4052df64ca491
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.