ERC-20
DeFi
Overview
Max Total Supply
1,777,112.0042730103448889 VISION
Holders
1,319 (0.00%)
Total Transfers
-
Market
Price
$0.19 @ 0.000055 ETH
Onchain Market Cap
$342,934.36
Circulating Supply Market Cap
$0.00
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|---|---|---|---|---|
1 | Quickswap | 0X034B2090B579228482520C589DBD397C53FC51CC-0X7CEB23FD6BC0ADD59E62AC25578270CFF1B9F619 | $0.2376 0.0000682 Eth | $24.87 104.662 0X034B2090B579228482520C589DBD397C53FC51CC | 56.7327% |
2 | Uniswap V2 (Ethereum) | 0XF406F7A9046793267BC276908778B29563323996-0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2 | $0.2475 0.0000711 Eth | $18.07 73.033 0XF406F7A9046793267BC276908778B29563323996 | 39.5879% |
3 | ComethSwap | 0X034B2090B579228482520C589DBD397C53FC51CC-0X7CEB23FD6BC0ADD59E62AC25578270CFF1B9F619 | $0.2392 0.0000688 Eth | $1.24 5.168 0X034B2090B579228482520C589DBD397C53FC51CC | 2.8013% |
4 | Balancer V2 (Polygon) | 0X034B2090B579228482520C589DBD397C53FC51CC-0X7CEB23FD6BC0ADD59E62AC25578270CFF1B9F619 | $0.2358 0.0000695 Eth | $0.382 1.620 0X034B2090B579228482520C589DBD397C53FC51CC | 0.8781% |
Contract Name:
VisionToken
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-11-16 */ pragma solidity 0.5.17; /** * Source: https://raw.githubusercontent.com/simple-restricted-token/reference-implementation/master/contracts/token/ERC1404/ERC1404.sol * With ERC-20 APIs removed (will be implemented as a separate contract). * And adding authorizeTransfer. */ interface IWhitelist { /** * @notice Detects if a transfer will be reverted and if so returns an appropriate reference code * @param from Sending address * @param to Receiving address * @param value Amount of tokens being transferred * @return Code by which to reference message for rejection reasoning * @dev Overwrite with your custom transfer restriction logic */ function detectTransferRestriction( address from, address to, uint value ) external view returns (uint8); /** * @notice Returns a human-readable message for a given restriction code * @param restrictionCode Identifier for looking up a message * @return Text showing the restriction's reasoning * @dev Overwrite with your custom message and restrictionCode handling */ function messageForTransferRestriction(uint8 restrictionCode) external pure returns (string memory); /** * @notice Called by the DAT contract before a transfer occurs. * @dev This call will revert when the transfer is not authorized. * This is a mutable call to allow additional data to be recorded, * such as when the user aquired their tokens. */ function authorizeTransfer( address _from, address _to, uint _value, bool _isSell ) external; function activateWallet( address _wallet ) external; function deactivateWallet( address _wallet ) external; function walletActivated( address _wallet ) external returns(bool); } interface IERC20Detailed { /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view returns (uint8); function name() external view returns (string memory); function symbol() external view returns (string memory); } /** * @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. * * _Available since v2.4.0._ */ 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. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 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. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } /** * @title Reduces the size of terms before multiplication, to avoid an overflow, and then * restores the proper size after division. * @notice This effectively allows us to overflow values in the numerator and/or denominator * of a fraction, so long as the end result does not overflow as well. * @dev Results may be off by 1 + 0.000001% for 2x1 calls and 2 + 0.00001% for 2x2 calls. * Do not use if your contract expects very small result values to be accurate. */ library BigDiv { using SafeMath for uint; /// @notice The max possible value uint private constant MAX_UINT = 2**256 - 1; /// @notice When multiplying 2 terms <= this value the result won't overflow uint private constant MAX_BEFORE_SQUARE = 2**128 - 1; /// @notice The max error target is off by 1 plus up to 0.000001% error /// for bigDiv2x1 and that `* 2` for bigDiv2x2 uint private constant MAX_ERROR = 100000000; /// @notice A larger error threshold to use when multiple rounding errors may apply uint private constant MAX_ERROR_BEFORE_DIV = MAX_ERROR * 2; /** * @notice Returns the approx result of `a * b / d` so long as the result is <= MAX_UINT * @param _numA the first numerator term * @param _numB the second numerator term * @param _den the denominator * @return the approx result with up to off by 1 + MAX_ERROR, rounding down if needed */ function bigDiv2x1( uint _numA, uint _numB, uint _den ) internal pure returns (uint) { if (_numA == 0 || _numB == 0) { // would div by 0 or underflow if we don't special case 0 return 0; } uint value; if (MAX_UINT / _numA >= _numB) { // a*b does not overflow, return exact math value = _numA * _numB; value /= _den; return value; } // Sort numerators uint numMax = _numB; uint numMin = _numA; if (_numA > _numB) { numMax = _numA; numMin = _numB; } value = numMax / _den; if (value > MAX_ERROR) { // _den is small enough to be MAX_ERROR or better w/o a factor value = value.mul(numMin); return value; } // formula = ((a / f) * b) / (d / f) // factor >= a / sqrt(MAX) * (b / sqrt(MAX)) uint factor = numMin - 1; factor /= MAX_BEFORE_SQUARE; factor += 1; uint temp = numMax - 1; temp /= MAX_BEFORE_SQUARE; temp += 1; if (MAX_UINT / factor >= temp) { factor *= temp; value = numMax / factor; if (value > MAX_ERROR_BEFORE_DIV) { value = value.mul(numMin); temp = _den - 1; temp /= factor; temp = temp.add(1); value /= temp; return value; } } // formula: (a / (d / f)) * (b / f) // factor: b / sqrt(MAX) factor = numMin - 1; factor /= MAX_BEFORE_SQUARE; factor += 1; value = numMin / factor; temp = _den - 1; temp /= factor; temp += 1; temp = numMax / temp; value = value.mul(temp); return value; } /** * @notice Returns the approx result of `a * b / d` so long as the result is <= MAX_UINT * @param _numA the first numerator term * @param _numB the second numerator term * @param _den the denominator * @return the approx result with up to off by 1 + MAX_ERROR, rounding down if needed * @dev roundUp is implemented by first rounding down and then adding the max error to the result */ function bigDiv2x1RoundUp( uint _numA, uint _numB, uint _den ) internal pure returns (uint) { // first get the rounded down result uint value = bigDiv2x1(_numA, _numB, _den); if (value == 0) { // when the value rounds down to 0, assume up to an off by 1 error return 1; } // round down has a max error of MAX_ERROR, add that to the result // for a round up error of <= MAX_ERROR uint temp = value - 1; temp /= MAX_ERROR; temp += 1; if (MAX_UINT - value < temp) { // value + error would overflow, return MAX return MAX_UINT; } value += temp; return value; } /** * @notice Returns the approx result of `a * b / (c * d)` so long as the result is <= MAX_UINT * @param _numA the first numerator term * @param _numB the second numerator term * @param _denA the first denominator term * @param _denB the second denominator term * @return the approx result with up to off by 2 + MAX_ERROR*10 error, rounding down if needed * @dev this uses bigDiv2x1 and adds additional rounding error so the max error of this * formula is larger */ function bigDiv2x2( uint _numA, uint _numB, uint _denA, uint _denB ) internal pure returns (uint) { if (MAX_UINT / _denA >= _denB) { // denA*denB does not overflow, use bigDiv2x1 instead return bigDiv2x1(_numA, _numB, _denA * _denB); } if (_numA == 0 || _numB == 0) { // would div by 0 or underflow if we don't special case 0 return 0; } // Sort denominators uint denMax = _denB; uint denMin = _denA; if (_denA > _denB) { denMax = _denA; denMin = _denB; } uint value; if (MAX_UINT / _numA >= _numB) { // a*b does not overflow, use `a / d / c` value = _numA * _numB; value /= denMin; value /= denMax; return value; } // `ab / cd` where both `ab` and `cd` would overflow // Sort numerators uint numMax = _numB; uint numMin = _numA; if (_numA > _numB) { numMax = _numA; numMin = _numB; } // formula = (a/d) * b / c uint temp = numMax / denMin; if (temp > MAX_ERROR_BEFORE_DIV) { return bigDiv2x1(temp, numMin, denMax); } // formula: ((a/f) * b) / d then either * f / c or / c * f // factor >= a / sqrt(MAX) * (b / sqrt(MAX)) uint factor = numMin - 1; factor /= MAX_BEFORE_SQUARE; factor += 1; temp = numMax - 1; temp /= MAX_BEFORE_SQUARE; temp += 1; if (MAX_UINT / factor >= temp) { factor *= temp; value = numMax / factor; if (value > MAX_ERROR_BEFORE_DIV) { value = value.mul(numMin); value /= denMin; if (value > 0 && MAX_UINT / value >= factor) { value *= factor; value /= denMax; return value; } } } // formula: (a/f) * b / ((c*d)/f) // factor >= c / sqrt(MAX) * (d / sqrt(MAX)) factor = denMin; factor /= MAX_BEFORE_SQUARE; temp = denMax; // + 1 here prevents overflow of factor*temp temp /= MAX_BEFORE_SQUARE + 1; factor *= temp; return bigDiv2x1(numMax / factor, numMin, MAX_UINT); } } /** * @title Calculates the square root of a given value. * @dev Results may be off by 1. */ library Sqrt { /// @notice The max possible value uint private constant MAX_UINT = 2**256 - 1; // Source: https://github.com/ethereum/dapp-bin/pull/50 function sqrt(uint x) internal pure returns (uint y) { if (x == 0) { return 0; } else if (x <= 3) { return 1; } else if (x == MAX_UINT) { // Without this we fail on x + 1 below return 2**128 - 1; } uint z = (x + 1) / 2; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } } /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ 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); } /** * @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 Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @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]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context is Initializable { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Initializable, Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } uint256[50] private ______gap; } /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { require(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); role.bearer[account] = false; } /** * @dev Check if an account has this role. * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), "Roles: account is the zero address"); return role.bearer[account]; } } contract MinterRole is Initializable, Context { using Roles for Roles.Role; event MinterAdded(address indexed account); event MinterRemoved(address indexed account); Roles.Role private _minters; function initialize(address sender) public initializer { if (!isMinter(sender)) { _addMinter(sender); } } modifier onlyMinter() { require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role"); _; } function isMinter(address account) public view returns (bool) { return _minters.has(account); } function addMinter(address account) public onlyMinter { _addMinter(account); } function renounceMinter() public { _removeMinter(_msgSender()); } function _addMinter(address account) internal { _minters.add(account); emit MinterAdded(account); } function _removeMinter(address account) internal { _minters.remove(account); emit MinterRemoved(account); } uint256[50] private ______gap; } /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is Initializable, ERC20, MinterRole { function initialize(address sender) public initializer { MinterRole.initialize(sender); } /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { _mint(account, amount); return true; } uint256[50] private ______gap; } /** * @dev Extension of {ERC20Mintable} that adds a cap to the supply of tokens. */ contract ERC20Capped is Initializable, ERC20Mintable { uint256 private _cap; /** * @dev Sets the value of the `cap`. This value is immutable, it can only be * set once during construction. */ function initialize(uint256 cap, address sender) public initializer { ERC20Mintable.initialize(sender); require(cap > 0, "ERC20Capped: cap is 0"); _cap = cap; } /** * @dev Returns the cap on the token's total supply. */ function cap() public view returns (uint256) { return _cap; } /** * @dev See {ERC20Mintable-mint}. * * Requirements: * * - `value` must not cause the total supply to go over the cap. */ function _mint(address account, uint256 value) internal { require(totalSupply().add(value) <= _cap, "ERC20Capped: cap exceeded"); super._mint(account, value); } uint256[50] private ______gap; } contract PauserRole is Initializable, Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; function initialize(address sender) public initializer { if (!isPauser(sender)) { _addPauser(sender); } } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } uint256[50] private ______gap; } /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable is Initializable, Context, PauserRole { /** * @dev Emitted when the pause is triggered by a pauser (`account`). */ event Paused(address account); /** * @dev Emitted when the pause is lifted by a pauser (`account`). */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. Assigns the Pauser role * to the deployer. */ function initialize(address sender) public initializer { PauserRole.initialize(sender); _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } /** * @dev Called by a pauser to pause, triggers stopped state. */ function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Called by a pauser to unpause, returns to normal state. */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[50] private ______gap; } /** * @title Pausable token * @dev ERC20 with pausable transfers and allowances. * * Useful if you want to stop trades until the end of a crowdsale, or have * an emergency switch for freezing all token transfers in the event of a large * bug. */ contract ERC20Pausable is Initializable, ERC20, Pausable { function initialize(address sender) public initializer { Pausable.initialize(sender); } function transfer(address to, uint256 value) public whenNotPaused returns (bool) { return super.transfer(to, value); } function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) { return super.transferFrom(from, to, value); } function approve(address spender, uint256 value) public whenNotPaused returns (bool) { return super.approve(spender, value); } function increaseAllowance(address spender, uint256 addedValue) public whenNotPaused returns (bool) { return super.increaseAllowance(spender, addedValue); } function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotPaused returns (bool) { return super.decreaseAllowance(spender, subtractedValue); } uint256[50] private ______gap; } /** * @title Continuous Offering abstract contract * @notice A shared base for various offerings from Fairmint. */ contract ContinuousOffering is ERC20Pausable, ERC20Capped, IERC20Detailed { using SafeMath for uint; using Sqrt for uint; using SafeERC20 for IERC20; /** * Events */ event Buy( address indexed _from, address indexed _to, uint _currencyValue, uint _fairValue ); event Sell( address indexed _from, address indexed _to, uint _currencyValue, uint _fairValue ); event Burn( address indexed _from, uint _fairValue ); event StateChange( uint _previousState, uint _newState ); /** * Constants */ /// @notice The default state uint internal constant STATE_INIT = 0; /// @notice The state after initGoal has been reached uint internal constant STATE_RUN = 1; /// @notice The state after closed by the `beneficiary` account from STATE_RUN uint internal constant STATE_CLOSE = 2; /// @notice The state after closed by the `beneficiary` account from STATE_INIT uint internal constant STATE_CANCEL = 3; /// @notice When multiplying 2 terms, the max value is 2^128-1 uint internal constant MAX_BEFORE_SQUARE = 2**128 - 1; /// @notice The denominator component for values specified in basis points. uint internal constant BASIS_POINTS_DEN = 10000; /// @notice The max `totalSupply() + burnedSupply` /// @dev This limit ensures that the DAT's formulas do not overflow (<MAX_BEFORE_SQUARE/2) uint internal constant MAX_SUPPLY = 10 ** 38; /** * Data specific to our token business logic */ /// @notice The contract for transfer authorizations, if any. IWhitelist public whitelist; /// @notice The total number of burned FAIR tokens, excluding tokens burned from a `Sell` action in the DAT. uint public burnedSupply; /** * Data for DAT business logic */ /// @dev unused slot which remains to ensure compatible upgrades bool private __autoBurn; /// @notice The address of the beneficiary organization which receives the investments. /// Points to the wallet of the organization. address payable public beneficiary; /// @notice The buy slope of the bonding curve. /// Does not affect the financial model, only the granularity of FAIR. /// @dev This is the numerator component of the fractional value. uint public buySlopeNum; /// @notice The buy slope of the bonding curve. /// Does not affect the financial model, only the granularity of FAIR. /// @dev This is the denominator component of the fractional value. uint public buySlopeDen; /// @notice The address from which the updatable variables can be updated address public control; /// @notice The address of the token used as reserve in the bonding curve /// (e.g. the DAI contract). Use ETH if 0. IERC20 public currency; /// @notice The address where fees are sent. address payable public feeCollector; /// @notice The percent fee collected each time new FAIR are issued expressed in basis points. uint public feeBasisPoints; /// @notice The initial fundraising goal (expressed in FAIR) to start the c-org. /// `0` means that there is no initial fundraising and the c-org immediately moves to run state. uint public initGoal; /// @notice A map with all investors in init state using address as a key and amount as value. /// @dev This structure's purpose is to make sure that only investors can withdraw their money if init_goal is not reached. mapping(address => uint) public initInvestors; /// @notice The initial number of FAIR created at initialization for the beneficiary. /// Technically however, this variable is not a constant as we must always have ///`init_reserve>=total_supply+burnt_supply` which means that `init_reserve` will be automatically /// decreased to equal `total_supply+burnt_supply` in case `init_reserve>total_supply+burnt_supply` /// after an investor sells his FAIRs. /// @dev Organizations may move these tokens into vesting contract(s) uint public initReserve; /// @notice The investment reserve of the c-org. Defines the percentage of the value invested that is /// automatically funneled and held into the buyback_reserve expressed in basis points. /// Internal since this is n/a to all derivative contracts. uint internal __investmentReserveBasisPoints; /// @dev unused slot which remains to ensure compatible upgrades uint private __openUntilAtLeast; /// @notice The minimum amount of `currency` investment accepted. uint public minInvestment; /// @dev The revenue commitment of the organization. Defines the percentage of the value paid through the contract /// that is automatically funneled and held into the buyback_reserve expressed in basis points. /// Internal since this is n/a to all derivative contracts. uint internal __revenueCommitmentBasisPoints; /// @notice The current state of the contract. /// @dev See the constants above for possible state values. uint public state; /// @dev If this value changes we need to reconstruct the DOMAIN_SEPARATOR string public constant version = "3"; // --- EIP712 niceties --- // Original source: https://etherscan.io/address/0x6b175474e89094c44da98b954eedeac495271d0f#code mapping (address => uint) public nonces; bytes32 public DOMAIN_SEPARATOR; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // The success fee (expressed in currency) that will be earned by setupFeeRecipient as soon as initGoal // is reached. We must have setup_fee <= buy_slope*init_goal^(2)/2 uint public setupFee; // The recipient of the setup_fee once init_goal is reached address payable public setupFeeRecipient; /// @notice The minimum time before which the c-org contract cannot be closed once the contract has /// reached the `run` state. /// @dev When updated, the new value of `minimum_duration` cannot be earlier than the previous value. uint public minDuration; /// @dev Initialized at `0` and updated when the contract switches from `init` state to `run` state /// or when the initial trial period ends. uint public __startedOn; /// @notice The max possible value uint internal constant MAX_UINT = 2**256 - 1; // keccak256("PermitBuy(address from,address to,uint256 currencyValue,uint256 minTokensBought,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_BUY_TYPEHASH = 0xaf42a244b3020d6a2253d9f291b4d3e82240da42b22129a8113a58aa7a3ddb6a; // keccak256("PermitSell(address from,address to,uint256 quantityToSell,uint256 minCurrencyReturned,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_SELL_TYPEHASH = 0x5dfdc7fb4c68a4c249de5e08597626b84fbbe7bfef4ed3500f58003e722cc548; modifier authorizeTransfer( address _from, address _to, uint _value, bool _isSell ) { if(address(whitelist) != address(0)) { //automatically activate wallet _from //does not activate if, //1. _from is zero address, //2. it is burn if(!whitelist.walletActivated(_from) && _from != address(0) && !(_to == address(0) && !_isSell)){ whitelist.activateWallet(_from); } //automatically activate wallet _to //does not activate if, //1. _to is zero address, if(!whitelist.walletActivated(_to) && _to != address(0)){ whitelist.activateWallet(_to); } // This is not set for the minting of initialReserve whitelist.authorizeTransfer(_from, _to, _value, _isSell); } _; if(address(whitelist) != address(0)){ //automatically deactivates _from if _from's balance is zero if(balanceOf(_from) == 0 && _from != address(0) && !(_to==address(0) && !_isSell)){ //deactivate wallets without balance whitelist.deactivateWallet(_from); } } } /** * Buyback reserve */ /// @notice The total amount of currency value currently locked in the contract and available to sellers. function buybackReserve() public view returns (uint) { uint reserve = address(this).balance; if(address(currency) != address(0)) { reserve = currency.balanceOf(address(this)); } if(reserve > MAX_BEFORE_SQUARE) { /// Math: If the reserve becomes excessive, cap the value to prevent overflowing in other formulas return MAX_BEFORE_SQUARE; } return reserve; } /** * Functions required by the ERC-20 token standard */ /// @dev Moves tokens from one account to another if authorized. function _transfer( address _from, address _to, uint _amount ) internal authorizeTransfer(_from, _to, _amount, false) { require(state != STATE_INIT || _from == beneficiary, "ONLY_BENEFICIARY_DURING_INIT"); super._transfer(_from, _to, _amount); } /// @dev Removes tokens from the circulating supply. function _burn( address _from, uint _amount, bool _isSell ) internal authorizeTransfer(_from, address(0), _amount, _isSell) { super._burn(_from, _amount); if(!_isSell) { // This is a burn require(state == STATE_RUN, "INVALID_STATE"); // SafeMath not required as we cap how high this value may get during mint burnedSupply += _amount; emit Burn(_from, _amount); } } /// @notice Called to mint tokens on `buy`. function _mint( address _to, uint _quantity ) internal authorizeTransfer(address(0), _to, _quantity, false) { super._mint(_to, _quantity); // Math: If this value got too large, the DAT may overflow on sell require(totalSupply().add(burnedSupply) <= MAX_SUPPLY, "EXCESSIVE_SUPPLY"); } /** * Transaction Helpers */ /// @notice Confirms the transfer of `_quantityToInvest` currency to the contract. function _collectInvestment( address payable _from, uint _quantityToInvest, uint _msgValue, bool _refundRemainder ) internal { if(address(currency) == address(0)) { // currency is ETH if(_refundRemainder) { // Math: if _msgValue was not sufficient then revert uint refund = _msgValue.sub(_quantityToInvest); if(refund > 0) { Address.sendValue(msg.sender, refund); } } else { require(_quantityToInvest == _msgValue, "INCORRECT_MSG_VALUE"); } } else { // currency is ERC20 require(_msgValue == 0, "DO_NOT_SEND_ETH"); currency.safeTransferFrom(_from, address(this), _quantityToInvest); } } /// @dev Send `_amount` currency from the contract to the `_to` account. function _transferCurrency( address payable _to, uint _amount ) internal { if(_amount > 0) { if(address(currency) == address(0)) { Address.sendValue(_to, _amount); } else { currency.safeTransfer(_to, _amount); } } } /** * Config / Control */ /// @notice Called once after deploy to set the initial configuration. /// None of the values provided here may change once initially set. /// @dev using the init pattern in order to support zos upgrades function _initialize( uint _initReserve, address _currencyAddress, uint _initGoal, uint _buySlopeNum, uint _buySlopeDen, uint _setupFee, address payable _setupFeeRecipient ) internal { // The ERC-20 implementation will confirm initialize is only run once ERC20Capped.initialize((5000000 * (10 ** 18)), msg.sender); // Also update the pausable setting _addPauser(msg.sender); require(_buySlopeNum > 0, "INVALID_SLOPE_NUM"); require(_buySlopeDen > 0, "INVALID_SLOPE_DEN"); require(_buySlopeNum < MAX_BEFORE_SQUARE, "EXCESSIVE_SLOPE_NUM"); require(_buySlopeDen < MAX_BEFORE_SQUARE, "EXCESSIVE_SLOPE_DEN"); buySlopeNum = _buySlopeNum; buySlopeDen = _buySlopeDen; // Setup Fee require(_setupFee == 0 || _setupFeeRecipient != address(0), "MISSING_SETUP_FEE_RECIPIENT"); require(_setupFeeRecipient == address(0) || _setupFee != 0, "MISSING_SETUP_FEE"); // setup_fee <= (n/d)*(g^2)/2 uint initGoalInCurrency = _initGoal * _initGoal; initGoalInCurrency = initGoalInCurrency.mul(_buySlopeNum); initGoalInCurrency /= 2 * _buySlopeDen; require(_setupFee <= initGoalInCurrency, "EXCESSIVE_SETUP_FEE"); setupFee = _setupFee; setupFeeRecipient = _setupFeeRecipient; // Set default values (which may be updated using `updateConfig`) uint decimals = 18; if(_currencyAddress != address(0)) { decimals = IERC20Detailed(_currencyAddress).decimals(); } minInvestment = 100 * (10 ** decimals); beneficiary = msg.sender; control = msg.sender; feeCollector = msg.sender; // Save currency currency = IERC20(_currencyAddress); // Mint the initial reserve if(_initReserve > 0) { initReserve = _initReserve; _mint(beneficiary, initReserve); } initializeDomainSeparator(); } /// @notice Used to initialize the domain separator used in meta-transactions /// @dev This is separate from `initialize` to allow upgraded contracts to update the version /// There is no harm in calling this multiple times / no permissions required function initializeDomainSeparator() public { uint id; // solium-disable-next-line assembly { id := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name())), keccak256(bytes(version)), id, address(this) ) ); } function _updateConfig( address _whitelistAddress, address payable _beneficiary, address _control, address payable _feeCollector, uint _feeBasisPoints, uint _minInvestment, uint _minDuration ) internal { // This require(also confirms that initialize has been called. require(msg.sender == control, "CONTROL_ONLY"); // address(0) is okay whitelist = IWhitelist(_whitelistAddress); require(_control != address(0), "INVALID_ADDRESS"); control = _control; require(_feeCollector != address(0), "INVALID_ADDRESS"); feeCollector = _feeCollector; require(_feeBasisPoints <= BASIS_POINTS_DEN, "INVALID_FEE"); feeBasisPoints = _feeBasisPoints; require(_minInvestment > 0, "INVALID_MIN_INVESTMENT"); minInvestment = _minInvestment; require(_minDuration >= minDuration, "MIN_DURATION_MAY_NOT_BE_REDUCED"); minDuration = _minDuration; if(beneficiary != _beneficiary) { require(_beneficiary != address(0), "INVALID_ADDRESS"); uint tokens = balanceOf(beneficiary); initInvestors[_beneficiary] = initInvestors[_beneficiary].add(initInvestors[beneficiary]); initInvestors[beneficiary] = 0; if(tokens > 0) { _transfer(beneficiary, _beneficiary, tokens); } beneficiary = _beneficiary; } } /** * Functions for our business logic */ /// @notice Burn the amount of tokens from the address msg.sender if authorized. /// @dev Note that this is not the same as a `sell` via the DAT. function burn( uint _amount ) public { _burn(msg.sender, _amount, false); } /// @notice Burn the amount of tokens from the given address if approved. function burnFrom( address _from, uint _amount ) public { _approve(_from, msg.sender, allowance(_from, msg.sender).sub(_amount, "ERC20: burn amount exceeds allowance")); _burn(_from, _amount, false); } // Buy /// @dev Distributes _value currency between the buybackReserve, beneficiary, and feeCollector. function _distributeInvestment(uint _value) internal; /// @notice Calculate how many FAIR tokens you would buy with the given amount of currency if `buy` was called now. /// @param _currencyValue How much currency to spend in order to buy FAIR. function estimateBuyValue( uint _currencyValue ) public view returns (uint) { if(_currencyValue < minInvestment) { return 0; } /// Calculate the tokenValue for this investment uint tokenValue; if(state == STATE_INIT) { uint currencyValue = _currencyValue; uint _totalSupply = totalSupply(); // (buy_slope*init_goal)*(init_goal+init_reserve-total_supply) // n/d: buy_slope (MAX_BEFORE_SQUARE / MAX_BEFORE_SQUARE) // g: init_goal (MAX_BEFORE_SQUARE) // t: total_supply (MAX_BEFORE_SQUARE) // r: init_reserve (MAX_BEFORE_SQUARE) // source: ((n/d)*g)*(g+r-t) // impl: (g n (g + r - t))/(d) uint max = BigDiv.bigDiv2x1( initGoal * buySlopeNum, initGoal + initReserve - _totalSupply, buySlopeDen ); if(currencyValue > max) { currencyValue = max; } // Math: worst case // MAX * MAX_BEFORE_SQUARE // / MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE tokenValue = BigDiv.bigDiv2x1( currencyValue, buySlopeDen, initGoal * buySlopeNum ); if(currencyValue != _currencyValue) { currencyValue = _currencyValue - max; // ((2*next_amount/buy_slope)+init_goal^2)^(1/2)-init_goal // a: next_amount | currencyValue // n/d: buy_slope (MAX_BEFORE_SQUARE / MAX_BEFORE_SQUARE) // g: init_goal (MAX_BEFORE_SQUARE/2) // r: init_reserve (MAX_BEFORE_SQUARE/2) // sqrt(((2*a/(n/d))+g^2)-g // sqrt((2 d a + n g^2)/n) - g // currencyValue == 2 d a uint temp = 2 * buySlopeDen; currencyValue = temp.mul(currencyValue); // temp == g^2 temp = initGoal; temp *= temp; // temp == n g^2 temp = temp.mul(buySlopeNum); // temp == (2 d a) + n g^2 temp = currencyValue.add(temp); // temp == (2 d a + n g^2)/n temp /= buySlopeNum; // temp == sqrt((2 d a + n g^2)/n) temp = temp.sqrt(); // temp == sqrt((2 d a + n g^2)/n) - g temp -= initGoal; tokenValue = tokenValue.add(temp); } } else if(state == STATE_RUN) { // initReserve is reduced on sell as necessary to ensure that this line will not overflow uint supply = totalSupply() + burnedSupply - initReserve; // Math: worst case // MAX * 2 * MAX_BEFORE_SQUARE // / MAX_BEFORE_SQUARE tokenValue = BigDiv.bigDiv2x1( _currencyValue, 2 * buySlopeDen, buySlopeNum ); // Math: worst case MAX + (MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE) tokenValue = tokenValue.add(supply * supply); tokenValue = tokenValue.sqrt(); // Math: small chance of underflow due to possible rounding in sqrt tokenValue = tokenValue.sub(supply); } else { // invalid state return 0; } return tokenValue; } function _buy( address payable _from, address _to, uint _currencyValue, uint _minTokensBought ) internal { require(_to != address(0), "INVALID_ADDRESS"); require(_minTokensBought > 0, "MUST_BUY_AT_LEAST_1"); // Calculate the tokenValue for this investment uint tokenValue = estimateBuyValue(_currencyValue); require(tokenValue >= _minTokensBought, "PRICE_SLIPPAGE"); emit Buy(_from, _to, _currencyValue, tokenValue); _collectInvestment(_from, _currencyValue, msg.value, false); // Update state, initInvestors, and distribute the investment when appropriate if(state == STATE_INIT) { // Math worst case: MAX_BEFORE_SQUARE initInvestors[_to] += tokenValue; // Math worst case: // MAX_BEFORE_SQUARE + MAX_BEFORE_SQUARE if(totalSupply() + tokenValue - initReserve >= initGoal) { emit StateChange(state, STATE_RUN); state = STATE_RUN; if(__startedOn == 0) { __startedOn = block.timestamp; } // Math worst case: // MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE/2 // / MAX_BEFORE_SQUARE uint beneficiaryContribution = BigDiv.bigDiv2x1( initInvestors[beneficiary], buySlopeNum * initGoal, buySlopeDen ); if(setupFee > 0) { _transferCurrency(setupFeeRecipient, setupFee); if(beneficiaryContribution > setupFee) { beneficiaryContribution -= setupFee; } else { beneficiaryContribution = 0; } } _distributeInvestment(buybackReserve().sub(beneficiaryContribution)); } } else // implied: if(state == STATE_RUN) { if(_to != beneficiary) { _distributeInvestment(_currencyValue); } } _mint(_to, tokenValue); } /// @notice Purchase FAIR tokens with the given amount of currency. /// @param _to The account to receive the FAIR tokens from this purchase. /// @param _currencyValue How much currency to spend in order to buy FAIR. /// @param _minTokensBought Buy at least this many FAIR tokens or the transaction reverts. /// @dev _minTokensBought is necessary as the price will change if some elses transaction mines after /// yours was submitted. function buy( address _to, uint _currencyValue, uint _minTokensBought ) public payable { _buy(msg.sender, _to, _currencyValue, _minTokensBought); } /// @notice Allow users to sign a message authorizing a buy function permitBuy( address payable _from, address _to, uint _currencyValue, uint _minTokensBought, uint _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external { require(_deadline >= block.timestamp, "EXPIRED"); bytes32 digest = keccak256(abi.encode(PERMIT_BUY_TYPEHASH, _from, _to, _currencyValue, _minTokensBought, nonces[_from]++, _deadline)); digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, digest ) ); address recoveredAddress = ecrecover(digest, _v, _r, _s); require(recoveredAddress != address(0) && recoveredAddress == _from, "INVALID_SIGNATURE"); _buy(_from, _to, _currencyValue, _minTokensBought); } /// Sell function estimateSellValue( uint _quantityToSell ) public view returns(uint) { uint reserve = buybackReserve(); // Calculate currencyValue for this sale uint currencyValue; if(state == STATE_RUN) { uint supply = totalSupply() + burnedSupply; // buyback_reserve = r // total_supply = t // burnt_supply = b // amount = a // source: (t+b)*a*(2*r)/((t+b)^2)-(((2*r)/((t+b)^2)*a^2)/2)+((2*r)/((t+b)^2)*a*b^2)/(2*(t)) // imp: (a b^2 r)/(t (b + t)^2) + (2 a r)/(b + t) - (a^2 r)/(b + t)^2 // Math: burnedSupply is capped in FAIR such that the square will never overflow // Math worst case: // MAX * MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE/2 * MAX_BEFORE_SQUARE/2 // / MAX_BEFORE_SQUARE/2 * MAX_BEFORE_SQUARE/2 * MAX_BEFORE_SQUARE/2 currencyValue = BigDiv.bigDiv2x2( _quantityToSell.mul(reserve), burnedSupply * burnedSupply, totalSupply(), supply * supply ); // Math: worst case currencyValue is MAX_BEFORE_SQUARE (max reserve, 1 supply) // Math worst case: // MAX * 2 * MAX_BEFORE_SQUARE uint temp = _quantityToSell.mul(2 * reserve); temp /= supply; // Math: worst-case temp is MAX_BEFORE_SQUARE (max reserve, 1 supply) // Math: considering the worst-case for currencyValue and temp, this can never overflow currencyValue += temp; // Math: worst case // MAX * MAX * MAX_BEFORE_SQUARE // / MAX_BEFORE_SQUARE/2 * MAX_BEFORE_SQUARE/2 temp = BigDiv.bigDiv2x1RoundUp( _quantityToSell.mul(_quantityToSell), reserve, supply * supply ); if(currencyValue > temp) { currencyValue -= temp; } else { currencyValue = 0; } } else if(state == STATE_CLOSE) { // Math worst case // MAX * MAX_BEFORE_SQUARE currencyValue = _quantityToSell.mul(reserve); currencyValue /= totalSupply(); } else { // STATE_INIT or STATE_CANCEL // Math worst case: // MAX * MAX_BEFORE_SQUARE currencyValue = _quantityToSell.mul(reserve); // Math: FAIR blocks initReserve from being burned unless we reach the RUN state which prevents an underflow currencyValue /= totalSupply() - initReserve; } return currencyValue; } function _sell( address _from, address payable _to, uint _quantityToSell, uint _minCurrencyReturned ) internal { require(_from != beneficiary || state >= STATE_CLOSE, "BENEFICIARY_ONLY_SELL_IN_CLOSE_OR_CANCEL"); require(_minCurrencyReturned > 0, "MUST_SELL_AT_LEAST_1"); uint currencyValue = estimateSellValue(_quantityToSell); require(currencyValue >= _minCurrencyReturned, "PRICE_SLIPPAGE"); if(state == STATE_INIT || state == STATE_CANCEL) { initInvestors[_from] = initInvestors[_from].sub(_quantityToSell); } _burn(_from, _quantityToSell, true); uint supply = totalSupply() + burnedSupply; if(supply < initReserve) { initReserve = supply; } _transferCurrency(_to, currencyValue); emit Sell(_from, _to, currencyValue, _quantityToSell); } /// @notice Sell FAIR tokens for at least the given amount of currency. /// @param _to The account to receive the currency from this sale. /// @param _quantityToSell How many FAIR tokens to sell for currency value. /// @param _minCurrencyReturned Get at least this many currency tokens or the transaction reverts. /// @dev _minCurrencyReturned is necessary as the price will change if some elses transaction mines after /// yours was submitted. function sell( address payable _to, uint _quantityToSell, uint _minCurrencyReturned ) public { _sell(msg.sender, _to, _quantityToSell, _minCurrencyReturned); } /// @notice Allow users to sign a message authorizing a sell function permitSell( address _from, address payable _to, uint _quantityToSell, uint _minCurrencyReturned, uint _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external { require(_deadline >= block.timestamp, "EXPIRED"); bytes32 digest = keccak256(abi.encode(PERMIT_SELL_TYPEHASH, _from, _to, _quantityToSell, _minCurrencyReturned, nonces[_from]++, _deadline)); digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, digest ) ); address recoveredAddress = ecrecover(digest, _v, _r, _s); require(recoveredAddress != address(0) && recoveredAddress == _from, "INVALID_SIGNATURE"); _sell(_from, _to, _quantityToSell, _minCurrencyReturned); } /// Close /// @notice Called by the beneficiary account to STATE_CLOSE or STATE_CANCEL the c-org, /// preventing any more tokens from being minted. /// @dev Requires an `exitFee` to be paid. If the currency is ETH, include a little more than /// what appears to be required and any remainder will be returned to your account. This is /// because another user may have a transaction mined which changes the exitFee required. /// For other `currency` types, the beneficiary account will be billed the exact amount required. function _close() internal { require(msg.sender == beneficiary, "BENEFICIARY_ONLY"); if(state == STATE_INIT) { // Allow the org to cancel anytime if the initGoal was not reached. emit StateChange(state, STATE_CANCEL); state = STATE_CANCEL; } else if(state == STATE_RUN) { // Collect the exitFee and close the c-org. require(MAX_UINT - minDuration > __startedOn, "MAY_NOT_CLOSE"); require(minDuration + __startedOn <= block.timestamp, "TOO_EARLY"); emit StateChange(state, STATE_CLOSE); state = STATE_CLOSE; } else { revert("INVALID_STATE"); } } // --- Approve by signature --- // EIP-2612 // Original source: https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol function permit( address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s ) external { require(deadline >= block.timestamp, "EXPIRED"); bytes32 digest = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)); digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, digest ) ); address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNATURE"); _approve(owner, spender, value); } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return "Vision Token"; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return "VISION"; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return 18; } uint256[50] private __gap; } /** * @title Decentralized Autonomous Trust * This contract is the reference implementation provided by Fairmint for a * Decentralized Autonomous Trust as described in the continuous * organization whitepaper (https://github.com/c-org/whitepaper) and * specified here: https://github.com/fairmint/c-org/wiki. Use at your own * risk. If you have question or if you're looking for a ready-to-use * solution using this contract, you might be interested in Fairmint's * offering. Do not hesitate to get in touch with us: https://fairmint.co */ contract VisionToken is ContinuousOffering { event Close(uint _exitFee); event Pay(address indexed _from, uint _currencyValue); event UpdateConfig( address _whitelistAddress, address indexed _beneficiary, address indexed _control, address indexed _feeCollector, uint _revenueCommitmentBasisPoints, uint _feeBasisPoints, uint _minInvestment, uint _minDuration ); /// @notice The revenue commitment of the organization. Defines the percentage of the value paid through the contract /// that is automatically funneled and held into the buyback_reserve expressed in basis points. /// Internal since this is n/a to all derivative contracts. function revenueCommitmentBasisPoints() public view returns (uint) { return __revenueCommitmentBasisPoints; } /// @notice The investment reserve of the c-org. Defines the percentage of the value invested that is /// automatically funneled and held into the buyback_reserve expressed in basis points. /// Internal since this is n/a to all derivative contracts. function investmentReserveBasisPoints() public view returns (uint) { return __investmentReserveBasisPoints; } /// @notice Initialized at `0` and updated when the contract switches from `init` state to `run` state /// with the current timestamp. function runStartedOn() public view returns (uint) { return __startedOn; } function initialize( uint _initReserve, address _currencyAddress, uint _initGoal, uint _buySlopeNum, uint _buySlopeDen, uint _investmentReserveBasisPoints, uint _setupFee, address payable _setupFeeRecipient ) public { // _initialize will enforce this is only called once super._initialize( _initReserve, _currencyAddress, _initGoal, _buySlopeNum, _buySlopeDen, _setupFee, _setupFeeRecipient ); // Set initGoal, which in turn defines the initial state if(_initGoal == 0) { emit StateChange(state, STATE_RUN); state = STATE_RUN; __startedOn = block.timestamp; } else { // Math: If this value got too large, the DAT would overflow on sell require(_initGoal < MAX_SUPPLY, "EXCESSIVE_GOAL"); initGoal = _initGoal; } // 100% or less require(_investmentReserveBasisPoints <= BASIS_POINTS_DEN, "INVALID_RESERVE"); __investmentReserveBasisPoints = _investmentReserveBasisPoints; } /// Close function estimateExitFee(uint _msgValue) public view returns (uint) { uint exitFee; if (state == STATE_RUN) { uint reserve = buybackReserve(); reserve = reserve.sub(_msgValue); // Source: t*(t+b)*(n/d)-r // Implementation: (b n t)/d + (n t^2)/d - r uint _totalSupply = totalSupply(); // Math worst case: // MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE/2 * MAX_BEFORE_SQUARE exitFee = BigDiv.bigDiv2x1( _totalSupply, burnedSupply * buySlopeNum, buySlopeDen ); // Math worst case: // MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE * MAX_BEFORE_SQUARE exitFee += BigDiv.bigDiv2x1( _totalSupply, buySlopeNum * _totalSupply, buySlopeDen ); // Math: this if condition avoids a potential overflow if (exitFee <= reserve) { exitFee = 0; } else { exitFee -= reserve; } } return exitFee; } /// @notice Called by the beneficiary account to STATE_CLOSE or STATE_CANCEL the c-org, /// preventing any more tokens from being minted. /// @dev Requires an `exitFee` to be paid. If the currency is ETH, include a little more than /// what appears to be required and any remainder will be returned to your account. This is /// because another user may have a transaction mined which changes the exitFee required. /// For other `currency` types, the beneficiary account will be billed the exact amount required. function close() public payable { uint exitFee = 0; if (state == STATE_RUN) { exitFee = estimateExitFee(msg.value); _collectInvestment(msg.sender, exitFee, msg.value, true); } super._close(); emit Close(exitFee); } /// Pay /// @dev Pay the organization on-chain. /// @param _currencyValue How much currency which was paid. function pay(uint _currencyValue) public payable { _collectInvestment(msg.sender, _currencyValue, msg.value, false); require(state == STATE_RUN, "INVALID_STATE"); require(_currencyValue > 0, "MISSING_CURRENCY"); // Send a portion of the funds to the beneficiary, the rest is added to the buybackReserve // Math: if _currencyValue is < (2^256 - 1) / 10000 this will not overflow uint reserve = _currencyValue.mul(__revenueCommitmentBasisPoints); reserve /= BASIS_POINTS_DEN; // Math: this will never underflow since revenueCommitmentBasisPoints is capped to BASIS_POINTS_DEN _transferCurrency(beneficiary, _currencyValue - reserve); emit Pay(msg.sender, _currencyValue); } /// @notice Pay the organization on-chain without minting any tokens. /// @dev This allows you to add funds directly to the buybackReserve. function() external payable { require(address(currency) == address(0), "ONLY_FOR_CURRENCY_ETH"); } function updateConfig( address _whitelistAddress, address payable _beneficiary, address _control, address payable _feeCollector, uint _feeBasisPoints, uint _revenueCommitmentBasisPoints, uint _minInvestment, uint _minDuration ) public { _updateConfig( _whitelistAddress, _beneficiary, _control, _feeCollector, _feeBasisPoints, _minInvestment, _minDuration ); require( _revenueCommitmentBasisPoints <= BASIS_POINTS_DEN, "INVALID_COMMITMENT" ); require( _revenueCommitmentBasisPoints >= __revenueCommitmentBasisPoints, "COMMITMENT_MAY_NOT_BE_REDUCED" ); __revenueCommitmentBasisPoints = _revenueCommitmentBasisPoints; emit UpdateConfig( _whitelistAddress, _beneficiary, _control, _feeCollector, _revenueCommitmentBasisPoints, _feeBasisPoints, _minInvestment, _minDuration ); } /// @notice A temporary function to set `runStartedOn`, to be used by contracts which were /// already deployed before this feature was introduced. /// @dev This function will be removed once known users have called the function. function initializeRunStartedOn( uint _runStartedOn ) external { require(msg.sender == control, "CONTROL_ONLY"); require(state == STATE_RUN, "ONLY_CALL_IN_RUN"); require(__startedOn == 0, "ONLY_CALL_IF_NOT_AUTO_SET"); require(_runStartedOn <= block.timestamp, "DATE_MUST_BE_IN_PAST"); __startedOn = _runStartedOn; } /// @dev Distributes _value currency between the buybackReserve, beneficiary, and feeCollector. function _distributeInvestment( uint _value ) internal { // Rounding favors buybackReserve, then beneficiary, and feeCollector is last priority. // Math: if investment value is < (2^256 - 1) / 10000 this will never overflow. // Except maybe with a huge single investment, but they can try again with multiple smaller investments. uint reserve = __investmentReserveBasisPoints.mul(_value); reserve /= BASIS_POINTS_DEN; reserve = _value.sub(reserve); uint fee = reserve.mul(feeBasisPoints); fee /= BASIS_POINTS_DEN; // Math: since feeBasisPoints is <= BASIS_POINTS_DEN, this will never underflow. _transferCurrency(beneficiary, reserve - fee); _transferCurrency(feeCollector, fee); } }
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":false,"internalType":"uint256","name":"_fairValue","type":"uint256"}],"name":"Burn","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":"_currencyValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fairValue","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_exitFee","type":"uint256"}],"name":"Close","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_currencyValue","type":"uint256"}],"name":"Pay","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":"_currencyValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fairValue","type":"uint256"}],"name":"Sell","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previousState","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newState","type":"uint256"}],"name":"StateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_whitelistAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":true,"internalType":"address","name":"_control","type":"address"},{"indexed":true,"internalType":"address","name":"_feeCollector","type":"address"},{"indexed":false,"internalType":"uint256","name":"_revenueCommitmentBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_feeBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_minInvestment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_minDuration","type":"uint256"}],"name":"UpdateConfig","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_BUY_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_SELL_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"__startedOn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"burnedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_currencyValue","type":"uint256"},{"internalType":"uint256","name":"_minTokensBought","type":"uint256"}],"name":"buy","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"buySlopeDen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"buySlopeNum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"buybackReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"close","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"control","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currency","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_currencyValue","type":"uint256"}],"name":"estimateBuyValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_msgValue","type":"uint256"}],"name":"estimateExitFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_quantityToSell","type":"uint256"}],"name":"estimateSellValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initGoal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"initInvestors","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"initReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_initReserve","type":"uint256"},{"internalType":"address","name":"_currencyAddress","type":"address"},{"internalType":"uint256","name":"_initGoal","type":"uint256"},{"internalType":"uint256","name":"_buySlopeNum","type":"uint256"},{"internalType":"uint256","name":"_buySlopeDen","type":"uint256"},{"internalType":"uint256","name":"_investmentReserveBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_setupFee","type":"uint256"},{"internalType":"address payable","name":"_setupFeeRecipient","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"cap","type":"uint256"},{"internalType":"address","name":"sender","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"initializeDomainSeparator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_runStartedOn","type":"uint256"}],"name":"initializeRunStartedOn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"investmentReserveBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minInvestment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_currencyValue","type":"uint256"}],"name":"pay","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_currencyValue","type":"uint256"},{"internalType":"uint256","name":"_minTokensBought","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permitBuy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_quantityToSell","type":"uint256"},{"internalType":"uint256","name":"_minCurrencyReturned","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permitSell","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"revenueCommitmentBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"runStartedOn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_quantityToSell","type":"uint256"},{"internalType":"uint256","name":"_minCurrencyReturned","type":"uint256"}],"name":"sell","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"setupFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"setupFeeRecipient","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_whitelistAddress","type":"address"},{"internalType":"address payable","name":"_beneficiary","type":"address"},{"internalType":"address","name":"_control","type":"address"},{"internalType":"address payable","name":"_feeCollector","type":"address"},{"internalType":"uint256","name":"_feeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_revenueCommitmentBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_minInvestment","type":"uint256"},{"internalType":"uint256","name":"_minDuration","type":"uint256"}],"name":"updateConfig","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"whitelist","outputs":[{"internalType":"contract IWhitelist","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052615791806100136000396000f3fe6080604052600436106103ef5760003560e01c806382dc1ec411610208578063af575ab711610118578063c7159307116100ab578063d9cce5261161007a578063d9cce52614610e1b578063da35a26f14610e7d578063dd62ed3e14610eb6578063e5a6b10f14610ef1578063ff90956014610f06576103ef565b8063c715930714610d7e578063d29157fb14610d93578063d505accf14610da8578063d8de658714610e06576103ef565b8063c25b25bd116100e7578063c25b25bd14610d04578063c290d69114610d19578063c415b95c14610d36578063c4d66de814610d4b576103ef565b8063af575ab714610c4a578063b12f415314610cb0578063b8606eef14610cda578063c19d93fb14610cef576103ef565b80639df3f4f61161019b578063a59ac6dd1161016a578063a59ac6dd14610b82578063a71ddd2514610bb4578063a9059cbb14610bc9578063aa271e1a14610c02578063ad3b763314610c35576103ef565b80639df3f4f614610aba578063a40b56b914610acf578063a457c2d714610ae4578063a551bfc414610b1d576103ef565b806393e59dc1116101d757806393e59dc114610a4857806395d89b4114610a5d578063983b2d5614610a725780639865027514610aa5576103ef565b806382dc1ec4146109c15780638456cb59146109f4578063896d170814610a095780638ac2c68014610a33576103ef565b80633f4ba83a1161030357806358439fa5116102965780636ef8d66d116102655780636ef8d66d146108da57806370a08231146108ef578063736dcb1f1461092257806379cc6790146109555780637ecebe001461098e576103ef565b806358439fa51461085c5780635c975abb146108715780636177e37c146108865780636a2724621461089b576103ef565b806346fbf68e116102d257806346fbf68e146107ea57806354fd4d501461081d57806355d0a1d0146108325780635671576114610847576103ef565b80633f4ba83a1461076a57806340c10f191461077f57806342966c68146107b857806343d726d6146107e2576103ef565b80632e872bb311610386578063355274ea11610355578063355274ea146106c157806335e5cc31146106d65780633644e515146106eb57806338af3eed146107005780633950935114610731576103ef565b80632e872bb3146106425780632ff791611461066c57806330adf81f14610681578063313ce56714610696576103ef565b806323b872dd116103c257806323b872dd1461055b578063263154381461059e578063270588ee146105b35780632973434a14610618576103ef565b806306fdde0314610448578063095ea7b3146104d257806318160ddd1461051f5780631d833ec514610546575b61019e546001600160a01b031615610446576040805162461bcd60e51b815260206004820152601560248201527409e9c98b2be8c9ea4be86aaa4a48a9c86b2be8aa89605b1b604482015290519081900360640190fd5b005b34801561045457600080fd5b5061045d610f1b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049757818101518382015260200161047f565b50505050905090810190601f1680156104c45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104de57600080fd5b5061050b600480360360408110156104f557600080fd5b506001600160a01b038135169060200135610f42565b604080519115158252519081900360200190f35b34801561052b57600080fd5b50610534610fa3565b60408051918252519081900360200190f35b34801561055257600080fd5b50610534610fa9565b34801561056757600080fd5b5061050b6004803603606081101561057e57600080fd5b506001600160a01b03813581169160208101359091169060400135610fcd565b3480156105aa57600080fd5b50610534611030565b3480156105bf57600080fd5b5061044660048036036101008110156105d757600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060ff60a0820135169060c08101359060e00135611037565b34801561062457600080fd5b506104466004803603602081101561063b57600080fd5b503561122e565b34801561064e57600080fd5b506105346004803603602081101561066557600080fd5b5035611370565b34801561067857600080fd5b506104466114fb565b34801561068d57600080fd5b506105346115a0565b3480156106a257600080fd5b506106ab6115c4565b6040805160ff9092168252519081900360200190f35b3480156106cd57600080fd5b506105346115c9565b3480156106e257600080fd5b506105346115d0565b3480156106f757600080fd5b506105346115d7565b34801561070c57600080fd5b506107156115de565b604080516001600160a01b039092168252519081900360200190f35b34801561073d57600080fd5b5061050b6004803603604081101561075457600080fd5b506001600160a01b0381351690602001356115f3565b34801561077657600080fd5b5061044661164b565b34801561078b57600080fd5b5061050b600480360360408110156107a257600080fd5b506001600160a01b038135169060200135611734565b3480156107c457600080fd5b50610446600480360360208110156107db57600080fd5b5035611794565b6104466117a3565b3480156107f657600080fd5b5061050b6004803603602081101561080d57600080fd5b50356001600160a01b0316611808565b34801561082957600080fd5b5061045d61181b565b34801561083e57600080fd5b50610534611838565b34801561085357600080fd5b5061053461183f565b34801561086857600080fd5b50610534611846565b34801561087d57600080fd5b5061050b61184d565b34801561089257600080fd5b50610534611856565b3480156108a757600080fd5b50610446600480360360608110156108be57600080fd5b506001600160a01b03813516906020810135906040013561185d565b3480156108e657600080fd5b5061044661186e565b3480156108fb57600080fd5b506105346004803603602081101561091257600080fd5b50356001600160a01b0316611880565b34801561092e57600080fd5b506105346004803603602081101561094557600080fd5b50356001600160a01b031661189b565b34801561096157600080fd5b506104466004803603604081101561097857600080fd5b506001600160a01b0381351690602001356118ae565b34801561099a57600080fd5b50610534600480360360208110156109b157600080fd5b50356001600160a01b03166118fc565b3480156109cd57600080fd5b50610446600480360360208110156109e457600080fd5b50356001600160a01b031661190f565b348015610a0057600080fd5b5061044661195e565b348015610a1557600080fd5b5061053460048036036020811015610a2c57600080fd5b5035611a25565b348015610a3f57600080fd5b50610534611aac565b348015610a5457600080fd5b50610715611ab3565b348015610a6957600080fd5b5061045d611ac3565b348015610a7e57600080fd5b5061044660048036036020811015610a9557600080fd5b50356001600160a01b0316611ae3565b348015610ab157600080fd5b50610446611b32565b348015610ac657600080fd5b50610534611b42565b348015610adb57600080fd5b50610534611b49565b348015610af057600080fd5b5061050b60048036036040811015610b0757600080fd5b506001600160a01b038135169060200135611b50565b348015610b2957600080fd5b506104466004803603610100811015610b4157600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060ff60a0820135169060c08101359060e00135611ba8565b61044660048036036060811015610b9857600080fd5b506001600160a01b038135169060208101359060400135611d93565b348015610bc057600080fd5b50610534611d9f565b348015610bd557600080fd5b5061050b60048036036040811015610bec57600080fd5b506001600160a01b038135169060200135611da6565b348015610c0e57600080fd5b5061050b60048036036020811015610c2557600080fd5b50356001600160a01b0316611dfe565b348015610c4157600080fd5b50610534611e12565b348015610c5657600080fd5b506104466004803603610100811015610c6e57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a08101359060c08101359060e00135611e19565b348015610cbc57600080fd5b5061053460048036036020811015610cd357600080fd5b5035611f40565b348015610ce657600080fd5b50610534612060565b348015610cfb57600080fd5b50610534612067565b348015610d1057600080fd5b5061071561206e565b61044660048036036020811015610d2f57600080fd5b503561207e565b348015610d4257600080fd5b50610715612193565b348015610d5757600080fd5b5061044660048036036020811015610d6e57600080fd5b50356001600160a01b03166121a3565b348015610d8a57600080fd5b5061053461224e565b348015610d9f57600080fd5b50610534612255565b348015610db457600080fd5b50610446600480360360e0811015610dcb57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612279565b348015610e1257600080fd5b50610715612466565b348015610e2757600080fd5b506104466004803603610100811015610e3f57600080fd5b508035906001600160a01b03602082013581169160408101359160608201359160808101359160a08201359160c08101359160e09091013516612476565b348015610e8957600080fd5b5061044660048036036040811015610ea057600080fd5b50803590602001356001600160a01b0316612578565b348015610ec257600080fd5b5061053460048036036040811015610ed957600080fd5b506001600160a01b0381358116916020013516612677565b348015610efd57600080fd5b506107156126a2565b348015610f1257600080fd5b506105346126b2565b60408051808201909152600c81526b2b34b9b4b7b7102a37b5b2b760a11b60208201525b90565b609b5460009060ff1615610f90576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383612768565b90505b92915050565b60355490565b7faf42a244b3020d6a2253d9f291b4d3e82240da42b22129a8113a58aa7a3ddb6a81565b609b5460009060ff161561101b576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b61102684848461277c565b90505b9392505050565b6101a15481565b42841015611076576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380891660008181526101a9602090815260408083208054600180820190925582517faf42a244b3020d6a2253d9f291b4d3e82240da42b22129a8113a58aa7a3ddb6a8186015280840196909652958d166060860152608085018c905260a085018b905260c085019590955260e08085018a905281518086039091018152610100850182528051908301206101aa5461190160f01b6101208701526101228601526101428086019190915281518086039091018152610162850180835281519184019190912090849052610182850180835281905260ff89166101a28601526101c285018890526101e285018790529051909492936102028082019392601f1981019281900390910190855afa15801561119b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906111d15750896001600160a01b0316816001600160a01b0316145b611216576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6112228a8a8a8a612804565b50505050505050505050565b61019d546001600160a01b0316331461127d576040805162461bcd60e51b815260206004820152600c60248201526b434f4e54524f4c5f4f4e4c5960a01b604482015290519081900360640190fd5b60016101a854146112c8576040805162461bcd60e51b815260206004820152601060248201526f27a7262cafa1a0a6262fa4a72fa92aa760811b604482015290519081900360640190fd5b6101ae541561131e576040805162461bcd60e51b815260206004820152601960248201527f4f4e4c595f43414c4c5f49465f4e4f545f4155544f5f53455400000000000000604482015290519081900360640190fd5b4281111561136a576040805162461bcd60e51b81526020600482015260146024820152731110551157d35554d517d09157d25397d41054d560621b604482015290519081900360640190fd5b6101ae55565b60006101a654821015611385575060006114f6565b6000806101a854141561147a5782600061139d610fa3565b905060006113c161019b546101a15402836101a3546101a154010361019c54612aa8565b9050808311156113cf578092505b6113e58361019c5461019b546101a15402612aa8565b93508583146114725761019c54818703935060020261140a818563ffffffff612c3116565b6101a15461019b549195508002915061142a90829063ffffffff612c3116565b905061143c848263ffffffff612c8a16565b905061019b54818161144a57fe5b04905061145681612ce4565b6101a1549003905061146e858263ffffffff612c8a16565b9450505b5050506114f3565b60016101a85414156114e95760006101a35461019954611498610fa3565b010390506114b08461019c5460020261019b54612aa8565b91506114c48282800263ffffffff612c8a16565b91506114cf82612ce4565b91506114e1828263ffffffff612d5316565b9150506114f3565b60009150506114f6565b90505b919050565b604051469080605261554d82396052019050604051809103902061151d610f1b565b805160209182012060408051808201825260018152603360f81b90840152805180840194909452838101919091527f2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de606084015260808301939093523060a0808401919091528351808403909101815260c090920190925280519101206101aa55565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601290565b6101655490565b61019b5481565b6101aa5481565b61019a5461010090046001600160a01b031681565b609b5460009060ff1615611641576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383612d95565b61165b611656612de9565b611808565b6116965760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b609b5460ff166116e4576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b609b805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611717612de9565b604080516001600160a01b039092168252519081900360200190a1565b6000611746611741612de9565b611dfe565b6117815760405162461bcd60e51b81526004018080602001828103825260308152602001806154fc6030913960400191505060405180910390fd5b61178b8383612ded565b50600192915050565b6117a0338260006131db565b50565b6101a854600090600114156117ca576117bb34611a25565b90506117ca33823460016135f3565b6117d26136ed565b6040805182815290517fbf67515a38ee520223d32c1266d52101c30d936ed1f3e436c8caeb0a43cb06bf9181900360200190a150565b60006114f360688363ffffffff61389816565b604051806040016040528060018152602001603360f81b81525081565b6101995481565b6101ad5481565b61019c5481565b609b5460ff1690565b6101a75490565b611869338484846138ff565b505050565b61187e611879612de9565b613af1565b565b6001600160a01b031660009081526033602052604090205490565b6101a26020526000908152604090205481565b6118ec82336118e784604051806060016040528060248152602001615658602491396118da8833612677565b919063ffffffff613b3916565b613bd0565b6118f8828260006131db565b5050565b6101a96020526000908152604090205481565b61191a611656612de9565b6119555760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b6117a081613cbc565b611969611656612de9565b6119a45760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b609b5460ff16156119ef576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b609b805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611717612de9565b60008060016101a85414156114f3576000611a3e6126b2565b9050611a50818563ffffffff612d5316565b90506000611a5c610fa3565b9050611a748161019b54610199540261019c54612aa8565b9250611a89818261019b540261019c54612aa8565b83019250818311611a9d5760009250611aa3565b81830392505b50509050919050565b6101a65481565b610198546001600160a01b031681565b6040805180820190915260068152652b24a9a4a7a760d11b602082015290565b611aee611741612de9565b611b295760405162461bcd60e51b81526004018080602001828103825260308152602001806154fc6030913960400191505060405180910390fd5b6117a081613d04565b61187e611b3d612de9565b613d4d565b6101a45490565b6101ab5481565b609b5460009060ff1615611b9e576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383613d96565b42841015611be7576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380891660008181526101a9602090815260408083208054600180820190925582517f5dfdc7fb4c68a4c249de5e08597626b84fbbe7bfef4ed3500f58003e722cc5488186015280840196909652958d166060860152608085018c905260a085018b905260c085019590955260e08085018a905281518086039091018152610100850182528051908301206101aa5461190160f01b6101208701526101228601526101428086019190915281518086039091018152610162850180835281519184019190912090849052610182850180835281905260ff89166101a28601526101c285018890526101e285018790529051909492936102028082019392601f1981019281900390910190855afa158015611d0c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611d425750896001600160a01b0316816001600160a01b0316145b611d87576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6112228a8a8a8a6138ff565b61186933848484612804565b6101a35481565b609b5460009060ff1615611df4576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383613e04565b60006114f36101008363ffffffff61389816565b6101ae5481565b611e2888888888888787613e18565b612710831115611e74576040805162461bcd60e51b81526020600482015260126024820152711253959053125117d0d3d35352551351539560721b604482015290519081900360640190fd5b6101a754831015611ecc576040805162461bcd60e51b815260206004820152601d60248201527f434f4d4d49544d454e545f4d41595f4e4f545f42455f52454455434544000000604482015290519081900360640190fd5b6101a7839055604080516001600160a01b038a8116825260208201869052818301879052606082018590526080820184905291518288169289811692908b16917fab33ca83001031840bf8a88b6a384c984aeb1ffcfebc562f13dab66a81306f969181900360a00190a45050505050505050565b600080611f4b6126b2565b9050600060016101a8541415611ffa57600061019954611f69610fa3565b019050611f95611f7f868563ffffffff612c3116565b610199548002611f8d610fa3565b848502614190565b91506000611fac866002860263ffffffff612c3116565b9050818181611fb757fe5b04928301929050611fda611fd1878063ffffffff612c3116565b8584850261433c565b905080831115611fee578083039250611ff3565b600092505b5050611029565b60026101a854141561203057612016848363ffffffff612c3116565b9050612020610fa3565b818161202857fe5b049050611029565b612040848363ffffffff612c3116565b90506101a35461204e610fa3565b03818161205757fe5b04949350505050565b6101a05481565b6101a85481565b6101ac546001600160a01b031681565b61208b33823460006135f3565b60016101a854146120d3576040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b6000811161211b576040805162461bcd60e51b815260206004820152601060248201526f4d495353494e475f43555252454e435960801b604482015290519081900360640190fd5b60006121336101a75483612c3190919063ffffffff16565b61019a5461271090910491506121599061010090046001600160a01b0316828403614387565b60408051838152905133917f357b676c439b9e49b4410f8eb8680bee4223724802d8e3fd422e1756f87b475f919081900360200190a25050565b61019f546001600160a01b031681565b600054610100900460ff16806121bc57506121bc6143cb565b806121ca575060005460ff16155b6122055760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff16158015612230576000805460ff1961ff0019909116610100171660011790555b612239826143d1565b80156118f8576000805461ff00191690555050565b6101ae5490565b7f5dfdc7fb4c68a4c249de5e08597626b84fbbe7bfef4ed3500f58003e722cc54881565b428410156122b8576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380881660008181526101a9602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e0850182528051908301206101aa5461190160f01b6101008701526101028601526101228086019190915281518086039091018152610142850180835281519184019190912090849052610162850180835281905260ff89166101828601526101a285018890526101c285018790529051909492936101e28082019392601f1981019281900390910190855afa1580156123d5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061240b5750886001600160a01b0316816001600160a01b0316145b612450576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b61245b898989613bd0565b505050505050505050565b61019d546001600160a01b031681565b61248588888888888787614474565b856124c6576101a8546040805191825260016020830152805160008051602061559f8339815191529281900390910190a160016101a855426101ae55612522565b6f4b3b4ca85a86c47a098a224000000000861061251b576040805162461bcd60e51b815260206004820152600e60248201526d115610d154d4d2559157d1d3d05360921b604482015290519081900360640190fd5b6101a18690555b61271083111561256b576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5245534552564560881b604482015290519081900360640190fd5b50506101a4555050505050565b600054610100900460ff168061259157506125916143cb565b8061259f575060005460ff16155b6125da5760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff16158015612605576000805460ff1961ff0019909116610100171660011790555b61260e826121a3565b6000831161265b576040805162461bcd60e51b8152602060048201526015602482015274045524332304361707065643a20636170206973203605c1b604482015290519081900360640190fd5b6101658390558015611869576000805461ff0019169055505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61019e546001600160a01b031681565b61019e5460009047906001600160a01b0316156127445761019e54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d602081101561273f57600080fd5b505190505b6001600160801b03811115612763576001600160801b03915050610f3f565b905090565b600061178b612775612de9565b8484613bd0565b600061278984848461482e565b6127fa84612795612de9565b6118e7856040518060600160405280602881526020016155e0602891396001600160a01b038a166000908152603460205260408120906127d3612de9565b6001600160a01b03168152602081019190915260400160002054919063ffffffff613b3916565b5060019392505050565b6001600160a01b038316612851576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000811161289c576040805162461bcd60e51b81526020600482015260136024820152724d5553545f4255595f41545f4c454153545f3160681b604482015290519081900360640190fd5b60006128a783611370565b9050818110156128ef576040805162461bcd60e51b815260206004820152600e60248201526d50524943455f534c49505041474560901b604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b03167f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e8584604051808381526020018281526020019250505060405180910390a361294f85843460006135f3565b6101a854612a73576001600160a01b03841660009081526101a2602052604090208054820190556101a1546101a35482612987610fa3565b010310612a6e576101a8546040805191825260016020830152805160008051602061559f8339815191529281900390910190a160016101a8556101ae546129ce57426101ae555b61019a5461010090046001600160a01b031660009081526101a260205260408120546101a15461019b5461019c54612a0b93929190910290612aa8565b6101ab5490915015612a4c576101ac546101ab54612a32916001600160a01b031690614387565b6101ab54811115612a48576101ab549003612a4c565b5060005b612a6c612a6782612a5b6126b2565b9063ffffffff612d5316565b614b62565b505b612a97565b61019a546001600160a01b038581166101009092041614612a9757612a9783614b62565b612aa18482612ded565b5050505050565b6000831580612ab5575082155b15612ac257506000611029565b6000838560001981612ad057fe5b0410612aed5750838302828181612ae357fe5b0491506110299050565b838581811115612afd5750859050845b848281612b0657fe5b0492506305f5e100831115612b3057612b25838263ffffffff612c3116565b935061102992505050565b60001981016001600160801b038104600101905060001983016001600160801b0381046001019050808260001981612b6457fe5b0410612bd45790810290818481612b7757fe5b049450630bebc200851115612bd457612b96858463ffffffff612c3116565b9450506000198601818181612ba757fe5b049050612bbb81600163ffffffff612c8a16565b9050808581612bc657fe5b049550611029945050505050565b60016001600160801b03600019850104019150818381612bf057fe5b049450506000198601818181612c0257fe5b046001019050808481612c1157fe5b049050612c24858263ffffffff612c3116565b9998505050505050505050565b600082612c4057506000610f9d565b82820282848281612c4d57fe5b0414610f9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806155bf6021913960400191505060405180910390fd5b600082820183811015610f9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081612cf3575060006114f6565b60038211612d03575060016114f6565b600019821415612d1b57506001600160801b036114f6565b5080600260018201045b81811015612d4d57809150600281828581612d3c57fe5b040181612d4557fe5b049050612d25565b50919050565b6000610f9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613b39565b600061178b612da2612de9565b846118e78560346000612db3612de9565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612c8a16565b3390565b610198546000908390839083906001600160a01b0316156130a157610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b158015612e5857600080fd5b505af1158015612e6c573d6000803e3d6000fd5b505050506040513d6020811015612e8257600080fd5b5051158015612e9957506001600160a01b03841615155b8015612eb757506001600160a01b038316158015612eb5575080155b155b15612f245761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b158015612f0b57600080fd5b505af1158015612f1f573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b158015612f7457600080fd5b505af1158015612f88573d6000803e3d6000fd5b505050506040513d6020811015612f9e57600080fd5b5051158015612fb557506001600160a01b03831615155b156130225761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b15801561300957600080fd5b505af115801561301d573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b15801561308857600080fd5b505af115801561309c573d6000803e3d6000fd5b505050505b6130ab8686614be1565b6f4b3b4ca85a86c47a098a2240000000006130d7610199546130cb610fa3565b9063ffffffff612c8a16565b111561311d576040805162461bcd60e51b815260206004820152601060248201526f4558434553534956455f535550504c5960801b604482015290519081900360640190fd5b610198546001600160a01b0316156131d35761313884611880565b15801561314d57506001600160a01b03841615155b801561316b57506001600160a01b038316158015613169575080155b155b156131d3576101985460408051630b3ffd1d60e01b81526001600160a01b03878116600483015291519190921691630b3ffd1d91602480830192600092919082900301818387803b1580156131bf57600080fd5b505af1158015611222573d6000803e3d6000fd5b505050505050565b610198548390600090849084906001600160a01b03161561348f57610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561324657600080fd5b505af115801561325a573d6000803e3d6000fd5b505050506040513d602081101561327057600080fd5b505115801561328757506001600160a01b03841615155b80156132a557506001600160a01b0383161580156132a3575080155b155b156133125761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b1580156132f957600080fd5b505af115801561330d573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561336257600080fd5b505af1158015613376573d6000803e3d6000fd5b505050506040513d602081101561338c57600080fd5b50511580156133a357506001600160a01b03831615155b156134105761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b1580156133f757600080fd5b505af115801561340b573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b15801561347657600080fd5b505af115801561348a573d6000803e3d6000fd5b505050505b6134998787614c4e565b8461352f5760016101a854146134e6576040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b6101998054870190556040805187815290516001600160a01b038916917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a25b610198546001600160a01b0316156135ea5761354a84611880565b15801561355f57506001600160a01b03841615155b801561357d57506001600160a01b03831615801561357b575080155b155b156135ea576101985460408051630b3ffd1d60e01b81526001600160a01b03878116600483015291519190921691630b3ffd1d91602480830192600092919082900301818387803b1580156135d157600080fd5b505af11580156135e5573d6000803e3d6000fd5b505050505b50505050505050565b61019e546001600160a01b031661368357801561363457600061361c838563ffffffff612d5316565b9050801561362e5761362e3382614d4a565b5061367e565b81831461367e576040805162461bcd60e51b8152602060048201526013602482015272494e434f52524543545f4d53475f56414c554560681b604482015290519081900360640190fd5b6136e7565b81156136c8576040805162461bcd60e51b815260206004820152600f60248201526e0889ebe9c9ea8bea68a9c88be8aa89608b1b604482015290519081900360640190fd5b61019e546136e7906001600160a01b031685308663ffffffff614e2f16565b50505050565b61019a5461010090046001600160a01b03163314613745576040805162461bcd60e51b815260206004820152601060248201526f42454e45464943494152595f4f4e4c5960801b604482015290519081900360640190fd5b6101a854613784576101a8546040805191825260036020830152805160008051602061559f8339815191529281900390910190a160036101a85561187e565b60016101a854141561385b576101ae546101ad5419116137db576040805162461bcd60e51b815260206004820152600d60248201526c4d41595f4e4f545f434c4f534560981b604482015290519081900360640190fd5b426101ae546101ad54011115613824576040805162461bcd60e51b8152602060048201526009602482015268544f4f5f4541524c5960b81b604482015290519081900360640190fd5b6101a8546040805191825260026020830152805160008051602061559f8339815191529281900390910190a160026101a85561187e565b6040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b60006001600160a01b0382166138df5760405162461bcd60e51b81526004018080602001828103825260228152602001806156086022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b61019a546001600160a01b0385811661010090920416141580613926575060026101a85410155b6139615760405162461bcd60e51b815260040180806020018281038252602881526020018061567c6028913960400191505060405180910390fd5b600081116139ad576040805162461bcd60e51b81526020600482015260146024820152734d5553545f53454c4c5f41545f4c454153545f3160601b604482015290519081900360640190fd5b60006139b883611f40565b905081811015613a00576040805162461bcd60e51b815260206004820152600e60248201526d50524943455f534c49505041474560901b604482015290519081900360640190fd5b6101a8541580613a13575060036101a854145b15613a5d576001600160a01b03851660009081526101a26020526040902054613a42908463ffffffff612d5316565b6001600160a01b03861660009081526101a260205260409020555b613a69858460016131db565b600061019954613a77610fa3565b0190506101a354811015613a8c576101a38190555b613a968583614387565b846001600160a01b0316866001600160a01b03167fa082022e93cfcd9f1da5f9236718053910f7e840da080c789c7845698dc032ff8487604051808381526020018281526020019250505060405180910390a3505050505050565b613b0260688263ffffffff614e8916565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b60008184841115613bc85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613b8d578181015183820152602001613b75565b50505050905090810190601f168015613bba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316613c155760405162461bcd60e51b81526004018080602001828103825260248152602001806156ea6024913960400191505060405180910390fd5b6001600160a01b038216613c5a5760405162461bcd60e51b815260040180806020018281038252602281526020018061547a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613ccd60688263ffffffff614ef016565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b613d166101008263ffffffff614ef016565b6040516001600160a01b038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b613d5f6101008263ffffffff614e8916565b6040516001600160a01b038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b600061178b613da3612de9565b846118e7856040518060600160405280602581526020016157386025913960346000613dcd612de9565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff613b3916565b600061178b613e11612de9565b848461482e565b61019d546001600160a01b03163314613e67576040805162461bcd60e51b815260206004820152600c60248201526b434f4e54524f4c5f4f4e4c5960a01b604482015290519081900360640190fd5b61019880546001600160a01b0319166001600160a01b03898116919091179091558516613ecd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019d80546001600160a01b0319166001600160a01b03878116919091179091558416613f33576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019f80546001600160a01b0319166001600160a01b038616179055612710831115613f94576040805162461bcd60e51b815260206004820152600b60248201526a494e56414c49445f46454560a81b604482015290519081900360640190fd5b6101a083905581613fe5576040805162461bcd60e51b81526020600482015260166024820152751253959053125117d3525397d253959154d51351539560521b604482015290519081900360640190fd5b6101a68290556101ad54811015614043576040805162461bcd60e51b815260206004820152601f60248201527f4d494e5f4455524154494f4e5f4d41595f4e4f545f42455f5245445543454400604482015290519081900360640190fd5b6101ad81905561019a546001600160a01b0387811661010090920416146135ea576001600160a01b0386166140b1576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019a546000906140cf9061010090046001600160a01b0316611880565b61019a546001600160a01b03610100909104811660009081526101a2602052604080822054928b16825290205491925061410f919063ffffffff612c8a16565b6001600160a01b0380891660009081526101a260205260408082209390935561019a54610100900490911681529081205580156141635761019a546141639061010090046001600160a01b0316888361482e565b5061019a80546001600160a01b03881661010002610100600160a81b031990911617905550505050505050565b600081836000198161419e57fe5b04106141b8576141b18585848602612aa8565b9050614334565b8415806141c3575083155b156141d057506000614334565b8183818111156141e05750839050825b60008688600019816141ee57fe5b0410614219575086860281818161420157fe5b04905082818161420d57fe5b04935061433492505050565b8688818111156142295750889050875b600084838161423457fe5b049050630bebc20081111561425b5761424e818388612aa8565b9650505050505050614334565b506001600160801b03600019838101829004600190810192848301040190829082908161428457fe5b04106142ff57810280848161429557fe5b049450630bebc2008511156142ff576142b4858463ffffffff612c3116565b94508585816142bf57fe5b0494506000851180156142dd57508085600019816142d957fe5b0410155b156142ff57938402938685816142ef57fe5b0497506143349650505050505050565b5050600160801b85046001600160801b038504810261432a81858161432057fe5b0484600019612aa8565b9750505050505050505b949350505050565b60008061434a858585612aa8565b90508061435b576001915050611029565b60016305f5e10060001983010401811981111561437e5760001992505050611029565b01949350505050565b80156118f85761019e546001600160a01b03166143ad576143a88282614d4a565b6118f8565b61019e546118f8906001600160a01b0316838363ffffffff614f7116565b303b1590565b600054610100900460ff16806143ea57506143ea6143cb565b806143f8575060005460ff16155b6144335760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff1615801561445e576000805460ff1961ff0019909116610100171660011790555b61446782611dfe565b6122395761223982613d04565b6144896a0422ca8b0a00a42500000033612578565b61449233613cbc565b600084116144db576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f534c4f50455f4e554d60781b604482015290519081900360640190fd5b60008311614524576040805162461bcd60e51b815260206004820152601160248201527024a72b20a624a22fa9a627a822afa222a760791b604482015290519081900360640190fd5b6001600160801b038410614575576040805162461bcd60e51b81526020600482015260136024820152724558434553534956455f534c4f50455f4e554d60681b604482015290519081900360640190fd5b6001600160801b0383106145c6576040805162461bcd60e51b815260206004820152601360248201527222ac21a2a9a9a4ab22afa9a627a822afa222a760691b604482015290519081900360640190fd5b61019b84905561019c8390558115806145e757506001600160a01b03811615155b614638576040805162461bcd60e51b815260206004820152601b60248201527f4d495353494e475f53455455505f4645455f524543495049454e540000000000604482015290519081900360640190fd5b6001600160a01b038116158061464d57508115155b614692576040805162461bcd60e51b81526020600482015260116024820152704d495353494e475f53455455505f46454560781b604482015290519081900360640190fd5b8480026146a5818663ffffffff612c3116565b90508360020281816146b357fe5b04905080831115614701576040805162461bcd60e51b81526020600482015260136024820152724558434553534956455f53455455505f46454560681b604482015290519081900360640190fd5b6101ab8390556101ac80546001600160a01b0319166001600160a01b038481169190911790915560129088161561479d57876001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561476b57600080fd5b505afa15801561477f573d6000803e3d6000fd5b505050506040513d602081101561479557600080fd5b505160ff1690505b600a81900a6064026101a65561019a8054610100600160a81b0319163361010081029190911790915561019d80546001600160a01b0319908116831790915561019f8054821690921790915561019e80549091166001600160a01b038a161790558815614826576101a389905561019a546148269061010090046001600160a01b03168a612ded565b61245b6114fb565b610198548390839083906000906001600160a01b031615614ae257610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561489957600080fd5b505af11580156148ad573d6000803e3d6000fd5b505050506040513d60208110156148c357600080fd5b50511580156148da57506001600160a01b03841615155b80156148f857506001600160a01b0383161580156148f6575080155b155b156149655761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b15801561494c57600080fd5b505af1158015614960573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b1580156149b557600080fd5b505af11580156149c9573d6000803e3d6000fd5b505050506040513d60208110156149df57600080fd5b50511580156149f657506001600160a01b03831615155b15614a635761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b158015614a4a57600080fd5b505af1158015614a5e573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b158015614ac957600080fd5b505af1158015614add573d6000803e3d6000fd5b505050505b6101a854151580614b06575061019a546001600160a01b0388811661010090920416145b614b57576040805162461bcd60e51b815260206004820152601c60248201527f4f4e4c595f42454e45464943494152595f445552494e475f494e495400000000604482015290519081900360640190fd5b61352f878787614fc3565b6101a454600090614b79908363ffffffff612c3116565b61271090049050614b8a8282612d53565b90506000614ba46101a05483612c3190919063ffffffff16565b61019a546127109091049150614bca9061010090046001600160a01b0316828403614387565b61019f54611869906001600160a01b031682614387565b61016554614bf1826130cb610fa3565b1115614c44576040805162461bcd60e51b815260206004820152601960248201527f45524332304361707065643a2063617020657863656564656400000000000000604482015290519081900360640190fd5b6118f88282615121565b6001600160a01b038216614c935760405162461bcd60e51b81526004018080602001828103825260218152602001806156a46021913960400191505060405180910390fd5b614cd681604051806060016040528060228152602001615428602291396001600160a01b038516600090815260336020526040902054919063ffffffff613b3916565b6001600160a01b038316600090815260336020526040902055603554614d02908263ffffffff612d5316565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b80471015614d9f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114614dea576040519150601f19603f3d011682016040523d82523d6000602084013e614def565b606091505b50509050806118695760405162461bcd60e51b815260040180806020018281038252603a8152602001806154c2603a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526136e7908590615213565b614e938282613898565b614ece5760405162461bcd60e51b815260040180806020018281038252602181526020018061552c6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b614efa8282613898565b15614f4c576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611869908490615213565b6001600160a01b0383166150085760405162461bcd60e51b81526004018080602001828103825260258152602001806156c56025913960400191505060405180910390fd5b6001600160a01b03821661504d5760405162461bcd60e51b81526004018080602001828103825260238152602001806154056023913960400191505060405180910390fd5b6150908160405180606001604052806026815260200161549c602691396001600160a01b038616600090815260336020526040902054919063ffffffff613b3916565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546150c5908263ffffffff612c8a16565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6001600160a01b03821661517c576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b60355461518f908263ffffffff612c8a16565b6035556001600160a01b0382166000908152603360205260409020546151bb908263ffffffff612c8a16565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b615225826001600160a01b03166153cb565b615276576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106152b45780518252601f199092019160209182019101615295565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114615316576040519150601f19603f3d011682016040523d82523d6000602084013e61531b565b606091505b509150915081615372576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156136e75780806020019051602081101561538e57600080fd5b50516136e75760405162461bcd60e51b815260040180806020018281038252602a81526020018061570e602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061433457505015159291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c6545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429107dddb4541735557564238389eccfc9979bfdde5e57e24e9777b6fe79b4d22f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636542454e45464943494152595f4f4e4c595f53454c4c5f494e5f434c4f53455f4f525f43414e43454c45524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a723158203f15b98e3dbe20b7002f3cf3d64568f40a6db9746000ff689c31c40a9f4bb62864736f6c63430005110032
Deployed Bytecode
0x6080604052600436106103ef5760003560e01c806382dc1ec411610208578063af575ab711610118578063c7159307116100ab578063d9cce5261161007a578063d9cce52614610e1b578063da35a26f14610e7d578063dd62ed3e14610eb6578063e5a6b10f14610ef1578063ff90956014610f06576103ef565b8063c715930714610d7e578063d29157fb14610d93578063d505accf14610da8578063d8de658714610e06576103ef565b8063c25b25bd116100e7578063c25b25bd14610d04578063c290d69114610d19578063c415b95c14610d36578063c4d66de814610d4b576103ef565b8063af575ab714610c4a578063b12f415314610cb0578063b8606eef14610cda578063c19d93fb14610cef576103ef565b80639df3f4f61161019b578063a59ac6dd1161016a578063a59ac6dd14610b82578063a71ddd2514610bb4578063a9059cbb14610bc9578063aa271e1a14610c02578063ad3b763314610c35576103ef565b80639df3f4f614610aba578063a40b56b914610acf578063a457c2d714610ae4578063a551bfc414610b1d576103ef565b806393e59dc1116101d757806393e59dc114610a4857806395d89b4114610a5d578063983b2d5614610a725780639865027514610aa5576103ef565b806382dc1ec4146109c15780638456cb59146109f4578063896d170814610a095780638ac2c68014610a33576103ef565b80633f4ba83a1161030357806358439fa5116102965780636ef8d66d116102655780636ef8d66d146108da57806370a08231146108ef578063736dcb1f1461092257806379cc6790146109555780637ecebe001461098e576103ef565b806358439fa51461085c5780635c975abb146108715780636177e37c146108865780636a2724621461089b576103ef565b806346fbf68e116102d257806346fbf68e146107ea57806354fd4d501461081d57806355d0a1d0146108325780635671576114610847576103ef565b80633f4ba83a1461076a57806340c10f191461077f57806342966c68146107b857806343d726d6146107e2576103ef565b80632e872bb311610386578063355274ea11610355578063355274ea146106c157806335e5cc31146106d65780633644e515146106eb57806338af3eed146107005780633950935114610731576103ef565b80632e872bb3146106425780632ff791611461066c57806330adf81f14610681578063313ce56714610696576103ef565b806323b872dd116103c257806323b872dd1461055b578063263154381461059e578063270588ee146105b35780632973434a14610618576103ef565b806306fdde0314610448578063095ea7b3146104d257806318160ddd1461051f5780631d833ec514610546575b61019e546001600160a01b031615610446576040805162461bcd60e51b815260206004820152601560248201527409e9c98b2be8c9ea4be86aaa4a48a9c86b2be8aa89605b1b604482015290519081900360640190fd5b005b34801561045457600080fd5b5061045d610f1b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049757818101518382015260200161047f565b50505050905090810190601f1680156104c45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104de57600080fd5b5061050b600480360360408110156104f557600080fd5b506001600160a01b038135169060200135610f42565b604080519115158252519081900360200190f35b34801561052b57600080fd5b50610534610fa3565b60408051918252519081900360200190f35b34801561055257600080fd5b50610534610fa9565b34801561056757600080fd5b5061050b6004803603606081101561057e57600080fd5b506001600160a01b03813581169160208101359091169060400135610fcd565b3480156105aa57600080fd5b50610534611030565b3480156105bf57600080fd5b5061044660048036036101008110156105d757600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060ff60a0820135169060c08101359060e00135611037565b34801561062457600080fd5b506104466004803603602081101561063b57600080fd5b503561122e565b34801561064e57600080fd5b506105346004803603602081101561066557600080fd5b5035611370565b34801561067857600080fd5b506104466114fb565b34801561068d57600080fd5b506105346115a0565b3480156106a257600080fd5b506106ab6115c4565b6040805160ff9092168252519081900360200190f35b3480156106cd57600080fd5b506105346115c9565b3480156106e257600080fd5b506105346115d0565b3480156106f757600080fd5b506105346115d7565b34801561070c57600080fd5b506107156115de565b604080516001600160a01b039092168252519081900360200190f35b34801561073d57600080fd5b5061050b6004803603604081101561075457600080fd5b506001600160a01b0381351690602001356115f3565b34801561077657600080fd5b5061044661164b565b34801561078b57600080fd5b5061050b600480360360408110156107a257600080fd5b506001600160a01b038135169060200135611734565b3480156107c457600080fd5b50610446600480360360208110156107db57600080fd5b5035611794565b6104466117a3565b3480156107f657600080fd5b5061050b6004803603602081101561080d57600080fd5b50356001600160a01b0316611808565b34801561082957600080fd5b5061045d61181b565b34801561083e57600080fd5b50610534611838565b34801561085357600080fd5b5061053461183f565b34801561086857600080fd5b50610534611846565b34801561087d57600080fd5b5061050b61184d565b34801561089257600080fd5b50610534611856565b3480156108a757600080fd5b50610446600480360360608110156108be57600080fd5b506001600160a01b03813516906020810135906040013561185d565b3480156108e657600080fd5b5061044661186e565b3480156108fb57600080fd5b506105346004803603602081101561091257600080fd5b50356001600160a01b0316611880565b34801561092e57600080fd5b506105346004803603602081101561094557600080fd5b50356001600160a01b031661189b565b34801561096157600080fd5b506104466004803603604081101561097857600080fd5b506001600160a01b0381351690602001356118ae565b34801561099a57600080fd5b50610534600480360360208110156109b157600080fd5b50356001600160a01b03166118fc565b3480156109cd57600080fd5b50610446600480360360208110156109e457600080fd5b50356001600160a01b031661190f565b348015610a0057600080fd5b5061044661195e565b348015610a1557600080fd5b5061053460048036036020811015610a2c57600080fd5b5035611a25565b348015610a3f57600080fd5b50610534611aac565b348015610a5457600080fd5b50610715611ab3565b348015610a6957600080fd5b5061045d611ac3565b348015610a7e57600080fd5b5061044660048036036020811015610a9557600080fd5b50356001600160a01b0316611ae3565b348015610ab157600080fd5b50610446611b32565b348015610ac657600080fd5b50610534611b42565b348015610adb57600080fd5b50610534611b49565b348015610af057600080fd5b5061050b60048036036040811015610b0757600080fd5b506001600160a01b038135169060200135611b50565b348015610b2957600080fd5b506104466004803603610100811015610b4157600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060ff60a0820135169060c08101359060e00135611ba8565b61044660048036036060811015610b9857600080fd5b506001600160a01b038135169060208101359060400135611d93565b348015610bc057600080fd5b50610534611d9f565b348015610bd557600080fd5b5061050b60048036036040811015610bec57600080fd5b506001600160a01b038135169060200135611da6565b348015610c0e57600080fd5b5061050b60048036036020811015610c2557600080fd5b50356001600160a01b0316611dfe565b348015610c4157600080fd5b50610534611e12565b348015610c5657600080fd5b506104466004803603610100811015610c6e57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060808101359060a08101359060c08101359060e00135611e19565b348015610cbc57600080fd5b5061053460048036036020811015610cd357600080fd5b5035611f40565b348015610ce657600080fd5b50610534612060565b348015610cfb57600080fd5b50610534612067565b348015610d1057600080fd5b5061071561206e565b61044660048036036020811015610d2f57600080fd5b503561207e565b348015610d4257600080fd5b50610715612193565b348015610d5757600080fd5b5061044660048036036020811015610d6e57600080fd5b50356001600160a01b03166121a3565b348015610d8a57600080fd5b5061053461224e565b348015610d9f57600080fd5b50610534612255565b348015610db457600080fd5b50610446600480360360e0811015610dcb57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612279565b348015610e1257600080fd5b50610715612466565b348015610e2757600080fd5b506104466004803603610100811015610e3f57600080fd5b508035906001600160a01b03602082013581169160408101359160608201359160808101359160a08201359160c08101359160e09091013516612476565b348015610e8957600080fd5b5061044660048036036040811015610ea057600080fd5b50803590602001356001600160a01b0316612578565b348015610ec257600080fd5b5061053460048036036040811015610ed957600080fd5b506001600160a01b0381358116916020013516612677565b348015610efd57600080fd5b506107156126a2565b348015610f1257600080fd5b506105346126b2565b60408051808201909152600c81526b2b34b9b4b7b7102a37b5b2b760a11b60208201525b90565b609b5460009060ff1615610f90576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383612768565b90505b92915050565b60355490565b7faf42a244b3020d6a2253d9f291b4d3e82240da42b22129a8113a58aa7a3ddb6a81565b609b5460009060ff161561101b576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b61102684848461277c565b90505b9392505050565b6101a15481565b42841015611076576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380891660008181526101a9602090815260408083208054600180820190925582517faf42a244b3020d6a2253d9f291b4d3e82240da42b22129a8113a58aa7a3ddb6a8186015280840196909652958d166060860152608085018c905260a085018b905260c085019590955260e08085018a905281518086039091018152610100850182528051908301206101aa5461190160f01b6101208701526101228601526101428086019190915281518086039091018152610162850180835281519184019190912090849052610182850180835281905260ff89166101a28601526101c285018890526101e285018790529051909492936102028082019392601f1981019281900390910190855afa15801561119b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906111d15750896001600160a01b0316816001600160a01b0316145b611216576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6112228a8a8a8a612804565b50505050505050505050565b61019d546001600160a01b0316331461127d576040805162461bcd60e51b815260206004820152600c60248201526b434f4e54524f4c5f4f4e4c5960a01b604482015290519081900360640190fd5b60016101a854146112c8576040805162461bcd60e51b815260206004820152601060248201526f27a7262cafa1a0a6262fa4a72fa92aa760811b604482015290519081900360640190fd5b6101ae541561131e576040805162461bcd60e51b815260206004820152601960248201527f4f4e4c595f43414c4c5f49465f4e4f545f4155544f5f53455400000000000000604482015290519081900360640190fd5b4281111561136a576040805162461bcd60e51b81526020600482015260146024820152731110551157d35554d517d09157d25397d41054d560621b604482015290519081900360640190fd5b6101ae55565b60006101a654821015611385575060006114f6565b6000806101a854141561147a5782600061139d610fa3565b905060006113c161019b546101a15402836101a3546101a154010361019c54612aa8565b9050808311156113cf578092505b6113e58361019c5461019b546101a15402612aa8565b93508583146114725761019c54818703935060020261140a818563ffffffff612c3116565b6101a15461019b549195508002915061142a90829063ffffffff612c3116565b905061143c848263ffffffff612c8a16565b905061019b54818161144a57fe5b04905061145681612ce4565b6101a1549003905061146e858263ffffffff612c8a16565b9450505b5050506114f3565b60016101a85414156114e95760006101a35461019954611498610fa3565b010390506114b08461019c5460020261019b54612aa8565b91506114c48282800263ffffffff612c8a16565b91506114cf82612ce4565b91506114e1828263ffffffff612d5316565b9150506114f3565b60009150506114f6565b90505b919050565b604051469080605261554d82396052019050604051809103902061151d610f1b565b805160209182012060408051808201825260018152603360f81b90840152805180840194909452838101919091527f2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de606084015260808301939093523060a0808401919091528351808403909101815260c090920190925280519101206101aa55565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601290565b6101655490565b61019b5481565b6101aa5481565b61019a5461010090046001600160a01b031681565b609b5460009060ff1615611641576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383612d95565b61165b611656612de9565b611808565b6116965760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b609b5460ff166116e4576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b609b805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611717612de9565b604080516001600160a01b039092168252519081900360200190a1565b6000611746611741612de9565b611dfe565b6117815760405162461bcd60e51b81526004018080602001828103825260308152602001806154fc6030913960400191505060405180910390fd5b61178b8383612ded565b50600192915050565b6117a0338260006131db565b50565b6101a854600090600114156117ca576117bb34611a25565b90506117ca33823460016135f3565b6117d26136ed565b6040805182815290517fbf67515a38ee520223d32c1266d52101c30d936ed1f3e436c8caeb0a43cb06bf9181900360200190a150565b60006114f360688363ffffffff61389816565b604051806040016040528060018152602001603360f81b81525081565b6101995481565b6101ad5481565b61019c5481565b609b5460ff1690565b6101a75490565b611869338484846138ff565b505050565b61187e611879612de9565b613af1565b565b6001600160a01b031660009081526033602052604090205490565b6101a26020526000908152604090205481565b6118ec82336118e784604051806060016040528060248152602001615658602491396118da8833612677565b919063ffffffff613b3916565b613bd0565b6118f8828260006131db565b5050565b6101a96020526000908152604090205481565b61191a611656612de9565b6119555760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b6117a081613cbc565b611969611656612de9565b6119a45760405162461bcd60e51b815260040180806020018281038252603081526020018061544a6030913960400191505060405180910390fd5b609b5460ff16156119ef576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b609b805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611717612de9565b60008060016101a85414156114f3576000611a3e6126b2565b9050611a50818563ffffffff612d5316565b90506000611a5c610fa3565b9050611a748161019b54610199540261019c54612aa8565b9250611a89818261019b540261019c54612aa8565b83019250818311611a9d5760009250611aa3565b81830392505b50509050919050565b6101a65481565b610198546001600160a01b031681565b6040805180820190915260068152652b24a9a4a7a760d11b602082015290565b611aee611741612de9565b611b295760405162461bcd60e51b81526004018080602001828103825260308152602001806154fc6030913960400191505060405180910390fd5b6117a081613d04565b61187e611b3d612de9565b613d4d565b6101a45490565b6101ab5481565b609b5460009060ff1615611b9e576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383613d96565b42841015611be7576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380891660008181526101a9602090815260408083208054600180820190925582517f5dfdc7fb4c68a4c249de5e08597626b84fbbe7bfef4ed3500f58003e722cc5488186015280840196909652958d166060860152608085018c905260a085018b905260c085019590955260e08085018a905281518086039091018152610100850182528051908301206101aa5461190160f01b6101208701526101228601526101428086019190915281518086039091018152610162850180835281519184019190912090849052610182850180835281905260ff89166101a28601526101c285018890526101e285018790529051909492936102028082019392601f1981019281900390910190855afa158015611d0c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611d425750896001600160a01b0316816001600160a01b0316145b611d87576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6112228a8a8a8a6138ff565b61186933848484612804565b6101a35481565b609b5460009060ff1615611df4576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b610f9a8383613e04565b60006114f36101008363ffffffff61389816565b6101ae5481565b611e2888888888888787613e18565b612710831115611e74576040805162461bcd60e51b81526020600482015260126024820152711253959053125117d0d3d35352551351539560721b604482015290519081900360640190fd5b6101a754831015611ecc576040805162461bcd60e51b815260206004820152601d60248201527f434f4d4d49544d454e545f4d41595f4e4f545f42455f52454455434544000000604482015290519081900360640190fd5b6101a7839055604080516001600160a01b038a8116825260208201869052818301879052606082018590526080820184905291518288169289811692908b16917fab33ca83001031840bf8a88b6a384c984aeb1ffcfebc562f13dab66a81306f969181900360a00190a45050505050505050565b600080611f4b6126b2565b9050600060016101a8541415611ffa57600061019954611f69610fa3565b019050611f95611f7f868563ffffffff612c3116565b610199548002611f8d610fa3565b848502614190565b91506000611fac866002860263ffffffff612c3116565b9050818181611fb757fe5b04928301929050611fda611fd1878063ffffffff612c3116565b8584850261433c565b905080831115611fee578083039250611ff3565b600092505b5050611029565b60026101a854141561203057612016848363ffffffff612c3116565b9050612020610fa3565b818161202857fe5b049050611029565b612040848363ffffffff612c3116565b90506101a35461204e610fa3565b03818161205757fe5b04949350505050565b6101a05481565b6101a85481565b6101ac546001600160a01b031681565b61208b33823460006135f3565b60016101a854146120d3576040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b6000811161211b576040805162461bcd60e51b815260206004820152601060248201526f4d495353494e475f43555252454e435960801b604482015290519081900360640190fd5b60006121336101a75483612c3190919063ffffffff16565b61019a5461271090910491506121599061010090046001600160a01b0316828403614387565b60408051838152905133917f357b676c439b9e49b4410f8eb8680bee4223724802d8e3fd422e1756f87b475f919081900360200190a25050565b61019f546001600160a01b031681565b600054610100900460ff16806121bc57506121bc6143cb565b806121ca575060005460ff16155b6122055760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff16158015612230576000805460ff1961ff0019909116610100171660011790555b612239826143d1565b80156118f8576000805461ff00191690555050565b6101ae5490565b7f5dfdc7fb4c68a4c249de5e08597626b84fbbe7bfef4ed3500f58003e722cc54881565b428410156122b8576040805162461bcd60e51b81526020600482015260076024820152661156141254915160ca1b604482015290519081900360640190fd5b6001600160a01b0380881660008181526101a9602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e0850182528051908301206101aa5461190160f01b6101008701526101028601526101228086019190915281518086039091018152610142850180835281519184019190912090849052610162850180835281905260ff89166101828601526101a285018890526101c285018790529051909492936101e28082019392601f1981019281900390910190855afa1580156123d5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061240b5750886001600160a01b0316816001600160a01b0316145b612450576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b61245b898989613bd0565b505050505050505050565b61019d546001600160a01b031681565b61248588888888888787614474565b856124c6576101a8546040805191825260016020830152805160008051602061559f8339815191529281900390910190a160016101a855426101ae55612522565b6f4b3b4ca85a86c47a098a224000000000861061251b576040805162461bcd60e51b815260206004820152600e60248201526d115610d154d4d2559157d1d3d05360921b604482015290519081900360640190fd5b6101a18690555b61271083111561256b576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5245534552564560881b604482015290519081900360640190fd5b50506101a4555050505050565b600054610100900460ff168061259157506125916143cb565b8061259f575060005460ff16155b6125da5760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff16158015612605576000805460ff1961ff0019909116610100171660011790555b61260e826121a3565b6000831161265b576040805162461bcd60e51b8152602060048201526015602482015274045524332304361707065643a20636170206973203605c1b604482015290519081900360640190fd5b6101658390558015611869576000805461ff0019169055505050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61019e546001600160a01b031681565b61019e5460009047906001600160a01b0316156127445761019e54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b15801561271557600080fd5b505afa158015612729573d6000803e3d6000fd5b505050506040513d602081101561273f57600080fd5b505190505b6001600160801b03811115612763576001600160801b03915050610f3f565b905090565b600061178b612775612de9565b8484613bd0565b600061278984848461482e565b6127fa84612795612de9565b6118e7856040518060600160405280602881526020016155e0602891396001600160a01b038a166000908152603460205260408120906127d3612de9565b6001600160a01b03168152602081019190915260400160002054919063ffffffff613b3916565b5060019392505050565b6001600160a01b038316612851576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000811161289c576040805162461bcd60e51b81526020600482015260136024820152724d5553545f4255595f41545f4c454153545f3160681b604482015290519081900360640190fd5b60006128a783611370565b9050818110156128ef576040805162461bcd60e51b815260206004820152600e60248201526d50524943455f534c49505041474560901b604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b03167f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e8584604051808381526020018281526020019250505060405180910390a361294f85843460006135f3565b6101a854612a73576001600160a01b03841660009081526101a2602052604090208054820190556101a1546101a35482612987610fa3565b010310612a6e576101a8546040805191825260016020830152805160008051602061559f8339815191529281900390910190a160016101a8556101ae546129ce57426101ae555b61019a5461010090046001600160a01b031660009081526101a260205260408120546101a15461019b5461019c54612a0b93929190910290612aa8565b6101ab5490915015612a4c576101ac546101ab54612a32916001600160a01b031690614387565b6101ab54811115612a48576101ab549003612a4c565b5060005b612a6c612a6782612a5b6126b2565b9063ffffffff612d5316565b614b62565b505b612a97565b61019a546001600160a01b038581166101009092041614612a9757612a9783614b62565b612aa18482612ded565b5050505050565b6000831580612ab5575082155b15612ac257506000611029565b6000838560001981612ad057fe5b0410612aed5750838302828181612ae357fe5b0491506110299050565b838581811115612afd5750859050845b848281612b0657fe5b0492506305f5e100831115612b3057612b25838263ffffffff612c3116565b935061102992505050565b60001981016001600160801b038104600101905060001983016001600160801b0381046001019050808260001981612b6457fe5b0410612bd45790810290818481612b7757fe5b049450630bebc200851115612bd457612b96858463ffffffff612c3116565b9450506000198601818181612ba757fe5b049050612bbb81600163ffffffff612c8a16565b9050808581612bc657fe5b049550611029945050505050565b60016001600160801b03600019850104019150818381612bf057fe5b049450506000198601818181612c0257fe5b046001019050808481612c1157fe5b049050612c24858263ffffffff612c3116565b9998505050505050505050565b600082612c4057506000610f9d565b82820282848281612c4d57fe5b0414610f9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806155bf6021913960400191505060405180910390fd5b600082820183811015610f9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081612cf3575060006114f6565b60038211612d03575060016114f6565b600019821415612d1b57506001600160801b036114f6565b5080600260018201045b81811015612d4d57809150600281828581612d3c57fe5b040181612d4557fe5b049050612d25565b50919050565b6000610f9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613b39565b600061178b612da2612de9565b846118e78560346000612db3612de9565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612c8a16565b3390565b610198546000908390839083906001600160a01b0316156130a157610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b158015612e5857600080fd5b505af1158015612e6c573d6000803e3d6000fd5b505050506040513d6020811015612e8257600080fd5b5051158015612e9957506001600160a01b03841615155b8015612eb757506001600160a01b038316158015612eb5575080155b155b15612f245761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b158015612f0b57600080fd5b505af1158015612f1f573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b158015612f7457600080fd5b505af1158015612f88573d6000803e3d6000fd5b505050506040513d6020811015612f9e57600080fd5b5051158015612fb557506001600160a01b03831615155b156130225761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b15801561300957600080fd5b505af115801561301d573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b15801561308857600080fd5b505af115801561309c573d6000803e3d6000fd5b505050505b6130ab8686614be1565b6f4b3b4ca85a86c47a098a2240000000006130d7610199546130cb610fa3565b9063ffffffff612c8a16565b111561311d576040805162461bcd60e51b815260206004820152601060248201526f4558434553534956455f535550504c5960801b604482015290519081900360640190fd5b610198546001600160a01b0316156131d35761313884611880565b15801561314d57506001600160a01b03841615155b801561316b57506001600160a01b038316158015613169575080155b155b156131d3576101985460408051630b3ffd1d60e01b81526001600160a01b03878116600483015291519190921691630b3ffd1d91602480830192600092919082900301818387803b1580156131bf57600080fd5b505af1158015611222573d6000803e3d6000fd5b505050505050565b610198548390600090849084906001600160a01b03161561348f57610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561324657600080fd5b505af115801561325a573d6000803e3d6000fd5b505050506040513d602081101561327057600080fd5b505115801561328757506001600160a01b03841615155b80156132a557506001600160a01b0383161580156132a3575080155b155b156133125761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b1580156132f957600080fd5b505af115801561330d573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561336257600080fd5b505af1158015613376573d6000803e3d6000fd5b505050506040513d602081101561338c57600080fd5b50511580156133a357506001600160a01b03831615155b156134105761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b1580156133f757600080fd5b505af115801561340b573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b15801561347657600080fd5b505af115801561348a573d6000803e3d6000fd5b505050505b6134998787614c4e565b8461352f5760016101a854146134e6576040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b6101998054870190556040805187815290516001600160a01b038916917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a25b610198546001600160a01b0316156135ea5761354a84611880565b15801561355f57506001600160a01b03841615155b801561357d57506001600160a01b03831615801561357b575080155b155b156135ea576101985460408051630b3ffd1d60e01b81526001600160a01b03878116600483015291519190921691630b3ffd1d91602480830192600092919082900301818387803b1580156135d157600080fd5b505af11580156135e5573d6000803e3d6000fd5b505050505b50505050505050565b61019e546001600160a01b031661368357801561363457600061361c838563ffffffff612d5316565b9050801561362e5761362e3382614d4a565b5061367e565b81831461367e576040805162461bcd60e51b8152602060048201526013602482015272494e434f52524543545f4d53475f56414c554560681b604482015290519081900360640190fd5b6136e7565b81156136c8576040805162461bcd60e51b815260206004820152600f60248201526e0889ebe9c9ea8bea68a9c88be8aa89608b1b604482015290519081900360640190fd5b61019e546136e7906001600160a01b031685308663ffffffff614e2f16565b50505050565b61019a5461010090046001600160a01b03163314613745576040805162461bcd60e51b815260206004820152601060248201526f42454e45464943494152595f4f4e4c5960801b604482015290519081900360640190fd5b6101a854613784576101a8546040805191825260036020830152805160008051602061559f8339815191529281900390910190a160036101a85561187e565b60016101a854141561385b576101ae546101ad5419116137db576040805162461bcd60e51b815260206004820152600d60248201526c4d41595f4e4f545f434c4f534560981b604482015290519081900360640190fd5b426101ae546101ad54011115613824576040805162461bcd60e51b8152602060048201526009602482015268544f4f5f4541524c5960b81b604482015290519081900360640190fd5b6101a8546040805191825260026020830152805160008051602061559f8339815191529281900390910190a160026101a85561187e565b6040805162461bcd60e51b815260206004820152600d60248201526c494e56414c49445f535441544560981b604482015290519081900360640190fd5b60006001600160a01b0382166138df5760405162461bcd60e51b81526004018080602001828103825260228152602001806156086022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b61019a546001600160a01b0385811661010090920416141580613926575060026101a85410155b6139615760405162461bcd60e51b815260040180806020018281038252602881526020018061567c6028913960400191505060405180910390fd5b600081116139ad576040805162461bcd60e51b81526020600482015260146024820152734d5553545f53454c4c5f41545f4c454153545f3160601b604482015290519081900360640190fd5b60006139b883611f40565b905081811015613a00576040805162461bcd60e51b815260206004820152600e60248201526d50524943455f534c49505041474560901b604482015290519081900360640190fd5b6101a8541580613a13575060036101a854145b15613a5d576001600160a01b03851660009081526101a26020526040902054613a42908463ffffffff612d5316565b6001600160a01b03861660009081526101a260205260409020555b613a69858460016131db565b600061019954613a77610fa3565b0190506101a354811015613a8c576101a38190555b613a968583614387565b846001600160a01b0316866001600160a01b03167fa082022e93cfcd9f1da5f9236718053910f7e840da080c789c7845698dc032ff8487604051808381526020018281526020019250505060405180910390a3505050505050565b613b0260688263ffffffff614e8916565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b60008184841115613bc85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613b8d578181015183820152602001613b75565b50505050905090810190601f168015613bba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b038316613c155760405162461bcd60e51b81526004018080602001828103825260248152602001806156ea6024913960400191505060405180910390fd5b6001600160a01b038216613c5a5760405162461bcd60e51b815260040180806020018281038252602281526020018061547a6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260346020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613ccd60688263ffffffff614ef016565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b613d166101008263ffffffff614ef016565b6040516001600160a01b038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b613d5f6101008263ffffffff614e8916565b6040516001600160a01b038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b600061178b613da3612de9565b846118e7856040518060600160405280602581526020016157386025913960346000613dcd612de9565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff613b3916565b600061178b613e11612de9565b848461482e565b61019d546001600160a01b03163314613e67576040805162461bcd60e51b815260206004820152600c60248201526b434f4e54524f4c5f4f4e4c5960a01b604482015290519081900360640190fd5b61019880546001600160a01b0319166001600160a01b03898116919091179091558516613ecd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019d80546001600160a01b0319166001600160a01b03878116919091179091558416613f33576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019f80546001600160a01b0319166001600160a01b038616179055612710831115613f94576040805162461bcd60e51b815260206004820152600b60248201526a494e56414c49445f46454560a81b604482015290519081900360640190fd5b6101a083905581613fe5576040805162461bcd60e51b81526020600482015260166024820152751253959053125117d3525397d253959154d51351539560521b604482015290519081900360640190fd5b6101a68290556101ad54811015614043576040805162461bcd60e51b815260206004820152601f60248201527f4d494e5f4455524154494f4e5f4d41595f4e4f545f42455f5245445543454400604482015290519081900360640190fd5b6101ad81905561019a546001600160a01b0387811661010090920416146135ea576001600160a01b0386166140b1576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61019a546000906140cf9061010090046001600160a01b0316611880565b61019a546001600160a01b03610100909104811660009081526101a2602052604080822054928b16825290205491925061410f919063ffffffff612c8a16565b6001600160a01b0380891660009081526101a260205260408082209390935561019a54610100900490911681529081205580156141635761019a546141639061010090046001600160a01b0316888361482e565b5061019a80546001600160a01b03881661010002610100600160a81b031990911617905550505050505050565b600081836000198161419e57fe5b04106141b8576141b18585848602612aa8565b9050614334565b8415806141c3575083155b156141d057506000614334565b8183818111156141e05750839050825b60008688600019816141ee57fe5b0410614219575086860281818161420157fe5b04905082818161420d57fe5b04935061433492505050565b8688818111156142295750889050875b600084838161423457fe5b049050630bebc20081111561425b5761424e818388612aa8565b9650505050505050614334565b506001600160801b03600019838101829004600190810192848301040190829082908161428457fe5b04106142ff57810280848161429557fe5b049450630bebc2008511156142ff576142b4858463ffffffff612c3116565b94508585816142bf57fe5b0494506000851180156142dd57508085600019816142d957fe5b0410155b156142ff57938402938685816142ef57fe5b0497506143349650505050505050565b5050600160801b85046001600160801b038504810261432a81858161432057fe5b0484600019612aa8565b9750505050505050505b949350505050565b60008061434a858585612aa8565b90508061435b576001915050611029565b60016305f5e10060001983010401811981111561437e5760001992505050611029565b01949350505050565b80156118f85761019e546001600160a01b03166143ad576143a88282614d4a565b6118f8565b61019e546118f8906001600160a01b0316838363ffffffff614f7116565b303b1590565b600054610100900460ff16806143ea57506143ea6143cb565b806143f8575060005460ff16155b6144335760405162461bcd60e51b815260040180806020018281038252602e81526020018061562a602e913960400191505060405180910390fd5b600054610100900460ff1615801561445e576000805460ff1961ff0019909116610100171660011790555b61446782611dfe565b6122395761223982613d04565b6144896a0422ca8b0a00a42500000033612578565b61449233613cbc565b600084116144db576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f534c4f50455f4e554d60781b604482015290519081900360640190fd5b60008311614524576040805162461bcd60e51b815260206004820152601160248201527024a72b20a624a22fa9a627a822afa222a760791b604482015290519081900360640190fd5b6001600160801b038410614575576040805162461bcd60e51b81526020600482015260136024820152724558434553534956455f534c4f50455f4e554d60681b604482015290519081900360640190fd5b6001600160801b0383106145c6576040805162461bcd60e51b815260206004820152601360248201527222ac21a2a9a9a4ab22afa9a627a822afa222a760691b604482015290519081900360640190fd5b61019b84905561019c8390558115806145e757506001600160a01b03811615155b614638576040805162461bcd60e51b815260206004820152601b60248201527f4d495353494e475f53455455505f4645455f524543495049454e540000000000604482015290519081900360640190fd5b6001600160a01b038116158061464d57508115155b614692576040805162461bcd60e51b81526020600482015260116024820152704d495353494e475f53455455505f46454560781b604482015290519081900360640190fd5b8480026146a5818663ffffffff612c3116565b90508360020281816146b357fe5b04905080831115614701576040805162461bcd60e51b81526020600482015260136024820152724558434553534956455f53455455505f46454560681b604482015290519081900360640190fd5b6101ab8390556101ac80546001600160a01b0319166001600160a01b038481169190911790915560129088161561479d57876001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561476b57600080fd5b505afa15801561477f573d6000803e3d6000fd5b505050506040513d602081101561479557600080fd5b505160ff1690505b600a81900a6064026101a65561019a8054610100600160a81b0319163361010081029190911790915561019d80546001600160a01b0319908116831790915561019f8054821690921790915561019e80549091166001600160a01b038a161790558815614826576101a389905561019a546148269061010090046001600160a01b03168a612ded565b61245b6114fb565b610198548390839083906000906001600160a01b031615614ae257610198546040805163187601f760e21b81526001600160a01b038781166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b15801561489957600080fd5b505af11580156148ad573d6000803e3d6000fd5b505050506040513d60208110156148c357600080fd5b50511580156148da57506001600160a01b03841615155b80156148f857506001600160a01b0383161580156148f6575080155b155b156149655761019854604080516303e28f3760e01b81526001600160a01b038781166004830152915191909216916303e28f3791602480830192600092919082900301818387803b15801561494c57600080fd5b505af1158015614960573d6000803e3d6000fd5b505050505b610198546040805163187601f760e21b81526001600160a01b038681166004830152915191909216916361d807dc9160248083019260209291908290030181600087803b1580156149b557600080fd5b505af11580156149c9573d6000803e3d6000fd5b505050506040513d60208110156149df57600080fd5b50511580156149f657506001600160a01b03831615155b15614a635761019854604080516303e28f3760e01b81526001600160a01b038681166004830152915191909216916303e28f3791602480830192600092919082900301818387803b158015614a4a57600080fd5b505af1158015614a5e573d6000803e3d6000fd5b505050505b61019854604080516336dffedf60e01b81526001600160a01b0387811660048301528681166024830152604482018690528415156064830152915191909216916336dffedf91608480830192600092919082900301818387803b158015614ac957600080fd5b505af1158015614add573d6000803e3d6000fd5b505050505b6101a854151580614b06575061019a546001600160a01b0388811661010090920416145b614b57576040805162461bcd60e51b815260206004820152601c60248201527f4f4e4c595f42454e45464943494152595f445552494e475f494e495400000000604482015290519081900360640190fd5b61352f878787614fc3565b6101a454600090614b79908363ffffffff612c3116565b61271090049050614b8a8282612d53565b90506000614ba46101a05483612c3190919063ffffffff16565b61019a546127109091049150614bca9061010090046001600160a01b0316828403614387565b61019f54611869906001600160a01b031682614387565b61016554614bf1826130cb610fa3565b1115614c44576040805162461bcd60e51b815260206004820152601960248201527f45524332304361707065643a2063617020657863656564656400000000000000604482015290519081900360640190fd5b6118f88282615121565b6001600160a01b038216614c935760405162461bcd60e51b81526004018080602001828103825260218152602001806156a46021913960400191505060405180910390fd5b614cd681604051806060016040528060228152602001615428602291396001600160a01b038516600090815260336020526040902054919063ffffffff613b3916565b6001600160a01b038316600090815260336020526040902055603554614d02908263ffffffff612d5316565b6035556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b80471015614d9f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114614dea576040519150601f19603f3d011682016040523d82523d6000602084013e614def565b606091505b50509050806118695760405162461bcd60e51b815260040180806020018281038252603a8152602001806154c2603a913960400191505060405180910390fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526136e7908590615213565b614e938282613898565b614ece5760405162461bcd60e51b815260040180806020018281038252602181526020018061552c6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b614efa8282613898565b15614f4c576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611869908490615213565b6001600160a01b0383166150085760405162461bcd60e51b81526004018080602001828103825260258152602001806156c56025913960400191505060405180910390fd5b6001600160a01b03821661504d5760405162461bcd60e51b81526004018080602001828103825260238152602001806154056023913960400191505060405180910390fd5b6150908160405180606001604052806026815260200161549c602691396001600160a01b038616600090815260336020526040902054919063ffffffff613b3916565b6001600160a01b0380851660009081526033602052604080822093909355908416815220546150c5908263ffffffff612c8a16565b6001600160a01b0380841660008181526033602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6001600160a01b03821661517c576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b60355461518f908263ffffffff612c8a16565b6035556001600160a01b0382166000908152603360205260409020546151bb908263ffffffff612c8a16565b6001600160a01b03831660008181526033602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b615225826001600160a01b03166153cb565b615276576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106152b45780518252601f199092019160209182019101615295565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114615316576040519150601f19603f3d011682016040523d82523d6000602084013e61531b565b606091505b509150915081615372576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156136e75780806020019051602081101561538e57600080fd5b50516136e75760405162461bcd60e51b815260040180806020018281038252602a81526020018061570e602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061433457505015159291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e6365506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c6545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429107dddb4541735557564238389eccfc9979bfdde5e57e24e9777b6fe79b4d22f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a656445524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e636542454e45464943494152595f4f4e4c595f53454c4c5f494e5f434c4f53455f4f525f43414e43454c45524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a723158203f15b98e3dbe20b7002f3cf3d64568f40a6db9746000ff689c31c40a9f4bb62864736f6c63430005110032
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.