Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xec72720633712608b5c96a135af7295eb2181b53.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- Dao
- Optimization enabled
- true
- Compiler version
- v0.8.15+commit.e14f2714
- Optimization runs
- 200
- Verified at
- 2023-05-09T19:23:17.690665Z
Contract source code
// created by cryptodo.app
// _____ _ _____
// / ____| | | | __ \
// | | _ __ _ _ _ __ | |_ ___ | | | | ___
// | | | '__|| | | || '_ \ | __|/ _ \ | | | | / _ \
// | |____ | | | |_| || |_) || |_| (_) || |__| || (_) |
// \_____||_| \__, || .__/ \__|\___/ |_____/ \___/
// __/ || |
// |___/ |_|
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.7;
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
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);
}
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) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeERC20 {
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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
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'
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_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. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
library ECDSA {
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return recover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return recover(hash, r, vs);
} else {
revert("ECDSA: invalid signature length");
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
bytes32 s;
uint8 v;
assembly {
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
v := add(shr(255, vs), 27)
}
return recover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
require(
uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
"ECDSA: invalid signature 's' value"
);
require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
require(signer != address(0), "ECDSA: invalid signature");
return signer;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @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. This is the value {ERC20} uses, unless this function is
* overridden;
*
* 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 virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override 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 virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override 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 virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
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 virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + 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 virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This 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 virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(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:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(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 virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This 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 virtual {
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 Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
interface IAdapter {
function withdraw(
address _recipient,
address _pool,
uint256 _share // multiplied by 1e18, for example 20% = 2e17
) external returns (bool);
}
interface ENSInterface {
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// Logged when the resolver for a node changes.
event NewResolver(bytes32 indexed node, address resolver);
// Logged when the TTL of a node changes
event NewTTL(bytes32 indexed node, uint64 ttl);
function setSubnodeOwner(
bytes32 node,
bytes32 label,
address owner
) external;
function setResolver(bytes32 node, address resolver) external;
function setOwner(bytes32 node, address owner) external;
function setTTL(bytes32 node, uint64 ttl) external;
function owner(bytes32 node) external view returns (address);
function resolver(bytes32 node) external view returns (address);
function ttl(bytes32 node) external view returns (uint64);
}
interface PointerInterface {
function getAddress() external view returns (address);
}
interface OwnableInterface {
function owner() external returns (address);
function transferOwnership(address recipient) external;
function acceptOwnership() external;
}
contract ConfirmedOwnerWithProposal is OwnableInterface {
address private s_owner;
address private s_pendingOwner;
event OwnershipTransferRequested(address indexed from, address indexed to);
event OwnershipTransferred(address indexed from, address indexed to);
constructor(address newOwner, address pendingOwner) {
require(newOwner != address(0), "Cannot set owner to zero");
s_owner = newOwner;
if (pendingOwner != address(0)) {
_transferOwnership(pendingOwner);
}
}
/**
* @notice Allows an owner to begin transferring ownership to a new address,
* pending.
*/
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
/**
* @notice Allows an ownership transfer to be completed by the recipient.
*/
function acceptOwnership() external override {
require(msg.sender == s_pendingOwner, "Must be proposed owner");
address oldOwner = s_owner;
s_owner = msg.sender;
s_pendingOwner = address(0);
emit OwnershipTransferred(oldOwner, msg.sender);
}
/**
* @notice Get the current owner
*/
function owner() public view override returns (address) {
return s_owner;
}
/**
* @notice validate, transfer ownership, and emit relevant events
*/
function _transferOwnership(address to) private {
require(to != msg.sender, "Cannot transfer to self");
s_pendingOwner = to;
emit OwnershipTransferRequested(s_owner, to);
}
/**
* @notice validate access
*/
function _validateOwnership() internal view {
require(msg.sender == s_owner, "Only callable by owner");
}
/**
* @notice Reverts if called by anyone other than the contract owner.
*/
modifier onlyOwner() {
_validateOwnership();
_;
}
}
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
contract Dao is ReentrancyGuard, ERC20, ConfirmedOwner {
using EnumerableSet for EnumerableSet.AddressSet;
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;
using ECDSA for bytes32;
/*----STATE------------------------------------------*/
//voting duration in days
uint32 public VOTING_DURATION = 3 days;
// These contracts help burn LP's
EnumerableSet.AddressSet private adapters;
// LP Token Address
address public lp = address(0);
// Quorum >=1 <=100
uint8 public quorum;
//Voting api url
string apiUrl;
//Contract address nonce
uint nonce = 0;
address[] partners;
uint256[] shares;
// Proposals
struct Proposal {
address target;
bytes data;
uint256 value;
string discription;
uint256 timestamp;
}
uint lastProposalId;
mapping(uint => Proposal) proposals;
mapping(uint => bool) proposalPreQuorum;
// Executed Proposal
struct ExecutedProposal {
address target;
bytes data;
uint256 value;
uint256 nonce;
uint256 timestamp;
uint256 executionTimestamp;
bytes32 txHash;
bytes[] sigs;
}
ExecutedProposal[] internal executedProposal;
mapping(bytes32 => bool) public executedTx;
// GT
bool public mintable = true;
bool public burnable = true;
/*----EVENTS-----------------------------------------*/
event RequestQuorumStatus(bytes32 indexed requestId, uint id, bool status);
event Executed(
address indexed target,
bytes data,
uint256 value,
uint256 indexed nonce,
uint256 timestamp,
uint256 executionTimestamp,
bytes32 txHash
);
/*----MODIFIERS--------------------------------------*/
modifier onlyDao() {
require(
msg.sender == address(this),
"DAO: this function is only for DAO"
);
_;
}
/*----CONSTRUCTOR------------------------------------*/
constructor(
string memory _name,
string memory _symbol,
uint8 _quorum,
address[] memory _partners,
uint256[] memory _shares,
string memory _apiUrl
) ERC20(_name, _symbol) ConfirmedOwner(msg.sender) {
require(
_quorum >= 1 && _quorum <= 100,
"DAO: quorum should be 1 <= q <= 100"
);
quorum = _quorum;
require(
_partners.length > 0 && _partners.length == _shares.length,
"DAO: shares distribution is invalid"
);
partners = _partners;
shares = _shares;
apiUrl = _apiUrl;
apiUrl = _apiUrl;
for (uint256 i = 0; i < _partners.length; i++) {
_mint(_partners[i], _shares[i]);
}
}
/*----MAIN FUNCTIONS TO RULE--------------------------*/
function addProposal(
address target,
bytes calldata data,
uint256 value,
string calldata discription
) external nonReentrant returns (uint thisId) {
require(balanceOf(msg.sender) > 0, "DAO: only for members");
thisId = lastProposalId++;
uint256 timestamp = block.timestamp;
proposals[thisId] = Proposal(target, data, value, discription, timestamp);
}
function execute(
uint256 _proposalId,
bytes[] memory _sigs
) external nonReentrant returns (bool) {
require(balanceOf(msg.sender) > 0, "DAO: only for members");
require(proposalPreQuorum[_proposalId], "DAO: preQuorum is not reached");
Proposal memory proposal = getProposalById(_proposalId);
address _target = proposal.target;
bytes memory _data = proposal.data;
uint256 _value = proposal.value;
uint256 _timestamp = proposal.timestamp;
uint256 _nonce = nonce;
require(
_timestamp + VOTING_DURATION >= block.timestamp,
"DAO: voting is over"
);
bytes32 txHash = getTxHash(_target, _data, _value, _nonce, _timestamp);
require(!executedTx[txHash], "DAO: propose already executed");
require(_checkSigs(_sigs, txHash), "DAO: quorum is not reached");
executedTx[txHash] = true;
executedProposal.push(
ExecutedProposal({
target: _target,
data: _data,
value: _value,
nonce: _nonce,
timestamp: _timestamp,
executionTimestamp: block.timestamp,
txHash: txHash,
sigs: _sigs
})
);
emit Executed(
_target,
_data,
_value,
_nonce,
_timestamp,
block.timestamp,
txHash
);
nonce++;
if (_data.length == 0) {
payable(_target).sendValue(_value);
} else {
if (_value == 0) {
_target.functionCall(_data);
} else {
_target.functionCallWithValue(_data, _value);
}
}
return true;
}
function getTxHash(
address _target,
bytes memory _data,
uint256 _value,
uint256 _nonce,
uint256 _timestamp
) public view returns (bytes32) {
return
keccak256(
abi.encode(
address(this),
_target,
_data,
_value,
_nonce,
_timestamp,
block.chainid
)
);
}
function _checkSigs(bytes[] memory _sigs, bytes32 _txHash)
public
view
returns (bool)
{
bytes32 ethSignedHash = _txHash.toEthSignedMessageHash();
uint256 share = 0;
address[] memory signers = new address[](_sigs.length);
for (uint256 i = 0; i < _sigs.length; i++) {
address signer = ethSignedHash.recover(_sigs[i]);
signers[i] = signer;
}
require(!_hasDuplicate(signers), "DAO: signatures are not unique");
for (uint256 i = 0; i < signers.length; i++) {
share += balanceOf(signers[i]);
}
if (share * 100 < totalSupply() * quorum) {
return false;
}
return true;
}
/*----BURN LP TOKENS---------------------------------*/
function burnLp(
address _recipient,
uint256 _share,
address[] memory _tokens,
address[] memory _adapters,
address[] memory _pools
) external nonReentrant returns (bool) {
require(lp != address(0), "DAO: LP not set yet");
require(msg.sender == lp, "DAO: only for LP");
require(
!_hasDuplicate(_tokens),
"DAO: duplicates are prohibited (tokens)"
);
for (uint256 i = 0; i < _tokens.length; i++) {
require(
_tokens[i] != lp && _tokens[i] != address(this),
"DAO: LP and GT cannot be part of a share"
);
}
require(_adapters.length == _pools.length, "DAO: adapters error");
if (_adapters.length > 0) {
uint256 length = _adapters.length;
if (length > 1) {
for (uint256 i = 0; i < length - 1; i++) {
for (uint256 j = i + 1; j < length; j++) {
require(
!(_adapters[i] == _adapters[j] &&
_pools[i] == _pools[j]),
"DAO: duplicates are prohibited (adapters)"
);
}
}
}
}
// ETH
payable(_recipient).sendValue((address(this).balance * _share) / 1e18);
// Tokens
if (_tokens.length > 0) {
uint256[] memory _tokenShares = new uint256[](_tokens.length);
for (uint256 i = 0; i < _tokens.length; i++) {
_tokenShares[i] = ((IERC20(_tokens[i]).balanceOf(
address(this)
) * _share) / 1e18);
}
for (uint256 i = 0; i < _tokens.length; i++) {
IERC20(_tokens[i]).safeTransfer(_recipient, _tokenShares[i]);
}
}
// Adapters
if (_adapters.length > 0) {
uint256 length = _adapters.length;
for (uint256 i = 0; i < length; i++) {
require(
adapters.contains(_adapters[i]),
"DAO: this is not an adapter"
);
bool b = IAdapter(_adapters[i]).withdraw(
_recipient,
_pools[i],
_share
);
require(b, "DAO: withdrawal error");
}
}
return true;
}
/*----GT MANAGEMENT----------------------------------*/
function mint(address _to, uint256 _amount)
external
onlyDao
returns (bool)
{
require(mintable, "DAO: GT minting is disabled");
_mint(_to, _amount);
return true;
}
function burn(address _to, uint256 _amount)
external
onlyDao
returns (bool)
{
require(burnable, "DAO: GT burning is disabled");
_burn(_to, _amount);
return true;
}
function move(
address _sender,
address _recipient,
uint256 _amount
) external onlyDao returns (bool) {
_transfer(_sender, _recipient, _amount);
return true;
}
function disableMinting() external onlyDao returns (bool) {
mintable = false;
return true;
}
function disableBurning() external onlyDao returns (bool) {
burnable = false;
return true;
}
/*----LP---------------------------------------------*/
function setLp(address _lp) external onlyDao returns (bool) { // onlyDao check for feauture edit
require(lp == address(0), "DAO: LP address has already been set");
//require(msg.sender == shop, "DAO: only Shop can set LP");
lp = _lp;
return true;
}
/*----QUORUM-----------------------------------------*/
function changeQuorum(uint8 _q) external onlyDao returns (bool) {
require(_q >= 1 && _q <= 100, "DAO: quorum should be 1 <= q <= 100");
quorum = _q;
return true;
}
/*----VIEW FUNCTIONS---------------------------------*/
function getPartners()
external
view
returns (address[] memory)
{
return partners;
}
function getShares()
external
view
returns (uint256[] memory)
{
return shares;
}
function getProposalById(uint id)
public
view
returns (Proposal memory)
{
return proposals[id];
}
function executedProposalByIndex(uint256 _index)
external
view
returns (ExecutedProposal memory)
{
return executedProposal[_index];
}
function getExecutedProposal()
external
view
returns (ExecutedProposal[] memory)
{
return executedProposal;
}
function numberOfAdapters() external view returns (uint256) {
return adapters.length();
}
function containsAdapter(address a) external view returns (bool) {
return adapters.contains(a);
}
function getAdapters() external view returns (address[] memory) {
uint256 adaptersLength = adapters.length();
if (adaptersLength == 0) {
return new address[](0);
} else {
address[] memory adaptersArray = new address[](adaptersLength);
for (uint256 i = 0; i < adaptersLength; i++) {
adaptersArray[i] = adapters.at(i);
}
return adaptersArray;
}
}
/*----PURE FUNCTIONS---------------------------------*/
function toAsciiString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2*i] = char(hi);
s[2*i+1] = char(lo);
}
return string(s);
}
function char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
function appendString(string memory _a, string memory _b, string memory _c) internal pure returns (string memory) {
return string(abi.encodePacked(_a, _b, _c));
}
function _hasDuplicate(address[] memory A) internal pure returns (bool) {
if (A.length <= 1) {
return false;
} else {
for (uint256 i = 0; i < A.length - 1; i++) {
address current = A[i];
for (uint256 j = i + 1; j < A.length; j++) {
if (current == A[j]) {
return true;
}
}
}
}
return false;
}
function transfer(address, uint256) public pure override returns (bool) {
revert("GT: transfer is prohibited");
}
function transferFrom(
address,
address,
uint256
) public pure override returns (bool) {
revert("GT: transferFrom is prohibited");
}
/*----RECEIVE ETH------------------------------------*/
event Received(address indexed, uint256);
receive() external payable {
emit Received(msg.sender, msg.value);
}
/*----Change voting duration---------------------------*/
function changeVotingDuration(uint32 _days)
external onlyDao returns (bool) {
require(_days >= 1 && _days <= 255, "DAO: Unsupported voting duration");
VOTING_DURATION = _days * 1 days;
return true;
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"uint8","name":"_quorum","internalType":"uint8"},{"type":"address[]","name":"_partners","internalType":"address[]"},{"type":"uint256[]","name":"_shares","internalType":"uint256[]"},{"type":"string","name":"_apiUrl","internalType":"string"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Executed","inputs":[{"type":"address","name":"target","internalType":"address","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"uint256","name":"nonce","internalType":"uint256","indexed":true},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"uint256","name":"executionTimestamp","internalType":"uint256","indexed":false},{"type":"bytes32","name":"txHash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferRequested","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Received","inputs":[{"type":"address","name":"","internalType":"address","indexed":true},{"type":"uint256","name":"","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RequestQuorumStatus","inputs":[{"type":"bytes32","name":"requestId","internalType":"bytes32","indexed":true},{"type":"uint256","name":"id","internalType":"uint256","indexed":false},{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"VOTING_DURATION","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"_checkSigs","inputs":[{"type":"bytes[]","name":"_sigs","internalType":"bytes[]"},{"type":"bytes32","name":"_txHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"thisId","internalType":"uint256"}],"name":"addProposal","inputs":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"string","name":"discription","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"burn","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"burnLp","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_share","internalType":"uint256"},{"type":"address[]","name":"_tokens","internalType":"address[]"},{"type":"address[]","name":"_adapters","internalType":"address[]"},{"type":"address[]","name":"_pools","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"burnable","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"changeQuorum","inputs":[{"type":"uint8","name":"_q","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"changeVotingDuration","inputs":[{"type":"uint32","name":"_days","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"containsAdapter","inputs":[{"type":"address","name":"a","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"disableBurning","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"disableMinting","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"execute","inputs":[{"type":"uint256","name":"_proposalId","internalType":"uint256"},{"type":"bytes[]","name":"_sigs","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Dao.ExecutedProposal","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"executionTimestamp","internalType":"uint256"},{"type":"bytes32","name":"txHash","internalType":"bytes32"},{"type":"bytes[]","name":"sigs","internalType":"bytes[]"}]}],"name":"executedProposalByIndex","inputs":[{"type":"uint256","name":"_index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"executedTx","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getAdapters","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Dao.ExecutedProposal[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"executionTimestamp","internalType":"uint256"},{"type":"bytes32","name":"txHash","internalType":"bytes32"},{"type":"bytes[]","name":"sigs","internalType":"bytes[]"}]}],"name":"getExecutedProposal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getPartners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Dao.Proposal","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"string","name":"discription","internalType":"string"},{"type":"uint256","name":"timestamp","internalType":"uint256"}]}],"name":"getProposalById","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getShares","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getTxHash","inputs":[{"type":"address","name":"_target","internalType":"address"},{"type":"bytes","name":"_data","internalType":"bytes"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"uint256","name":"_nonce","internalType":"uint256"},{"type":"uint256","name":"_timestamp","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"lp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mint","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"mintable","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"move","inputs":[{"type":"address","name":"_sender","internalType":"address"},{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numberOfAdapters","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"quorum","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"setLp","inputs":[{"type":"address","name":"_lp","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"to","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x60806040526007805463ffffffff60a01b19166107e960a71b179055600a80546001600160a01b03191690556000600c556014805461ffff19166101011790553480156200004c57600080fd5b5060405162004a3838038062004a388339810160408190526200006f9162000744565b6001600090815533908190888860046200008a8382620008c4565b506005620000998282620008c4565b5050506001600160a01b038216620000f85760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600680546001600160a01b0319166001600160a01b03848116919091179091558116156200012b576200012b81620002e8565b50505060018460ff161015801562000147575060648460ff1611155b620001a15760405162461bcd60e51b815260206004820152602360248201527f44414f3a2071756f72756d2073686f756c642062652031203c3d2071203c3d2060448201526203130360ec1b6064820152608401620000ef565b600a805460ff60a01b1916600160a01b60ff871602179055825115801590620001cb575081518351145b620002255760405162461bcd60e51b815260206004820152602360248201527f44414f3a2073686172657320646973747269627574696f6e20697320696e76616044820152621b1a5960ea1b6064820152608401620000ef565b82516200023a90600d9060208601906200047e565b5081516200025090600e906020850190620004e8565b50600b6200025f8282620008c4565b50600b6200026e8282620008c4565b5060005b8351811015620002db57620002c684828151811062000295576200029562000990565b6020026020010151848381518110620002b257620002b262000990565b60200260200101516200039460201b60201c565b80620002d281620009bc565b91505062000272565b50505050505050620009f3565b336001600160a01b03821603620003425760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620000ef565b600780546001600160a01b0319166001600160a01b03838116918217909255600654604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b6001600160a01b038216620003ec5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401620000ef565b8060036000828254620004009190620009d8565b90915550506001600160a01b038216600090815260016020526040812080548392906200042f908490620009d8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b505050565b828054828255906000526020600020908101928215620004d6579160200282015b82811115620004d657825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906200049f565b50620004e492915062000526565b5090565b828054828255906000526020600020908101928215620004d6579160200282015b82811115620004d657825182559160200191906001019062000509565b5b80821115620004e4576000815560010162000527565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200057e576200057e6200053d565b604052919050565b600082601f8301126200059857600080fd5b81516001600160401b03811115620005b457620005b46200053d565b6020620005ca601f8301601f1916820162000553565b8281528582848701011115620005df57600080fd5b60005b83811015620005ff578581018301518282018401528201620005e2565b83811115620006115760008385840101525b5095945050505050565b805160ff811681146200062d57600080fd5b919050565b60006001600160401b038211156200064e576200064e6200053d565b5060051b60200190565b600082601f8301126200066a57600080fd5b81516020620006836200067d8362000632565b62000553565b82815260059290921b84018101918181019086841115620006a357600080fd5b8286015b84811015620006d75780516001600160a01b0381168114620006c95760008081fd5b8352918301918301620006a7565b509695505050505050565b600082601f830112620006f457600080fd5b81516020620007076200067d8362000632565b82815260059290921b840181019181810190868411156200072757600080fd5b8286015b84811015620006d757805183529183019183016200072b565b60008060008060008060c087890312156200075e57600080fd5b86516001600160401b03808211156200077657600080fd5b620007848a838b0162000586565b975060208901519150808211156200079b57600080fd5b620007a98a838b0162000586565b9650620007b960408a016200061b565b95506060890151915080821115620007d057600080fd5b620007de8a838b0162000658565b94506080890151915080821115620007f557600080fd5b620008038a838b01620006e2565b935060a08901519150808211156200081a57600080fd5b506200082989828a0162000586565b9150509295509295509295565b600181811c908216806200084b57607f821691505b6020821081036200086c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200047957600081815260208120601f850160051c810160208610156200089b5750805b601f850160051c820191505b81811015620008bc57828155600101620008a7565b505050505050565b81516001600160401b03811115620008e057620008e06200053d565b620008f881620008f1845462000836565b8462000872565b602080601f831160018114620009305760008415620009175750858301515b600019600386901b1c1916600185901b178555620008bc565b600085815260208120601f198616915b82811015620009615788860151825594840194600190910190840162000940565b5085821015620009805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620009d157620009d1620009a6565b5060010190565b60008219821115620009ee57620009ee620009a6565b500190565b6140358062000a036000396000f3fe60806040526004361061024a5760003560e01c80637e5cd5c111610139578063bb35783b116100b6578063e5a076781161007a578063e5a076781461074d578063f00d192c1461076d578063f2fde38b1461079a578063f46c503d146107ba578063f4c2baa9146107dc578063fba4e62e146107fc57600080fd5b8063bb35783b14610675578063cbe380fc14610695578063cdb2c042146106b5578063d73fe0aa146106e5578063dd62ed3e1461070757600080fd5b8063a07c7ce4116100fd578063a07c7ce4146105c8578063a438d208146105e7578063a457c2d714610620578063a9059cbb14610640578063b82e16e31461066057600080fd5b80637e5cd5c11461054b5780638da5cb5b1461056057806395d89b411461057e57806398603cca146105935780639dc29fac146105a857600080fd5b806339509351116101c75780634bf365df1161018b5780634bf365df146104ad5780634faa2e7b146104c757806370a08231146104dc57806373e29b0d1461051257806379ba50971461053457600080fd5b8063395093511461040d5780633d4581831461042d5780633ef103421461044d57806340c10f191461046d578063442ec5821461048d57600080fd5b806323b872dd1161020e57806323b872dd14610354578063313c06a014610374578063313ce567146103ac5780633372358f146103c05780633656de21146103e057600080fd5b806305cf79b91461028b57806306fdde03146102c0578063095ea7b3146102e25780631703a0181461030257806318160ddd1461033557600080fd5b366102865760405134815233907f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258749060200160405180910390a2005b600080fd5b34801561029757600080fd5b506102ab6102a6366004613469565b61081c565b60405190151581526020015b60405180910390f35b3480156102cc57600080fd5b506102d56108d7565b6040516102b791906134e4565b3480156102ee57600080fd5b506102ab6102fd36600461350e565b610969565b34801561030e57600080fd5b50600a5461032390600160a01b900460ff1681565b60405160ff90911681526020016102b7565b34801561034157600080fd5b506003545b6040519081526020016102b7565b34801561036057600080fd5b506102ab61036f366004613538565b610980565b34801561038057600080fd5b50600a54610394906001600160a01b031681565b6040516001600160a01b0390911681526020016102b7565b3480156103b857600080fd5b506012610323565b3480156103cc57600080fd5b506103466103db366004613629565b6109cb565b3480156103ec57600080fd5b506104006103fb366004613691565b610a0b565b6040516102b791906136aa565b34801561041957600080fd5b506102ab61042836600461350e565b610bb1565b34801561043957600080fd5b506102ab610448366004613716565b610bed565b34801561045957600080fd5b506102ab6104683660046137e3565b610bfa565b34801561047957600080fd5b506102ab61048836600461350e565b611024565b34801561049957600080fd5b506103466104a8366004613871565b6110a1565b3480156104b957600080fd5b506014546102ab9060ff1681565b3480156104d357600080fd5b50610346611249565b3480156104e857600080fd5b506103466104f7366004613716565b6001600160a01b031660009081526001602052604090205490565b34801561051e57600080fd5b5061052761125a565b6040516102b791906138fa565b34801561054057600080fd5b506105496112bb565b005b34801561055757600080fd5b506102ab611369565b34801561056c57600080fd5b506006546001600160a01b0316610394565b34801561058a57600080fd5b506102d561139a565b34801561059f57600080fd5b506102ab6113a9565b3480156105b457600080fd5b506102ab6105c336600461350e565b6113db565b3480156105d457600080fd5b506014546102ab90610100900460ff1681565b3480156105f357600080fd5b5060075461060b90600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016102b7565b34801561062c57600080fd5b506102ab61063b36600461350e565b61145d565b34801561064c57600080fd5b506102ab61065b36600461350e565b6114f6565b34801561066c57600080fd5b50610527611541565b34801561068157600080fd5b506102ab610690366004613538565b611610565b3480156106a157600080fd5b506102ab6106b0366004613947565b611643565b3480156106c157600080fd5b506102ab6106d0366004613691565b60136020526000908152604090205460ff1681565b3480156106f157600080fd5b506106fa611865565b6040516102b7919061398b565b34801561071357600080fd5b506103466107223660046139c3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b34801561075957600080fd5b506102ab6107683660046139f6565b6118bc565b34801561077957600080fd5b5061078d610788366004613691565b611981565b6040516102b79190613adc565b3480156107a657600080fd5b506105496107b5366004613716565b611bbc565b3480156107c657600080fd5b506107cf611bd0565b6040516102b79190613aef565b3480156107e857600080fd5b506102ab6107f7366004613716565b611de3565b34801561080857600080fd5b506102ab610817366004613bb3565b611e8e565b60003330146108465760405162461bcd60e51b815260040161083d90613c55565b60405180910390fd5b60018260ff161015801561085e575060648260ff1611155b6108b65760405162461bcd60e51b815260206004820152602360248201527f44414f3a2071756f72756d2073686f756c642062652031203c3d2071203c3d2060448201526203130360ec1b606482015260840161083d565b50600a805460ff60a01b1916600160a01b60ff84160217905560015b919050565b6060600480546108e690613c97565b80601f016020809104026020016040519081016040528092919081815260200182805461091290613c97565b801561095f5780601f106109345761010080835404028352916020019161095f565b820191906000526020600020905b81548152906001019060200180831161094257829003601f168201915b5050505050905090565b60006109763384846125ce565b5060015b92915050565b60405162461bcd60e51b815260206004820152601e60248201527f47543a207472616e7366657246726f6d2069732070726f686962697465640000604482015260009060640161083d565b6000308686868686466040516020016109ea9796959493929190613cd1565b60405160208183030381529060405280519060200120905095945050505050565b610a466040518060a0016040528060006001600160a01b03168152602001606081526020016000815260200160608152602001600081525090565b600082815260106020908152604091829020825160a0810190935280546001600160a01b031683526001810180549192840191610a8290613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054610aae90613c97565b8015610afb5780601f10610ad057610100808354040283529160200191610afb565b820191906000526020600020905b815481529060010190602001808311610ade57829003601f168201915b5050505050815260200160028201548152602001600382018054610b1e90613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4a90613c97565b8015610b975780601f10610b6c57610100808354040283529160200191610b97565b820191906000526020600020905b815481529060010190602001808311610b7a57829003601f168201915b505050505081526020016004820154815250509050919050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610976918590610be8908690613d39565b6125ce565b600061097a6008836126f2565b6000600260005403610c1e5760405162461bcd60e51b815260040161083d90613d51565b600260009081553381526001602052604081205411610c775760405162461bcd60e51b815260206004820152601560248201527444414f3a206f6e6c7920666f72206d656d6265727360581b604482015260640161083d565b60008381526011602052604090205460ff16610cd55760405162461bcd60e51b815260206004820152601d60248201527f44414f3a2070726551756f72756d206973206e6f742072656163686564000000604482015260640161083d565b6000610ce084610a0b565b8051602082015160408301516080840151600c546007549596509394929391929091904290610d1c90600160a01b900463ffffffff1684613d39565b1015610d605760405162461bcd60e51b81526020600482015260136024820152722220a79d103b37ba34b7339034b99037bb32b960691b604482015260640161083d565b6000610d6f86868685876109cb565b60008181526013602052604090205490915060ff1615610dd15760405162461bcd60e51b815260206004820152601d60248201527f44414f3a2070726f706f736520616c7265616479206578656375746564000000604482015260640161083d565b610ddb8982611643565b610e275760405162461bcd60e51b815260206004820152601a60248201527f44414f3a2071756f72756d206973206e6f742072656163686564000000000000604482015260640161083d565b60008181526013602090815260408083208054600160ff1990911681179091558151610100810183526001600160a01b038b811682529381018a815292810189905260608101879052608081018890524260a082015260c0810186905260e081018e905260128054928301815590945283517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600890920291820180546001600160a01b0319169190941617835590517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344590910190610f069082613dd6565b5060408201516002820155606082015160038201556080820151600482015560a0820151600582015560c0820151600682015560e08201518051610f549160078401916020909101906133b4565b50505081866001600160a01b03167fd1b2db6ce2b127bbccbacbc1d2917e54605dfc8765b24f8240cf1adb16a3ec3e8787874287604051610f99959493929190613e95565b60405180910390a3600c8054906000610fb183613ecc565b91905055508451600003610fd757610fd26001600160a01b03871685612714565b61100e565b83600003610ff857610ff26001600160a01b03871686612832565b5061100e565b61100c6001600160a01b0387168686612874565b505b6001975050505050505050600160005592915050565b60003330146110455760405162461bcd60e51b815260040161083d90613c55565b60145460ff166110975760405162461bcd60e51b815260206004820152601b60248201527f44414f3a204754206d696e74696e672069732064697361626c65640000000000604482015260640161083d565b61097683836128a2565b60006002600054036110c55760405162461bcd60e51b815260040161083d90613d51565b60026000908155338152600160205260408120541161111e5760405162461bcd60e51b815260206004820152601560248201527444414f3a206f6e6c7920666f72206d656d6265727360581b604482015260640161083d565b600f805490600061112e83613ecc565b91905055905060004290506040518060a00160405280896001600160a01b0316815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602080820188905260408051601f88018390048302810183018252878152920191908790879081908401838280828437600092018290525093855250505060209182018490528481526010825260409020825181546001600160a01b0319166001600160a01b0390911617815590820151600182019061120c9082613dd6565b50604082015160028201556060820151600382019061122b9082613dd6565b50608091909101516004909101555060016000559695505050505050565b60006112556008612981565b905090565b6060600d80548060200260200160405190810160405280929190818152602001828054801561095f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611294575050505050905090565b6007546001600160a01b0316331461130e5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b604482015260640161083d565b600680546001600160a01b0319808216339081179093556007805490911690556040516001600160a01b03909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b600033301461138a5760405162461bcd60e51b815260040161083d90613c55565b506014805460ff19169055600190565b6060600580546108e690613c97565b60003330146113ca5760405162461bcd60e51b815260040161083d90613c55565b506014805461ff0019169055600190565b60003330146113fc5760405162461bcd60e51b815260040161083d90613c55565b601454610100900460ff166114535760405162461bcd60e51b815260206004820152601b60248201527f44414f3a204754206275726e696e672069732064697361626c65640000000000604482015260640161083d565b610976838361298b565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156114df5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161083d565b6114ec33858584036125ce565b5060019392505050565b60405162461bcd60e51b815260206004820152601a60248201527f47543a207472616e736665722069732070726f68696269746564000000000000604482015260009060640161083d565b6060600061154f6008612981565b90508060000361156d57505060408051600081526020810190915290565b6000816001600160401b0381111561158757611587613574565b6040519080825280602002602001820160405280156115b0578160200160208202803683370190505b50905060005b82811015611605576115c9600882612ad9565b8282815181106115db576115db613ee5565b6001600160a01b0390921660209283029190910190910152806115fd81613ecc565b9150506115b6565b5092915050565b5090565b60003330146116315760405162461bcd60e51b815260040161083d90613c55565b6114ec848484612ae5565b9392505050565b60008061169d836040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b905060008085516001600160401b038111156116bb576116bb613574565b6040519080825280602002602001820160405280156116e4578160200160208202803683370190505b50905060005b865181101561176157600061172188838151811061170a5761170a613ee5565b602002602001015186612cb590919063ffffffff16565b90508083838151811061173657611736613ee5565b6001600160a01b0390921660209283029190910190910152508061175981613ecc565b9150506116ea565b5061176b81612d57565b156117b85760405162461bcd60e51b815260206004820152601e60248201527f44414f3a207369676e61747572657320617265206e6f7420756e697175650000604482015260640161083d565b60005b815181101561181a576117fc8282815181106117d9576117d9613ee5565b60200260200101516001600160a01b031660009081526001602052604090205490565b6118069084613d39565b92508061181281613ecc565b9150506117bb565b50600a5460ff600160a01b9091041661183260035490565b61183c9190613efb565b611847836064613efb565b1015611859576000935050505061097a565b50600195945050505050565b6060600e80548060200260200160405190810160405280929190818152602001828054801561095f57602002820191906000526020600020905b81548152602001906001019080831161189f575050505050905090565b60003330146118dd5760405162461bcd60e51b815260040161083d90613c55565b60018263ffffffff16101580156118fb575060ff8263ffffffff1611155b6119475760405162461bcd60e51b815260206004820181905260248201527f44414f3a20556e737570706f7274656420766f74696e67206475726174696f6e604482015260640161083d565b6119548262015180613f1a565b6007805463ffffffff92909216600160a01b0263ffffffff60a01b19909216919091179055506001919050565b6119d560405180610100016040528060006001600160a01b03168152602001606081526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b601282815481106119e8576119e8613ee5565b600091825260209182902060408051610100810190915260089092020180546001600160a01b031682526001810180549293919291840191611a2990613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5590613c97565b8015611aa25780601f10611a7757610100808354040283529160200191611aa2565b820191906000526020600020905b815481529060010190602001808311611a8557829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015611bae578382906000526020600020018054611b2190613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611b4d90613c97565b8015611b9a5780601f10611b6f57610100808354040283529160200191611b9a565b820191906000526020600020905b815481529060010190602001808311611b7d57829003601f168201915b505050505081526020019060010190611b02565b505050915250909392505050565b611bc4612e28565b611bcd81612e7d565b50565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015611dda5760008481526020908190206040805161010081019091526008850290910180546001600160a01b031682526001810180549293919291840191611c3e90613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6a90613c97565b8015611cb75780601f10611c8c57610100808354040283529160200191611cb7565b820191906000526020600020905b815481529060010190602001808311611c9a57829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015611dc3578382906000526020600020018054611d3690613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6290613c97565b8015611daf5780601f10611d8457610100808354040283529160200191611daf565b820191906000526020600020905b815481529060010190602001808311611d9257829003601f168201915b505050505081526020019060010190611d17565b505050508152505081526020019060010190611bf4565b50505050905090565b6000333014611e045760405162461bcd60e51b815260040161083d90613c55565b600a546001600160a01b031615611e695760405162461bcd60e51b8152602060048201526024808201527f44414f3a204c5020616464726573732068617320616c7265616479206265656e604482015263081cd95d60e21b606482015260840161083d565b50600a80546001600160a01b0383166001600160a01b03199091161790556001919050565b6000600260005403611eb25760405162461bcd60e51b815260040161083d90613d51565b6002600055600a546001600160a01b0316611f055760405162461bcd60e51b8152602060048201526013602482015272111053ce881314081b9bdd081cd95d081e595d606a1b604482015260640161083d565b600a546001600160a01b03163314611f525760405162461bcd60e51b815260206004820152601060248201526f044414f3a206f6e6c7920666f72204c560841b604482015260640161083d565b611f5b84612d57565b15611fb85760405162461bcd60e51b815260206004820152602760248201527f44414f3a206475706c696361746573206172652070726f686962697465642028604482015266746f6b656e732960c81b606482015260840161083d565b60005b84518110156120a057600a5485516001600160a01b0390911690869083908110611fe757611fe7613ee5565b60200260200101516001600160a01b0316141580156120315750306001600160a01b031685828151811061201d5761201d613ee5565b60200260200101516001600160a01b031614155b61208e5760405162461bcd60e51b815260206004820152602860248201527f44414f3a204c5020616e642047542063616e6e6f742062652070617274206f66604482015267206120736861726560c01b606482015260840161083d565b8061209881613ecc565b915050611fbb565b5081518351146120e85760405162461bcd60e51b81526020600482015260136024820152722220a79d1030b230b83a32b9399032b93937b960691b604482015260640161083d565b82511561224557825160018111156122435760005b612108600183613f46565b81101561224157600061211c826001613d39565b90505b8281101561222e5785818151811061213957612139613ee5565b60200260200101516001600160a01b031686838151811061215c5761215c613ee5565b60200260200101516001600160a01b03161480156121bd575084818151811061218757612187613ee5565b60200260200101516001600160a01b03168583815181106121aa576121aa613ee5565b60200260200101516001600160a01b0316145b1561221c5760405162461bcd60e51b815260206004820152602960248201527f44414f3a206475706c696361746573206172652070726f68696269746564202860448201526861646170746572732960b81b606482015260840161083d565b8061222681613ecc565b91505061211f565b508061223981613ecc565b9150506120fd565b505b505b612275670de0b6b3a764000061225b8747613efb565b6122659190613f5d565b6001600160a01b03881690612714565b83511561241457600084516001600160401b0381111561229757612297613574565b6040519080825280602002602001820160405280156122c0578160200160208202803683370190505b50905060005b85518110156123a257670de0b6b3a7640000878783815181106122eb576122eb613ee5565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f9190613f7f565b6123699190613efb565b6123739190613f5d565b82828151811061238557612385613ee5565b60209081029190910101528061239a81613ecc565b9150506122c6565b5060005b8551811015612411576123ff888383815181106123c5576123c5613ee5565b60200260200101518884815181106123df576123df613ee5565b60200260200101516001600160a01b0316612f279092919063ffffffff16565b8061240981613ecc565b9150506123a6565b50505b8251156125be57825160005b818110156125bb5761245585828151811061243d5761243d613ee5565b602002602001015160086126f290919063ffffffff16565b6124a15760405162461bcd60e51b815260206004820152601b60248201527f44414f3a2074686973206973206e6f7420616e20616461707465720000000000604482015260640161083d565b60008582815181106124b5576124b5613ee5565b60200260200101516001600160a01b031663d9caed128a8785815181106124de576124de613ee5565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018b90526064016020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125619190613f98565b9050806125a85760405162461bcd60e51b81526020600482015260156024820152742220a79d103bb4ba34323930bbb0b61032b93937b960591b604482015260640161083d565b50806125b381613ecc565b915050612420565b50505b5060018060005595945050505050565b6001600160a01b0383166126305760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161083d565b6001600160a01b0382166126915760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161083d565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0381166000908152600183016020526040812054151561163c565b804710156127645760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161083d565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146127b1576040519150601f19603f3d011682016040523d82523d6000602084013e6127b6565b606091505b505090508061282d5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161083d565b505050565b606061163c83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612f79565b606061289a848484604051806060016040528060298152602001613fd760299139612f84565b949350505050565b6001600160a01b0382166128f85760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161083d565b806003600082825461290a9190613d39565b90915550506001600160a01b03821660009081526001602052604081208054839290612937908490613d39565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600061097a825490565b6001600160a01b0382166129eb5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161083d565b6001600160a01b03821660009081526001602052604090205481811015612a5f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161083d565b6001600160a01b0383166000908152600160205260408120838303905560038054849290612a8e908490613f46565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600061163c83836130ac565b6001600160a01b038316612b495760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161083d565b6001600160a01b038216612bab5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161083d565b6001600160a01b03831660009081526001602052604090205481811015612c235760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161083d565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290612c5a908490613d39565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ca691815260200190565b60405180910390a35b50505050565b60008151604103612ce85760208201516040830151606084015160001a612cde868285856130d6565b935050505061097a565b8151604003612d0f5760208201516040830151612d0685838361327f565b9250505061097a565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161083d565b60006001825111612d6a57506000919050565b60005b60018351612d7b9190613f46565b811015612e1f576000838281518110612d9657612d96613ee5565b602002602001015190506000826001612daf9190613d39565b90505b8451811015612e0a57848181518110612dcd57612dcd613ee5565b60200260200101516001600160a01b0316826001600160a01b031603612df857506001949350505050565b80612e0281613ecc565b915050612db2565b50508080612e1790613ecc565b915050612d6d565b50506000919050565b6006546001600160a01b03163314612e7b5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b604482015260640161083d565b565b336001600160a01b03821603612ed55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161083d565b600780546001600160a01b0319166001600160a01b03838116918217909255600654604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261282d9084906132a9565b606061289a84846000855b606082471015612fe55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161083d565b843b6130335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161083d565b600080866001600160a01b0316858760405161304f9190613fba565b60006040518083038185875af1925050503d806000811461308c576040519150601f19603f3d011682016040523d82523d6000602084013e613091565b606091505b50915091506130a182828661337b565b979650505050505050565b60008260000182815481106130c3576130c3613ee5565b9060005260206000200154905092915050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156131535760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161083d565b8360ff16601b148061316857508360ff16601c145b6131bf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161083d565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015613213573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166132765760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161083d565b95945050505050565b60006001600160ff1b03821660ff83901c601b0161329f868287856130d6565b9695505050505050565b60006132fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f799092919063ffffffff16565b80519091501561282d578080602001905181019061331c9190613f98565b61282d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161083d565b6060831561338a57508161163c565b82511561339a5782518084602001fd5b8160405162461bcd60e51b815260040161083d91906134e4565b8280548282559060005260206000209081019282156133fa579160200282015b828111156133fa57825182906133ea9082613dd6565b50916020019190600101906133d4565b5061160c9291505b8082111561160c576000613416828261341f565b50600101613402565b50805461342b90613c97565b6000825580601f1061343b575050565b601f016020900490600052602060002090810190611bcd91905b8082111561160c5760008155600101613455565b60006020828403121561347b57600080fd5b813560ff8116811461163c57600080fd5b60005b838110156134a757818101518382015260200161348f565b83811115612caf5750506000910152565b600081518084526134d081602086016020860161348c565b601f01601f19169290920160200192915050565b60208152600061163c60208301846134b8565b80356001600160a01b03811681146108d257600080fd5b6000806040838503121561352157600080fd5b61352a836134f7565b946020939093013593505050565b60008060006060848603121561354d57600080fd5b613556846134f7565b9250613564602085016134f7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156135b2576135b2613574565b604052919050565b600082601f8301126135cb57600080fd5b81356001600160401b038111156135e4576135e4613574565b6135f7601f8201601f191660200161358a565b81815284602083860101111561360c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561364157600080fd5b61364a866134f7565b945060208601356001600160401b0381111561366557600080fd5b613671888289016135ba565b959895975050505060408401359360608101359360809091013592509050565b6000602082840312156136a357600080fd5b5035919050565b602080825282516001600160a01b03168282015282015160a060408301526000906136d860c08401826134b8565b9050604084015160608401526060840151601f198483030160808501526136ff82826134b8565b915050608084015160a08401528091505092915050565b60006020828403121561372857600080fd5b61163c826134f7565b60006001600160401b0382111561374a5761374a613574565b5060051b60200190565b600082601f83011261376557600080fd5b8135602061377a61377583613731565b61358a565b82815260059290921b8401810191818101908684111561379957600080fd5b8286015b848110156137d85780356001600160401b038111156137bc5760008081fd5b6137ca8986838b01016135ba565b84525091830191830161379d565b509695505050505050565b600080604083850312156137f657600080fd5b8235915060208301356001600160401b0381111561381357600080fd5b61381f85828601613754565b9150509250929050565b60008083601f84011261383b57600080fd5b5081356001600160401b0381111561385257600080fd5b60208301915083602082850101111561386a57600080fd5b9250929050565b6000806000806000806080878903121561388a57600080fd5b613893876134f7565b955060208701356001600160401b03808211156138af57600080fd5b6138bb8a838b01613829565b90975095506040890135945060608901359150808211156138db57600080fd5b506138e889828a01613829565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b8181101561393b5783516001600160a01b031683529284019291840191600101613916565b50909695505050505050565b6000806040838503121561395a57600080fd5b82356001600160401b0381111561397057600080fd5b61397c85828601613754565b95602094909401359450505050565b6020808252825182820181905260009190848201906040850190845b8181101561393b578351835292840192918401916001016139a7565b600080604083850312156139d657600080fd5b6139df836134f7565b91506139ed602084016134f7565b90509250929050565b600060208284031215613a0857600080fd5b813563ffffffff8116811461163c57600080fd5b600061010060018060a01b0383511684526020808401518282870152613a44838701826134b8565b92505060408401516040860152606084015160608601526080840151608086015260a084015160a086015260c084015160c086015260e084015185830360e08701528281518085528385019150838160051b860101848401935060005b82811015613acf57601f19878303018452613abd8286516134b8565b94860194938601939150600101613aa1565b5098975050505050505050565b60208152600061163c6020830184613a1c565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613b4457603f19888603018452613b32858351613a1c565b94509285019290850190600101613b16565b5092979650505050505050565b600082601f830112613b6257600080fd5b81356020613b7261377583613731565b82815260059290921b84018101918181019086841115613b9157600080fd5b8286015b848110156137d857613ba6816134f7565b8352918301918301613b95565b600080600080600060a08688031215613bcb57600080fd5b613bd4866134f7565b94506020860135935060408601356001600160401b0380821115613bf757600080fd5b613c0389838a01613b51565b94506060880135915080821115613c1957600080fd5b613c2589838a01613b51565b93506080880135915080821115613c3b57600080fd5b50613c4888828901613b51565b9150509295509295909350565b60208082526022908201527f44414f3a20746869732066756e6374696f6e206973206f6e6c7920666f722044604082015261414f60f01b606082015260800190565b600181811c90821680613cab57607f821691505b602082108103613ccb57634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0388811682528716602082015260e060408201819052600090613cfd908301886134b8565b90508560608301528460808301528360a08301528260c083015298975050505050505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115613d4c57613d4c613d23565b500190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b601f82111561282d57600081815260208120601f850160051c81016020861015613daf5750805b601f850160051c820191505b81811015613dce57828155600101613dbb565b505050505050565b81516001600160401b03811115613def57613def613574565b613e0381613dfd8454613c97565b84613d88565b602080601f831160018114613e385760008415613e205750858301515b600019600386901b1c1916600185901b178555613dce565b600085815260208120601f198616915b82811015613e6757888601518255948401946001909101908401613e48565b5085821015613e855787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60a081526000613ea860a08301886134b8565b90508560208301528460408301528360608301528260808301529695505050505050565b600060018201613ede57613ede613d23565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615613f1557613f15613d23565b500290565b600063ffffffff80831681851681830481118215151615613f3d57613f3d613d23565b02949350505050565b600082821015613f5857613f58613d23565b500390565b600082613f7a57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215613f9157600080fd5b5051919050565b600060208284031215613faa57600080fd5b8151801515811461163c57600080fd5b60008251613fcc81846020870161348c565b919091019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220bdac98fc3108881d6bcf375b0854582e85733c8f83a4ee3da986a76f4f55b0fc64736f6c634300080f003300000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000044c5546490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034c55460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000016849ab36ebbd911ad11788c5308dfd57e1c733f00000000000000000000000094e84a13dc2b49962a0e3872ce71aecba7d152ee000000000000000000000000c27cc25a3331831692f03c73eccc15387af2e61d0000000000000000000000002da0fa4782a17cf4afcea08eb2d0ba5413bb3963000000000000000000000000d5e47254ade5d1b6f65f7b40cf27ea7eda04d83b000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002d68747470733a2f2f636f6e74726163742d6170692e64616f747269702e78797a2f64616f2f424954474552542f00000000000000000000000000000000000000
Deployed ByteCode
0x60806040526004361061024a5760003560e01c80637e5cd5c111610139578063bb35783b116100b6578063e5a076781161007a578063e5a076781461074d578063f00d192c1461076d578063f2fde38b1461079a578063f46c503d146107ba578063f4c2baa9146107dc578063fba4e62e146107fc57600080fd5b8063bb35783b14610675578063cbe380fc14610695578063cdb2c042146106b5578063d73fe0aa146106e5578063dd62ed3e1461070757600080fd5b8063a07c7ce4116100fd578063a07c7ce4146105c8578063a438d208146105e7578063a457c2d714610620578063a9059cbb14610640578063b82e16e31461066057600080fd5b80637e5cd5c11461054b5780638da5cb5b1461056057806395d89b411461057e57806398603cca146105935780639dc29fac146105a857600080fd5b806339509351116101c75780634bf365df1161018b5780634bf365df146104ad5780634faa2e7b146104c757806370a08231146104dc57806373e29b0d1461051257806379ba50971461053457600080fd5b8063395093511461040d5780633d4581831461042d5780633ef103421461044d57806340c10f191461046d578063442ec5821461048d57600080fd5b806323b872dd1161020e57806323b872dd14610354578063313c06a014610374578063313ce567146103ac5780633372358f146103c05780633656de21146103e057600080fd5b806305cf79b91461028b57806306fdde03146102c0578063095ea7b3146102e25780631703a0181461030257806318160ddd1461033557600080fd5b366102865760405134815233907f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258749060200160405180910390a2005b600080fd5b34801561029757600080fd5b506102ab6102a6366004613469565b61081c565b60405190151581526020015b60405180910390f35b3480156102cc57600080fd5b506102d56108d7565b6040516102b791906134e4565b3480156102ee57600080fd5b506102ab6102fd36600461350e565b610969565b34801561030e57600080fd5b50600a5461032390600160a01b900460ff1681565b60405160ff90911681526020016102b7565b34801561034157600080fd5b506003545b6040519081526020016102b7565b34801561036057600080fd5b506102ab61036f366004613538565b610980565b34801561038057600080fd5b50600a54610394906001600160a01b031681565b6040516001600160a01b0390911681526020016102b7565b3480156103b857600080fd5b506012610323565b3480156103cc57600080fd5b506103466103db366004613629565b6109cb565b3480156103ec57600080fd5b506104006103fb366004613691565b610a0b565b6040516102b791906136aa565b34801561041957600080fd5b506102ab61042836600461350e565b610bb1565b34801561043957600080fd5b506102ab610448366004613716565b610bed565b34801561045957600080fd5b506102ab6104683660046137e3565b610bfa565b34801561047957600080fd5b506102ab61048836600461350e565b611024565b34801561049957600080fd5b506103466104a8366004613871565b6110a1565b3480156104b957600080fd5b506014546102ab9060ff1681565b3480156104d357600080fd5b50610346611249565b3480156104e857600080fd5b506103466104f7366004613716565b6001600160a01b031660009081526001602052604090205490565b34801561051e57600080fd5b5061052761125a565b6040516102b791906138fa565b34801561054057600080fd5b506105496112bb565b005b34801561055757600080fd5b506102ab611369565b34801561056c57600080fd5b506006546001600160a01b0316610394565b34801561058a57600080fd5b506102d561139a565b34801561059f57600080fd5b506102ab6113a9565b3480156105b457600080fd5b506102ab6105c336600461350e565b6113db565b3480156105d457600080fd5b506014546102ab90610100900460ff1681565b3480156105f357600080fd5b5060075461060b90600160a01b900463ffffffff1681565b60405163ffffffff90911681526020016102b7565b34801561062c57600080fd5b506102ab61063b36600461350e565b61145d565b34801561064c57600080fd5b506102ab61065b36600461350e565b6114f6565b34801561066c57600080fd5b50610527611541565b34801561068157600080fd5b506102ab610690366004613538565b611610565b3480156106a157600080fd5b506102ab6106b0366004613947565b611643565b3480156106c157600080fd5b506102ab6106d0366004613691565b60136020526000908152604090205460ff1681565b3480156106f157600080fd5b506106fa611865565b6040516102b7919061398b565b34801561071357600080fd5b506103466107223660046139c3565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b34801561075957600080fd5b506102ab6107683660046139f6565b6118bc565b34801561077957600080fd5b5061078d610788366004613691565b611981565b6040516102b79190613adc565b3480156107a657600080fd5b506105496107b5366004613716565b611bbc565b3480156107c657600080fd5b506107cf611bd0565b6040516102b79190613aef565b3480156107e857600080fd5b506102ab6107f7366004613716565b611de3565b34801561080857600080fd5b506102ab610817366004613bb3565b611e8e565b60003330146108465760405162461bcd60e51b815260040161083d90613c55565b60405180910390fd5b60018260ff161015801561085e575060648260ff1611155b6108b65760405162461bcd60e51b815260206004820152602360248201527f44414f3a2071756f72756d2073686f756c642062652031203c3d2071203c3d2060448201526203130360ec1b606482015260840161083d565b50600a805460ff60a01b1916600160a01b60ff84160217905560015b919050565b6060600480546108e690613c97565b80601f016020809104026020016040519081016040528092919081815260200182805461091290613c97565b801561095f5780601f106109345761010080835404028352916020019161095f565b820191906000526020600020905b81548152906001019060200180831161094257829003601f168201915b5050505050905090565b60006109763384846125ce565b5060015b92915050565b60405162461bcd60e51b815260206004820152601e60248201527f47543a207472616e7366657246726f6d2069732070726f686962697465640000604482015260009060640161083d565b6000308686868686466040516020016109ea9796959493929190613cd1565b60405160208183030381529060405280519060200120905095945050505050565b610a466040518060a0016040528060006001600160a01b03168152602001606081526020016000815260200160608152602001600081525090565b600082815260106020908152604091829020825160a0810190935280546001600160a01b031683526001810180549192840191610a8290613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054610aae90613c97565b8015610afb5780601f10610ad057610100808354040283529160200191610afb565b820191906000526020600020905b815481529060010190602001808311610ade57829003601f168201915b5050505050815260200160028201548152602001600382018054610b1e90613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4a90613c97565b8015610b975780601f10610b6c57610100808354040283529160200191610b97565b820191906000526020600020905b815481529060010190602001808311610b7a57829003601f168201915b505050505081526020016004820154815250509050919050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610976918590610be8908690613d39565b6125ce565b600061097a6008836126f2565b6000600260005403610c1e5760405162461bcd60e51b815260040161083d90613d51565b600260009081553381526001602052604081205411610c775760405162461bcd60e51b815260206004820152601560248201527444414f3a206f6e6c7920666f72206d656d6265727360581b604482015260640161083d565b60008381526011602052604090205460ff16610cd55760405162461bcd60e51b815260206004820152601d60248201527f44414f3a2070726551756f72756d206973206e6f742072656163686564000000604482015260640161083d565b6000610ce084610a0b565b8051602082015160408301516080840151600c546007549596509394929391929091904290610d1c90600160a01b900463ffffffff1684613d39565b1015610d605760405162461bcd60e51b81526020600482015260136024820152722220a79d103b37ba34b7339034b99037bb32b960691b604482015260640161083d565b6000610d6f86868685876109cb565b60008181526013602052604090205490915060ff1615610dd15760405162461bcd60e51b815260206004820152601d60248201527f44414f3a2070726f706f736520616c7265616479206578656375746564000000604482015260640161083d565b610ddb8982611643565b610e275760405162461bcd60e51b815260206004820152601a60248201527f44414f3a2071756f72756d206973206e6f742072656163686564000000000000604482015260640161083d565b60008181526013602090815260408083208054600160ff1990911681179091558151610100810183526001600160a01b038b811682529381018a815292810189905260608101879052608081018890524260a082015260c0810186905260e081018e905260128054928301815590945283517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600890920291820180546001600160a01b0319169190941617835590517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec344590910190610f069082613dd6565b5060408201516002820155606082015160038201556080820151600482015560a0820151600582015560c0820151600682015560e08201518051610f549160078401916020909101906133b4565b50505081866001600160a01b03167fd1b2db6ce2b127bbccbacbc1d2917e54605dfc8765b24f8240cf1adb16a3ec3e8787874287604051610f99959493929190613e95565b60405180910390a3600c8054906000610fb183613ecc565b91905055508451600003610fd757610fd26001600160a01b03871685612714565b61100e565b83600003610ff857610ff26001600160a01b03871686612832565b5061100e565b61100c6001600160a01b0387168686612874565b505b6001975050505050505050600160005592915050565b60003330146110455760405162461bcd60e51b815260040161083d90613c55565b60145460ff166110975760405162461bcd60e51b815260206004820152601b60248201527f44414f3a204754206d696e74696e672069732064697361626c65640000000000604482015260640161083d565b61097683836128a2565b60006002600054036110c55760405162461bcd60e51b815260040161083d90613d51565b60026000908155338152600160205260408120541161111e5760405162461bcd60e51b815260206004820152601560248201527444414f3a206f6e6c7920666f72206d656d6265727360581b604482015260640161083d565b600f805490600061112e83613ecc565b91905055905060004290506040518060a00160405280896001600160a01b0316815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602080820188905260408051601f88018390048302810183018252878152920191908790879081908401838280828437600092018290525093855250505060209182018490528481526010825260409020825181546001600160a01b0319166001600160a01b0390911617815590820151600182019061120c9082613dd6565b50604082015160028201556060820151600382019061122b9082613dd6565b50608091909101516004909101555060016000559695505050505050565b60006112556008612981565b905090565b6060600d80548060200260200160405190810160405280929190818152602001828054801561095f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611294575050505050905090565b6007546001600160a01b0316331461130e5760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b604482015260640161083d565b600680546001600160a01b0319808216339081179093556007805490911690556040516001600160a01b03909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b600033301461138a5760405162461bcd60e51b815260040161083d90613c55565b506014805460ff19169055600190565b6060600580546108e690613c97565b60003330146113ca5760405162461bcd60e51b815260040161083d90613c55565b506014805461ff0019169055600190565b60003330146113fc5760405162461bcd60e51b815260040161083d90613c55565b601454610100900460ff166114535760405162461bcd60e51b815260206004820152601b60248201527f44414f3a204754206275726e696e672069732064697361626c65640000000000604482015260640161083d565b610976838361298b565b3360009081526002602090815260408083206001600160a01b0386168452909152812054828110156114df5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161083d565b6114ec33858584036125ce565b5060019392505050565b60405162461bcd60e51b815260206004820152601a60248201527f47543a207472616e736665722069732070726f68696269746564000000000000604482015260009060640161083d565b6060600061154f6008612981565b90508060000361156d57505060408051600081526020810190915290565b6000816001600160401b0381111561158757611587613574565b6040519080825280602002602001820160405280156115b0578160200160208202803683370190505b50905060005b82811015611605576115c9600882612ad9565b8282815181106115db576115db613ee5565b6001600160a01b0390921660209283029190910190910152806115fd81613ecc565b9150506115b6565b5092915050565b5090565b60003330146116315760405162461bcd60e51b815260040161083d90613c55565b6114ec848484612ae5565b9392505050565b60008061169d836040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b905060008085516001600160401b038111156116bb576116bb613574565b6040519080825280602002602001820160405280156116e4578160200160208202803683370190505b50905060005b865181101561176157600061172188838151811061170a5761170a613ee5565b602002602001015186612cb590919063ffffffff16565b90508083838151811061173657611736613ee5565b6001600160a01b0390921660209283029190910190910152508061175981613ecc565b9150506116ea565b5061176b81612d57565b156117b85760405162461bcd60e51b815260206004820152601e60248201527f44414f3a207369676e61747572657320617265206e6f7420756e697175650000604482015260640161083d565b60005b815181101561181a576117fc8282815181106117d9576117d9613ee5565b60200260200101516001600160a01b031660009081526001602052604090205490565b6118069084613d39565b92508061181281613ecc565b9150506117bb565b50600a5460ff600160a01b9091041661183260035490565b61183c9190613efb565b611847836064613efb565b1015611859576000935050505061097a565b50600195945050505050565b6060600e80548060200260200160405190810160405280929190818152602001828054801561095f57602002820191906000526020600020905b81548152602001906001019080831161189f575050505050905090565b60003330146118dd5760405162461bcd60e51b815260040161083d90613c55565b60018263ffffffff16101580156118fb575060ff8263ffffffff1611155b6119475760405162461bcd60e51b815260206004820181905260248201527f44414f3a20556e737570706f7274656420766f74696e67206475726174696f6e604482015260640161083d565b6119548262015180613f1a565b6007805463ffffffff92909216600160a01b0263ffffffff60a01b19909216919091179055506001919050565b6119d560405180610100016040528060006001600160a01b03168152602001606081526020016000815260200160008152602001600081526020016000815260200160008019168152602001606081525090565b601282815481106119e8576119e8613ee5565b600091825260209182902060408051610100810190915260089092020180546001600160a01b031682526001810180549293919291840191611a2990613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5590613c97565b8015611aa25780601f10611a7757610100808354040283529160200191611aa2565b820191906000526020600020905b815481529060010190602001808311611a8557829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015611bae578382906000526020600020018054611b2190613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611b4d90613c97565b8015611b9a5780601f10611b6f57610100808354040283529160200191611b9a565b820191906000526020600020905b815481529060010190602001808311611b7d57829003601f168201915b505050505081526020019060010190611b02565b505050915250909392505050565b611bc4612e28565b611bcd81612e7d565b50565b60606012805480602002602001604051908101604052809291908181526020016000905b82821015611dda5760008481526020908190206040805161010081019091526008850290910180546001600160a01b031682526001810180549293919291840191611c3e90613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6a90613c97565b8015611cb75780601f10611c8c57610100808354040283529160200191611cb7565b820191906000526020600020905b815481529060010190602001808311611c9a57829003601f168201915b50505050508152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020016000905b82821015611dc3578382906000526020600020018054611d3690613c97565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6290613c97565b8015611daf5780601f10611d8457610100808354040283529160200191611daf565b820191906000526020600020905b815481529060010190602001808311611d9257829003601f168201915b505050505081526020019060010190611d17565b505050508152505081526020019060010190611bf4565b50505050905090565b6000333014611e045760405162461bcd60e51b815260040161083d90613c55565b600a546001600160a01b031615611e695760405162461bcd60e51b8152602060048201526024808201527f44414f3a204c5020616464726573732068617320616c7265616479206265656e604482015263081cd95d60e21b606482015260840161083d565b50600a80546001600160a01b0383166001600160a01b03199091161790556001919050565b6000600260005403611eb25760405162461bcd60e51b815260040161083d90613d51565b6002600055600a546001600160a01b0316611f055760405162461bcd60e51b8152602060048201526013602482015272111053ce881314081b9bdd081cd95d081e595d606a1b604482015260640161083d565b600a546001600160a01b03163314611f525760405162461bcd60e51b815260206004820152601060248201526f044414f3a206f6e6c7920666f72204c560841b604482015260640161083d565b611f5b84612d57565b15611fb85760405162461bcd60e51b815260206004820152602760248201527f44414f3a206475706c696361746573206172652070726f686962697465642028604482015266746f6b656e732960c81b606482015260840161083d565b60005b84518110156120a057600a5485516001600160a01b0390911690869083908110611fe757611fe7613ee5565b60200260200101516001600160a01b0316141580156120315750306001600160a01b031685828151811061201d5761201d613ee5565b60200260200101516001600160a01b031614155b61208e5760405162461bcd60e51b815260206004820152602860248201527f44414f3a204c5020616e642047542063616e6e6f742062652070617274206f66604482015267206120736861726560c01b606482015260840161083d565b8061209881613ecc565b915050611fbb565b5081518351146120e85760405162461bcd60e51b81526020600482015260136024820152722220a79d1030b230b83a32b9399032b93937b960691b604482015260640161083d565b82511561224557825160018111156122435760005b612108600183613f46565b81101561224157600061211c826001613d39565b90505b8281101561222e5785818151811061213957612139613ee5565b60200260200101516001600160a01b031686838151811061215c5761215c613ee5565b60200260200101516001600160a01b03161480156121bd575084818151811061218757612187613ee5565b60200260200101516001600160a01b03168583815181106121aa576121aa613ee5565b60200260200101516001600160a01b0316145b1561221c5760405162461bcd60e51b815260206004820152602960248201527f44414f3a206475706c696361746573206172652070726f68696269746564202860448201526861646170746572732960b81b606482015260840161083d565b8061222681613ecc565b91505061211f565b508061223981613ecc565b9150506120fd565b505b505b612275670de0b6b3a764000061225b8747613efb565b6122659190613f5d565b6001600160a01b03881690612714565b83511561241457600084516001600160401b0381111561229757612297613574565b6040519080825280602002602001820160405280156122c0578160200160208202803683370190505b50905060005b85518110156123a257670de0b6b3a7640000878783815181106122eb576122eb613ee5565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f9190613f7f565b6123699190613efb565b6123739190613f5d565b82828151811061238557612385613ee5565b60209081029190910101528061239a81613ecc565b9150506122c6565b5060005b8551811015612411576123ff888383815181106123c5576123c5613ee5565b60200260200101518884815181106123df576123df613ee5565b60200260200101516001600160a01b0316612f279092919063ffffffff16565b8061240981613ecc565b9150506123a6565b50505b8251156125be57825160005b818110156125bb5761245585828151811061243d5761243d613ee5565b602002602001015160086126f290919063ffffffff16565b6124a15760405162461bcd60e51b815260206004820152601b60248201527f44414f3a2074686973206973206e6f7420616e20616461707465720000000000604482015260640161083d565b60008582815181106124b5576124b5613ee5565b60200260200101516001600160a01b031663d9caed128a8785815181106124de576124de613ee5565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018b90526064016020604051808303816000875af115801561253d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125619190613f98565b9050806125a85760405162461bcd60e51b81526020600482015260156024820152742220a79d103bb4ba34323930bbb0b61032b93937b960591b604482015260640161083d565b50806125b381613ecc565b915050612420565b50505b5060018060005595945050505050565b6001600160a01b0383166126305760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161083d565b6001600160a01b0382166126915760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161083d565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0381166000908152600183016020526040812054151561163c565b804710156127645760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161083d565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146127b1576040519150601f19603f3d011682016040523d82523d6000602084013e6127b6565b606091505b505090508061282d5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161083d565b505050565b606061163c83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612f79565b606061289a848484604051806060016040528060298152602001613fd760299139612f84565b949350505050565b6001600160a01b0382166128f85760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161083d565b806003600082825461290a9190613d39565b90915550506001600160a01b03821660009081526001602052604081208054839290612937908490613d39565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600061097a825490565b6001600160a01b0382166129eb5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161083d565b6001600160a01b03821660009081526001602052604090205481811015612a5f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161083d565b6001600160a01b0383166000908152600160205260408120838303905560038054849290612a8e908490613f46565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600061163c83836130ac565b6001600160a01b038316612b495760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161083d565b6001600160a01b038216612bab5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161083d565b6001600160a01b03831660009081526001602052604090205481811015612c235760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161083d565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290612c5a908490613d39565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612ca691815260200190565b60405180910390a35b50505050565b60008151604103612ce85760208201516040830151606084015160001a612cde868285856130d6565b935050505061097a565b8151604003612d0f5760208201516040830151612d0685838361327f565b9250505061097a565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161083d565b60006001825111612d6a57506000919050565b60005b60018351612d7b9190613f46565b811015612e1f576000838281518110612d9657612d96613ee5565b602002602001015190506000826001612daf9190613d39565b90505b8451811015612e0a57848181518110612dcd57612dcd613ee5565b60200260200101516001600160a01b0316826001600160a01b031603612df857506001949350505050565b80612e0281613ecc565b915050612db2565b50508080612e1790613ecc565b915050612d6d565b50506000919050565b6006546001600160a01b03163314612e7b5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b604482015260640161083d565b565b336001600160a01b03821603612ed55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161083d565b600780546001600160a01b0319166001600160a01b03838116918217909255600654604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261282d9084906132a9565b606061289a84846000855b606082471015612fe55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161083d565b843b6130335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161083d565b600080866001600160a01b0316858760405161304f9190613fba565b60006040518083038185875af1925050503d806000811461308c576040519150601f19603f3d011682016040523d82523d6000602084013e613091565b606091505b50915091506130a182828661337b565b979650505050505050565b60008260000182815481106130c3576130c3613ee5565b9060005260206000200154905092915050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156131535760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161083d565b8360ff16601b148061316857508360ff16601c145b6131bf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161083d565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015613213573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166132765760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161083d565b95945050505050565b60006001600160ff1b03821660ff83901c601b0161329f868287856130d6565b9695505050505050565b60006132fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f799092919063ffffffff16565b80519091501561282d578080602001905181019061331c9190613f98565b61282d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161083d565b6060831561338a57508161163c565b82511561339a5782518084602001fd5b8160405162461bcd60e51b815260040161083d91906134e4565b8280548282559060005260206000209081019282156133fa579160200282015b828111156133fa57825182906133ea9082613dd6565b50916020019190600101906133d4565b5061160c9291505b8082111561160c576000613416828261341f565b50600101613402565b50805461342b90613c97565b6000825580601f1061343b575050565b601f016020900490600052602060002090810190611bcd91905b8082111561160c5760008155600101613455565b60006020828403121561347b57600080fd5b813560ff8116811461163c57600080fd5b60005b838110156134a757818101518382015260200161348f565b83811115612caf5750506000910152565b600081518084526134d081602086016020860161348c565b601f01601f19169290920160200192915050565b60208152600061163c60208301846134b8565b80356001600160a01b03811681146108d257600080fd5b6000806040838503121561352157600080fd5b61352a836134f7565b946020939093013593505050565b60008060006060848603121561354d57600080fd5b613556846134f7565b9250613564602085016134f7565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156135b2576135b2613574565b604052919050565b600082601f8301126135cb57600080fd5b81356001600160401b038111156135e4576135e4613574565b6135f7601f8201601f191660200161358a565b81815284602083860101111561360c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561364157600080fd5b61364a866134f7565b945060208601356001600160401b0381111561366557600080fd5b613671888289016135ba565b959895975050505060408401359360608101359360809091013592509050565b6000602082840312156136a357600080fd5b5035919050565b602080825282516001600160a01b03168282015282015160a060408301526000906136d860c08401826134b8565b9050604084015160608401526060840151601f198483030160808501526136ff82826134b8565b915050608084015160a08401528091505092915050565b60006020828403121561372857600080fd5b61163c826134f7565b60006001600160401b0382111561374a5761374a613574565b5060051b60200190565b600082601f83011261376557600080fd5b8135602061377a61377583613731565b61358a565b82815260059290921b8401810191818101908684111561379957600080fd5b8286015b848110156137d85780356001600160401b038111156137bc5760008081fd5b6137ca8986838b01016135ba565b84525091830191830161379d565b509695505050505050565b600080604083850312156137f657600080fd5b8235915060208301356001600160401b0381111561381357600080fd5b61381f85828601613754565b9150509250929050565b60008083601f84011261383b57600080fd5b5081356001600160401b0381111561385257600080fd5b60208301915083602082850101111561386a57600080fd5b9250929050565b6000806000806000806080878903121561388a57600080fd5b613893876134f7565b955060208701356001600160401b03808211156138af57600080fd5b6138bb8a838b01613829565b90975095506040890135945060608901359150808211156138db57600080fd5b506138e889828a01613829565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b8181101561393b5783516001600160a01b031683529284019291840191600101613916565b50909695505050505050565b6000806040838503121561395a57600080fd5b82356001600160401b0381111561397057600080fd5b61397c85828601613754565b95602094909401359450505050565b6020808252825182820181905260009190848201906040850190845b8181101561393b578351835292840192918401916001016139a7565b600080604083850312156139d657600080fd5b6139df836134f7565b91506139ed602084016134f7565b90509250929050565b600060208284031215613a0857600080fd5b813563ffffffff8116811461163c57600080fd5b600061010060018060a01b0383511684526020808401518282870152613a44838701826134b8565b92505060408401516040860152606084015160608601526080840151608086015260a084015160a086015260c084015160c086015260e084015185830360e08701528281518085528385019150838160051b860101848401935060005b82811015613acf57601f19878303018452613abd8286516134b8565b94860194938601939150600101613aa1565b5098975050505050505050565b60208152600061163c6020830184613a1c565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015613b4457603f19888603018452613b32858351613a1c565b94509285019290850190600101613b16565b5092979650505050505050565b600082601f830112613b6257600080fd5b81356020613b7261377583613731565b82815260059290921b84018101918181019086841115613b9157600080fd5b8286015b848110156137d857613ba6816134f7565b8352918301918301613b95565b600080600080600060a08688031215613bcb57600080fd5b613bd4866134f7565b94506020860135935060408601356001600160401b0380821115613bf757600080fd5b613c0389838a01613b51565b94506060880135915080821115613c1957600080fd5b613c2589838a01613b51565b93506080880135915080821115613c3b57600080fd5b50613c4888828901613b51565b9150509295509295909350565b60208082526022908201527f44414f3a20746869732066756e6374696f6e206973206f6e6c7920666f722044604082015261414f60f01b606082015260800190565b600181811c90821680613cab57607f821691505b602082108103613ccb57634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0388811682528716602082015260e060408201819052600090613cfd908301886134b8565b90508560608301528460808301528360a08301528260c083015298975050505050505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115613d4c57613d4c613d23565b500190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b601f82111561282d57600081815260208120601f850160051c81016020861015613daf5750805b601f850160051c820191505b81811015613dce57828155600101613dbb565b505050505050565b81516001600160401b03811115613def57613def613574565b613e0381613dfd8454613c97565b84613d88565b602080601f831160018114613e385760008415613e205750858301515b600019600386901b1c1916600185901b178555613dce565b600085815260208120601f198616915b82811015613e6757888601518255948401946001909101908401613e48565b5085821015613e855787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60a081526000613ea860a08301886134b8565b90508560208301528460408301528360608301528260808301529695505050505050565b600060018201613ede57613ede613d23565b5060010190565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615613f1557613f15613d23565b500290565b600063ffffffff80831681851681830481118215151615613f3d57613f3d613d23565b02949350505050565b600082821015613f5857613f58613d23565b500390565b600082613f7a57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215613f9157600080fd5b5051919050565b600060208284031215613faa57600080fd5b8151801515811461163c57600080fd5b60008251613fcc81846020870161348c565b919091019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220bdac98fc3108881d6bcf375b0854582e85733c8f83a4ee3da986a76f4f55b0fc64736f6c634300080f0033