Source Code
Latest 25 from a total of 10,624 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 23750989 | 114 days ago | IN | 0 ETH | 0.00029861 | ||||
| Emergency Withdr... | 21683325 | 403 days ago | IN | 0 ETH | 0.00028013 | ||||
| Withdraw | 19552838 | 700 days ago | IN | 0 ETH | 0.00258431 | ||||
| Withdraw | 19394749 | 722 days ago | IN | 0 ETH | 0.00701962 | ||||
| Emergency Withdr... | 18433329 | 857 days ago | IN | 0 ETH | 0.00089502 | ||||
| Emergency Withdr... | 18433305 | 857 days ago | IN | 0 ETH | 0.00072382 | ||||
| Set | 18022423 | 915 days ago | IN | 0 ETH | 0.00127184 | ||||
| Set | 18022422 | 915 days ago | IN | 0 ETH | 0.00126724 | ||||
| Set | 18022421 | 915 days ago | IN | 0 ETH | 0.00122605 | ||||
| Set | 18022420 | 915 days ago | IN | 0 ETH | 0.00123567 | ||||
| Set | 18022420 | 915 days ago | IN | 0 ETH | 0.00123567 | ||||
| Set | 18022419 | 915 days ago | IN | 0 ETH | 0.0012029 | ||||
| Set | 18022418 | 915 days ago | IN | 0 ETH | 0.00118767 | ||||
| Set | 18022417 | 915 days ago | IN | 0 ETH | 0.00121612 | ||||
| Set | 18022416 | 915 days ago | IN | 0 ETH | 0.00117794 | ||||
| Set | 18022416 | 915 days ago | IN | 0 ETH | 0.00117794 | ||||
| Set | 18022415 | 915 days ago | IN | 0 ETH | 0.0011967 | ||||
| Set | 18022414 | 915 days ago | IN | 0 ETH | 0.00119084 | ||||
| Set | 18022414 | 915 days ago | IN | 0 ETH | 0.00119084 | ||||
| Set | 18022413 | 915 days ago | IN | 0 ETH | 0.00120739 | ||||
| Set | 18022412 | 915 days ago | IN | 0 ETH | 0.00126163 | ||||
| Deposit | 16867969 | 1077 days ago | IN | 0 ETH | 0.00246993 | ||||
| Deposit | 16867934 | 1077 days ago | IN | 0 ETH | 0.00190253 | ||||
| Deposit | 16867882 | 1077 days ago | IN | 0 ETH | 0.00166294 | ||||
| Deposit | 16856248 | 1079 days ago | IN | 0 ETH | 0.00203998 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
UnicFarm
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-05-15
*/
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: @openzeppelin/contracts/math/SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: @openzeppelin/contracts/utils/Address.sol
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// 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;
// solhint-disable-next-line no-inline-assembly
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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @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'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. 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
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File: @openzeppelin/contracts/utils/EnumerableSet.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
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;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
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] = toDeleteIndex + 1; // All indexes are 1-based
// 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) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
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(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(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(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(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));
}
}
// File: @openzeppelin/contracts/GSN/Context.sol
pragma solidity >=0.6.0 <0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view 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 {_setupDecimals} is
* called.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view 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);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal 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);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This 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 Sets {decimals} to a value other than the default one of 18.
*
* WARNING: This function should only be called from the constructor. Most
* applications that interact with token contracts will not expect
* {decimals} to ever change, and may work incorrectly if it does.
*/
function _setupDecimals(uint8 decimals_) internal {
_decimals = decimals_;
}
/**
* @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 to 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 { }
}
// File: @openzeppelin/contracts/token/ERC20/ERC20Capped.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Extension of {ERC20} that adds a cap to the supply of tokens.
*/
abstract contract ERC20Capped is ERC20 {
using SafeMath for uint256;
uint256 private _cap;
/**
* @dev Sets the value of the `cap`. This value is immutable, it can only be
* set once during construction.
*/
constructor (uint256 cap_) internal {
require(cap_ > 0, "ERC20Capped: cap is 0");
_cap = cap_;
}
/**
* @dev Returns the cap on the token's total supply.
*/
function cap() public view returns (uint256) {
return _cap;
}
/**
* @dev See {ERC20-_beforeTokenTransfer}.
*
* Requirements:
*
* - minted tokens must not cause the total supply to go over the cap.
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
if (from == address(0)) { // When minting tokens
require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
}
}
}
// File: @openzeppelin/contracts/token/ERC20/ERC20Burnable.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
using SafeMath for uint256;
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), decreasedAllowance);
_burn(account, amount);
}
}
// File: contracts/Unic.sol
pragma solidity 0.6.12;
// Unic with Governance.
contract Unic is ERC20, ERC20Capped, ERC20Burnable, Ownable {
constructor ()
public
ERC20("UNIC", "UNIC")
ERC20Capped(1_000_000e18)
{
// Mint 1 UNIC to me because I deserve it
_mint(_msgSender(), 1e18);
_moveDelegates(address(0), _delegates[_msgSender()], 1e18);
}
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner.
function mint(address _to, uint256 _amount) public onlyOwner returns (bool) {
_mint(_to, _amount);
_moveDelegates(address(0), _delegates[_to], _amount);
return true;
}
// Copied and modified from YAM code:
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
// Which is copied and modified from COMPOUND:
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol
/// @dev A record of each accounts delegate
mapping (address => address) internal _delegates;
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint256 votes;
}
/// @notice A record of votes checkpoints for each account, by index
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping (address => uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegator The address to get delegatee for
*/
function delegates(address delegator)
external
view
returns (address)
{
return _delegates[delegator];
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) external {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(
address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
)
external
{
bytes32 domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name())),
getChainId(),
address(this)
)
);
bytes32 structHash = keccak256(
abi.encode(
DELEGATION_TYPEHASH,
delegatee,
nonce,
expiry
)
);
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
domainSeparator,
structHash
)
);
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "UNIC::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "UNIC::delegateBySig: invalid nonce");
require(now <= expiry, "UNIC::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account)
external
view
returns (uint256)
{
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint blockNumber)
external
view
returns (uint256)
{
require(blockNumber < block.number, "UNIC::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee)
internal
{
address currentDelegate = _delegates[delegator];
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying UNICs (not scaled);
_delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
// decrease old representative
uint32 srcRepNum = numCheckpoints[srcRep];
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepNew = srcRepOld.sub(amount);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
// increase new representative
uint32 dstRepNum = numCheckpoints[dstRep];
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepNew = dstRepOld.add(amount);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(
address delegatee,
uint32 nCheckpoints,
uint256 oldVotes,
uint256 newVotes
)
internal
{
uint32 blockNumber = safe32(block.number, "UNIC::_writeCheckpoint: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
/**
* @dev See {ERC20-_beforeTokenTransfer}.
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override(ERC20, ERC20Capped) {
super._beforeTokenTransfer(from, to, amount);
}
}
// File: @openzeppelin/contracts/introspection/ERC165Checker.sol
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Returns true if `account` supports the {IERC165} interface,
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return supportsERC165(account) &&
_supportsERC165Interface(account, interfaceId);
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
// query support of ERC165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in _interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!_supportsERC165Interface(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
* Interface identification is specified in ERC-165.
*/
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
// success determines whether the staticcall succeeded and result determines
// whether the contract at account indicates support of _interfaceId
(bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
return (success && result);
}
/**
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return success true if the STATICCALL succeeded, false otherwise
* @return result true if the STATICCALL succeeded and the contract at account
* indicates support of the interface with identifier interfaceId, false otherwise
*/
function _callERC165SupportsInterface(address account, bytes4 interfaceId)
private
view
returns (bool, bool)
{
bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
(bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams);
if (result.length < 32) return (false, false);
return (success, abi.decode(result, (bool)));
}
}
// File: @openzeppelin/contracts/introspection/IERC165.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/token/ERC721/IERC721.sol
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155.sol
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}
// File: @openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
@dev Handles the receipt of a single ERC1155 token type. This function is
called at the end of a `safeTransferFrom` after the balance has been updated.
To accept the transfer, this must return
`bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
(i.e. 0xf23a6e61, or its own function selector).
@param operator The address which initiated the transfer (i.e. msg.sender)
@param from The address which previously owned the token
@param id The ID of the token being transferred
@param value The amount of tokens being transferred
@param data Additional data with no specified format
@return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
)
external
returns(bytes4);
/**
@dev Handles the receipt of a multiple ERC1155 token types. This function
is called at the end of a `safeBatchTransferFrom` after the balances have
been updated. To accept the transfer(s), this must return
`bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
(i.e. 0xbc197c81, or its own function selector).
@param operator The address which initiated the batch transfer (i.e. msg.sender)
@param from The address which previously owned the token
@param ids An array containing ids of each token being transferred (order and length must match values array)
@param values An array containing amounts of each token being transferred (order and length must match ids array)
@param data Additional data with no specified format
@return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
returns(bytes4);
}
// File: @openzeppelin/contracts/introspection/ERC165.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
abstract contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
// File: @openzeppelin/contracts/token/ERC1155/ERC1155Receiver.sol
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev _Available since v3.1._
*/
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
constructor() internal {
_registerInterface(
ERC1155Receiver(0).onERC1155Received.selector ^
ERC1155Receiver(0).onERC1155BatchReceived.selector
);
}
}
// File: contracts/interfaces/IUnicFactory.sol
pragma solidity >=0.5.0;
interface IUnicFactory {
event TokenCreated(address indexed caller, address indexed uToken);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getUToken(address uToken) external view returns (uint);
function uTokens(uint) external view returns (address);
function uTokensLength() external view returns (uint);
function createUToken(uint256 totalSupply, uint8 decimals, string calldata name, string calldata symbol, uint256 threshold, string calldata description) external returns (address);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
// File: contracts/Converter.sol
pragma solidity 0.6.12;
contract Converter is ERC20, ERC1155Receiver {
using SafeMath for uint;
// List of NFTs that have been deposited
struct NFT {
address contractAddr;
uint256 tokenId;
uint256 amount;
bool claimed;
}
struct Bid {
address bidder;
uint256 amount;
uint time;
}
mapping(uint256 => NFT) public nfts;
// Current index and length of nfts
uint256 public currentNFTIndex = 0;
// If active, NFTs can’t be withdrawn
bool public active = false;
uint256 public totalBidAmount = 0;
uint256 public unlockVotes = 0;
uint256 public _threshold;
address public issuer;
string public _description;
uint256 public cap;
// Amount of uTokens each user has voted to unlock collection
mapping(address => uint256) public unlockApproved;
IUnicFactory public factory;
// NFT index to Bid
mapping(uint256 => Bid) public bids;
// NFT index to address to amount
mapping(uint256 => mapping(address => uint256)) public bidRefunds;
uint public constant TOP_BID_LOCK_TIME = 3 days;
event Deposited(uint256[] tokenIDs, uint256[] amounts, address contractAddr);
event Refunded();
event Issued();
event BidCreated(address sender, uint256 nftIndex, uint256 bidAmount);
event BidRemoved(address sender, uint256 nftIndex);
event ClaimedNFT(address winner, uint256 nftIndex, uint256 tokenId);
bytes private constant VALIDATOR = bytes('JCMY');
constructor (uint256 totalSupply, uint8 decimals, string memory name, string memory symbol, uint256 threshold, string memory description, address _issuer, IUnicFactory _factory)
public
ERC20(name, symbol)
{
_setupDecimals(decimals);
issuer = _issuer;
_description = description;
_threshold = threshold;
factory = _factory;
cap = totalSupply;
}
// deposits an nft using the transferFrom action of the NFT contractAddr
function deposit(uint256[] calldata tokenIDs, uint256[] calldata amounts, address contractAddr) external {
require(msg.sender == issuer, "Converter: Only issuer can deposit");
require(tokenIDs.length <= 50, "Converter: A maximum of 50 tokens can be deposited in one go");
require(tokenIDs.length > 0, "Converter: You must specify at least one token ID");
if (ERC165Checker.supportsInterface(contractAddr, 0xd9b67a26)){
IERC1155(contractAddr).safeBatchTransferFrom(msg.sender, address(this), tokenIDs, amounts, VALIDATOR);
for (uint8 i = 0; i < 50; i++){
if (tokenIDs.length == i){
break;
}
nfts[currentNFTIndex++] = NFT(contractAddr, tokenIDs[i], amounts[i], false);
}
}
//else if (ERC165Checker.supportsInterface(contractAddr, 0x80ac58cd)){
else {
for (uint8 i = 0; i < 50; i++){
if (tokenIDs.length == i){
break;
}
IERC721(contractAddr).transferFrom(msg.sender, address(this), tokenIDs[i]);
nfts[currentNFTIndex++] = NFT(contractAddr, tokenIDs[i], 1, false);
}
}
emit Deposited(tokenIDs, amounts, contractAddr);
}
// Function that locks NFT collateral and issues the uTokens to the issuer
function issue() external {
require(msg.sender == issuer, "Converter: Only issuer can issue the tokens");
require(active == false, "Converter: Token is already active");
active = true;
address feeTo = factory.feeTo();
uint256 feeAmount = 0;
if (feeTo != address(0)) {
// 0.5% of uToken supply is sent to feeToAddress if fee is on
feeAmount = cap.div(200);
_mint(feeTo, feeAmount);
}
_mint(issuer, cap - feeAmount);
emit Issued();
}
// Function that allows NFTs to be refunded (prior to issue being called)
function refund(address _to) external {
require(!active, "Converter: Contract is already active - cannot refund");
require(msg.sender == issuer, "Converter: Only issuer can refund");
// Only transfer maximum of 50 at a time to limit gas per call
uint8 _i = 0;
uint256 _index = currentNFTIndex;
bytes memory data;
while (_index > 0 && _i < 50){
NFT memory nft = nfts[_index - 1];
if (ERC165Checker.supportsInterface(nft.contractAddr, 0xd9b67a26)){
IERC1155(nft.contractAddr).safeTransferFrom(address(this), _to, nft.tokenId, nft.amount, data);
}
//else if (ERC165Checker.supportsInterface(nft.contractAddr, 0x80ac58cd)){
else {
IERC721(nft.contractAddr).safeTransferFrom(address(this), _to, nft.tokenId);
}
delete nfts[_index - 1];
_index--;
_i++;
}
currentNFTIndex = _index;
emit Refunded();
}
function bid(uint256 nftIndex) external payable {
require(unlockVotes < _threshold, "Converter: Release threshold has been met, no more bids allowed");
Bid memory topBid = bids[nftIndex];
require(topBid.bidder != msg.sender, "Converter: You have an active bid");
require(topBid.amount < msg.value, "Converter: Bid too low");
require(bidRefunds[nftIndex][msg.sender] == 0, "Converter: Collect bid refund");
bids[nftIndex] = Bid(msg.sender, msg.value, getBlockTimestamp());
bidRefunds[nftIndex][topBid.bidder] = topBid.amount;
totalBidAmount += msg.value - topBid.amount;
emit BidCreated(msg.sender, nftIndex, msg.value);
}
function unbid(uint256 nftIndex) external {
Bid memory topBid = bids[nftIndex];
bool isTopBidder = topBid.bidder == msg.sender;
if (unlockVotes >= _threshold) {
require(!isTopBidder, "Converter: Release threshold has been met, winner can't unbid");
}
if (isTopBidder) {
require(topBid.time + TOP_BID_LOCK_TIME < getBlockTimestamp(), "Converter: Top bid locked");
totalBidAmount -= topBid.amount;
bids[nftIndex] = Bid(address(0), 0, getBlockTimestamp());
(bool sent, bytes memory data) = msg.sender.call{value: topBid.amount}("");
require(sent, "Converter: Failed to send Ether");
emit BidRemoved(msg.sender, nftIndex);
}
else {
uint256 refundAmount = bidRefunds[nftIndex][msg.sender];
require(refundAmount > 0, "Converter: no bid found");
bidRefunds[nftIndex][msg.sender] = 0;
(bool sent, bytes memory data) = msg.sender.call{value: refundAmount}("");
require(sent, "Converter: Failed to send Ether");
}
}
// Claim NFT if address is winning bidder
function claim(uint256 nftIndex) external {
require(unlockVotes >= _threshold, "Converter: Threshold not met");
require(!nfts[nftIndex].claimed, "Converter: Already claimed");
Bid memory topBid = bids[nftIndex];
require(msg.sender == topBid.bidder, "Converter: Only winner can claim");
nfts[nftIndex].claimed = true;
NFT memory winningNFT = nfts[nftIndex];
if (ERC165Checker.supportsInterface(winningNFT.contractAddr, 0xd9b67a26)){
bytes memory data;
IERC1155(winningNFT.contractAddr).safeTransferFrom(address(this), topBid.bidder, winningNFT.tokenId, winningNFT.amount, data);
}
//else if (ERC165Checker.supportsInterface(winningNFT.contractAddr, 0x80ac58cd)){
else {
IERC721(winningNFT.contractAddr).safeTransferFrom(address(this), topBid.bidder, winningNFT.tokenId);
}
emit ClaimedNFT(topBid.bidder, nftIndex, winningNFT.tokenId);
}
// Approve collection unlock
function approveUnlock(uint256 amount) external {
require(unlockVotes < _threshold, "Converter: Threshold reached");
_transfer(msg.sender, address(this), amount);
unlockApproved[msg.sender] += amount;
unlockVotes += amount;
}
// Unapprove collection unlock
function unapproveUnlock(uint256 amount) external {
require(unlockVotes < _threshold, "Converter: Threshold reached");
require(unlockApproved[msg.sender] >= amount, "Converter: Not enough uTokens locked by user");
unlockVotes -= amount;
unlockApproved[msg.sender] -= amount;
_transfer(address(this), msg.sender, amount);
}
// Claim ETH function
function redeemETH(uint256 amount) external {
require(unlockVotes >= _threshold, "Converter: Threshold not met");
// Deposit uTokens
if (amount > 0) {
_transfer(msg.sender, address(this), amount);
}
// Combine approved balance + newly deposited balance
uint256 finalBalance = amount + unlockApproved[msg.sender];
// Remove locked uTokens tracked for user
unlockApproved[msg.sender] = 0;
// Redeem ETH corresponding to uToken amount
(bool sent, bytes memory data) = msg.sender.call{value: totalBidAmount.mul(finalBalance).div(this.totalSupply())}("");
require(sent, "Converter: Failed to send Ether");
}
function getBlockTimestamp() internal view returns (uint) {
// solium-disable-next-line security/no-block-members
return block.timestamp;
}
/**
* ERC1155 Token ERC1155Receiver
*/
function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) override external returns(bytes4) {
if(keccak256(_data) == keccak256(VALIDATOR)){
return 0xf23a6e61;
}
}
function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) override external returns(bytes4) {
if(keccak256(_data) == keccak256(VALIDATOR)){
return 0xbc197c81;
}
}
}
// File: contracts/UnicFarm.sol
pragma solidity 0.6.12;
// Copied from https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol
// Modified by 0xLeia
// UnicFarm is where liquidity providers on UnicSwap can stake their LP tokens for UNIC rewards
// The ownership of UnicFarm will be transferred to a governance smart contract once UNIC has been sufficiently distributed
contract UnicFarm is Ownable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
// Info of each user.
struct UserInfo {
uint256 amount; // How many LP tokens the user has provided.
uint256 rewardDebt; // Reward debt. See explanation below.
//
// We do some fancy math here. Basically, any point in time, the amount of UNICs
// entitled to a user but is pending to be distributed is:
//
// pending reward = (user.amount * pool.accUnicPerShare) - user.rewardDebt
//
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
// 1. The pool's `accUnicPerShare` (and `lastRewardBlock`) gets updated.
// 2. User receives the pending reward sent to his/her address.
// 3. User's `amount` gets updated.
// 4. User's `rewardDebt` gets updated.
}
// Info of each pool.
struct PoolInfo {
IERC20 lpToken; // Address of LP token contract.
uint256 allocPoint; // How many allocation points assigned to this pool. UNICs to distribute per block.
uint256 lastRewardBlock; // Last block number that UNICs distribution occurs.
uint256 accUnicPerShare; // Accumulated UNICs per share, times 1e12. See below.
address uToken;
}
// The UNIC TOKEN!
Unic public unic;
// Dev address.
address public devaddr;
// Mint rate controllers
uint256 public mintRateMultiplier;
uint256 public mintRateDivider;
// Blocks per tranche used to calculate current mint rate (6500 blocks per day * 30 = 195000)
uint256 public blocksPerTranche;
// Current tranche
uint256 public tranche = 0;
// Whitelist mapping of address to bool
mapping(address => bool) public whitelist;
// UNIC tokens created per block.
uint256 public unicPerBlock;
// Info of each pool.
PoolInfo[] public poolInfo;
// Info of each user that stakes LP tokens.
mapping (uint256 => mapping (address => UserInfo)) public userInfo;
// Total allocation points. Must be the sum of all allocation points in all pools.
uint256 public totalAllocPoint = 0;
// The block number when UNIC mining starts.
uint256 public startBlock;
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
// New events so that the graph works
event Add(uint256 allocPoint, address lpToken, bool withUpdate);
event Set(uint256 pid, uint256 allocPoint, bool withUpdate);
event MassUpdatePools();
event UpdatePool(uint256 pid);
event Dev(address devaddr);
constructor(
Unic _unic,
address _devaddr,
uint256 _mintRateMultiplier,
uint256 _mintRateDivider,
uint256 _unicPerBlock,
uint256 _startBlock,
uint256 _blocksPerTranche
) public {
unic = _unic;
devaddr = _devaddr;
mintRateMultiplier = _mintRateMultiplier;
mintRateDivider = _mintRateDivider;
unicPerBlock = _unicPerBlock;
startBlock = _startBlock;
blocksPerTranche = _blocksPerTranche;
}
function poolLength() external view returns (uint256) {
return poolInfo.length;
}
// Add a new lp to the pool. Can only be called by the owner.
// address(0) for uToken if there's no uToken involved. Input uToken address if there is.
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate, address _uToken) public onlyOwner {
require(!whitelist[address(_lpToken)]);
if (_withUpdate) {
massUpdatePools();
}
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock;
totalAllocPoint = totalAllocPoint.add(_allocPoint);
poolInfo.push(PoolInfo({
lpToken: _lpToken,
allocPoint: _allocPoint,
lastRewardBlock: lastRewardBlock,
accUnicPerShare: 0,
uToken: _uToken
}));
whitelist[address(_lpToken)] = true;
emit Add(_allocPoint, address(_lpToken), _withUpdate);
}
// Update the given pool's UNIC allocation point. Can only be called by the owner.
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner {
if (_withUpdate) {
massUpdatePools();
}
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);
poolInfo[_pid].allocPoint = _allocPoint;
emit Set(_pid, _allocPoint, _withUpdate);
}
// Return rewards over the given _from to _to block.
// Rewards accumulate for a maximum of 195000 blocks.
function getRewards(uint256 _from, uint256 _to) public view returns (uint256) {
uint256 lastTrancheBlock = startBlock.add(tranche.mul(blocksPerTranche));
if (_to.sub(_from) > blocksPerTranche) {
_from = _to.sub(blocksPerTranche);
}
if (_from > lastTrancheBlock) {
return _to.sub(_from).mul(unicPerBlock);
} else {
// Use prior mint rate for blocks staked before last tranche block
return lastTrancheBlock.sub(_from).mul(unicPerBlock).mul(mintRateDivider).div(mintRateMultiplier).add(
_to.sub(lastTrancheBlock).mul(unicPerBlock)
);
}
}
// View function to see pending UNICs on frontend.
function pendingUnic(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 accUnicPerShare = pool.accUnicPerShare;
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (block.number > pool.lastRewardBlock && lpSupply != 0) {
uint256 unicReward = getRewards(pool.lastRewardBlock, block.number).mul(pool.allocPoint).div(totalAllocPoint);
accUnicPerShare = accUnicPerShare.add(unicReward.mul(1e12).div(lpSupply));
}
return user.amount.mul(accUnicPerShare).div(1e12).sub(user.rewardDebt);
}
// Update reward variables for all pools. Be careful of gas spending!
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
}
emit MassUpdatePools();
}
// Update reward variables of the given pool to be up-to-date.
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
if (pool.uToken != address(0) && pool.allocPoint > 0) {
if (Converter(pool.uToken).unlockVotes() >= Converter(pool.uToken)._threshold()) {
totalAllocPoint = totalAllocPoint.sub(pool.allocPoint);
pool.allocPoint = 0;
emit Set(_pid, 0, false);
}
}
if (block.number <= pool.lastRewardBlock) {
return;
}
uint256 lpSupply = pool.lpToken.balanceOf(address(this));
if (lpSupply == 0) {
pool.lastRewardBlock = block.number;
return;
}
// Update block rewards and tranche based on block height
if (block.number >= startBlock.add(tranche.mul(blocksPerTranche)).add(blocksPerTranche)) {
tranche++;
unicPerBlock = unicPerBlock.mul(mintRateMultiplier).div(mintRateDivider);
}
uint256 unicReward = getRewards(pool.lastRewardBlock, block.number).mul(pool.allocPoint).div(totalAllocPoint);
unic.mint(devaddr, unicReward.div(9));
unic.mint(address(this), unicReward);
pool.accUnicPerShare = pool.accUnicPerShare.add(unicReward.mul(1e12).div(lpSupply));
pool.lastRewardBlock = block.number;
emit UpdatePool(_pid);
}
// Deposit LP tokens to UnicFarm for UNIC allocation.
function deposit(uint256 _pid, uint256 _amount) public {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
if (user.amount > 0) {
uint256 pending = user.amount.mul(pool.accUnicPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
safeUnicTransfer(msg.sender, pending);
}
}
if(_amount > 0) {
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount);
user.amount = user.amount.add(_amount);
}
user.rewardDebt = user.amount.mul(pool.accUnicPerShare).div(1e12);
emit Deposit(msg.sender, _pid, _amount);
}
// Withdraw LP tokens from UnicFarm.
function withdraw(uint256 _pid, uint256 _amount) public {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount >= _amount, "withdraw: not good");
updatePool(_pid);
uint256 pending = user.amount.mul(pool.accUnicPerShare).div(1e12).sub(user.rewardDebt);
if(pending > 0) {
safeUnicTransfer(msg.sender, pending);
}
if(_amount > 0) {
user.amount = user.amount.sub(_amount);
pool.lpToken.safeTransfer(address(msg.sender), _amount);
}
user.rewardDebt = user.amount.mul(pool.accUnicPerShare).div(1e12);
emit Withdraw(msg.sender, _pid, _amount);
}
// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
uint256 amount = user.amount;
user.amount = 0;
user.rewardDebt = 0;
pool.lpToken.safeTransfer(address(msg.sender), amount);
emit EmergencyWithdraw(msg.sender, _pid, amount);
}
// Safe unic transfer function, just in case if rounding error causes pool to not have enough UNICs.
function safeUnicTransfer(address _to, uint256 _amount) internal {
uint256 unicBal = unic.balanceOf(address(this));
if (_amount > unicBal) {
unic.transfer(_to, unicBal);
} else {
unic.transfer(_to, _amount);
}
}
// Update dev address by the previous dev.
function dev(address _devaddr) public {
require(msg.sender == devaddr, "dev: wut?");
devaddr = _devaddr;
emit Dev(_devaddr);
}
// Set mint rate
function setMintRules(uint256 _mintRateMultiplier, uint256 _mintRateDivider, uint256 _unicPerBlock, uint256 _blocksPerTranche) public onlyOwner {
require(_mintRateDivider > 0, "no dividing by zero");
require(_blocksPerTranche > 0, "zero blocks per tranche not allowed");
mintRateMultiplier = _mintRateMultiplier;
mintRateDivider = _mintRateDivider;
unicPerBlock = _unicPerBlock;
blocksPerTranche = _blocksPerTranche;
}
function setStartBlock(uint256 _startBlock) public onlyOwner {
require(block.number < startBlock, "start block can not be modified after it has passed");
require(block.number < _startBlock, "new start block needs to be in the future");
startBlock = _startBlock;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract Unic","name":"_unic","type":"address"},{"internalType":"address","name":"_devaddr","type":"address"},{"internalType":"uint256","name":"_mintRateMultiplier","type":"uint256"},{"internalType":"uint256","name":"_mintRateDivider","type":"uint256"},{"internalType":"uint256","name":"_unicPerBlock","type":"uint256"},{"internalType":"uint256","name":"_startBlock","type":"uint256"},{"internalType":"uint256","name":"_blocksPerTranche","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"},{"indexed":false,"internalType":"address","name":"lpToken","type":"address"},{"indexed":false,"internalType":"bool","name":"withUpdate","type":"bool"}],"name":"Add","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"devaddr","type":"address"}],"name":"Dev","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[],"name":"MassUpdatePools","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"},{"indexed":false,"internalType":"bool","name":"withUpdate","type":"bool"}],"name":"Set","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"pid","type":"uint256"}],"name":"UpdatePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"contract IERC20","name":"_lpToken","type":"address"},{"internalType":"bool","name":"_withUpdate","type":"bool"},{"internalType":"address","name":"_uToken","type":"address"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blocksPerTranche","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_devaddr","type":"address"}],"name":"dev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devaddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_from","type":"uint256"},{"internalType":"uint256","name":"_to","type":"uint256"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintRateDivider","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintRateMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingUnic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accUnicPerShare","type":"uint256"},{"internalType":"address","name":"uToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintRateMultiplier","type":"uint256"},{"internalType":"uint256","name":"_mintRateDivider","type":"uint256"},{"internalType":"uint256","name":"_unicPerBlock","type":"uint256"},{"internalType":"uint256","name":"_blocksPerTranche","type":"uint256"}],"name":"setMintRules","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startBlock","type":"uint256"}],"name":"setStartBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tranche","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unic","outputs":[{"internalType":"contract Unic","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unicPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405260006006556000600b553480156200001b57600080fd5b50604051620033fe380380620033fe833981810160405260e08110156200004157600080fd5b81019080805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050506000620000a0620001f060201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35086600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600381905550836004819055508260088190555081600c819055508060058190555050505050505050620001f8565b600033905090565b6131f680620002086000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80637b452551116100f9578063d4381d7411610097578063e2bbb15811610071578063e2bbb15814610712578063e5ef8e381461074a578063f2fde38b1461077e578063f35e4a6e146107c2576101c4565b8063d4381d741461065e578063d49e77cd1461067c578063de15297e146106b0576101c4565b80638da5cb5b116100d35780638da5cb5b1461051b57806393f1a40b1461054f5780639b19251a146105b8578063cc11298e14610612576101c4565b80637b4525511461049b578063819a8142146104b95780638d88a90e146104d7576101c4565b806351eb05a611610166578063630b5ba111610140578063630b5ba11461042557806364482f791461042f5780636ebc0af114610473578063715018a614610491576101c4565b806351eb05a61461034f5780635312ea8e1461037d5780635f70edcf146103ab576101c4565b806317caf6f1116101a257806317caf6f11461028f5780631be0668a146102ad578063441a3e70146102f957806348cd4cb114610331576101c4565b806304436d5e146101c9578063081e3eda146101e75780631526fe2714610205575b600080fd5b6101d16107f0565b6040518082815260200191505060405180910390f35b6101ef6107f6565b6040518082815260200191505060405180910390f35b6102316004803603602081101561021b57600080fd5b8101908080359060200190929190505050610803565b604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019550505050505060405180910390f35b610297610886565b6040518082815260200191505060405180910390f35b6102f7600480360360808110156102c357600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061088c565b005b61032f6004803603604081101561030f57600080fd5b810190808035906020019092919080359060200190929190505050610a45565b005b610339610ca3565b6040518082815260200191505060405180910390f35b61037b6004803603602081101561036557600080fd5b8101908080359060200190929190505050610ca9565b005b6103a96004803603602081101561039357600080fd5b8101908080359060200190929190505050611311565b005b610423600480360360808110156103c157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611445565b005b61042d611790565b005b6104716004803603606081101561044557600080fd5b8101908080359060200190929190803590602001909291908035151590602001909291905050506117e9565b005b61047b61197c565b6040518082815260200191505060405180910390f35b610499611982565b005b6104a3611b08565b6040518082815260200191505060405180910390f35b6104c1611b0e565b6040518082815260200191505060405180910390f35b610519600480360360208110156104ed57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b14565b005b610523611c68565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61059b6004803603604081101561056557600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c91565b604051808381526020018281526020019250505060405180910390f35b6105fa600480360360208110156105ce57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611cc2565b60405180821515815260200191505060405180910390f35b6106486004803603604081101561062857600080fd5b810190808035906020019092919080359060200190929190505050611ce2565b6040518082815260200191505060405180910390f35b610666611e0e565b6040518082815260200191505060405180910390f35b610684611e14565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106fc600480360360408110156106c657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611e3a565b6040518082815260200191505060405180910390f35b6107486004803603604081101561072857600080fd5b810190808035906020019092919080359060200190929190505050612066565b005b61075261225a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107c06004803603602081101561079457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612280565b005b6107ee600480360360208110156107d857600080fd5b810190808035906020019092919050505061248b565b005b60055481565b6000600980549050905090565b6009818154811061081057fe5b90600052602060002090600502016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154908060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905085565b600b5481565b61089461260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610954576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600083116109ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f6e6f206469766964696e67206279207a65726f0000000000000000000000000081525060200191505060405180910390fd5b60008111610a23576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131416023913960400191505060405180910390fd5b8360038190555082600481905550816008819055508060058190555050505050565b600060098381548110610a5457fe5b906000526020600020906005020190506000600a600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508281600001541015610b32576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f77697468647261773a206e6f7420676f6f64000000000000000000000000000081525060200191505060405180910390fd5b610b3b84610ca9565b6000610b858260010154610b7764e8d4a51000610b698760030154876000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b90506000811115610b9b57610b9a3382612731565b5b6000841115610c1357610bbb8483600001546126e790919063ffffffff16565b8260000181905550610c1233858560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166129aa9092919063ffffffff16565b5b610c4564e8d4a51000610c378560030154856000015461261790919063ffffffff16565b61269d90919063ffffffff16565b8260010181905550843373ffffffffffffffffffffffffffffffffffffffff167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568866040518082815260200191505060405180910390a35050505050565b600c5481565b600060098281548110610cb857fe5b90600052602060002090600502019050600073ffffffffffffffffffffffffffffffffffffffff168160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015610d2d575060008160010154115b15610ef6578060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f3c81606040518163ffffffff1660e01b815260040160206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d6020811015610dc657600080fd5b81019080805190602001909291905050508160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e3a7c9036040518163ffffffff1660e01b815260040160206040518083038186803b158015610e4157600080fd5b505afa158015610e55573d6000803e3d6000fd5b505050506040513d6020811015610e6b57600080fd5b810190808051906020019092919050505010610ef557610e9a8160010154600b546126e790919063ffffffff16565b600b81905550600081600101819055507fc66cec52f6fc7c7c09b5f02578bd330a548d6b039f8ba5b5703204565bdb335b82600080604051808481526020018381526020018215158152602001935050505060405180910390a15b5b80600201544311610f07575061130e565b60008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610f9457600080fd5b505afa158015610fa8573d6000803e3d6000fd5b505050506040513d6020811015610fbe57600080fd5b810190808051906020019092919050505090506000811415610fea57438260020181905550505061130e565b61102960055461101b61100a60055460065461261790919063ffffffff16565b600c54612a4c90919063ffffffff16565b612a4c90919063ffffffff16565b43106110735760066000815480929190600101919050555061106c60045461105e60035460085461261790919063ffffffff16565b61269d90919063ffffffff16565b6008819055505b60006110ad600b5461109f8560010154611091876002015443611ce2565b61261790919063ffffffff16565b61269d90919063ffffffff16565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f19600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661112460098561269d90919063ffffffff16565b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561117757600080fd5b505af115801561118b573d6000803e3d6000fd5b505050506040513d60208110156111a157600080fd5b810190808051906020019092919050505050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f1930836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561124657600080fd5b505af115801561125a573d6000803e3d6000fd5b505050506040513d602081101561127057600080fd5b8101908080519060200190929190505050506112c26112af836112a164e8d4a510008561261790919063ffffffff16565b61269d90919063ffffffff16565b8460030154612a4c90919063ffffffff16565b83600301819055504383600201819055507f20f73897541b01c2d01f4eca5ac07cb2c486d778aadf60fac2d2dcfd3c1389f1846040518082815260200191505060405180910390a15050505b50565b60006009828154811061132057fe5b906000526020600020906005020190506000600a600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905060008260000181905550600082600101819055506113f033828560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166129aa9092919063ffffffff16565b833373ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595836040518082815260200191505060405180910390a350505050565b61144d61260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461150d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561156457600080fd5b811561157357611572611790565b5b6000600c54431161158657600c54611588565b435b905061159f85600b54612a4c90919063ffffffff16565b600b8190555060096040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001878152602001838152602001600081526020018473ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050506001600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f4677f0774f427b7084c61193b0b175490b6404bc62b3964f746c951253a7c448858585604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018215158152602001935050505060405180910390a15050505050565b6000600980549050905060005b818110156117b9576117ae81610ca9565b80600101905061179d565b507f3f73d20979eadee00e614817748ea556ec6dadb2721118bc18663dfd111484ff60405160405180910390a150565b6117f161260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146118b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80156118c0576118bf611790565b5b611905826118f7600986815481106118d457fe5b906000526020600020906005020160010154600b546126e790919063ffffffff16565b612a4c90919063ffffffff16565b600b81905550816009848154811061191957fe5b9060005260206000209060050201600101819055507fc66cec52f6fc7c7c09b5f02578bd330a548d6b039f8ba5b5703204565bdb335b838383604051808481526020018381526020018215158152602001935050505060405180910390a1505050565b60065481565b61198a61260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b60035481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bd7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f6465763a207775743f000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6787ec2e213b45f8a55bfa91346e72127488bde333c0e349257df192b861855581604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600a602052816000526040600020602052806000526040600020600091509150508060000154908060010154905082565b60076020528060005260406000206000915054906101000a900460ff1681565b600080611d10611cff60055460065461261790919063ffffffff16565b600c54612a4c90919063ffffffff16565b9050600554611d2885856126e790919063ffffffff16565b1115611d4657611d43600554846126e790919063ffffffff16565b93505b80841115611d7d57611d75600854611d6786866126e790919063ffffffff16565b61261790919063ffffffff16565b915050611e08565b611e04611da7600854611d9984876126e790919063ffffffff16565b61261790919063ffffffff16565b611df6600354611de8600454611dda600854611dcc8c8a6126e790919063ffffffff16565b61261790919063ffffffff16565b61261790919063ffffffff16565b61269d90919063ffffffff16565b612a4c90919063ffffffff16565b9150505b92915050565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060098481548110611e4a57fe5b906000526020600020906005020190506000600a600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260030154905060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611f4457600080fd5b505afa158015611f58573d6000803e3d6000fd5b505050506040513d6020811015611f6e57600080fd5b81019080805190602001909291905050509050836002015443118015611f95575060008114155b15612016576000611fd4600b54611fc68760010154611fb8896002015443611ce2565b61261790919063ffffffff16565b61269d90919063ffffffff16565b905061201261200383611ff564e8d4a510008561261790919063ffffffff16565b61269d90919063ffffffff16565b84612a4c90919063ffffffff16565b9250505b61205a836001015461204c64e8d4a5100061203e86886000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b94505050505092915050565b60006009838154811061207557fe5b906000526020600020906005020190506000600a600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506120e284610ca9565b600081600001541115612151576000612139826001015461212b64e8d4a5100061211d8760030154876000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b9050600081111561214f5761214e3382612731565b5b505b60008311156121cb576121ab3330858560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ad4909392919063ffffffff16565b6121c2838260000154612a4c90919063ffffffff16565b81600001819055505b6121fd64e8d4a510006121ef8460030154846000015461261790919063ffffffff16565b61269d90919063ffffffff16565b8160010181905550833373ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15856040518082815260200191505060405180910390a350505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61228861260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806130ab6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61249361260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612553576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600c5443106125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806131646033913960400191505060405180910390fd5b804310612605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806130f76029913960400191505060405180910390fd5b80600c8190555050565b600033905090565b60008083141561262a5760009050612697565b600082840290508284828161263b57fe5b0414612692576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131206021913960400191505060405180910390fd5b809150505b92915050565b60006126df83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612b95565b905092915050565b600061272983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c5b565b905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156127bc57600080fd5b505afa1580156127d0573d6000803e3d6000fd5b505050506040513d60208110156127e657600080fd5b81019080805190602001909291905050509050808211156128d557600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561289457600080fd5b505af11580156128a8573d6000803e3d6000fd5b505050506040513d60208110156128be57600080fd5b8101908080519060200190929190505050506129a5565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561296857600080fd5b505af115801561297c573d6000803e3d6000fd5b505050506040513d602081101561299257600080fd5b8101908080519060200190929190505050505b505050565b612a478363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612d1b565b505050565b600080828401905083811015612aca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b612b8f846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612d1b565b50505050565b60008083118290612c41576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612c06578082015181840152602081019050612beb565b50505050905090810190601f168015612c335780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612c4d57fe5b049050809150509392505050565b6000838311158290612d08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612ccd578082015181840152602081019050612cb2565b50505050905090810190601f168015612cfa5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6060612d7d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612e0a9092919063ffffffff16565b9050600081511115612e0557808060200190516020811015612d9e57600080fd5b8101908080519060200190929190505050612e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613197602a913960400191505060405180910390fd5b5b505050565b6060612e198484600085612e22565b90509392505050565b606082471015612e7d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806130d16026913960400191505060405180910390fd5b612e8685612fcb565b612ef8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310612f485780518252602082019150602081019050602083039250612f25565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612faa576040519150601f19603f3d011682016040523d82523d6000602084013e612faf565b606091505b5091509150612fbf828286612fde565b92505050949350505050565b600080823b905060008111915050919050565b60608315612fee578290506130a3565b6000835111156130015782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561306857808201518184015260208101905061304d565b50505050905090810190601f1680156130955780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c6e657720737461727420626c6f636b206e6565647320746f20626520696e2074686520667574757265536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777a65726f20626c6f636b7320706572207472616e636865206e6f7420616c6c6f776564737461727420626c6f636b2063616e206e6f74206265206d6f64696669656420616674657220697420686173207061737365645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220d5c055ca5b378e01e1efd0d71803c5bbf598fb11d361d48ec35028e1d30f7bd364736f6c634300060c003300000000000000000000000094e0bab2f6ab1f19f4750e42d7349f2740513ad5000000000000000000000000db8ec47f52e2602c92ac603079d9e7e90d3187cb00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000038ef86f0a0736000000000000000000000000000000000000000000000000000000000000be1bdf000000000000000000000000000000000000000000000000000000000002fb02
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80637b452551116100f9578063d4381d7411610097578063e2bbb15811610071578063e2bbb15814610712578063e5ef8e381461074a578063f2fde38b1461077e578063f35e4a6e146107c2576101c4565b8063d4381d741461065e578063d49e77cd1461067c578063de15297e146106b0576101c4565b80638da5cb5b116100d35780638da5cb5b1461051b57806393f1a40b1461054f5780639b19251a146105b8578063cc11298e14610612576101c4565b80637b4525511461049b578063819a8142146104b95780638d88a90e146104d7576101c4565b806351eb05a611610166578063630b5ba111610140578063630b5ba11461042557806364482f791461042f5780636ebc0af114610473578063715018a614610491576101c4565b806351eb05a61461034f5780635312ea8e1461037d5780635f70edcf146103ab576101c4565b806317caf6f1116101a257806317caf6f11461028f5780631be0668a146102ad578063441a3e70146102f957806348cd4cb114610331576101c4565b806304436d5e146101c9578063081e3eda146101e75780631526fe2714610205575b600080fd5b6101d16107f0565b6040518082815260200191505060405180910390f35b6101ef6107f6565b6040518082815260200191505060405180910390f35b6102316004803603602081101561021b57600080fd5b8101908080359060200190929190505050610803565b604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019550505050505060405180910390f35b610297610886565b6040518082815260200191505060405180910390f35b6102f7600480360360808110156102c357600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061088c565b005b61032f6004803603604081101561030f57600080fd5b810190808035906020019092919080359060200190929190505050610a45565b005b610339610ca3565b6040518082815260200191505060405180910390f35b61037b6004803603602081101561036557600080fd5b8101908080359060200190929190505050610ca9565b005b6103a96004803603602081101561039357600080fd5b8101908080359060200190929190505050611311565b005b610423600480360360808110156103c157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611445565b005b61042d611790565b005b6104716004803603606081101561044557600080fd5b8101908080359060200190929190803590602001909291908035151590602001909291905050506117e9565b005b61047b61197c565b6040518082815260200191505060405180910390f35b610499611982565b005b6104a3611b08565b6040518082815260200191505060405180910390f35b6104c1611b0e565b6040518082815260200191505060405180910390f35b610519600480360360208110156104ed57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b14565b005b610523611c68565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61059b6004803603604081101561056557600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c91565b604051808381526020018281526020019250505060405180910390f35b6105fa600480360360208110156105ce57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611cc2565b60405180821515815260200191505060405180910390f35b6106486004803603604081101561062857600080fd5b810190808035906020019092919080359060200190929190505050611ce2565b6040518082815260200191505060405180910390f35b610666611e0e565b6040518082815260200191505060405180910390f35b610684611e14565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106fc600480360360408110156106c657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611e3a565b6040518082815260200191505060405180910390f35b6107486004803603604081101561072857600080fd5b810190808035906020019092919080359060200190929190505050612066565b005b61075261225a565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107c06004803603602081101561079457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612280565b005b6107ee600480360360208110156107d857600080fd5b810190808035906020019092919050505061248b565b005b60055481565b6000600980549050905090565b6009818154811061081057fe5b90600052602060002090600502016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020154908060030154908060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905085565b600b5481565b61089461260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610954576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600083116109ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f6e6f206469766964696e67206279207a65726f0000000000000000000000000081525060200191505060405180910390fd5b60008111610a23576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131416023913960400191505060405180910390fd5b8360038190555082600481905550816008819055508060058190555050505050565b600060098381548110610a5457fe5b906000526020600020906005020190506000600a600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508281600001541015610b32576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f77697468647261773a206e6f7420676f6f64000000000000000000000000000081525060200191505060405180910390fd5b610b3b84610ca9565b6000610b858260010154610b7764e8d4a51000610b698760030154876000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b90506000811115610b9b57610b9a3382612731565b5b6000841115610c1357610bbb8483600001546126e790919063ffffffff16565b8260000181905550610c1233858560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166129aa9092919063ffffffff16565b5b610c4564e8d4a51000610c378560030154856000015461261790919063ffffffff16565b61269d90919063ffffffff16565b8260010181905550843373ffffffffffffffffffffffffffffffffffffffff167ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568866040518082815260200191505060405180910390a35050505050565b600c5481565b600060098281548110610cb857fe5b90600052602060002090600502019050600073ffffffffffffffffffffffffffffffffffffffff168160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015610d2d575060008160010154115b15610ef6578060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f3c81606040518163ffffffff1660e01b815260040160206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d6020811015610dc657600080fd5b81019080805190602001909291905050508160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e3a7c9036040518163ffffffff1660e01b815260040160206040518083038186803b158015610e4157600080fd5b505afa158015610e55573d6000803e3d6000fd5b505050506040513d6020811015610e6b57600080fd5b810190808051906020019092919050505010610ef557610e9a8160010154600b546126e790919063ffffffff16565b600b81905550600081600101819055507fc66cec52f6fc7c7c09b5f02578bd330a548d6b039f8ba5b5703204565bdb335b82600080604051808481526020018381526020018215158152602001935050505060405180910390a15b5b80600201544311610f07575061130e565b60008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610f9457600080fd5b505afa158015610fa8573d6000803e3d6000fd5b505050506040513d6020811015610fbe57600080fd5b810190808051906020019092919050505090506000811415610fea57438260020181905550505061130e565b61102960055461101b61100a60055460065461261790919063ffffffff16565b600c54612a4c90919063ffffffff16565b612a4c90919063ffffffff16565b43106110735760066000815480929190600101919050555061106c60045461105e60035460085461261790919063ffffffff16565b61269d90919063ffffffff16565b6008819055505b60006110ad600b5461109f8560010154611091876002015443611ce2565b61261790919063ffffffff16565b61269d90919063ffffffff16565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f19600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661112460098561269d90919063ffffffff16565b6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561117757600080fd5b505af115801561118b573d6000803e3d6000fd5b505050506040513d60208110156111a157600080fd5b810190808051906020019092919050505050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340c10f1930836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561124657600080fd5b505af115801561125a573d6000803e3d6000fd5b505050506040513d602081101561127057600080fd5b8101908080519060200190929190505050506112c26112af836112a164e8d4a510008561261790919063ffffffff16565b61269d90919063ffffffff16565b8460030154612a4c90919063ffffffff16565b83600301819055504383600201819055507f20f73897541b01c2d01f4eca5ac07cb2c486d778aadf60fac2d2dcfd3c1389f1846040518082815260200191505060405180910390a15050505b50565b60006009828154811061132057fe5b906000526020600020906005020190506000600a600084815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905060008260000181905550600082600101819055506113f033828560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166129aa9092919063ffffffff16565b833373ffffffffffffffffffffffffffffffffffffffff167fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595836040518082815260200191505060405180910390a350505050565b61144d61260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461150d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561156457600080fd5b811561157357611572611790565b5b6000600c54431161158657600c54611588565b435b905061159f85600b54612a4c90919063ffffffff16565b600b8190555060096040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001878152602001838152602001600081526020018473ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201556060820151816003015560808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050506001600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f4677f0774f427b7084c61193b0b175490b6404bc62b3964f746c951253a7c448858585604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018215158152602001935050505060405180910390a15050505050565b6000600980549050905060005b818110156117b9576117ae81610ca9565b80600101905061179d565b507f3f73d20979eadee00e614817748ea556ec6dadb2721118bc18663dfd111484ff60405160405180910390a150565b6117f161260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146118b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80156118c0576118bf611790565b5b611905826118f7600986815481106118d457fe5b906000526020600020906005020160010154600b546126e790919063ffffffff16565b612a4c90919063ffffffff16565b600b81905550816009848154811061191957fe5b9060005260206000209060050201600101819055507fc66cec52f6fc7c7c09b5f02578bd330a548d6b039f8ba5b5703204565bdb335b838383604051808481526020018381526020018215158152602001935050505060405180910390a1505050565b60065481565b61198a61260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611a4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b60035481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bd7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260098152602001807f6465763a207775743f000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6787ec2e213b45f8a55bfa91346e72127488bde333c0e349257df192b861855581604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600a602052816000526040600020602052806000526040600020600091509150508060000154908060010154905082565b60076020528060005260406000206000915054906101000a900460ff1681565b600080611d10611cff60055460065461261790919063ffffffff16565b600c54612a4c90919063ffffffff16565b9050600554611d2885856126e790919063ffffffff16565b1115611d4657611d43600554846126e790919063ffffffff16565b93505b80841115611d7d57611d75600854611d6786866126e790919063ffffffff16565b61261790919063ffffffff16565b915050611e08565b611e04611da7600854611d9984876126e790919063ffffffff16565b61261790919063ffffffff16565b611df6600354611de8600454611dda600854611dcc8c8a6126e790919063ffffffff16565b61261790919063ffffffff16565b61261790919063ffffffff16565b61269d90919063ffffffff16565b612a4c90919063ffffffff16565b9150505b92915050565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060098481548110611e4a57fe5b906000526020600020906005020190506000600a600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260030154905060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611f4457600080fd5b505afa158015611f58573d6000803e3d6000fd5b505050506040513d6020811015611f6e57600080fd5b81019080805190602001909291905050509050836002015443118015611f95575060008114155b15612016576000611fd4600b54611fc68760010154611fb8896002015443611ce2565b61261790919063ffffffff16565b61269d90919063ffffffff16565b905061201261200383611ff564e8d4a510008561261790919063ffffffff16565b61269d90919063ffffffff16565b84612a4c90919063ffffffff16565b9250505b61205a836001015461204c64e8d4a5100061203e86886000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b94505050505092915050565b60006009838154811061207557fe5b906000526020600020906005020190506000600a600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506120e284610ca9565b600081600001541115612151576000612139826001015461212b64e8d4a5100061211d8760030154876000015461261790919063ffffffff16565b61269d90919063ffffffff16565b6126e790919063ffffffff16565b9050600081111561214f5761214e3382612731565b5b505b60008311156121cb576121ab3330858560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612ad4909392919063ffffffff16565b6121c2838260000154612a4c90919063ffffffff16565b81600001819055505b6121fd64e8d4a510006121ef8460030154846000015461261790919063ffffffff16565b61269d90919063ffffffff16565b8160010181905550833373ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15856040518082815260200191505060405180910390a350505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61228861260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806130ab6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61249361260f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612553576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600c5443106125ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806131646033913960400191505060405180910390fd5b804310612605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806130f76029913960400191505060405180910390fd5b80600c8190555050565b600033905090565b60008083141561262a5760009050612697565b600082840290508284828161263b57fe5b0414612692576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806131206021913960400191505060405180910390fd5b809150505b92915050565b60006126df83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612b95565b905092915050565b600061272983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c5b565b905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156127bc57600080fd5b505afa1580156127d0573d6000803e3d6000fd5b505050506040513d60208110156127e657600080fd5b81019080805190602001909291905050509050808211156128d557600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561289457600080fd5b505af11580156128a8573d6000803e3d6000fd5b505050506040513d60208110156128be57600080fd5b8101908080519060200190929190505050506129a5565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561296857600080fd5b505af115801561297c573d6000803e3d6000fd5b505050506040513d602081101561299257600080fd5b8101908080519060200190929190505050505b505050565b612a478363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612d1b565b505050565b600080828401905083811015612aca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b612b8f846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612d1b565b50505050565b60008083118290612c41576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612c06578082015181840152602081019050612beb565b50505050905090810190601f168015612c335780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612c4d57fe5b049050809150509392505050565b6000838311158290612d08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612ccd578082015181840152602081019050612cb2565b50505050905090810190601f168015612cfa5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6060612d7d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612e0a9092919063ffffffff16565b9050600081511115612e0557808060200190516020811015612d9e57600080fd5b8101908080519060200190929190505050612e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613197602a913960400191505060405180910390fd5b5b505050565b6060612e198484600085612e22565b90509392505050565b606082471015612e7d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806130d16026913960400191505060405180910390fd5b612e8685612fcb565b612ef8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310612f485780518252602082019150602081019050602083039250612f25565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612faa576040519150601f19603f3d011682016040523d82523d6000602084013e612faf565b606091505b5091509150612fbf828286612fde565b92505050949350505050565b600080823b905060008111915050919050565b60608315612fee578290506130a3565b6000835111156130015782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561306857808201518184015260208101905061304d565b50505050905090810190601f1680156130955780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c6e657720737461727420626c6f636b206e6565647320746f20626520696e2074686520667574757265536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f777a65726f20626c6f636b7320706572207472616e636865206e6f7420616c6c6f776564737461727420626c6f636b2063616e206e6f74206265206d6f64696669656420616674657220697420686173207061737365645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220d5c055ca5b378e01e1efd0d71803c5bbf598fb11d361d48ec35028e1d30f7bd364736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000094e0bab2f6ab1f19f4750e42d7349f2740513ad5000000000000000000000000db8ec47f52e2602c92ac603079d9e7e90d3187cb00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000038ef86f0a0736000000000000000000000000000000000000000000000000000000000000be1bdf000000000000000000000000000000000000000000000000000000000002fb02
-----Decoded View---------------
Arg [0] : _unic (address): 0x94E0BAb2F6Ab1F19F4750E42d7349f2740513aD5
Arg [1] : _devaddr (address): 0xDB8eC47F52e2602C92Ac603079d9e7E90D3187Cb
Arg [2] : _mintRateMultiplier (uint256): 19
Arg [3] : _mintRateDivider (uint256): 20
Arg [4] : _unicPerBlock (uint256): 256415384600000000
Arg [5] : _startBlock (uint256): 12458975
Arg [6] : _blocksPerTranche (uint256): 195330
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000094e0bab2f6ab1f19f4750e42d7349f2740513ad5
Arg [1] : 000000000000000000000000db8ec47f52e2602c92ac603079d9e7e90d3187cb
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [4] : 000000000000000000000000000000000000000000000000038ef86f0a073600
Arg [5] : 0000000000000000000000000000000000000000000000000000000000be1bdf
Arg [6] : 000000000000000000000000000000000000000000000000000000000002fb02
Deployed Bytecode Sourcemap
85462:11641:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87147:31;;;:::i;:::-;;;;;;;;;;;;;;;;;;;88865:95;;;:::i;:::-;;;;;;;;;;;;;;;;;;;87437:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87680:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;96320:477;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;94486:740;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;87771:25;;;:::i;:::-;;;;;;;;;;;;;;;;;;;92236:1381;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;95297:385;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;89130:723;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;91945:215;;;:::i;:::-;;89949:357;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;87209:26;;;:::i;:::-;;;;;;;;;;;;;;;;;;;31424:148;;;:::i;:::-;;87011:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;86971:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;96130:160;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;30782:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;87519:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;87287:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;90431:675;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;87374:27;;;:::i;:::-;;;;;;;;;;;;;;;;;;;86912:22;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;91170:692;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;93684:752;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;86868:16;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;31727:244;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;96805:295;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;87147:31;;;;:::o;88865:95::-;88910:7;88937:8;:15;;;;88930:22;;88865:95;:::o;87437:26::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;87680:34::-;;;;:::o;96320:477::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96502:1:::1;96483:16;:20;96475:52;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;96566:1;96546:17;:21;96538:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96639:19;96618:18;:40;;;;96687:16;96669:15;:34;;;;96729:13;96714:12;:28;;;;96772:17;96753:16;:36;;;;96320:477:::0;;;;:::o;94486:740::-;94553:21;94577:8;94586:4;94577:14;;;;;;;;;;;;;;;;;;94553:38;;94602:21;94626:8;:14;94635:4;94626:14;;;;;;;;;;;:26;94641:10;94626:26;;;;;;;;;;;;;;;94602:50;;94686:7;94671:4;:11;;;:22;;94663:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94727:16;94738:4;94727:10;:16::i;:::-;94754:15;94772:68;94824:4;:15;;;94772:47;94814:4;94772:37;94788:4;:20;;;94772:4;:11;;;:15;;:37;;;;:::i;:::-;:41;;:47;;;;:::i;:::-;:51;;:68;;;;:::i;:::-;94754:86;;94864:1;94854:7;:11;94851:80;;;94882:37;94899:10;94911:7;94882:16;:37::i;:::-;94851:80;94954:1;94944:7;:11;94941:151;;;94986:24;95002:7;94986:4;:11;;;:15;;:24;;;;:::i;:::-;94972:4;:11;;:38;;;;95025:55;95059:10;95072:7;95025:4;:12;;;;;;;;;;;;:25;;;;:55;;;;;:::i;:::-;94941:151;95120:47;95162:4;95120:37;95136:4;:20;;;95120:4;:11;;;:15;;:37;;;;:::i;:::-;:41;;:47;;;;:::i;:::-;95102:4;:15;;:65;;;;95204:4;95192:10;95183:35;;;95210:7;95183:35;;;;;;;;;;;;;;;;;;94486:740;;;;;:::o;87771:25::-;;;;:::o;92236:1381::-;92288:21;92312:8;92321:4;92312:14;;;;;;;;;;;;;;;;;;92288:38;;92364:1;92341:25;;:4;:11;;;;;;;;;;;;:25;;;;:48;;;;;92388:1;92370:4;:15;;;:19;92341:48;92337:331;;;92460:4;:11;;;;;;;;;;;;92450:33;;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92420:4;:11;;;;;;;;;;;;92410:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:75;92406:251;;92524:36;92544:4;:15;;;92524;;:19;;:36;;;;:::i;:::-;92506:15;:54;;;;92597:1;92579:4;:15;;:19;;;;92622;92626:4;92632:1;92635:5;92622:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92406:251;92337:331;92698:4;:20;;;92682:12;:36;92678:75;;92735:7;;;92678:75;92763:16;92782:4;:12;;;;;;;;;;;;:22;;;92813:4;92782:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92763:56;;92846:1;92834:8;:13;92830:102;;;92887:12;92864:4;:20;;:35;;;;92914:7;;;;92830:102;93029:67;93079:16;;93029:45;93044:29;93056:16;;93044:7;;:11;;:29;;;;:::i;:::-;93029:10;;:14;;:45;;;;:::i;:::-;:49;;:67;;;;:::i;:::-;93013:12;:83;93009:212;;93113:7;;:9;;;;;;;;;;;;;93152:57;93193:15;;93152:36;93169:18;;93152:12;;:16;;:36;;;;:::i;:::-;:40;;:57;;;;:::i;:::-;93137:12;:72;;;;93009:212;93231:18;93252:88;93324:15;;93252:67;93303:4;:15;;;93252:46;93263:4;:20;;;93285:12;93252:10;:46::i;:::-;:50;;:67;;;;:::i;:::-;:71;;:88;;;;:::i;:::-;93231:109;;93351:4;;;;;;;;;;;:9;;;93361:7;;;;;;;;;;;93370:17;93385:1;93370:10;:14;;:17;;;;:::i;:::-;93351:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93399:4;;;;;;;;;;;:9;;;93417:4;93424:10;93399:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93469:60;93494:34;93519:8;93494:20;93509:4;93494:10;:14;;:20;;;;:::i;:::-;:24;;:34;;;;:::i;:::-;93469:4;:20;;;:24;;:60;;;;:::i;:::-;93446:4;:20;;:83;;;;93563:12;93540:4;:20;;:35;;;;93593:16;93604:4;93593:16;;;;;;;;;;;;;;;;;;92236:1381;;;;;:::o;95297:385::-;95356:21;95380:8;95389:4;95380:14;;;;;;;;;;;;;;;;;;95356:38;;95405:21;95429:8;:14;95438:4;95429:14;;;;;;;;;;;:26;95444:10;95429:26;;;;;;;;;;;;;;;95405:50;;95466:14;95483:4;:11;;;95466:28;;95519:1;95505:4;:11;;:15;;;;95549:1;95531:4;:15;;:19;;;;95561:54;95595:10;95608:6;95561:4;:12;;;;;;;;;;;;:25;;;;:54;;;;;:::i;:::-;95661:4;95649:10;95631:43;;;95667:6;95631:43;;;;;;;;;;;;;;;;;;95297:385;;;;:::o;89130:723::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89253:9:::1;:28;89271:8;89253:28;;;;;;;;;;;;;;;;;;;;;;;;;89252:29;89244:38;;;::::0;::::1;;89297:11;89293:61;;;89325:17;:15;:17::i;:::-;89293:61;89364:23;89405:10;;89390:12;:25;:53;;89433:10;;89390:53;;;89418:12;89390:53;89364:79;;89472:32;89492:11;89472:15;;:19;;:32;;;;:::i;:::-;89454:15;:50;;;;89515:8;89529:201;;;;;;;;89562:8;89529:201;;;;;;89597:11;89529:201;;;;89640:15;89529:201;;;;89687:1;89529:201;;;;89711:7;89529:201;;;;::::0;89515:216:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89775:4;89744:9;:28;89762:8;89744:28;;;;;;;;;;;;;;;;:35;;;;;;;;;;;;;;;;;;89797:48;89801:11;89822:8;89833:11;89797:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31064:1;89130:723:::0;;;;:::o;91945:215::-;91990:14;92007:8;:15;;;;91990:32;;92038:11;92033:85;92061:6;92055:3;:12;92033:85;;;92091:15;92102:3;92091:10;:15::i;:::-;92069:5;;;;;92033:85;;;;92135:17;;;;;;;;;;91945:215;:::o;89949:357::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90047:11:::1;90043:61;;;90075:17;:15;:17::i;:::-;90043:61;90132:63;90183:11;90132:46;90152:8;90161:4;90152:14;;;;;;;;;;;;;;;;;;:25;;;90132:15;;:19;;:46;;;;:::i;:::-;:50;;:63;;;;:::i;:::-;90114:15;:81;;;;90234:11;90206:8;90215:4;90206:14;;;;;;;;;;;;;;;;;;:25;;:39;;;;90263:35;90267:4;90273:11;90286;90263:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89949:357:::0;;;:::o;87209:26::-;;;;:::o;31424:148::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31531:1:::1;31494:40;;31515:6;::::0;::::1;;;;;;;;31494:40;;;;;;;;;;;;31562:1;31545:6:::0;::::1;:19;;;;;;;;;;;;;;;;;;31424:148::o:0;87011:30::-;;;;:::o;86971:33::-;;;;:::o;96130:160::-;96201:7;;;;;;;;;;;96187:21;;:10;:21;;;96179:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96243:8;96233:7;;:18;;;;;;;;;;;;;;;;;;96269:13;96273:8;96269:13;;;;;;;;;;;;;;;;;;;;96130:160;:::o;30782:79::-;30820:7;30847:6;;;;;;;;;;;30840:13;;30782:79;:::o;87519:66::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;87287:41::-;;;;;;;;;;;;;;;;;;;;;;:::o;90431:675::-;90500:7;90520:24;90547:45;90562:29;90574:16;;90562:7;;:11;;:29;;;;:::i;:::-;90547:10;;:14;;:45;;;;:::i;:::-;90520:72;;90624:16;;90607:14;90615:5;90607:3;:7;;:14;;;;:::i;:::-;:33;90603:99;;;90665:25;90673:16;;90665:3;:7;;:25;;;;:::i;:::-;90657:33;;90603:99;90724:16;90716:5;:24;90712:387;;;90764:32;90783:12;;90764:14;90772:5;90764:3;:7;;:14;;;;:::i;:::-;:18;;:32;;;;:::i;:::-;90757:39;;;;;90712:387;90916:171;91029:43;91059:12;;91029:25;91037:16;91029:3;:7;;:25;;;;:::i;:::-;:29;;:43;;;;:::i;:::-;90916:90;90987:18;;90916:66;90966:15;;90916:45;90948:12;;90916:27;90937:5;90916:16;:20;;:27;;;;:::i;:::-;:31;;:45;;;;:::i;:::-;:49;;:66;;;;:::i;:::-;:70;;:90;;;;:::i;:::-;:94;;:171;;;;:::i;:::-;90909:178;;;90431:675;;;;;:::o;87374:27::-;;;;:::o;86912:22::-;;;;;;;;;;;;;:::o;91170:692::-;91243:7;91263:21;91287:8;91296:4;91287:14;;;;;;;;;;;;;;;;;;91263:38;;91312:21;91336:8;:14;91345:4;91336:14;;;;;;;;;;;:21;91351:5;91336:21;;;;;;;;;;;;;;;91312:45;;91368:23;91394:4;:20;;;91368:46;;91425:16;91444:4;:12;;;;;;;;;;;;:22;;;91475:4;91444:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91425:56;;91511:4;:20;;;91496:12;:35;:52;;;;;91547:1;91535:8;:13;;91496:52;91492:282;;;91565:18;91586:88;91658:15;;91586:67;91637:4;:15;;;91586:46;91597:4;:20;;;91619:12;91586:10;:46::i;:::-;:50;;:67;;;;:::i;:::-;:71;;:88;;;;:::i;:::-;91565:109;;91707:55;91727:34;91752:8;91727:20;91742:4;91727:10;:14;;:20;;;;:::i;:::-;:24;;:34;;;;:::i;:::-;91707:15;:19;;:55;;;;:::i;:::-;91689:73;;91492:282;;91791:63;91838:4;:15;;;91791:42;91828:4;91791:32;91807:15;91791:4;:11;;;:15;;:32;;;;:::i;:::-;:36;;:42;;;;:::i;:::-;:46;;:63;;;;:::i;:::-;91784:70;;;;;;91170:692;;;;:::o;93684:752::-;93750:21;93774:8;93783:4;93774:14;;;;;;;;;;;;;;;;;;93750:38;;93799:21;93823:8;:14;93832:4;93823:14;;;;;;;;;;;:26;93838:10;93823:26;;;;;;;;;;;;;;;93799:50;;93860:16;93871:4;93860:10;:16::i;:::-;93905:1;93891:4;:11;;;:15;93887:236;;;93923:15;93941:68;93993:4;:15;;;93941:47;93983:4;93941:37;93957:4;:20;;;93941:4;:11;;;:15;;:37;;;;:::i;:::-;:41;;:47;;;;:::i;:::-;:51;;:68;;;;:::i;:::-;93923:86;;94037:1;94027:7;:11;94024:88;;;94059:37;94076:10;94088:7;94059:16;:37::i;:::-;94024:88;93887:236;;94146:1;94136:7;:11;94133:170;;;94164:74;94202:10;94223:4;94230:7;94164:4;:12;;;;;;;;;;;;:29;;;;:74;;;;;;:::i;:::-;94267:24;94283:7;94267:4;:11;;;:15;;:24;;;;:::i;:::-;94253:4;:11;;:38;;;;94133:170;94331:47;94373:4;94331:37;94347:4;:20;;;94331:4;:11;;;:15;;:37;;;;:::i;:::-;:41;;:47;;;;:::i;:::-;94313:4;:15;;:65;;;;94414:4;94402:10;94394:34;;;94420:7;94394:34;;;;;;;;;;;;;;;;;;93684:752;;;;:::o;86868:16::-;;;;;;;;;;;;;:::o;31727:244::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31836:1:::1;31816:22;;:8;:22;;;;31808:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31926:8;31897:38;;31918:6;::::0;::::1;;;;;;;;31897:38;;;;;;;;;;;;31955:8;31946:6;::::0;:17:::1;;;;;;;;;;;;;;;;;;31727:244:::0;:::o;96805:295::-;31004:12;:10;:12::i;:::-;30994:22;;:6;;;;;;;;;;:22;;;30986:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96900:10:::1;;96885:12;:25;96877:89;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97000:11;96985:12;:26;96977:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97081:11;97068:10;:24;;;;96805:295:::0;:::o;29317:106::-;29370:15;29405:10;29398:17;;29317:106;:::o;5129:471::-;5187:7;5437:1;5432;:6;5428:47;;;5462:1;5455:8;;;;5428:47;5487:9;5503:1;5499;:5;5487:17;;5532:1;5527;5523;:5;;;;;;:10;5515:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5591:1;5584:8;;;5129:471;;;;;:::o;6076:132::-;6134:7;6161:39;6165:1;6168;6161:39;;;;;;;;;;;;;;;;;:3;:39::i;:::-;6154:46;;6076:132;;;;:::o;4239:136::-;4297:7;4324:43;4328:1;4331;4324:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;4317:50;;4239:136;;;;:::o;95796:278::-;95872:15;95890:4;;;;;;;;;;;:14;;;95913:4;95890:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95872:47;;95944:7;95934;:17;95930:137;;;95968:4;;;;;;;;;;;:13;;;95982:3;95987:7;95968:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95930:137;;;96028:4;;;;;;;;;;;:13;;;96042:3;96047:7;96028:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95930:137;95796:278;;;:::o;15930:177::-;16013:86;16033:5;16063:23;;;16088:2;16092:5;16040:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16013:19;:86::i;:::-;15930:177;;;:::o;3775:181::-;3833:7;3853:9;3869:1;3865;:5;3853:17;;3894:1;3889;:6;;3881:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3947:1;3940:8;;;3775:181;;;;:::o;16115:205::-;16216:96;16236:5;16266:27;;;16295:4;16301:2;16305:5;16243:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16216:19;:96::i;:::-;16115:205;;;;:::o;6704:278::-;6790:7;6822:1;6818;:5;6825:12;6810:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6849:9;6865:1;6861;:5;;;;;;6849:17;;6973:1;6966:8;;;6704:278;;;;;:::o;4678:192::-;4764:7;4797:1;4792;:6;;4800:12;4784:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4824:9;4840:1;4836;:5;4824:17;;4861:1;4854:8;;;4678:192;;;;;:::o;18235:761::-;18659:23;18685:69;18713:4;18685:69;;;;;;;;;;;;;;;;;18693:5;18685:27;;;;:69;;;;;:::i;:::-;18659:95;;18789:1;18769:10;:17;:21;18765:224;;;18911:10;18900:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18892:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18765:224;18235:761;;;:::o;11927:195::-;12030:12;12062:52;12084:6;12092:4;12098:1;12101:12;12062:21;:52::i;:::-;12055:59;;11927:195;;;;;:::o;12979:530::-;13106:12;13164:5;13139:21;:30;;13131:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13231:18;13242:6;13231:10;:18::i;:::-;13223:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13357:12;13371:23;13398:6;:11;;13418:5;13426:4;13398:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13356:75;;;;13449:52;13467:7;13476:10;13488:12;13449:17;:52::i;:::-;13442:59;;;;12979:530;;;;;;:::o;9009:422::-;9069:4;9277:12;9388:7;9376:20;9368:28;;9422:1;9415:4;:8;9408:15;;;9009:422;;;:::o;14515:742::-;14630:12;14659:7;14655:595;;;14690:10;14683:17;;;;14655:595;14824:1;14804:10;:17;:21;14800:439;;;15067:10;15061:17;15128:15;15115:10;15111:2;15107:19;15100:44;15015:148;15210:12;15203:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14515:742;;;;;;:::o
Swarm Source
ipfs://d5c055ca5b378e01e1efd0d71803c5bbf598fb11d361d48ec35028e1d30f7bd3
Loading...
Loading
Loading...
Loading
Net Worth in USD
$3,201.02
Net Worth in ETH
1.627396
Token Allocations
UNIC
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.712657 | 4,491.6696 | $3,201.02 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.