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
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Init | 10745258 | 1634 days ago | IN | 0 ETH | 0.01295176 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
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 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 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"},{"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":"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
608060405234801561001057600080fd5b506144e7806100206000396000f3fe6080604052600436106102b25760003560e01c806379cc679011610175578063a95ad147116100dc578063c52987cf11610095578063d90a730e1161006f578063d90a730e14610b0e578063dd62ed3e14610b23578063de53fcd514610b5e578063e503d23914610b73576102bc565b8063c52987cf14610ab1578063c54e486214610ac6578063d8dfeb4514610af9576102bc565b8063a95ad14714610996578063b0df1cc714610a0d578063bdc7c12b14610a33578063be040fb014610a5d578063c132566114610a72578063c2507ac114610a87576102bc565b806399bc0aea1161012e57806399bc0aea1461088f5780639c83c847146108a4578063a0712d68146108d7578063a457c2d714610901578063a86265bb1461093a578063a9059cbb1461095d576102bc565b806379cc6790146107055780637c974fc41461073e57806387ab4a18146107c35780638ff1516b146107f65780639152cb591461082957806395d89b41146102c1576102bc565b8063449a52f8116102195780635d97d3e2116101d25780635d97d3e2146106105780636d6364781461065d5780636f012b8d146106725780636f307dc3146106b557806370a08231146106ca578063732a950d146106fd576102bc565b8063449a52f81461053357806345f79d1b1461056c5780634701eaa81461059f57806347713098146105b45780634ac8eb5f146105e65780634dd662ee146105fb576102bc565b806325a760c21161026b57806325a760c214610448578063313a9b4e14610473578063313ce56714610488578063395093511461049d5780633acc3af2146104d657806342966c6814610509576102bc565b806306fdde03146102c1578063095ea7b31461034b57806311b7bda71461039857806317d69bc8146103ad57806318160ddd146103de57806323b872dd14610405576102bc565b366102bc57600080fd5b600080fd5b3480156102cd57600080fd5b506102d6610ba6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103105781810151838201526020016102f8565b50505050905090810190601f16801561033d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561035757600080fd5b506103846004803603604081101561036e57600080fd5b506001600160a01b038135169060200135610bb6565b604080519115158252519081900360200190f35b3480156103a457600080fd5b506102d6610bcd565b3480156103b957600080fd5b506103c2610c5b565b604080516001600160a01b039092168252519081900360200190f35b3480156103ea57600080fd5b506103f3610c6a565b60408051918252519081900360200190f35b34801561041157600080fd5b506103846004803603606081101561042857600080fd5b506001600160a01b03813581169160208101359091169060400135610c70565b34801561045457600080fd5b5061045d610cc4565b6040805160ff9092168252519081900360200190f35b34801561047f57600080fd5b506103f3610ccd565b34801561049457600080fd5b5061045d610cd3565b3480156104a957600080fd5b50610384600480360360408110156104c057600080fd5b506001600160a01b038135169060200135610cdc565b3480156104e257600080fd5b506103f3600480360360208110156104f957600080fd5b50356001600160a01b0316610d1d565b34801561051557600080fd5b506103f36004803603602081101561052c57600080fd5b5035610d38565b34801561053f57600080fd5b506103f36004803603604081101561055657600080fd5b506001600160a01b038135169060200135610d44565b34801561057857600080fd5b506103f36004803603602081101561058f57600080fd5b50356001600160a01b0316610dca565b3480156105ab57600080fd5b506103f3610de5565b6103f3600480360360608110156105ca57600080fd5b506001600160a01b038135169060208101359060400135610deb565b3480156105f257600080fd5b506103f3610df8565b34801561060757600080fd5b506103f3610dfe565b34801561061c57600080fd5b5061063a6004803603602081101561063357600080fd5b5035610e04565b604080516001600160a01b03909316835260208301919091528051918290030190f35b34801561066957600080fd5b50610384610e4e565b34801561067e57600080fd5b5061069c6004803603602081101561069557600080fd5b5035610e5e565b6040805192835260208301919091528051918290030190f35b3480156106c157600080fd5b506103c2610eb4565b3480156106d657600080fd5b506103f3600480360360208110156106ed57600080fd5b50356001600160a01b0316610ec3565b6103f3610ede565b34801561071157600080fd5b506103f36004803603604081101561072857600080fd5b506001600160a01b038135169060200135610f35565b6103f36004803603606081101561075457600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561078457600080fd5b82018360208201111561079657600080fd5b803590602001918460208302840111640100000000831117156107b857600080fd5b509092509050610f48565b3480156107cf57600080fd5b506103f3600480360360208110156107e657600080fd5b50356001600160a01b0316610f91565b34801561080257600080fd5b506103f36004803603602081101561081957600080fd5b50356001600160a01b0316610fb8565b34801561083557600080fd5b5061088d600480360361010081101561084d57600080fd5b506001600160a01b0381358116916020810135821691604082013515159160608101359160808201359160a08101359160c0820135169060e00135610fc6565b005b34801561089b57600080fd5b506103f361144c565b3480156108b057600080fd5b506103f3600480360360208110156108c757600080fd5b50356001600160a01b0316611452565b3480156108e357600080fd5b506103f3600480360360208110156108fa57600080fd5b5035611460565b34801561090d57600080fd5b506103846004803603604081101561092457600080fd5b506001600160a01b0381351690602001356114de565b6103f36004803603604081101561095057600080fd5b508035906020013561151a565b34801561096957600080fd5b506103846004803603604081101561098057600080fd5b506001600160a01b038135169060200135611527565b6103f3600480360360408110156109ac57600080fd5b813591908101906040810160208201356401000000008111156109ce57600080fd5b8201836020820111156109e057600080fd5b80359060200191846020830284011164010000000083111715610a0257600080fd5b509092509050611534565b6103f360048036036020811015610a2357600080fd5b50356001600160a01b0316611574565b348015610a3f57600080fd5b506103f360048036036020811015610a5657600080fd5b50356115c6565b348015610a6957600080fd5b506103f36115f1565b348015610a7e57600080fd5b5061045d6115fc565b348015610a9357600080fd5b506103f360048036036020811015610aaa57600080fd5b503561160a565b348015610abd57600080fd5b506103f3611647565b348015610ad257600080fd5b506103f360048036036020811015610ae957600080fd5b50356001600160a01b031661164d565b348015610b0557600080fd5b506103c26116b8565b348015610b1a57600080fd5b506102d66116f1565b348015610b2f57600080fd5b506103f360048036036040811015610b4657600080fd5b506001600160a01b038135811691602001351661174c565b348015610b6a57600080fd5b506103c2611777565b348015610b7f57600080fd5b506103f360048036036020811015610b9657600080fd5b50356001600160a01b0316611786565b6060610bb06117e6565b90505b90565b6000610bc3338484611a17565b5060015b92915050565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610c535780601f10610c2857610100808354040283529160200191610c53565b820191906000526020600020905b815481529060010190602001808311610c3657829003601f168201915b505050505081565b6004546001600160a01b031681565b60005490565b6001600160a01b0383166000908152600260209081526040808320338085529252822054610caf918691610caa908663ffffffff611a2716565b611a69565b610cba848484611b55565b5060019392505050565b600c5460ff1681565b600d5481565b600c5460ff1690565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610bc3918590610d18908663ffffffff611b6016565b611a17565b6000610d30610d2b83610f91565b6115c6565b90505b919050565b6000610d303383611bba565b600080610d4f6116b8565b9050610d5a81611c8c565b15610dac576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a6d696e74546f3a20496e76616c69642063616c6c0000604482015290519081900360640190fd5b610db881333086611c99565b610dc28484611e22565b949350505050565b6001600160a01b03166000908152600f602052604090205490565b60095481565b6000610dc284848461205d565b60085481565b60105490565b6005546000908190600160a01b900460ff1615610e39576004546001600160a01b0316610e3084612103565b91509150610e49565b50506003546001600160a01b0316815b915091565b600554600160a01b900460ff1681565b6000806000610e6c846115c6565b90506000610e98620186a0610e8c6009548561212090919063ffffffff16565b9063ffffffff61217916565b9050610eaa828263ffffffff611a2716565b9350915050915091565b6003546001600160a01b031681565b6001600160a01b031660009081526001602052604090205490565b6000610ef0610eeb6116b8565b611c8c565b610f2b5760405162461bcd60e51b81526004018080602001828103825260238152602001806143696023913960400191505060405180910390fd5b610bb03334611e22565b6000610f418383611bba565b9392505050565b6000610f8885858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506121bb92505050565b95945050505050565b6000610f9b61222d565b15610fb057610fa982612235565b9050610d33565b506000610d33565b6000610d30610d2b83610dca565b6003546001600160a01b0316158015610fe857506004546001600160a01b0316155b8015610ff45750600654155b61102f5760405162461bcd60e51b81526004018080602001828103825260238152602001806143e56023913960400191505060405180910390fd5b428411611083576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a696e69743a20496e76616c6964206578706972790000604482015290519081900360640190fd5b600085116110c25760405162461bcd60e51b81526004018080602001828103825260248152602001806141686024913960400191505060405180910390fd5b866001600160a01b0316886001600160a01b03161415611129576040805162461bcd60e51b815260206004820152601b60248201527f41434f546f6b656e3a3a696e69743a2053616d65206173736574730000000000604482015290519081900360640190fd5b6101f4831115611180576040805162461bcd60e51b815260206004820152601f60248201527f41434f546f6b656e3a3a696e69743a20496e76616c69642041434f2066656500604482015290519081900360640190fd5b61118988611c8c565b806111a157506111a1886001600160a01b0316612290565b6111dc5760405162461bcd60e51b8152600401808060200182810382526022815260200180613fe96022913960400191505060405180910390fd5b6111e587611c8c565b806111fd57506111fd876001600160a01b0316612290565b6112385760405162461bcd60e51b815260040180806020018281038252602481526020018061438c6024913960400191505060405180910390fd5b6019811015801561124a575060968111155b6112855760405162461bcd60e51b815260040180806020018281038252603881526020018061410d6038913960400191505060405180910390fd5b600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a84161790556005805460068990556007889055600987905560ff60a01b1916600160a01b8a15150217909116918416919091179055600d8190556112f1886122c9565b600c805460ff191660ff9283161790819055604e9116106113435760405162461bcd60e51b815260040180806020018281038252602b81526020018061403a602b913960400191505060405180910390fd5b61134c876122c9565b600c60016101000a81548160ff021916908360ff16021790555061136f8861240e565b805161138391600a91602090910190613eea565b5061138d8761240e565b80516113a191600b91602090910190613eea565b50600c5460ff16600a0a600e55604080518082018252601981527f7472616e7366657228616464726573732c75696e7432353629000000000000006020918201526011805464ffffffff00191664a9059cbb001790558151606081019092526025808352906140659083013980516020909101206011805460ff1960e09390931c650100000000000268ffffffff000000000019909116179190911660011790555050505050505050565b60075481565b6000610d30610d2b83611786565b60008061146b6116b8565b905061147681611c8c565b156114c8576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a6d696e743a20496e76616c69642063616c6c00000000604482015290519081900360640190fd5b6114d481333086611c99565b610f413384611e22565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610bc3918590610d18908663ffffffff611a2716565b6000610f4133848461205d565b6000610bc3338484611b55565b6000610dc233858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506121bb92505050565b6000611581610eeb6116b8565b6115bc5760405162461bcd60e51b81526004018080602001828103825260258152602001806140be6025913960400191505060405180910390fd5b610d308234611e22565b600554600090600160a01b900460ff16156115e2575080610d33565b8115610fb057610fa982612103565b6000610bb033612618565b600c54610100900460ff1681565b600554600090600160a01b900460ff1615611626575080610d33565b8115610fb057610fa9600654610e8c600e548561212090919063ffffffff16565b60065481565b6000611659823361174c565b6001600160a01b0383166000908152600f602052604090205411156116af5760405162461bcd60e51b81526004018080602001828103825260278152602001806143426027913960400191505060405180910390fd5b610d3082612618565b600554600090600160a01b900460ff16156116df57506003546001600160a01b0316610bb3565b506004546001600160a01b0316610bb3565b600a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610c535780601f10610c2857610100808354040283529160200191610c53565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6005546001600160a01b031681565b6001600160a01b0381166000908152600f60205260408120546117a883610ec3565b11806117b957506117b761222d565b155b156117dd57506001600160a01b0381166000908152600f6020526040902054610d33565b610fa982610ec3565b6060600a611805600654600c60019054906101000a900460ff16612700565b600554600b9061181e90600160a01b900460ff166128a8565b6118296007546128ec565b604051602001808063020a1a7960e51b815250600401868054600181600116156101000203166002900480156118965780601f10611874576101008083540402835291820191611896565b820191906000526020600020905b815481529060010190602001808311611882575b505080602d60f81b81525060010185805190602001908083835b602083106118cf5780518252601f1990920191602091820191016118b0565b6001836020036101000a038019825116818451168082178552505050505050905001848054600181600116156101000203166002900480156119485780601f10611926576101008083540402835291820191611948565b820191906000526020600020905b815481529060010190602001808311611934575b505080602d60f81b81525060010183805190602001908083835b602083106119815780518252601f199092019160209182019101611962565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010182805190602001908083835b602083106119da5780518252601f1990920191602091820191016119bb565b6001836020036101000a03801982511681845116808217855250505050505090500195505050505050604051602081830303815290604052905090565b611a22838383611a69565b505050565b6000610f4183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612aea565b6001600160a01b038316611aae5760405162461bcd60e51b815260040180806020018281038252602481526020018061445d6024913960400191505060405180910390fd5b6001600160a01b038216611af35760405162461bcd60e51b81526004018080602001828103825260268152602001806142ec6026913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b611a22838383612b81565b600082820183811015610f41576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60115460009060ff16611c08576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611c1a61222d565b611c5f576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000611c6b8484612cc5565b9050611c778484612d93565b90506011805460ff1916600117905592915050565b6001600160a01b03161590565b601154604080516001600160a01b0386811660248301528581166044830152606480830186905283518084039091018152608490920183526020820180516501000000000090950460e01b6001600160e01b0319166001600160e01b03909516949094178452915181516000946060948a169392918291908083835b60208310611d345780518252601f199092019160209182019101611d15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611d96576040519150601f19603f3d011682016040523d82523d6000602084013e611d9b565b606091505b5091509150818015611dc9575080511580611dc95750808060200190516020811015611dc657600080fd5b50515b611e1a576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a5f7472616e7366657246726f6d455243323000000000604482015290519081900360640190fd5b505050505050565b60115460009060ff16611e70576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611e8261222d565b611ec7576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b60008211611f065760405162461bcd60e51b815260040180806020018281038252602f81526020018061400b602f913960400191505060405180910390fd5b611f0f83612dc1565b611f7357601080546001600160a01b0385166000818152600f60205260408120600190810184905583018455929092527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b6000611f7e8361160a565b905080611fbc5760405162461bcd60e51b815260040180806020018281038252602a8152602001806140e3602a913960400191505060405180910390fd5b6001600160a01b0384166000908152600f6020526040902054611fe5908263ffffffff611b6016565b6001600160a01b0385166000908152600f6020526040902055600854612011908463ffffffff611b6016565b6008556040805184815290516001600160a01b038616917ff645c19720906ca336d36d26058a9489c6c757fe35843b75a74e3b8aa972ecf5919081900360200190a2611c773382612de2565b60115460009060ff166120ab576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055600d546120c59085908590612ebd565b6120d0848484613095565b6000806120dc85610e5e565b915091506120eb868383613240565b925050506011805460ff191660011790559392505050565b6000610d30600e54610e8c6006548561212090919063ffffffff16565b60008261212f57506000610bc7565b8282028284828161213c57fe5b0414610f415760405162461bcd60e51b81526004018080602001828103825260218152602001806142236021913960400191505060405180910390fd5b6000610f4183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613370565b60115460009060ff16612209576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905581516122229085908590612ebd565b6120d08484846133d5565b600754421090565b600061224082610ec3565b6001600160a01b0383166000908152600f60205260409020541115610fb057610fa961226b83610ec3565b6001600160a01b0384166000908152600f60205260409020549063ffffffff611a2716565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610dc2575050151592915050565b60006122d482611c8c565b156122e157506012610d33565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106123475780518252601f199092019160209182019101612328565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146123a7576040519150601f19603f3d011682016040523d82523d6000602084013e6123ac565b606091505b5091509150816123ed5760405162461bcd60e51b8152600401808060200182810382526033815260200180613fb66033913960400191505060405180910390fd5b80806020019051602081101561240257600080fd5b50519250610d33915050565b606061241982611c8c565b1561243e575060408051808201909152600381526208aa8960eb1b6020820152610d33565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106124a45780518252601f199092019160209182019101612485565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612504576040519150601f19603f3d011682016040523d82523d6000602084013e612509565b606091505b50915091508161254a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614408602f913960400191505060405180910390fd5b80806020019051602081101561255f57600080fd5b810190808051604051939291908464010000000082111561257f57600080fd5b90830190602082018581111561259457600080fd5b82516401000000008111828201881017156125ae57600080fd5b82525081516020918201929091019080838360005b838110156125db5781810151838201526020016125c3565b50505050905090810190601f1680156126085780820380516001836020036101000a031916815260200191505b5060405250505092505050610d33565b60115460009060ff16612666576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905561267861222d565b156126b45760405162461bcd60e51b81526004018080602001828103825260288152602001806142c46028913960400191505060405180910390fd5b6001600160a01b0382166000908152600f60205260408120546126d8908490612cc5565b90506126ec836126e785610ec3565b61346d565b90506011805460ff19166001179055919050565b6060600080808086805b8115612765578315801561272c5750600a820615158061272c57508760ff1685145b15612738575060019250805b8315612754578760ff1685141561274d578592505b6001909501945b600a8260019096019504915061270a565b8760ff16851161278757848860ff168760020101039550600286039250612794565b8215612794576001909501945b60608667ffffffffffffffff811180156127ad57600080fd5b506040519080825280601f01601f1916602001820160405280156127d8576020820181803683370190505b5091925082919050600019870160005b88811015612898576000811180156127ff57508581145b1561283857601760f91b8383806001900394508151811061281c57fe5b60200101906001600160f81b031916908160001a905350612890565b8361285557600360fc1b8383806001900394508151811061281c57fe5b600a840660300160f81b8383806001900394508151811061287257fe5b60200101906001600160f81b031916908160001a905350600a840493505b6001016127e8565b50909a9950505050505050505050565b606081156128ce57506040805180820190915260018152604360f81b6020820152610d33565b506040805180820190915260018152600560fc1b6020820152610d33565b606060008060008060006128ff87613550565b509450945094509450945061291383613590565b61291c85613622565b61292587613834565b61292e85613590565b61293785613590565b6040516020018086805190602001908083835b602083106129695780518252601f19909201916020918201910161294a565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106129b15780518252601f199092019160209182019101612992565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106129f95780518252601f1990920191602091820191016129da565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010183805190602001908083835b60208310612a525780518252601f199092019160209182019101612a33565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612a9a5780518252601f199092019160209182019101612a7b565b5181516020939093036101000a60001901801990911692169190911790526255544360e81b92019182525060408051808303601c19018152600390920190529d9c50505050505050505050505050565b60008184841115612b795760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612b3e578181015183820152602001612b26565b50505050905090810190601f168015612b6b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316612bc65760405162461bcd60e51b81526004018080602001828103825260268152602001806144376026913960400191505060405180910390fd5b6001600160a01b038216612c0b5760405162461bcd60e51b81526004018080602001828103825260298152602001806141c46029913960400191505060405180910390fd5b6001600160a01b038316600090815260016020526040902054612c34908263ffffffff611a2716565b6001600160a01b038085166000908152600160205260408082209390935590841681522054612c69908263ffffffff611b6016565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000612cd083612dc1565b612d0b5760405162461bcd60e51b815260040180806020018281038252603481526020018061408a6034913960400191505060405180910390fd5b60008211612d4a5760405162461bcd60e51b81526004018080602001828103825260318152602001806144816031913960400191505060405180910390fd5b6001600160a01b0383166000908152600f602052604090208054612d74908463ffffffff611a2716565b8155612d7f846138c4565b610dc284612d8c856115c6565b6000613240565b6001600160a01b038216331415612db357612dae828261346d565b612dbd565b612dbd82826139d3565b5050565b6001600160a01b0381166000908152600f60205260408120610d3090613a18565b6001600160a01b038216612e275760405162461bcd60e51b81526004018080602001828103825260238152602001806142746023913960400191505060405180910390fd5b600054612e3a908263ffffffff611b6016565b60009081556001600160a01b038316815260016020526040902054612e65908263ffffffff611b6016565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b612ec561222d565b612f0a576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b60008211612f495760405162461bcd60e51b81526004018080602001828103825260308152602001806142446030913960400191505060405180910390fd5b612f5283612dc1565b15612fc7576001600160a01b0383166000908152600f6020526040902054612f8990612f7d85610ec3565b9063ffffffff611a2716565b821115612fc75760405162461bcd60e51b81526004018080602001828103825260368152602001806141ed6036913960400191505060405180910390fd5b612fd18383612d93565b600080612fdd84610e04565b9092509050612ff2818463ffffffff611b6016565b9050612ffd82611c8c565b15613045578034146130405760405162461bcd60e51b81526004018080602001828103825260308152602001806143126030913960400191505060405180910390fd5b61308e565b34156130825760405162461bcd60e51b815260040180806020018281038252602d815260200180614297602d913960400191505060405180910390fd5b61308e82333084611c99565b5050505050565b60105460009081906130ae90849063ffffffff613a1e16565b90508060005b6000861180156130c5575060105481105b156131745760006130f8601084815481106130dc57fe5b6000918252602090912001546001600160a01b0316888a613a60565b90508681101561315157600d54600190950194851080613116575080155b6131515760405162461bcd60e51b815260040180806020018281038252603881526020018061418c6038913960400191505060405180910390fd5b601054909650600190920191869083141561316b57600092505b506001016130b4565b85156131b15760405162461bcd60e51b8152600401808060200182810382526033815260200180613f836033913960400191505060405180910390fd5b600080836131c35760105493506131d7565b8484116131d7575050601054916000190160015b60005b8381101561323457600019909401938180156131f557508585105b1561320257829450600091505b61322c6010868154811061321257fe5b6000918252602090912001546001600160a01b03166138c4565b6001016131da565b50505050505050505050565b6000613264613255848463ffffffff611b6016565b6008549063ffffffff611a2716565b60085560006132716116b8565b905061327c81611c8c565b156132f657604051339085156108fc029086906000818181858888f193505050501580156132ae573d6000803e3d6000fd5b5082156132f1576005546040516001600160a01b039091169084156108fc029085906000818181858888f193505050501580156132ef573d6000803e3d6000fd5b505b61331f565b613301813386613ba2565b821561331f5760055461331f9082906001600160a01b031685613ba2565b6040805185815260208101859052815133926001600160a01b038916927fd3506bcc260407a7f95f487dd7c600bc45888cce58989ceadbe8c0bbf9257b28929081900390910190a350919392505050565b600081836133bf5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612b3e578181015183820152602001612b26565b5060008385816133cb57fe5b0495945050505050565b60005b815181101561342f57826133eb5761342f565b6134098282815181106133fa57fe5b60200260200101518486613a60565b925061342782828151811061341a57fe5b60200260200101516138c4565b6001016133d8565b508115611a225760405162461bcd60e51b81526004018080602001828103825260358152602001806143b06035913960400191505060405180910390fd5b6001600160a01b0382166134b25760405162461bcd60e51b81526004018080602001828103825260238152602001806141456023913960400191505060405180910390fd5b6001600160a01b0382166000908152600160205260409020546134db908263ffffffff611a2716565b6001600160a01b03831660009081526001602052604081209190915554613508908263ffffffff611a2716565b60009081556040805183815290516001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b60008080808080613565620151808804613d17565b91999098919750610e10620151809092068281049750603c9290068281049650919091069350915050565b60608061359c83613dad565b9050600a831015610fa957806040516020018080600360fc1b81525060010182805190602001908083835b602083106135e65780518252601f1990920191602091820191016135c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052915050610d33565b6060816001141561364d57506040805180820190915260038152622520a760e91b6020820152610d33565b816002141561367657506040805180820190915260038152622322a160e91b6020820152610d33565b816003141561369f575060408051808201909152600381526226a0a960e91b6020820152610d33565b81600414156136c8575060408051808201909152600381526220a82960e91b6020820152610d33565b81600514156136f157506040805180820190915260038152624d415960e81b6020820152610d33565b816006141561371a5750604080518082019091526003815262252aa760e91b6020820152610d33565b8160071415613743575060408051808201909152600381526212955360ea1b6020820152610d33565b816008141561376c575060408051808201909152600381526241554760e81b6020820152610d33565b8160091415613795575060408051808201909152600381526205345560ec1b6020820152610d33565b81600a14156137be575060408051808201909152600381526213d0d560ea1b6020820152610d33565b81600b14156137e757506040805180820190915260038152622727ab60e91b6020820152610d33565b81600c1415613810575060408051808201909152600381526244454360e81b6020820152610d33565b506040805180820190915260078152661253959053125160ca1b6020820152610d33565b60608061384083613dad565b60408051600280825281830190925291925060609190602082018180368337505083519192505060011901805b83518110156138ba5783818151811061388257fe5b602001015160f81c60f81b838383038151811061389b57fe5b60200101906001600160f81b031916908160001a90535060010161386d565b5090949350505050565b6001600160a01b0381166000908152600f602052604090206138e581613a18565b612dbd5760105460018201546000199091019081146139825760006010828154811061390d57fe5b60009182526020808320909101546001868101546001600160a01b03909216808552600f90935260409093209092018290556010805491935083929091811061395257fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b601080548061398d57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600f90526040812081815560010155505050565b6001600160a01b038216600090815260026020908152604080832033808552925290912054613a0e918491610caa908563ffffffff611a2716565b612dbd828261346d565b54151590565b6000610f4183836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250613e88565b600080613a6c85612235565b90508015613b99576001600160a01b0385166000908152600f602052604081209085831015613aae575081613aa7868263ffffffff611a2716565b9550613ab3565b506000945b600080613abf83610e04565b9092509050613ad581600163ffffffff611b6016565b8454909150613aea908463ffffffff611a2716565b8455613af582611c8c565b15613b36576040516001600160a01b038a169082156108fc029083906000818181858888f19350505050158015613b30573d6000803e3d6000fd5b50613b41565b613b41828a83613ba2565b866001600160a01b0316896001600160a01b03167f5f283076724262032199f54be27a9364634b895b3a37c1e66bfe47d5d05347698386604051808381526020018281526020019250505060405180910390a3505050505b50919392505050565b601154604080516001600160a01b0385811660248301526044808301869052835180840390910181526064909201835260208201805161010090950460e01b6001600160e01b0319166001600160e01b039095169490941784529151815160009460609489169392918291908083835b60208310613c315780518252601f199092019160209182019101613c12565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c93576040519150601f19603f3d011682016040523d82523d6000602084013e613c98565b606091505b5091509150818015613cc6575080511580613cc65750808060200190516020811015613cc357600080fd5b50515b61308e576040805162461bcd60e51b815260206004820152601860248201527f41434f546f6b656e3a3a5f7472616e7366657245524332300000000000000000604482015290519081900360640190fd5b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f8460500281613d6e57fe5b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b606081613dd257506040805180820190915260018152600360fc1b6020820152610d33565b8160005b8115613dea57600101600a82049150613dd6565b60608167ffffffffffffffff81118015613e0357600080fd5b506040519080825280601f01601f191660200182016040528015613e2e576020820181803683370190505b50859350905060001982015b8315613e7f57600a840660300160f81b82828060019003935081518110613e5d57fe5b60200101906001600160f81b031916908160001a905350600a84049350613e3a565b50949350505050565b60008183613ed75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612b3e578181015183820152602001612b26565b50828481613ee157fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613f2b57805160ff1916838001178555613f58565b82800160010185558215613f58579182015b82811115613f58578251825591602001919060010190613f3d565b50613f64929150613f68565b5090565b610bb391905b80821115613f645760008155600101613f6e56fe41434f546f6b656e3a3a5f65786572636973654f776e6572733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a5f6765744173736574446563696d616c733a20496e76616c696420617373657420646563696d616c7341434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6741434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420636f6c6c61746572616c20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6720646563696d616c737472616e7366657246726f6d28616464726573732c616464726573732c75696e743235362941434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a204e6f20636f6c6c61746572616c20617661696c61626c6541434f546f6b656e3a3a6d696e74546f50617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c6964206e756d62657220746f206d617820657865726369736564206163636f756e747345524332303a3a5f6275726e416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520707269636541434f546f6b656e3a3a5f65786572636973654f776e6572733a20546f6f206d616e79206163636f756e747320746f20657865726369736545524332303a3a5f7472616e73666572416374696f6e3a20496e76616c696420726563697069656e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20546f6b656e20616d6f756e74206e6f7420617661696c61626c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7741434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420746f6b656e20616d6f756e7445524332303a3a5f6d696e74416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a204e6f20657468657220657870656374656441434f546f6b656e3a3a5f72656465656d3a20546f6b656e206e6f7420657870697265642079657445524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964207370656e64657241434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420657468657220616d6f756e7441434f546f6b656e3a3a72656465656d46726f6d3a20416c6c6f77616e636520746f6f206c6f7741434f546f6b656e3a3a6d696e7450617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520617373657441434f546f6b656e3a3a5f65786572636973654163636f756e74733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a696e69743a20416c726561647920696e697469616c697a656441434f546f6b656e3a3a5f676574417373657453796d626f6c3a20496e76616c69642061737365742073796d626f6c45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c69642073656e64657245524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964206f776e657241434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a20496e76616c696420746f6b656e20616d6f756e74a2646970667358221220132b11c8e08a66d7ac3326606ac359c39d8a86667f84472891efae17b37a65e364736f6c63430006060033
Deployed Bytecode
0x6080604052600436106102b25760003560e01c806379cc679011610175578063a95ad147116100dc578063c52987cf11610095578063d90a730e1161006f578063d90a730e14610b0e578063dd62ed3e14610b23578063de53fcd514610b5e578063e503d23914610b73576102bc565b8063c52987cf14610ab1578063c54e486214610ac6578063d8dfeb4514610af9576102bc565b8063a95ad14714610996578063b0df1cc714610a0d578063bdc7c12b14610a33578063be040fb014610a5d578063c132566114610a72578063c2507ac114610a87576102bc565b806399bc0aea1161012e57806399bc0aea1461088f5780639c83c847146108a4578063a0712d68146108d7578063a457c2d714610901578063a86265bb1461093a578063a9059cbb1461095d576102bc565b806379cc6790146107055780637c974fc41461073e57806387ab4a18146107c35780638ff1516b146107f65780639152cb591461082957806395d89b41146102c1576102bc565b8063449a52f8116102195780635d97d3e2116101d25780635d97d3e2146106105780636d6364781461065d5780636f012b8d146106725780636f307dc3146106b557806370a08231146106ca578063732a950d146106fd576102bc565b8063449a52f81461053357806345f79d1b1461056c5780634701eaa81461059f57806347713098146105b45780634ac8eb5f146105e65780634dd662ee146105fb576102bc565b806325a760c21161026b57806325a760c214610448578063313a9b4e14610473578063313ce56714610488578063395093511461049d5780633acc3af2146104d657806342966c6814610509576102bc565b806306fdde03146102c1578063095ea7b31461034b57806311b7bda71461039857806317d69bc8146103ad57806318160ddd146103de57806323b872dd14610405576102bc565b366102bc57600080fd5b600080fd5b3480156102cd57600080fd5b506102d6610ba6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103105781810151838201526020016102f8565b50505050905090810190601f16801561033d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561035757600080fd5b506103846004803603604081101561036e57600080fd5b506001600160a01b038135169060200135610bb6565b604080519115158252519081900360200190f35b3480156103a457600080fd5b506102d6610bcd565b3480156103b957600080fd5b506103c2610c5b565b604080516001600160a01b039092168252519081900360200190f35b3480156103ea57600080fd5b506103f3610c6a565b60408051918252519081900360200190f35b34801561041157600080fd5b506103846004803603606081101561042857600080fd5b506001600160a01b03813581169160208101359091169060400135610c70565b34801561045457600080fd5b5061045d610cc4565b6040805160ff9092168252519081900360200190f35b34801561047f57600080fd5b506103f3610ccd565b34801561049457600080fd5b5061045d610cd3565b3480156104a957600080fd5b50610384600480360360408110156104c057600080fd5b506001600160a01b038135169060200135610cdc565b3480156104e257600080fd5b506103f3600480360360208110156104f957600080fd5b50356001600160a01b0316610d1d565b34801561051557600080fd5b506103f36004803603602081101561052c57600080fd5b5035610d38565b34801561053f57600080fd5b506103f36004803603604081101561055657600080fd5b506001600160a01b038135169060200135610d44565b34801561057857600080fd5b506103f36004803603602081101561058f57600080fd5b50356001600160a01b0316610dca565b3480156105ab57600080fd5b506103f3610de5565b6103f3600480360360608110156105ca57600080fd5b506001600160a01b038135169060208101359060400135610deb565b3480156105f257600080fd5b506103f3610df8565b34801561060757600080fd5b506103f3610dfe565b34801561061c57600080fd5b5061063a6004803603602081101561063357600080fd5b5035610e04565b604080516001600160a01b03909316835260208301919091528051918290030190f35b34801561066957600080fd5b50610384610e4e565b34801561067e57600080fd5b5061069c6004803603602081101561069557600080fd5b5035610e5e565b6040805192835260208301919091528051918290030190f35b3480156106c157600080fd5b506103c2610eb4565b3480156106d657600080fd5b506103f3600480360360208110156106ed57600080fd5b50356001600160a01b0316610ec3565b6103f3610ede565b34801561071157600080fd5b506103f36004803603604081101561072857600080fd5b506001600160a01b038135169060200135610f35565b6103f36004803603606081101561075457600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561078457600080fd5b82018360208201111561079657600080fd5b803590602001918460208302840111640100000000831117156107b857600080fd5b509092509050610f48565b3480156107cf57600080fd5b506103f3600480360360208110156107e657600080fd5b50356001600160a01b0316610f91565b34801561080257600080fd5b506103f36004803603602081101561081957600080fd5b50356001600160a01b0316610fb8565b34801561083557600080fd5b5061088d600480360361010081101561084d57600080fd5b506001600160a01b0381358116916020810135821691604082013515159160608101359160808201359160a08101359160c0820135169060e00135610fc6565b005b34801561089b57600080fd5b506103f361144c565b3480156108b057600080fd5b506103f3600480360360208110156108c757600080fd5b50356001600160a01b0316611452565b3480156108e357600080fd5b506103f3600480360360208110156108fa57600080fd5b5035611460565b34801561090d57600080fd5b506103846004803603604081101561092457600080fd5b506001600160a01b0381351690602001356114de565b6103f36004803603604081101561095057600080fd5b508035906020013561151a565b34801561096957600080fd5b506103846004803603604081101561098057600080fd5b506001600160a01b038135169060200135611527565b6103f3600480360360408110156109ac57600080fd5b813591908101906040810160208201356401000000008111156109ce57600080fd5b8201836020820111156109e057600080fd5b80359060200191846020830284011164010000000083111715610a0257600080fd5b509092509050611534565b6103f360048036036020811015610a2357600080fd5b50356001600160a01b0316611574565b348015610a3f57600080fd5b506103f360048036036020811015610a5657600080fd5b50356115c6565b348015610a6957600080fd5b506103f36115f1565b348015610a7e57600080fd5b5061045d6115fc565b348015610a9357600080fd5b506103f360048036036020811015610aaa57600080fd5b503561160a565b348015610abd57600080fd5b506103f3611647565b348015610ad257600080fd5b506103f360048036036020811015610ae957600080fd5b50356001600160a01b031661164d565b348015610b0557600080fd5b506103c26116b8565b348015610b1a57600080fd5b506102d66116f1565b348015610b2f57600080fd5b506103f360048036036040811015610b4657600080fd5b506001600160a01b038135811691602001351661174c565b348015610b6a57600080fd5b506103c2611777565b348015610b7f57600080fd5b506103f360048036036020811015610b9657600080fd5b50356001600160a01b0316611786565b6060610bb06117e6565b90505b90565b6000610bc3338484611a17565b5060015b92915050565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610c535780601f10610c2857610100808354040283529160200191610c53565b820191906000526020600020905b815481529060010190602001808311610c3657829003601f168201915b505050505081565b6004546001600160a01b031681565b60005490565b6001600160a01b0383166000908152600260209081526040808320338085529252822054610caf918691610caa908663ffffffff611a2716565b611a69565b610cba848484611b55565b5060019392505050565b600c5460ff1681565b600d5481565b600c5460ff1690565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610bc3918590610d18908663ffffffff611b6016565b611a17565b6000610d30610d2b83610f91565b6115c6565b90505b919050565b6000610d303383611bba565b600080610d4f6116b8565b9050610d5a81611c8c565b15610dac576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a6d696e74546f3a20496e76616c69642063616c6c0000604482015290519081900360640190fd5b610db881333086611c99565b610dc28484611e22565b949350505050565b6001600160a01b03166000908152600f602052604090205490565b60095481565b6000610dc284848461205d565b60085481565b60105490565b6005546000908190600160a01b900460ff1615610e39576004546001600160a01b0316610e3084612103565b91509150610e49565b50506003546001600160a01b0316815b915091565b600554600160a01b900460ff1681565b6000806000610e6c846115c6565b90506000610e98620186a0610e8c6009548561212090919063ffffffff16565b9063ffffffff61217916565b9050610eaa828263ffffffff611a2716565b9350915050915091565b6003546001600160a01b031681565b6001600160a01b031660009081526001602052604090205490565b6000610ef0610eeb6116b8565b611c8c565b610f2b5760405162461bcd60e51b81526004018080602001828103825260238152602001806143696023913960400191505060405180910390fd5b610bb03334611e22565b6000610f418383611bba565b9392505050565b6000610f8885858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506121bb92505050565b95945050505050565b6000610f9b61222d565b15610fb057610fa982612235565b9050610d33565b506000610d33565b6000610d30610d2b83610dca565b6003546001600160a01b0316158015610fe857506004546001600160a01b0316155b8015610ff45750600654155b61102f5760405162461bcd60e51b81526004018080602001828103825260238152602001806143e56023913960400191505060405180910390fd5b428411611083576040805162461bcd60e51b815260206004820152601e60248201527f41434f546f6b656e3a3a696e69743a20496e76616c6964206578706972790000604482015290519081900360640190fd5b600085116110c25760405162461bcd60e51b81526004018080602001828103825260248152602001806141686024913960400191505060405180910390fd5b866001600160a01b0316886001600160a01b03161415611129576040805162461bcd60e51b815260206004820152601b60248201527f41434f546f6b656e3a3a696e69743a2053616d65206173736574730000000000604482015290519081900360640190fd5b6101f4831115611180576040805162461bcd60e51b815260206004820152601f60248201527f41434f546f6b656e3a3a696e69743a20496e76616c69642041434f2066656500604482015290519081900360640190fd5b61118988611c8c565b806111a157506111a1886001600160a01b0316612290565b6111dc5760405162461bcd60e51b8152600401808060200182810382526022815260200180613fe96022913960400191505060405180910390fd5b6111e587611c8c565b806111fd57506111fd876001600160a01b0316612290565b6112385760405162461bcd60e51b815260040180806020018281038252602481526020018061438c6024913960400191505060405180910390fd5b6019811015801561124a575060968111155b6112855760405162461bcd60e51b815260040180806020018281038252603881526020018061410d6038913960400191505060405180910390fd5b600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a84161790556005805460068990556007889055600987905560ff60a01b1916600160a01b8a15150217909116918416919091179055600d8190556112f1886122c9565b600c805460ff191660ff9283161790819055604e9116106113435760405162461bcd60e51b815260040180806020018281038252602b81526020018061403a602b913960400191505060405180910390fd5b61134c876122c9565b600c60016101000a81548160ff021916908360ff16021790555061136f8861240e565b805161138391600a91602090910190613eea565b5061138d8761240e565b80516113a191600b91602090910190613eea565b50600c5460ff16600a0a600e55604080518082018252601981527f7472616e7366657228616464726573732c75696e7432353629000000000000006020918201526011805464ffffffff00191664a9059cbb001790558151606081019092526025808352906140659083013980516020909101206011805460ff1960e09390931c650100000000000268ffffffff000000000019909116179190911660011790555050505050505050565b60075481565b6000610d30610d2b83611786565b60008061146b6116b8565b905061147681611c8c565b156114c8576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a6d696e743a20496e76616c69642063616c6c00000000604482015290519081900360640190fd5b6114d481333086611c99565b610f413384611e22565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610bc3918590610d18908663ffffffff611a2716565b6000610f4133848461205d565b6000610bc3338484611b55565b6000610dc233858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506121bb92505050565b6000611581610eeb6116b8565b6115bc5760405162461bcd60e51b81526004018080602001828103825260258152602001806140be6025913960400191505060405180910390fd5b610d308234611e22565b600554600090600160a01b900460ff16156115e2575080610d33565b8115610fb057610fa982612103565b6000610bb033612618565b600c54610100900460ff1681565b600554600090600160a01b900460ff1615611626575080610d33565b8115610fb057610fa9600654610e8c600e548561212090919063ffffffff16565b60065481565b6000611659823361174c565b6001600160a01b0383166000908152600f602052604090205411156116af5760405162461bcd60e51b81526004018080602001828103825260278152602001806143426027913960400191505060405180910390fd5b610d3082612618565b600554600090600160a01b900460ff16156116df57506003546001600160a01b0316610bb3565b506004546001600160a01b0316610bb3565b600a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610c535780601f10610c2857610100808354040283529160200191610c53565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6005546001600160a01b031681565b6001600160a01b0381166000908152600f60205260408120546117a883610ec3565b11806117b957506117b761222d565b155b156117dd57506001600160a01b0381166000908152600f6020526040902054610d33565b610fa982610ec3565b6060600a611805600654600c60019054906101000a900460ff16612700565b600554600b9061181e90600160a01b900460ff166128a8565b6118296007546128ec565b604051602001808063020a1a7960e51b815250600401868054600181600116156101000203166002900480156118965780601f10611874576101008083540402835291820191611896565b820191906000526020600020905b815481529060010190602001808311611882575b505080602d60f81b81525060010185805190602001908083835b602083106118cf5780518252601f1990920191602091820191016118b0565b6001836020036101000a038019825116818451168082178552505050505050905001848054600181600116156101000203166002900480156119485780601f10611926576101008083540402835291820191611948565b820191906000526020600020905b815481529060010190602001808311611934575b505080602d60f81b81525060010183805190602001908083835b602083106119815780518252601f199092019160209182019101611962565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010182805190602001908083835b602083106119da5780518252601f1990920191602091820191016119bb565b6001836020036101000a03801982511681845116808217855250505050505090500195505050505050604051602081830303815290604052905090565b611a22838383611a69565b505050565b6000610f4183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612aea565b6001600160a01b038316611aae5760405162461bcd60e51b815260040180806020018281038252602481526020018061445d6024913960400191505060405180910390fd5b6001600160a01b038216611af35760405162461bcd60e51b81526004018080602001828103825260268152602001806142ec6026913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b611a22838383612b81565b600082820183811015610f41576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60115460009060ff16611c08576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611c1a61222d565b611c5f576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b6000611c6b8484612cc5565b9050611c778484612d93565b90506011805460ff1916600117905592915050565b6001600160a01b03161590565b601154604080516001600160a01b0386811660248301528581166044830152606480830186905283518084039091018152608490920183526020820180516501000000000090950460e01b6001600160e01b0319166001600160e01b03909516949094178452915181516000946060948a169392918291908083835b60208310611d345780518252601f199092019160209182019101611d15565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611d96576040519150601f19603f3d011682016040523d82523d6000602084013e611d9b565b606091505b5091509150818015611dc9575080511580611dc95750808060200190516020811015611dc657600080fd5b50515b611e1a576040805162461bcd60e51b815260206004820152601c60248201527f41434f546f6b656e3a3a5f7472616e7366657246726f6d455243323000000000604482015290519081900360640190fd5b505050505050565b60115460009060ff16611e70576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055611e8261222d565b611ec7576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b60008211611f065760405162461bcd60e51b815260040180806020018281038252602f81526020018061400b602f913960400191505060405180910390fd5b611f0f83612dc1565b611f7357601080546001600160a01b0385166000818152600f60205260408120600190810184905583018455929092527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720180546001600160a01b03191690911790555b6000611f7e8361160a565b905080611fbc5760405162461bcd60e51b815260040180806020018281038252602a8152602001806140e3602a913960400191505060405180910390fd5b6001600160a01b0384166000908152600f6020526040902054611fe5908263ffffffff611b6016565b6001600160a01b0385166000908152600f6020526040902055600854612011908463ffffffff611b6016565b6008556040805184815290516001600160a01b038616917ff645c19720906ca336d36d26058a9489c6c757fe35843b75a74e3b8aa972ecf5919081900360200190a2611c773382612de2565b60115460009060ff166120ab576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff19169055600d546120c59085908590612ebd565b6120d0848484613095565b6000806120dc85610e5e565b915091506120eb868383613240565b925050506011805460ff191660011790559392505050565b6000610d30600e54610e8c6006548561212090919063ffffffff16565b60008261212f57506000610bc7565b8282028284828161213c57fe5b0414610f415760405162461bcd60e51b81526004018080602001828103825260218152602001806142236021913960400191505060405180910390fd5b6000610f4183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613370565b60115460009060ff16612209576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905581516122229085908590612ebd565b6120d08484846133d5565b600754421090565b600061224082610ec3565b6001600160a01b0383166000908152600f60205260409020541115610fb057610fa961226b83610ec3565b6001600160a01b0384166000908152600f60205260409020549063ffffffff611a2716565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610dc2575050151592915050565b60006122d482611c8c565b156122e157506012610d33565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106123475780518252601f199092019160209182019101612328565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146123a7576040519150601f19603f3d011682016040523d82523d6000602084013e6123ac565b606091505b5091509150816123ed5760405162461bcd60e51b8152600401808060200182810382526033815260200180613fb66033913960400191505060405180910390fd5b80806020019051602081101561240257600080fd5b50519250610d33915050565b606061241982611c8c565b1561243e575060408051808201909152600381526208aa8960eb1b6020820152610d33565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b178152915181516000936060936001600160a01b038816939092909182918083835b602083106124a45780518252601f199092019160209182019101612485565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612504576040519150601f19603f3d011682016040523d82523d6000602084013e612509565b606091505b50915091508161254a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614408602f913960400191505060405180910390fd5b80806020019051602081101561255f57600080fd5b810190808051604051939291908464010000000082111561257f57600080fd5b90830190602082018581111561259457600080fd5b82516401000000008111828201881017156125ae57600080fd5b82525081516020918201929091019080838360005b838110156125db5781810151838201526020016125c3565b50505050905090810190601f1680156126085780820380516001836020036101000a031916815260200191505b5060405250505092505050610d33565b60115460009060ff16612666576040805162461bcd60e51b815260206004820152601160248201527041434f546f6b656e3a3a5265656e74727960781b604482015290519081900360640190fd5b6011805460ff1916905561267861222d565b156126b45760405162461bcd60e51b81526004018080602001828103825260288152602001806142c46028913960400191505060405180910390fd5b6001600160a01b0382166000908152600f60205260408120546126d8908490612cc5565b90506126ec836126e785610ec3565b61346d565b90506011805460ff19166001179055919050565b6060600080808086805b8115612765578315801561272c5750600a820615158061272c57508760ff1685145b15612738575060019250805b8315612754578760ff1685141561274d578592505b6001909501945b600a8260019096019504915061270a565b8760ff16851161278757848860ff168760020101039550600286039250612794565b8215612794576001909501945b60608667ffffffffffffffff811180156127ad57600080fd5b506040519080825280601f01601f1916602001820160405280156127d8576020820181803683370190505b5091925082919050600019870160005b88811015612898576000811180156127ff57508581145b1561283857601760f91b8383806001900394508151811061281c57fe5b60200101906001600160f81b031916908160001a905350612890565b8361285557600360fc1b8383806001900394508151811061281c57fe5b600a840660300160f81b8383806001900394508151811061287257fe5b60200101906001600160f81b031916908160001a905350600a840493505b6001016127e8565b50909a9950505050505050505050565b606081156128ce57506040805180820190915260018152604360f81b6020820152610d33565b506040805180820190915260018152600560fc1b6020820152610d33565b606060008060008060006128ff87613550565b509450945094509450945061291383613590565b61291c85613622565b61292587613834565b61292e85613590565b61293785613590565b6040516020018086805190602001908083835b602083106129695780518252601f19909201916020918201910161294a565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106129b15780518252601f199092019160209182019101612992565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106129f95780518252601f1990920191602091820191016129da565b6001836020036101000a03801982511681845116808217855250505050505090500180602d60f81b81525060010183805190602001908083835b60208310612a525780518252601f199092019160209182019101612a33565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612a9a5780518252601f199092019160209182019101612a7b565b5181516020939093036101000a60001901801990911692169190911790526255544360e81b92019182525060408051808303601c19018152600390920190529d9c50505050505050505050505050565b60008184841115612b795760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612b3e578181015183820152602001612b26565b50505050905090810190601f168015612b6b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316612bc65760405162461bcd60e51b81526004018080602001828103825260268152602001806144376026913960400191505060405180910390fd5b6001600160a01b038216612c0b5760405162461bcd60e51b81526004018080602001828103825260298152602001806141c46029913960400191505060405180910390fd5b6001600160a01b038316600090815260016020526040902054612c34908263ffffffff611a2716565b6001600160a01b038085166000908152600160205260408082209390935590841681522054612c69908263ffffffff611b6016565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000612cd083612dc1565b612d0b5760405162461bcd60e51b815260040180806020018281038252603481526020018061408a6034913960400191505060405180910390fd5b60008211612d4a5760405162461bcd60e51b81526004018080602001828103825260318152602001806144816031913960400191505060405180910390fd5b6001600160a01b0383166000908152600f602052604090208054612d74908463ffffffff611a2716565b8155612d7f846138c4565b610dc284612d8c856115c6565b6000613240565b6001600160a01b038216331415612db357612dae828261346d565b612dbd565b612dbd82826139d3565b5050565b6001600160a01b0381166000908152600f60205260408120610d3090613a18565b6001600160a01b038216612e275760405162461bcd60e51b81526004018080602001828103825260238152602001806142746023913960400191505060405180910390fd5b600054612e3a908263ffffffff611b6016565b60009081556001600160a01b038316815260016020526040902054612e65908263ffffffff611b6016565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b612ec561222d565b612f0a576040805162461bcd60e51b81526020600482015260116024820152701050d3d51bdad95b8e8e915e1c1a5c9959607a1b604482015290519081900360640190fd5b60008211612f495760405162461bcd60e51b81526004018080602001828103825260308152602001806142446030913960400191505060405180910390fd5b612f5283612dc1565b15612fc7576001600160a01b0383166000908152600f6020526040902054612f8990612f7d85610ec3565b9063ffffffff611a2716565b821115612fc75760405162461bcd60e51b81526004018080602001828103825260368152602001806141ed6036913960400191505060405180910390fd5b612fd18383612d93565b600080612fdd84610e04565b9092509050612ff2818463ffffffff611b6016565b9050612ffd82611c8c565b15613045578034146130405760405162461bcd60e51b81526004018080602001828103825260308152602001806143126030913960400191505060405180910390fd5b61308e565b34156130825760405162461bcd60e51b815260040180806020018281038252602d815260200180614297602d913960400191505060405180910390fd5b61308e82333084611c99565b5050505050565b60105460009081906130ae90849063ffffffff613a1e16565b90508060005b6000861180156130c5575060105481105b156131745760006130f8601084815481106130dc57fe5b6000918252602090912001546001600160a01b0316888a613a60565b90508681101561315157600d54600190950194851080613116575080155b6131515760405162461bcd60e51b815260040180806020018281038252603881526020018061418c6038913960400191505060405180910390fd5b601054909650600190920191869083141561316b57600092505b506001016130b4565b85156131b15760405162461bcd60e51b8152600401808060200182810382526033815260200180613f836033913960400191505060405180910390fd5b600080836131c35760105493506131d7565b8484116131d7575050601054916000190160015b60005b8381101561323457600019909401938180156131f557508585105b1561320257829450600091505b61322c6010868154811061321257fe5b6000918252602090912001546001600160a01b03166138c4565b6001016131da565b50505050505050505050565b6000613264613255848463ffffffff611b6016565b6008549063ffffffff611a2716565b60085560006132716116b8565b905061327c81611c8c565b156132f657604051339085156108fc029086906000818181858888f193505050501580156132ae573d6000803e3d6000fd5b5082156132f1576005546040516001600160a01b039091169084156108fc029085906000818181858888f193505050501580156132ef573d6000803e3d6000fd5b505b61331f565b613301813386613ba2565b821561331f5760055461331f9082906001600160a01b031685613ba2565b6040805185815260208101859052815133926001600160a01b038916927fd3506bcc260407a7f95f487dd7c600bc45888cce58989ceadbe8c0bbf9257b28929081900390910190a350919392505050565b600081836133bf5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612b3e578181015183820152602001612b26565b5060008385816133cb57fe5b0495945050505050565b60005b815181101561342f57826133eb5761342f565b6134098282815181106133fa57fe5b60200260200101518486613a60565b925061342782828151811061341a57fe5b60200260200101516138c4565b6001016133d8565b508115611a225760405162461bcd60e51b81526004018080602001828103825260358152602001806143b06035913960400191505060405180910390fd5b6001600160a01b0382166134b25760405162461bcd60e51b81526004018080602001828103825260238152602001806141456023913960400191505060405180910390fd5b6001600160a01b0382166000908152600160205260409020546134db908263ffffffff611a2716565b6001600160a01b03831660009081526001602052604081209190915554613508908263ffffffff611a2716565b60009081556040805183815290516001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b60008080808080613565620151808804613d17565b91999098919750610e10620151809092068281049750603c9290068281049650919091069350915050565b60608061359c83613dad565b9050600a831015610fa957806040516020018080600360fc1b81525060010182805190602001908083835b602083106135e65780518252601f1990920191602091820191016135c7565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052915050610d33565b6060816001141561364d57506040805180820190915260038152622520a760e91b6020820152610d33565b816002141561367657506040805180820190915260038152622322a160e91b6020820152610d33565b816003141561369f575060408051808201909152600381526226a0a960e91b6020820152610d33565b81600414156136c8575060408051808201909152600381526220a82960e91b6020820152610d33565b81600514156136f157506040805180820190915260038152624d415960e81b6020820152610d33565b816006141561371a5750604080518082019091526003815262252aa760e91b6020820152610d33565b8160071415613743575060408051808201909152600381526212955360ea1b6020820152610d33565b816008141561376c575060408051808201909152600381526241554760e81b6020820152610d33565b8160091415613795575060408051808201909152600381526205345560ec1b6020820152610d33565b81600a14156137be575060408051808201909152600381526213d0d560ea1b6020820152610d33565b81600b14156137e757506040805180820190915260038152622727ab60e91b6020820152610d33565b81600c1415613810575060408051808201909152600381526244454360e81b6020820152610d33565b506040805180820190915260078152661253959053125160ca1b6020820152610d33565b60608061384083613dad565b60408051600280825281830190925291925060609190602082018180368337505083519192505060011901805b83518110156138ba5783818151811061388257fe5b602001015160f81c60f81b838383038151811061389b57fe5b60200101906001600160f81b031916908160001a90535060010161386d565b5090949350505050565b6001600160a01b0381166000908152600f602052604090206138e581613a18565b612dbd5760105460018201546000199091019081146139825760006010828154811061390d57fe5b60009182526020808320909101546001868101546001600160a01b03909216808552600f90935260409093209092018290556010805491935083929091811061395257fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b601080548061398d57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0385168252600f90526040812081815560010155505050565b6001600160a01b038216600090815260026020908152604080832033808552925290912054613a0e918491610caa908563ffffffff611a2716565b612dbd828261346d565b54151590565b6000610f4183836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250613e88565b600080613a6c85612235565b90508015613b99576001600160a01b0385166000908152600f602052604081209085831015613aae575081613aa7868263ffffffff611a2716565b9550613ab3565b506000945b600080613abf83610e04565b9092509050613ad581600163ffffffff611b6016565b8454909150613aea908463ffffffff611a2716565b8455613af582611c8c565b15613b36576040516001600160a01b038a169082156108fc029083906000818181858888f19350505050158015613b30573d6000803e3d6000fd5b50613b41565b613b41828a83613ba2565b866001600160a01b0316896001600160a01b03167f5f283076724262032199f54be27a9364634b895b3a37c1e66bfe47d5d05347698386604051808381526020018281526020019250505060405180910390a3505050505b50919392505050565b601154604080516001600160a01b0385811660248301526044808301869052835180840390910181526064909201835260208201805161010090950460e01b6001600160e01b0319166001600160e01b039095169490941784529151815160009460609489169392918291908083835b60208310613c315780518252601f199092019160209182019101613c12565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c93576040519150601f19603f3d011682016040523d82523d6000602084013e613c98565b606091505b5091509150818015613cc6575080511580613cc65750808060200190516020811015613cc357600080fd5b50515b61308e576040805162461bcd60e51b815260206004820152601860248201527f41434f546f6b656e3a3a5f7472616e7366657245524332300000000000000000604482015290519081900360640190fd5b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f8460500281613d6e57fe5b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b606081613dd257506040805180820190915260018152600360fc1b6020820152610d33565b8160005b8115613dea57600101600a82049150613dd6565b60608167ffffffffffffffff81118015613e0357600080fd5b506040519080825280601f01601f191660200182016040528015613e2e576020820181803683370190505b50859350905060001982015b8315613e7f57600a840660300160f81b82828060019003935081518110613e5d57fe5b60200101906001600160f81b031916908160001a905350600a84049350613e3a565b50949350505050565b60008183613ed75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315612b3e578181015183820152602001612b26565b50828481613ee157fe5b06949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613f2b57805160ff1916838001178555613f58565b82800160010185558215613f58579182015b82811115613f58578251825591602001919060010190613f3d565b50613f64929150613f68565b5090565b610bb391905b80821115613f645760008155600101613f6e56fe41434f546f6b656e3a3a5f65786572636973654f776e6572733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a5f6765744173736574446563696d616c733a20496e76616c696420617373657420646563696d616c7341434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6741434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420636f6c6c61746572616c20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420756e6465726c79696e6720646563696d616c737472616e7366657246726f6d28616464726573732c616464726573732c75696e743235362941434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a204e6f20636f6c6c61746572616c20617661696c61626c6541434f546f6b656e3a3a6d696e74546f50617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a5f6d696e74546f6b656e3a20496e76616c696420746f6b656e20616d6f756e7441434f546f6b656e3a3a696e69743a20496e76616c6964206e756d62657220746f206d617820657865726369736564206163636f756e747345524332303a3a5f6275726e416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520707269636541434f546f6b656e3a3a5f65786572636973654f776e6572733a20546f6f206d616e79206163636f756e747320746f20657865726369736545524332303a3a5f7472616e73666572416374696f6e3a20496e76616c696420726563697069656e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20546f6b656e20616d6f756e74206e6f7420617661696c61626c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7741434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420746f6b656e20616d6f756e7445524332303a3a5f6d696e74416374696f6e3a20496e76616c6964206163636f756e7441434f546f6b656e3a3a5f76616c6964617465416e644275726e3a204e6f20657468657220657870656374656441434f546f6b656e3a3a5f72656465656d3a20546f6b656e206e6f7420657870697265642079657445524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964207370656e64657241434f546f6b656e3a3a5f76616c6964617465416e644275726e3a20496e76616c696420657468657220616d6f756e7441434f546f6b656e3a3a72656465656d46726f6d3a20416c6c6f77616e636520746f6f206c6f7741434f546f6b656e3a3a6d696e7450617961626c653a20496e76616c69642063616c6c41434f546f6b656e3a3a696e69743a20496e76616c696420737472696b6520617373657441434f546f6b656e3a3a5f65786572636973654163636f756e74733a20496e76616c69642072656d61696e696e6720616d6f756e7441434f546f6b656e3a3a696e69743a20416c726561647920696e697469616c697a656441434f546f6b656e3a3a5f676574417373657453796d626f6c3a20496e76616c69642061737365742073796d626f6c45524332303a3a5f7472616e73666572416374696f6e3a20496e76616c69642073656e64657245524332303a3a5f617070726f7665416374696f6e3a20496e76616c6964206f776e657241434f546f6b656e3a3a5f72656465656d436f6c6c61746572616c3a20496e76616c696420746f6b656e20616d6f756e74a2646970667358221220132b11c8e08a66d7ac3326606ac359c39d8a86667f84472891efae17b37a65e364736f6c63430006060033
Deployed Bytecode Sourcemap
221:39652:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;221:39652:1;12:1:-1;9;2:12;7823:93:1;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7823: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;7823: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;:::-;;;;;;;;;;;;;;;;;;2999:31:1;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2999:31:1;;;:::i;2067:26::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2067:26:1;;;:::i;:::-;;;;-1:-1:-1;;;;;2067: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;3109:31:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3109:31:1;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3360:35;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3360:35:1;;;:::i;8248:100::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8248: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;9487:148:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9487:148:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;9487:148:1;-1:-1:-1;;;;;9487:148:1;;:::i;16985:117::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;16985:117:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;16985:117:1;;:::i;16322:366::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;16322:366:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;16322:366:1;;;;;;;;:::i;9862:134::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9862:134:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;9862:134:1;-1:-1:-1;;;;;9862:134:1;;:::i;2800:21::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2800:21:1;;;:::i;19898:171::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;19898:171:1;;;;;;;;;;;;;:::i;2668:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2668:30:1;;;:::i;12291:121::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12291:121:1;;;:::i;13033:274::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;13033:274:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;13033:274:1;;:::i;:::-;;;;-1:-1:-1;;;;;13033:274:1;;;;;;;;;;;;;;;;;;;;;2315:18;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2315:18:1;;;:::i;13550:331::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;13550:331:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;13550:331:1;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1932:25;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1932: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;14413:197:1:-;;;:::i;17571:135::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17571:135:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;17571:135:1;;;;;;;;:::i;21379:210::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;21379:210:1;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;21379:210:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;21379: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;21379:210:1;;-1:-1:-1;21379:210:1;-1:-1:-1;21379:210:1;:::i;10880:213::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10880:213:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;10880:213:1;-1:-1:-1;;;;;10880:213:1;;:::i;8553:156::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8553:156:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8553:156:1;-1:-1:-1;;;;;8553:156:1;;:::i;5556:2022::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5556:2022:1;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;5556:2022:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;2551:25;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2551:25:1;;;:::i;9043:152::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9043:152:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;9043:152:1;-1:-1:-1;;;;;9043:152:1;;:::i;15509:348::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;15509:348:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15509: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;19102:153:1:-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;19102: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;20522:192:1:-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;20522:192:1;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;20522:192:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;20522: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;20522:192:1;;-1:-1:-1;20522:192:1;-1:-1:-1;20522:192:1;:::i;15011:212::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15011:212:1;-1:-1:-1;;;;;15011:212:1;;:::i;11303:297::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11303:297:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;11303:297:1;;:::i;17921:89::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;17921:89:1;;;:::i;3215:32::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3215:32:1;;;:::i;11815:324::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11815:324:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;11815:324:1;;:::i;2441:26::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2441:26:1;;;:::i;18407:227::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;18407:227:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;18407:227:1;-1:-1:-1;;;;;18407:227:1;;:::i;14015:176::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;14015:176:1;;;:::i;2897:30::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2897: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;2193:37:1:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2193:37:1;;;:::i;10321:279::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10321:279:1;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;10321:279:1;-1:-1:-1;;;;;10321:279:1;;:::i;7823:93::-;7868:13;7901:7;:5;:7::i;:::-;7894:14;;7823: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;2999:31:1:-;;;;;;;;;;;;;;;-1:-1:-1;;2999:31:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2067:26::-;;;-1:-1:-1;;;;;2067: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;3109:31:1:-;;;;;;:::o;3360:35::-;;;;:::o;8248:100::-;8322:18;;;;8248: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;9487:148:1:-;9554:7;9581:46;9601:25;9618:7;9601:16;:25::i;:::-;9581:19;:46::i;:::-;9574:53;;9487:148;;;;:::o;16985:117::-;17037:7;17064:30;17070:10;17082:11;17064:5;:30::i;16322:366::-;16398:7;16418:19;16440:12;:10;:12::i;:::-;16418:34;;16472:21;16481:11;16472:8;:21::i;:::-;16471:22;16463:65;;;;;-1:-1:-1;;;16463:65:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;16549:76;16568:11;16581:10;16601:4;16608:16;16549:18;:76::i;:::-;16643:37;16654:7;16663:16;16643:10;:37::i;:::-;16636:44;16322:366;-1:-1:-1;;;;16322:366:1:o;9862:134::-;-1:-1:-1;;;;;9963:18:1;9936:7;9963:18;;;:9;:18;;;;;:25;;9862:134::o;2800:21::-;;;;:::o;19898:171::-;19997:7;20024:37;20034:7;20043:11;20056:4;20024:9;:37::i;2668:30::-;;;;:::o;12291:121::-;12380:17;:24;12291:121;:::o;13033:274::-;13136:6;;13103:7;;;;-1:-1:-1;;;13136:6:1;;;;13132:168;;;13167:11;;-1:-1:-1;;;;;13167:11:1;13180:41;13209:11;13180:28;:41::i;:::-;13159:63;;;;;;13132:168;-1:-1:-1;;13264:10:1;;-1:-1:-1;;;;;13264:10:1;13276:11;13132:168;13033:274;;;:::o;2315:18::-;;;-1:-1:-1;;;2315:18:1;;;;;:::o;13550:331::-;13624:7;13633;13653:24;13680:32;13700:11;13680:19;:32::i;:::-;13653:59;;13723:11;13737:40;13770:6;13737:28;13758:6;;13737:16;:20;;:28;;;;:::i;:::-;:32;:40;:32;:40;:::i;:::-;13723:54;-1:-1:-1;13807:25:1;:16;13723:54;13807:25;:20;:25;:::i;:::-;13788:44;-1:-1:-1;13869:3:1;-1:-1:-1;;13550:331:1;;;:::o;1932:25::-;;;-1:-1:-1;;;;;1932:25:1;;:::o;699:118:4:-;-1:-1:-1;;;;;791:18:4;764:7;791:18;;;:9;:18;;;;;;;699:118::o;14413:197:1:-;14461:7;14489:22;14498:12;:10;:12::i;:::-;14489:8;:22::i;:::-;14481:70;;;;-1:-1:-1;;;14481:70:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14569:33;14580:10;14592:9;14569:10;:33::i;17571:135::-;17644:7;17671:27;17677:7;17686:11;17671:5;:27::i;:::-;17664:34;17571:135;-1:-1:-1;;;17571:135:1:o;21379:210::-;21501:7;21528:53;21550:7;21559:11;21572:8;;21528:53;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;21528:21:1;;-1:-1:-1;;;21528:53:1:i;:::-;21521:60;21379:210;-1:-1:-1;;;;;21379:210:1:o;10880:213::-;10943:7;10967:13;:11;:13::i;:::-;10963:123;;;11004:29;11025:7;11004:20;:29::i;:::-;10997:36;;;;10963:123;-1:-1:-1;11073:1:1;11066:8;;8553:156;8617:7;8644:57;8664:36;8692:7;8664:27;:36::i;5556:2022::-;5856:10;;-1:-1:-1;;;;;5856:10:1;:24;:53;;;;-1:-1:-1;5884:11:1;;-1:-1:-1;;;;;5884:11:1;:25;5856:53;:73;;;;-1:-1:-1;5913:11:1;;:16;5856:73;5848:121;;;;-1:-1:-1;;;5848:121:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6012:3;5998:11;:17;5990:60;;;;;-1:-1:-1;;;5990:60:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6084:1;6069:12;:16;6061:65;;;;-1:-1:-1;;;6061:65:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6160:12;-1:-1:-1;;;;;6145:27:1;:11;-1:-1:-1;;;;;6145:27:1;;;6137:67;;;;;-1:-1:-1;;;6137:67:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6234:3;6223:7;:14;;6215:58;;;;;-1:-1:-1;;;6215:58:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;6311:21;6320:11;6311:8;:21::i;:::-;:49;;;;6336:24;:11;-1:-1:-1;;;;;6336:22:1;;:24::i;:::-;6303:96;;;;-1:-1:-1;;;6303:96:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6418:22;6427:12;6418:8;:22::i;:::-;:51;;;;6444:25;:12;-1:-1:-1;;;;;6444:23:1;;:25::i;:::-;6410:100;;;;-1:-1:-1;;;6410:100:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6554:2;6529:21;:27;;:59;;;;;6585:3;6560:21;:28;;6529:59;6521:128;;;;-1:-1:-1;;;6521:128:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6670:10;:24;;-1:-1:-1;;;;;;6670:24:1;;;-1:-1:-1;;;;;6670:24:1;;;;;;;;;;6705:11;:26;;;;;;;;;;6742:6;:16;;6769:11;:26;;;6806:10;:24;;;6841:6;:16;;;-1:-1:-1;;;;6742:16:1;-1:-1:-1;;;6742:16:1;;;;;6868:32;;;;;;;;;;;;6911:20;:44;;;6987:30;6670:24;6987:17;:30::i;:::-;6966:18;:51;;-1:-1:-1;;6966:51:1;;;;;;;;;;7057:2;7036:18;;:23;7028:79;;;;-1:-1:-1;;;7028:79:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7140:31;7158:12;7140:17;:31::i;:::-;7118:19;;:53;;;;;;;;;;;;;;;;;;7201:28;7217:11;7201:15;:28::i;:::-;7182:47;;;;:16;;:47;;;;;;:::i;:::-;;7260:29;7276:12;7260:15;:29::i;:::-;7240:49;;;;:17;;:49;;;;;;:::i;:::-;-1:-1:-1;7336:18:1;;;;7322:2;:33;7300:19;:55;7405:34;;;;;;;;;;;;;;;;;7368:17;:73;;-1:-1:-1;;7368:73:1;;;;;7493:46;;;;;;;;;;;;;;;;;;7483:57;;;;;;;7452:21;:89;;-1:-1:-1;;7452:89:1;;;;;;;-1:-1:-1;;7452:89:1;;;;7552:18;;;;-1:-1:-1;7552:18:1;;;-1:-1:-1;;;;;;;;5556:2022:1:o;2551:25::-;;;;:::o;9043:152::-;9112:7;9139:48;9159:27;9178:7;9159:18;:27::i;15509:348::-;15566:7;15586:19;15608:12;:10;:12::i;:::-;15586:34;;15640:21;15649:11;15640:8;:21::i;:::-;15639:22;15631:63;;;;;-1:-1:-1;;;15631:63:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;15715:76;15734:11;15747:10;15767:4;15774:16;15715:18;:76::i;:::-;15809:40;15820:10;15832:16;15809: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;19102:153:1:-;19180:7;19207:40;19217:10;19229:11;19242:4;19207:9;:40::i;975:164:4:-;1052:4;1069:40;1079:10;1091:9;1102:6;1069:9;:40::i;20522:192:1:-;20623:7;20650:56;20672:10;20684:11;20697:8;;20650:56;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;20650:21:1;;-1:-1:-1;;;20650:56:1:i;15011:212::-;15076:7;15104:22;15113:12;:10;:12::i;15104:22::-;15096:72;;;;-1:-1:-1;;;15096:72:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15185:30;15196:7;15205:9;15185:10;:30::i;11303:297::-;11397:6;;11373:7;;-1:-1:-1;;;11397:6:1;;;;11393:200;;;-1:-1:-1;11427:11:1;11420:18;;11393:200;11460:15;;11456:137;;11499:41;11528:11;11499:28;:41::i;17921:89::-;17956:7;17983:19;17991:10;17983:7;:19::i;3215:32::-;;;;;;;;;:::o;11815:324::-;11909:6;;11885:7;;-1:-1:-1;;;11909:6:1;;;;11905:227;;;-1:-1:-1;11939:16:1;11932:23;;11905:227;11977:20;;11973:159;;12021:58;12067:11;;12021:41;12042:19;;12021:16;:20;;:41;;;;:::i;2441:26::-;;;;:::o;18407:227::-;18461:7;18518:30;18528:7;18537:10;18518:9;:30::i;:::-;-1:-1:-1;;;;;18489:18:1;;;;;;:9;:18;;;;;:25;:59;;18481:111;;;;-1:-1:-1;;;18481:111:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18610:16;18618:7;18610;:16::i;14015:176::-;14081:6;;14057:7;;-1:-1:-1;;;14081:6:1;;;;14077:107;;;-1:-1:-1;14111:10:1;;-1:-1:-1;;;;;14111:10:1;14104:17;;14077:107;-1:-1:-1;14161:11:1;;-1:-1:-1;;;;;14161:11:1;14154:18;;2897:30;;;;;;;;;;;;;;;-1:-1:-1;;2897:30:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;825:142:4;-1:-1:-1;;;;;932:18:4;;;905:7;932:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;825:142::o;2193:37:1:-;;;-1:-1:-1;;;;;2193:37:1;;:::o;10321:279::-;-1:-1:-1;;;;;10431:18:1;;10386:7;10431:18;;;:9;:18;;;;;:25;10410:18;10441:7;10410:9;:18::i;:::-;:46;:64;;;;10461:13;:11;:13::i;:::-;10460:14;10410:64;10406:187;;;-1:-1:-1;;;;;;10498:18:1;;;;;;:9;:18;;;;;:25;10491:32;;10406:187;10563:18;10573:7;10563:9;:18::i;37043:435::-;37082:13;37174:16;37223:63;37253:11;;37266:19;;;;;;;;;;;37223:29;:63::i;:::-;37379:6;;37301:17;;37351:35;;-1:-1:-1;;;37379:6:1;;;;37351:27;:35::i;:::-;37419:39;37447:10;;37419:27;:39::i;:::-;37122:347;;;;;;-1:-1:-1;;;37122:347:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;37122: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;;;37122:347:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;37122: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;;;37122:347:1;;;;;;;-1:-1:-1;;;37122: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;;;37122:347:1;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;37122:347:1;;;37108:362;;37043: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;;;;;;;;;;;;;;;;;;;;;;;;;;;33613:264:1;4578:11;;33707:7;;4578:11;;4570:41;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;;;;4622:11;:19;;-1:-1:-1;;4622:19:1;;;4355:13:::1;:11;:13::i;:::-;4347:43;;;::::0;;-1:-1:-1;;;4347:43:1;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4347:43:1;;;;;;;;;;;;;::::1;;33727:24:::2;33754:39;33772:7;33781:11;33754:17;:39::i;:::-;33727:66;;33804:31;33814:7;33823:11;33804:9;:31::i;:::-;33853:16:::0;-1:-1:-1;4664:11:1;:18;;-1:-1:-1;;4664:18:1;4678:4;4664:18;;;33613:264;;-1:-1:-1;;33613:264:1:o;36677:112::-;-1:-1:-1;;;;;36759:22:1;;;36677:112::o;39501:369::-;39691:21;;39668:72;;;-1:-1:-1;;;;;39668:72:1;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;39668:72:1;;;;;;;25:18:-1;;61:17;;39691:21:1;;;;;;-1:-1:-1;;;;;;39668:72:1;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;39657:84:1;;;;-1:-1:-1;;39630:23:1;;39657:10;;;39668:72;39657:84;;;25:18:-1;39657: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;;;39657: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;;39615:126:1;;;;39760:7;:69;;;;-1:-1:-1;39772:17:1;;:22;;:56;;;39809:10;39798:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;39798:30:1;39772:56;39752:110;;;;;-1:-1:-1;;;39752:110:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;39501:369;;;;;;:::o;22711:869::-;4578:11;;22815:7;;4578:11;;4570:41;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;;;;4622:11;:19;;-1:-1:-1;;4622:19:1;;;4355:13:::1;:11;:13::i;:::-;4347:43;;;::::0;;-1:-1:-1;;;4347:43:1;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4347:43:1;;;;;;;;;;;;;::::1;;22862:1:::2;22843:16;:20;22835:80;;;;-1:-1:-1::0;;;22835:80:1::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22941:30;22963:7;22941:21;:30::i;:::-;22936:161;;23015:17;:24:::0;;-1:-1:-1;;;;;22988:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:24:::2;::::0;;::::2;:51:::0;;;23:18:-1;::::2;45:23:::0;;23054:31:1;;;;;::::2;::::0;;-1:-1:-1;;;;;;23054:31:1::2;::::0;;::::2;::::0;;22936:161:::2;23117:19;23139:32;23154:16;23139:14;:32::i;:::-;23117:54:::0;-1:-1:-1;23190:16:1;23182:71:::2;;;;-1:-1:-1::0;;;23182:71:1::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;23292:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:25;:42:::2;::::0;23322:11;23292:42:::2;:29;:42;:::i;:::-;-1:-1:-1::0;;;;;23264:18:1;::::2;;::::0;;;:9:::2;:18;::::0;;;;:70;23373:15:::2;::::0;:37:::2;::::0;23393:16;23373:37:::2;:19;:37;:::i;:::-;23355:15;:55:::0;23436:44:::2;::::0;;;;;;;-1:-1:-1;;;;;23436:44:1;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;::::2;23501:42;23519:10;23531:11;23501:17;:42::i;25214:402::-:0;4578:11;;25315:7;;4578:11;;4570:41;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;;;;4622:11;:19;;-1:-1:-1;;4622:19:1;;;25374:20:::1;::::0;25335:60:::1;::::0;25352:7;;25361:11;;25335:16:::1;:60::i;:::-;25407:43;25423:7;25432:11;25445:4;25407:15;:43::i;:::-;25462:24;25488:11:::0;25503:36:::1;25527:11;25503:23;:36::i;:::-;25461:78;;;;25557:51;25577:7;25586:16;25604:3;25557:19;:51::i;:::-;25550:58;;;;4664:11:::0;:18;;-1:-1:-1;;4664:18:1;4678:4;4664:18;;;25214:402;;-1:-1:-1;;;25214:402:1:o;32530:169::-;32611:7;32638:53;32671:19;;32638:28;32654:11;;32638;: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;25958:427:1:-;4578:11;;26084:7;;4578:11;;4570:41;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;;;;4622:11;:19;;-1:-1:-1;;4622:19:1;;;26143:15;;26104:55:::1;::::0;26121:7;;26130:11;;26104:16:::1;:55::i;:::-;26170:49;26188:7;26197:11;26210:8;26170:17;:49::i;35675:93::-:0;35750:10;;35744:3;:16;35675:93;:::o;34518:272::-;34587:7;34639:18;34649:7;34639:9;:18::i;:::-;-1:-1:-1;;;;;34611:18:1;;;;;;:9;:18;;;;;:25;:46;34607:176;;;34681:49;34711:18;34721:7;34711:9;:18::i;:::-;-1:-1:-1;;;;;34681: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;37641:422:1:-;37705:5;37727:15;37736:5;37727:8;:15::i;:::-;37723:333;;;-1:-1:-1;37772:2:1;37759:16;;37723:333;37867:37;;;22:32:-1;6:49;;37867:37:1;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;37850:55:1;;;;37809:12;;37823:23;;-1:-1:-1;;;;;37850:16:1;;;37867:37;;37850: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;;;37850: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;;37808:97:1;;;;37928:7;37920:71;;;;-1:-1:-1;;;37920:71:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38024:10;38013:31;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;38013:31:1;;-1:-1:-1;38006:38:1;;-1:-1:-1;;38006:38:1;38222:419;38284:13;38314:15;38323:5;38314:8;:15::i;:::-;38310:324;;;-1:-1:-1;38346:12:1;;;;;;;;;;;;-1:-1:-1;;;38346:12:1;;;;;;38310:324;38450:35;;;22:32:-1;6:49;;38450:35:1;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;38433:53:1;;;;38392:12;;38406:23;;-1:-1:-1;;;;;38433:16:1;;;38450:35;;38433: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;;;38433: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;;38391:95:1;;;;38509:7;38501:67;;;;-1:-1:-1;;;38501:67:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38601:10;38590:32;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;38590: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;38590:32:1;;420:4:-1;411:14;;;;38590:32:1;;;;;411:14:-1;38590: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;38590:32:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38583:39;;;;;;32967:351;4578:11;;33031:7;;4578:11;;4570:41;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;-1:-1:-1;;;4570:41:1;;;;;;;;;;;;;;;4622:11;:19;;-1:-1:-1;;4622:19:1;;;33060:13:::1;:11;:13::i;:::-;33059:14;33051:67;;;;-1:-1:-1::0;;;33051:67:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;33193:18:1;::::1;33139:24;33193:18:::0;;;:9:::1;:18;::::0;;;;:25;33166:53:::1;::::0;33184:7;;33166:17:::1;:53::i;:::-;33139:80;;33230:46;33248:7;33257:18;33267:7;33257:9;:18::i;:::-;33230:17;:46::i;:::-;33294:16:::0;-1:-1:-1;4664:11:1;:18;;-1:-1:-1;;4664:18:1;4678:4;4664:18;;;32967:351;;-1:-1:-1;32967: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;21845:575:1:-;21927:7;21955:30;21977:7;21955:21;:30::i;:::-;21947:95;;;;-1:-1:-1;;;21947:95:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22075:1;22061:11;:15;22053:77;;;;-1:-1:-1;;;22053:77:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22186:18:1;;22151:32;22186:18;;;:9;:18;;;;;22229:11;;:28;;22245:11;22229:28;:15;:28;:::i;:::-;22215:42;;22278:41;22311:7;22278:32;:41::i;:::-;22347:65;22367:7;22376:32;22396:11;22376:19;:32::i;:::-;22410:1;22347:19;:65::i;34059:247::-;-1:-1:-1;;;;;34140:21:1;;34151:10;34140:21;34136:163;;;34178:39;34196:7;34205:11;34178:17;:39::i;:::-;34136:163;;;34250:37;34266:7;34275:11;34250:15;:37::i;:::-;34059:247;;:::o;35985:136::-;-1:-1:-1;;;;;36094:18:1;;36055:4;36094:18;;;:9;:18;;;;;36079: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;31193:1123:1:-;4355:13;:11;:13::i;:::-;4347:43;;;;;-1:-1:-1;;;4347:43:1;;;;;;;;;;;;-1:-1:-1;;;4347:43:1;;;;;;;;;;;;;;;31343:1:::1;31329:11;:15;31321:76;;;;-1:-1:-1::0;;;31321:76:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31540:30;31562:7;31540:21;:30::i;:::-;31536:195;;;-1:-1:-1::0;;;;;31633:18:1;::::1;;::::0;;;:9:::1;:18;::::0;;;;:25;31610:49:::1;::::0;:18:::1;31643:7:::0;31610:9:::1;:18::i;:::-;:22:::0;:49:::1;:22;:49;:::i;:::-;31595:11;:64;;31587:131;;;;-1:-1:-1::0;;;31587:131:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31751:31;31761:7;31770:11;31751:9;:31::i;:::-;31804:21;31827:22:::0;31853:32:::1;31873:11;31853:19;:32::i;:::-;31803:82:::0;;-1:-1:-1;31803:82:1;-1:-1:-1;31913:43:1::1;31803:82:::0;31932:23;31913:43:::1;:18;:43;:::i;:::-;31896:60;;31973:23;31982:13;31973:8;:23::i;:::-;31969:340;;;32034:14;32021:9;:27;32013:88;;;;-1:-1:-1::0;;;32013:88:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31969:340;;;32142:9;:14:::0;32134:72:::1;;;;-1:-1:-1::0;;;32134:72:1::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32221:76;32240:13;32255:10;32275:4;32282:14;32221:18;:76::i;:::-;4401:1;;31193:1123:::0;;;:::o;26748:1713::-;26918:17;:24;26853:25;;;;26909:34;;:4;;:34;:8;:34;:::i;:::-;26893:50;-1:-1:-1;26893:50:1;26954:13;27014:653;27035:1;27021:11;:15;:51;;;;-1:-1:-1;27048:17:1;:24;27040:32;;27021:51;27014:653;;;27103:23;27129:72;27146:17;27164:5;27146:24;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;27146:24:1;27172:11;27185:15;27129:16;:72::i;:::-;27103:98;;27238:11;27220:15;:29;27216:241;;;27336:20;;27270:19;;;;;27316:40;;;:64;;-1:-1:-1;27360:20:1;;27316:64;27308:133;;;;-1:-1:-1;;;27308:133:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27564:17;:24;27485:15;;-1:-1:-1;27529:7:1;;;;;27485:15;;27555:33;;27551:83;;;27617:1;27609:9;;27551:83;-1:-1:-1;27648:7:1;;27014:653;;;27685:16;;27677:80;;;;-1:-1:-1;;;27677:80:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27778:30;;27868:10;27864:252;;27903:17;:24;;-1:-1:-1;27864:252:1;;;27958:5;27949;:14;27945:171;;-1:-1:-1;;28080:17:1;:24;;-1:-1:-1;;28005:9:1;28013:1;27945:171;28145:9;28140:314;28164:5;28160:1;:9;28140:314;;;-1:-1:-1;;28191:7:1;;;;28217:21;:38;;;;;28250:5;28242;:13;28217:38;28213:157;;;28284:22;28276:30;;28349:5;28325:29;;28213:157;28384:58;28417:17;28435:5;28417:24;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28417:24:1;28384:32;:58::i;:::-;28171:3;;28140:314;;;;26748:1713;;;;;;;;;:::o;24058:784::-;24160:7;24208:46;24228:25;:16;24249:3;24228:25;:20;:25;:::i;:::-;24208:15;;;:46;:19;:46;:::i;:::-;24190:15;:64;24275:19;24297:12;:10;:12::i;:::-;24275:34;;24324:21;24333:11;24324:8;:21::i;:::-;24320:393;;;24362:46;;24370:10;;24362:46;;;;;24391:16;;24362:46;;;;24391:16;24370:10;24362:46;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;24427:7:1;;24423:79;;24455:14;;:28;;-1:-1:-1;;;;;24455:14:1;;;;:28;;;;;24479:3;;24455:14;:28;:14;:28;24479:3;24455:14;:28;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;24455:28:1;24423:79;24320:393;;;24534:57;24549:11;24562:10;24574:16;24534:14;:57::i;:::-;24610:7;;24606:96;;24666:14;;24638:48;;24653:11;;-1:-1:-1;;;;;24666:14:1;24682:3;24638:14;:48::i;:::-;24738:62;;;;;;;;;;;;;;24766:10;;-1:-1:-1;;;;;24738:62:1;;;;;;;;;;;;;;-1:-1:-1;24818:16:1;;24058:784;-1:-1:-1;;;24058: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;28774:502:1:-;28899:9;28894:282;28918:8;:15;28914:1;:19;28894:282;;;28959:16;28955:62;;28996:5;;28955:62;29045:59;29062:8;29071:1;29062:11;;;;;;;;;;;;;;29075;29088:15;29045:16;:59::i;:::-;29031:73;;29119:45;29152:8;29161:1;29152:11;;;;;;;;;;;;;;29119:32;:45::i;:::-;28935:3;;28894:282;;;-1:-1:-1;29194:16:1;;29186:82;;;;-1:-1:-1;;;29186: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;34969:559:1:-;-1:-1:-1;;;;;35083:18:1;;35048:32;35083:18;;;:9;:18;;;;;35117:20;35083:18;35117:14;:20::i;:::-;35112:409;;35174:17;:24;35201:1;35234:10;;;-1:-1:-1;;35174:28:1;;;;35221:23;;35217:215;;35265:12;35280:17;35298:9;35280:28;;;;;;;;;;;;;;;;;;;;;35351:10;;;;-1:-1:-1;;;;;35280:28:1;;;35327:15;;;:9;:15;;;;;;;:21;;;:34;;;35380:17;:29;;35280:28;;-1:-1:-1;35280:28:1;;35380:17;;:29;;;;;;;;;;;;;;:36;;;;;-1:-1:-1;;;;;35380:36:1;;;;;-1:-1:-1;;;;;35380:36:1;;;;;;35217:215;;35446:17;:23;;;;;;;;;;;;;;;;;-1:-1:-1;;35446:23:1;;;;;-1:-1:-1;;;;;;35446:23:1;;;;;;;;;-1:-1:-1;;;;;35491:18:1;;;;:9;:18;;;;;35484:25;;;35446:23;35484:25;;-1:-1:-1;34969:559:1;;:::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;36343:127:1:-;36447:11;:15;;;36343:127::o;4578:130:6:-;4636:7;4663:37;4667:1;4670;4663:37;;;;;;;;;;;;;;;;;:3;:37::i;29650:1211:1:-;29756:7;29776:17;29796:29;29817:7;29796:20;:29::i;:::-;29776:49;-1:-1:-1;29840:13:1;;29836:989;;-1:-1:-1;;;;;29919:18:1;;29884:32;29919:18;;;:9;:18;;;;;;29994:23;;;29990:254;;;-1:-1:-1;30056:9:1;30098:26;:11;30056:9;30098:26;:15;:26;:::i;:::-;30084:40;;29990:254;;;-1:-1:-1;30227:1:1;;29990:254;30273:21;30296:14;30314:36;30334:15;30314:19;:36::i;:::-;30272:78;;-1:-1:-1;30272:78:1;-1:-1:-1;30433:13:1;30272:78;30444:1;30433:13;:10;:13;:::i;:::-;30489:11;;30424:22;;-1:-1:-1;30489:32:1;;30505:15;30489:32;:15;:32;:::i;:::-;30475:46;;30555:23;30564:13;30555:8;:23::i;:::-;30551:184;;;30599:33;;-1:-1:-1;;;;;30599:25:1;;;:33;;;;;30625:6;;30599:33;;;;30625:6;30599:25;:33;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30599:33:1;30551:184;;;30673:46;30688:13;30703:7;30712:6;30673:14;:46::i;:::-;30772:15;-1:-1:-1;;;;;30754:59:1;30763:7;-1:-1:-1;;;;;30754:59:1;;30789:6;30797:15;30754:59;;;;;;;;;;;;;;;;;;;;;;;;29836:989;;;;;-1:-1:-1;30842:11:1;;29650:1211;-1:-1:-1;;;29650:1211:1:o;38876:333::-;39046:17;;39023:60;;;-1:-1:-1;;;;;39023:60:1;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;39023:60:1;;;;;;;25:18:-1;;61:17;;39046::1;;;;;;-1:-1:-1;;;;;;39023:60:1;-1:-1:-1;;;;;182:15;;;179:29;;;;160:49;;39012:72:1;;;;-1:-1:-1;;38985:23:1;;39012:10;;;39023:60;39012:72;;;25:18:-1;39012: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;;;39012: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;;38970:114:1;;;;39103:7;:69;;;;-1:-1:-1;39115:17:1;;:22;;:56;;;39152:10;39141:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;39141:30:1;39115:56;39095:106;;;;;-1:-1:-1;;;39095: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:39652:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;221:39652:1;;;-1:-1:-1;221:39652:1;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
ipfs://132b11c8e08a66d7ac3326606ac359c39d8a86667f84472891efae17b37a65e3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 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.