Source Code
Overview
GLMR Balance
GLMR Value
$0.00View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenSaleDistributor
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./IERC20.sol";
import "./SafeERC20.sol";
import "./TokenSaleDistributorStorage.sol";
import "./TokenSaleDistributorProxy.sol";
import "./ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract TokenSaleDistributor is ReentrancyGuard, TokenSaleDistributorStorage {
using SafeERC20 for IERC20;
event Claimed(address indexed recipient, uint amount);
/** The token address was set by the administrator. */
event AdminSetToken(address tokenAddress);
/** The administratory withdrew tokens. */
event AdminWithdrewTokens(address tokenAddress, uint amount, address targetAddress);
/// @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 An event thats emitted when the voting enabled property changes.
event VotingEnabledChanged(bool oldValue, bool newValue);
/// @notice A record of each accounts delegate
mapping (address => address) public delegates;
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint 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 Whether or not voting is enabled.
bool public votingEnabled;
/// @notice EIP-20 token name for this token
string public constant name = "vWELL";
function getChainId() internal view returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
/**
* @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, ECDSA.RecoverError error) = ECDSA.tryRecover(digest, v, r, s);
require(error == ECDSA.RecoverError.NoError, "invalid sig");
require(signatory != address(0), "invalid sig");
require(nonce == nonces[signatory]++, "invalid nonce");
require(block.timestamp <= expiry, "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 (uint) {
// No users have any voting power if voting is disabled.
if (!votingEnabled) {
return 0;
}
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 (uint) {
require(blockNumber < block.number, "not yet determined");
// No users have any voting power if voting is disabled.
if (!votingEnabled) {
return 0;
}
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];
uint delegatorBalance = totalVotingPower(delegator);
delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint amount) internal {
if (srcRep != dstRep && amount != 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint srcRepOld = srcRepNum != 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint srcRepNew = srcRepOld - amount;
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint dstRepOld = dstRepNum != 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint dstRepNew = dstRepOld + amount;
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint oldVotes, uint newVotes) internal {
uint32 blockNumber = uint32(block.number);
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 totalVotingPower(address user) public view returns (uint) {
uint totalAllocatedToUser = totalAllocated(user);
uint totalClaimedByUser = totalClaimed(user);
return totalAllocatedToUser - totalClaimedByUser;
}
/********************************************************
* *
* PUBLIC FUNCTIONS *
* *
********************************************************/
/**
* @notice Claim the tokens that have already vested
*/
function claim() external nonReentrant {
uint claimed;
uint length = allocations[msg.sender].length;
for (uint i; i < length; ++i) {
claimed += _claim(allocations[msg.sender][i]);
}
if (claimed != 0) {
emit Claimed(msg.sender, claimed);
_moveDelegates(delegates[msg.sender], address(0), claimed);
}
}
/**
* @notice Get the total number of allocations for `recipient`
*/
function totalAllocations(address recipient) external view returns (uint) {
return allocations[recipient].length;
}
/**
* @notice Get all allocations for `recipient`
*/
function getUserAllocations(address recipient) external view returns (Allocation[] memory) {
return allocations[recipient];
}
/**
* @notice Get the total amount of tokens allocated for `recipient`
*/
function totalAllocated(address recipient) public view returns (uint) {
uint total;
uint length = allocations[recipient].length;
for (uint i; i < length; ++i) {
total += allocations[recipient][i].amount;
}
return total;
}
/**
* @notice Get the total amount of vested tokens for `recipient` so far
*/
function totalVested(address recipient) external view returns (uint) {
uint tokensVested;
uint length = allocations[recipient].length;
for (uint i; i < length; ++i) {
tokensVested += _vested(allocations[recipient][i]);
}
return tokensVested;
}
/**
* @notice Get the total amount of claimed tokens by `recipient`
*/
function totalClaimed(address recipient) public view returns (uint) {
uint total;
uint length = allocations[recipient].length;
for (uint i; i < length; ++i) {
total += allocations[recipient][i].claimed;
}
return total;
}
/**
* @notice Get the total amount of claimable tokens by `recipient`
*/
function totalClaimable(address recipient) external view returns (uint) {
uint total;
uint length = allocations[recipient].length;
for (uint i; i < length; ++i) {
total += _claimable(allocations[recipient][i]);
}
return total;
}
/********************************************************
* *
* ADMIN-ONLY FUNCTIONS *
* *
********************************************************/
/**
* @notice Set the amount of purchased tokens per user.
* @param recipients Token recipients
* @param isLinear Allocation types
* @param epochs Vesting epochs
* @param vestingDurations Vesting period lengths
* @param cliffs Vesting cliffs, if any
* @param cliffPercentages Vesting cliff unlock percentages, if any
* @param amounts Purchased token amounts
*/
function setAllocations(
address[] memory recipients,
bool[] memory isLinear,
uint[] memory epochs,
uint[] memory vestingDurations,
uint[] memory cliffs,
uint[] memory cliffPercentages,
uint[] memory amounts
)
external
adminOnly
{
require(recipients.length == epochs.length);
require(recipients.length == isLinear.length);
require(recipients.length == vestingDurations.length);
require(recipients.length == cliffs.length);
require(recipients.length == cliffPercentages.length);
require(recipients.length == amounts.length);
uint length = recipients.length;
for (uint i; i < length; ++i) {
require(cliffPercentages[i] <= 1e18);
allocations[recipients[i]].push(
Allocation(
isLinear[i],
epochs[i],
vestingDurations[i],
cliffs[i],
cliffPercentages[i],
amounts[i],
0
)
);
_moveDelegates(address(0), delegates[recipients[i]], amounts[i]);
}
}
/**
* @notice Reset all claims data for the given addresses and transfer tokens to the admin.
* @param targetUser The address data to reset. This will also reduce the voting power of these users.
*/
function resetAllocationsByUser(address targetUser) external adminOnly {
// Get the user's current total voting power, which is the number of unclaimed tokens in the contract
uint votingPower = totalVotingPower(targetUser);
// Decrease the voting power to zero
_moveDelegates(delegates[targetUser], address(0), votingPower);
// Delete all allocations
delete allocations[targetUser];
// Withdraw tokens associated with the user's voting power
if (votingPower != 0) {
IERC20(tokenAddress).safeTransfer(admin, votingPower);
}
emit AdminWithdrewTokens(tokenAddress, votingPower, admin);
}
/**
* @notice Withdraw deposited tokens from the contract. This method cannot be used with the reward token
*
* @param token The token address to withdraw
* @param amount Amount to withdraw from the contract balance
*/
function withdraw(address token, uint amount) external adminOnly {
require(token != tokenAddress, "use resetAllocationsByUser");
if (amount != 0) {
IERC20(token).safeTransfer(admin, amount);
}
}
/**
* @notice Enables or disables voting for all users on this contract, in case of emergency.
* @param enabled Whether or not voting should be allowed
*/
function setVotingEnabled(bool enabled) external adminOnly {
// Cache old value.
bool oldValue = votingEnabled;
votingEnabled = enabled;
emit VotingEnabledChanged(oldValue, votingEnabled);
}
/**
* @notice Set the vested token address
* @param newTokenAddress ERC-20 token address
*/
function setTokenAddress(address newTokenAddress) external adminOnly {
require(tokenAddress == address(0), "address already set");
tokenAddress = newTokenAddress;
emit AdminSetToken(newTokenAddress);
}
/**
* @notice Accept this contract as the implementation for a proxy.
* @param proxy TokenSaleDistributorProxy
*/
function becomeImplementation(TokenSaleDistributorProxy proxy) external {
require(msg.sender == proxy.admin(), "not proxy admin");
proxy.acceptPendingImplementation();
}
/********************************************************
* *
* INTERNAL FUNCTIONS *
* *
********************************************************/
/**
* @notice Calculate the amount of vested tokens at the time of calling
* @return Amount of vested tokens
*/
function _vested(Allocation memory allocation) internal view returns (uint) {
if (block.timestamp < allocation.epoch + allocation.cliff) {
return 0;
}
uint initialAmount = allocation.amount * allocation.cliffPercentage / 1e18;
uint postCliffAmount = allocation.amount - initialAmount;
uint elapsed = block.timestamp - allocation.epoch - allocation.cliff;
if (allocation.isLinear) {
if (elapsed >= allocation.vestingDuration) {
return allocation.amount;
}
return initialAmount + (postCliffAmount * elapsed / allocation.vestingDuration);
}
uint elapsedPeriods = elapsed / monthlyVestingInterval;
if (elapsedPeriods >= allocation.vestingDuration) {
return allocation.amount;
}
uint monthlyVestedAmount = postCliffAmount / allocation.vestingDuration;
return initialAmount + (monthlyVestedAmount * elapsedPeriods);
}
/**
* @notice Get the amount of claimable tokens for `allocation`
*/
function _claimable(Allocation memory allocation) internal view returns (uint) {
return _vested(allocation) - allocation.claimed;
}
/**
* @notice Claim all vested tokens from the allocation
* @return The amount of claimed tokens
*/
function _claim(Allocation storage allocation) internal returns (uint) {
uint claimable = _claimable(allocation);
if (claimable == 0) {
return 0;
}
allocation.claimed += claimable;
IERC20(tokenAddress).safeTransfer(msg.sender, claimable);
return claimable;
}
modifier adminOnly {
require(msg.sender == admin, "admin only");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./IERC20.sol";
import "./Address.sol";
/**
* @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 Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./TokenSaleDistributorProxyStorage.sol";
contract TokenSaleDistributorStorage is TokenSaleDistributorProxyStorage {
address public tokenAddress;
// 60 * 60 * 24 * 365 / 12 seconds
uint public constant monthlyVestingInterval = 2628000;
mapping(address => Allocation[]) public allocations;
struct Allocation {
// True for linear vesting, false for monthly
bool isLinear;
// Vesting start timestamp
uint epoch;
// Linear: The amount of seconds after the cliff before all tokens are vested
// Monthly: The number of monthly claims before all tokens are vested
uint vestingDuration;
// Seconds after epoch when tokens start vesting
uint cliff;
// Percentage of tokens that become vested immediately after the cliff. 100 % = 1e18.
uint cliffPercentage;
// Total amount of allocated tokens
uint amount;
// Amount of claimed tokens from this allocation
uint claimed;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./ReentrancyGuard.sol";
import "./TokenSaleDistributorProxyStorage.sol";
contract TokenSaleDistributorProxy is ReentrancyGuard, TokenSaleDistributorProxyStorage {
/** The admin was changed */
event AdminChanged(address newAdmin);
/** The implementation was changed */
event ImplChanged(address newImpl);
constructor() public {
admin = msg.sender;
}
/**
* Request a new admin to be set for the contract.
*
* @param newAdmin New admin address
*/
function setPendingAdmin(address newAdmin) public adminOnly {
require(newAdmin != address(0), "Cannot set to zero address");
pendingAdmin = newAdmin;
}
/**
* Accept admin transfer from the current admin to the new.
*/
function acceptPendingAdmin() public {
require(msg.sender == pendingAdmin && pendingAdmin != address(0), "Caller must be the pending admin");
admin = pendingAdmin;
pendingAdmin = address(0);
emit AdminChanged(admin);
}
/**
* Request a new implementation to be set for the contract.
*
* @param newImplementation New contract implementation contract address
*/
function setPendingImplementation(address newImplementation) public adminOnly {
require(newImplementation != address(0), "Cannot set to zero address");
pendingImplementation = newImplementation;
}
/**
* Accept pending implementation change
*/
function acceptPendingImplementation() public {
require(msg.sender == pendingImplementation && pendingImplementation != address(0), "Only the pending implementation contract can call this");
implementation = pendingImplementation;
pendingImplementation = address(0);
emit ImplChanged(implementation);
}
fallback() payable external {
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
let size := returndatasize()
returndatacopy(free_mem_ptr, 0, size)
switch success
case 0 { revert(free_mem_ptr, size) }
default { return(free_mem_ptr, size) }
}
}
/********************************************************
* *
* MODIFIERS *
* *
********************************************************/
modifier adminOnly {
require(msg.sender == admin, "admin only");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() public {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, 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");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
contract TokenSaleDistributorProxyStorage {
// Current contract admin address
address public admin;
// Requested new admin for the contract
address public pendingAdmin;
// Current contract implementation address
address public implementation;
// Requested new contract implementation address
address public pendingImplementation;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"AdminSetToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"}],"name":"AdminWithdrewTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"oldValue","type":"bool"},{"indexed":false,"internalType":"bool","name":"newValue","type":"bool"}],"name":"VotingEnabledChanged","type":"event"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"allocations","outputs":[{"internalType":"bool","name":"isLinear","type":"bool"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"},{"internalType":"uint256","name":"cliff","type":"uint256"},{"internalType":"uint256","name":"cliffPercentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"claimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract TokenSaleDistributorProxy","name":"proxy","type":"address"}],"name":"becomeImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint256","name":"votes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"getUserAllocations","outputs":[{"components":[{"internalType":"bool","name":"isLinear","type":"bool"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"vestingDuration","type":"uint256"},{"internalType":"uint256","name":"cliff","type":"uint256"},{"internalType":"uint256","name":"cliffPercentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"claimed","type":"uint256"}],"internalType":"struct TokenSaleDistributorStorage.Allocation[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"monthlyVestingInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"targetUser","type":"address"}],"name":"resetAllocationsByUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"bool[]","name":"isLinear","type":"bool[]"},{"internalType":"uint256[]","name":"epochs","type":"uint256[]"},{"internalType":"uint256[]","name":"vestingDurations","type":"uint256[]"},{"internalType":"uint256[]","name":"cliffs","type":"uint256[]"},{"internalType":"uint256[]","name":"cliffPercentages","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setAllocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTokenAddress","type":"address"}],"name":"setTokenAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setVotingEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"totalAllocated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"totalAllocations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"totalClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"totalClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"totalVested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"totalVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506001600055612fc1806100256000396000f3fe608060405234801561001057600080fd5b506004361061020b5760003560e01c8063782d6fe11161012a578063c3cda520116100bd578063ed361b351161008c578063f1127ed811610071578063f1127ed8146105cb578063f3fef3a314610622578063f851a4401461063557600080fd5b8063ed361b35146105a5578063ef5d9ae8146105b857600080fd5b8063c3cda52014610522578063e7a324dc14610535578063e855060f1461055c578063eaac8c321461059257600080fd5b8063a518488e116100f9578063a518488e146104c9578063b13e4a9d146104e9578063b4b5ea57146104fc578063bb90d9a91461050f57600080fd5b8063782d6fe11461046c5780637ecebe001461047f57806396e9a3eb1461049f5780639d76ea58146104a957600080fd5b80634e71d92d116101a2578063640e116811610171578063640e1168146103ee57806364872f5f1461040b578063657059db1461041e5780636fcfff451461043157600080fd5b80634e71d92d1461037d578063587cde1e146103855780635c19a95c146103bb5780635c60da1b146103ce57600080fd5b806323868491116101de57806323868491146102f0578063267822471461030557806326a4e8d21461034a578063396f7b231461035d57600080fd5b8063010bc33c1461021057806306fdde031461025f5780631dfce5c6146102a857806320606b70146102c9575b600080fd5b61022361021e366004612847565b610655565b6040805197151588526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0015b60405180910390f35b61029b6040518060400160405280600581526020017f7657454c4c00000000000000000000000000000000000000000000000000000081525081565b604051610256919061289f565b6102bb6102b63660046128f0565b6106b3565b604051908152602001610256565b6102bb7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103036102fe36600461291b565b6107af565b005b6002546103259073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610256565b6103036103583660046128f0565b6108af565b6004546103259073ffffffffffffffffffffffffffffffffffffffff1681565b610303610a29565b6103256103933660046128f0565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6103036103c93660046128f0565b610b81565b6003546103259073ffffffffffffffffffffffffffffffffffffffff1681565b600b546103fb9060ff1681565b6040519015158152602001610256565b6102bb6104193660046128f0565b610b8e565b61030361042c366004612b0d565b610bbb565b61045761043f3660046128f0565b60096020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001610256565b6102bb61047a366004612847565b610f33565b6102bb61048d3660046128f0565b600a6020526000908152604090205481565b6102bb622819a081565b6005546103259073ffffffffffffffffffffffffffffffffffffffff1681565b6104dc6104d73660046128f0565b611203565b6040516102569190612c28565b6102bb6104f73660046128f0565b6112ca565b6102bb61050a3660046128f0565b6113bd565b61030361051d3660046128f0565b611461565b610303610530366004612cac565b6115e0565b6102bb7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6102bb61056a3660046128f0565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b6103036105a03660046128f0565b611970565b6102bb6105b33660046128f0565b611ad6565b6102bb6105c63660046128f0565b611b6e565b6106066105d9366004612d0e565b60086020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b6040805163ffffffff9093168352602083019190915201610256565b610303610630366004612847565b611c06565b6001546103259073ffffffffffffffffffffffffffffffffffffffff1681565b6006602052816000526040600020818154811061067157600080fd5b6000918252602090912060079091020180546001820154600283015460038401546004850154600586015460069096015460ff90951697509295509093909287565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805461078a91908390811061072157610721612d50565b60009182526020918290206040805160e0810182526007909302909101805460ff16151583526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a082015260069091015460c0820152611d3d565b6107949084612dae565b925061079f81612dc6565b90506106dd565b50909392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c790000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600b80548215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00821681179092556040805160ff9283168015158252929093161515602084015290917f18ebc081a3d5a29f7a5be783c402fcf3136f0aa8c9614ad3c39a3877b6ecb14e91015b60405180910390a15050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610930576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60055473ffffffffffffffffffffffffffffffffffffffff16156109b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f6164647265737320616c72656164792073657400000000000000000000000000604482015260640161082c565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ffff847241a814a368b845d49aa06534bae1e893f6c606a681e2d782e8eb98f889060200160405180910390a150565b60026000541415610a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161082c565b6002600090815533815260066020526040812054815b81811015610b09573360009081526006602052604090208054610aed919083908110610ada57610ada612d50565b9060005260206000209060070201611d57565b610af79084612dae565b9250610b0281612dc6565b9050610aac565b508115610b785760405182815233907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a233600090815260076020526040812054610b789173ffffffffffffffffffffffffffffffffffffffff9091169084611e03565b50506001600055565b610b8b3382611fce565b50565b600080610b9a83611ad6565b90506000610ba784611b6e565b9050610bb38183612dff565b949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b8451875114610c4a57600080fd5b8551875114610c5857600080fd5b8351875114610c6657600080fd5b8251875114610c7457600080fd5b8151875114610c8257600080fd5b8051875114610c9057600080fd5b865160005b81811015610f2857670de0b6b3a7640000848281518110610cb857610cb8612d50565b60200260200101511115610ccb57600080fd5b600660008a8381518110610ce157610ce1612d50565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052808a8481518110610d4057610d40612d50565b602002602001015115158152602001898481518110610d6157610d61612d50565b60200260200101518152602001888481518110610d8057610d80612d50565b60200260200101518152602001878481518110610d9f57610d9f612d50565b60200260200101518152602001868481518110610dbe57610dbe612d50565b60200260200101518152602001858481518110610ddd57610ddd612d50565b602090810291909101810151825260009181018290528354600180820186559483528183208451600792830290910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091178155918401519482019490945560408301516002820155606083015160038201556080830151600482015560a0830151600582015560c0909201516006909201919091558a51610f18929082908d9086908110610e9657610e96612d50565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858481518110610f0b57610f0b612d50565b6020026020010151611e03565b610f2181612dc6565b9050610c95565b505050505050505050565b6000438210610f9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f74207965742064657465726d696e65640000000000000000000000000000604482015260640161082c565b600b5460ff16610fb0575060006111fd565b73ffffffffffffffffffffffffffffffffffffffff831660009081526009602052604090205463ffffffff1680610feb5760009150506111fd565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600860205260408120849161101d600185612e16565b63ffffffff908116825260208201929092526040016000205416116110935773ffffffffffffffffffffffffffffffffffffffff841660009081526008602052604081209061106d600184612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101549150506111fd565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260086020908152604080832083805290915290205463ffffffff168310156110db5760009150506111fd565b6000806110e9600184612e16565b90505b8163ffffffff168163ffffffff1611156111be576000600261110e8484612e16565b6111189190612e6a565b6111229083612e16565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260086020908152604080832063ffffffff8086168552908352928190208151808301909252805490931680825260019093015491810191909152919250871415611192576020015194506111fd9350505050565b805163ffffffff168711156111a9578193506111b7565b6111b4600183612e16565b92505b50506110ec565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260086020908152604080832063ffffffff909416835292905220600101549150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660209081526040808320805482518185028101850190935280835260609492939192909184015b828210156112bf5760008481526020908190206040805160e08101825260078602909201805460ff1615158352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a08401526006015460c08301529083529092019101611248565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff8516600090815260066020526040902080546113a191908390811061133857611338612d50565b60009182526020918290206040805160e0810182526007909302909101805460ff16151583526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a082015260069091015460c0820152612095565b6113ab9084612dae565b92506113b681612dc6565b90506112f4565b600b5460009060ff166113d257506000919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604090205463ffffffff168061140a57600061145a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526008602052604081209061143b600184612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146114e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60006114ed82610b8e565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260076020526040812054929350611525929091169083611e03565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600660205260408120611553916127a4565b8015611583576001546005546115839173ffffffffffffffffffffffffffffffffffffffff9182169116836121c4565b6005546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681526020810185905292909116908201527fc979c8583dcc6bae4df6f025c882f3e8de7e3622e22d56b997d8061bc0894991906060016108a3565b604080518082018252600581527f7657454c4c00000000000000000000000000000000000000000000000000000060209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527ff8033fc0b97d824d386a6f0ec3d9ac37e8b24a9f281505f79d9f2dfc41bf490681840152466060820152306080808301919091528351808303909101815260a0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c083015273ffffffffffffffffffffffffffffffffffffffff8a1660e0830152610100820189905261012080830189905284518084039091018152610140830185528051908401207f19010000000000000000000000000000000000000000000000000000000000006101608401526101628301829052610182808401829052855180850390910181526101a29093019094528151919092012090919060008061175483898989612251565b9092509050600081600481111561176d5761176d612e8d565b146117d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f696e76616c696420736967000000000000000000000000000000000000000000604482015260640161082c565b73ffffffffffffffffffffffffffffffffffffffff8216611851576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f696e76616c696420736967000000000000000000000000000000000000000000604482015260640161082c565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a6020526040812080549161188283612dc6565b919050558a146118ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f696e76616c6964206e6f6e636500000000000000000000000000000000000000604482015260640161082c565b88421115611958576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f7369676e61747572652065787069726564000000000000000000000000000000604482015260640161082c565b611962828c611fce565b50505050505b505050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119df9190612ebc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f742070726f78792061646d696e0000000000000000000000000000000000604482015260640161082c565b8073ffffffffffffffffffffffffffffffffffffffff166316ec205c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611abb57600080fd5b505af1158015611acf573d6000803e3d6000fd5b5050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805482908110611b3f57611b3f612d50565b90600052602060002090600702016005015483611b5c9190612dae565b9250611b6781612dc6565b9050611b00565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805482908110611bd757611bd7612d50565b90600052602060002090600702016006015483611bf49190612dae565b9250611bff81612dc6565b9050611b98565b60015473ffffffffffffffffffffffffffffffffffffffff163314611c87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60055473ffffffffffffffffffffffffffffffffffffffff83811691161415611d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f757365207265736574416c6c6f636174696f6e73427955736572000000000000604482015260640161082c565b8015611d3957600154611d399073ffffffffffffffffffffffffffffffffffffffff8481169116836121c4565b5050565b60008160c00151611d4d83612095565b6111fd9190612dff565b6040805160e081018252825460ff1615158152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c08201526000908190611db690611d3d565b905080611dc65750600092915050565b80836006016000828254611dda9190612dae565b90915550506005546111fd9073ffffffffffffffffffffffffffffffffffffffff1633836121c4565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611e3e57508015155b15611fc95773ffffffffffffffffffffffffffffffffffffffff831615611f085773ffffffffffffffffffffffffffffffffffffffff831660009081526009602052604081205463ffffffff169081611e98576000611ee8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260086020526040812090611ec9600185612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b90506000611ef68483612dff565b9050611f0486848484612369565b5050505b73ffffffffffffffffffffffffffffffffffffffff821615611fc95773ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604081205463ffffffff169081611f5d576000611fad565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260086020526040812090611f8e600185612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b90506000611fbb8483612dae565b905061196885848484612369565b505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600760205260408120549091169061200284610b8e565b73ffffffffffffffffffffffffffffffffffffffff85811660008181526007602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461208f828483611e03565b50505050565b6000816060015182602001516120ab9190612dae565b4210156120ba57506000919050565b6000670de0b6b3a764000083608001518460a001516120d99190612ed9565b6120e39190612f16565b90506000818460a001516120f79190612dff565b9050600084606001518560200151426121109190612dff565b61211a9190612dff565b855190915015612166578460400151811061213a575050505060a0015190565b60408501516121498284612ed9565b6121539190612f16565b61215d9084612dae565b95945050505050565b6000612175622819a083612f16565b9050856040015181106121915750505060a09092015192915050565b60008660400151846121a39190612f16565b90506121af8282612ed9565b6121b99086612dae565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611fc990849061255c565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156122885750600090506003612360565b8460ff16601b141580156122a057508460ff16601c14155b156122b15750600090506004612360565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612305573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661235957600060019250925050612360565b9150600090505b94509492505050565b4363ffffffff8416158015906123ce575073ffffffffffffffffffffffffffffffffffffffff8516600090815260086020526040812063ffffffff8316916123b2600188612e16565b63ffffffff908116825260208201929092526040016000205416145b156124245773ffffffffffffffffffffffffffffffffffffffff851660009081526008602052604081208391612405600188612e16565b63ffffffff168152602081019190915260400160002060010155612504565b60408051808201825263ffffffff8381168252602080830186815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600883528581208a85168252909252939020915182547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016911617815590516001918201556124ab908590612f2a565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b604080518481526020810184905273ffffffffffffffffffffffffffffffffffffffff8716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b60006125be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126689092919063ffffffff16565b805190915015611fc957808060200190518101906125dc9190612f52565b611fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161082c565b6060610bb3848460008585843b6126db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161082c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516127049190612f6f565b60006040518083038185875af1925050503d8060008114612741576040519150601f19603f3d011682016040523d82523d6000602084013e612746565b606091505b50915091506121b98282866060831561276057508161145a565b8251156127705782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082c919061289f565b5080546000825560070290600052602060002090810190610b8b91905b808211156128215780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681556000600182018190556002820181905560038201819055600482018190556005820181905560068201556007016127c1565b5090565b73ffffffffffffffffffffffffffffffffffffffff81168114610b8b57600080fd5b6000806040838503121561285a57600080fd5b823561286581612825565b946020939093013593505050565b60005b8381101561288e578181015183820152602001612876565b8381111561208f5750506000910152565b60208152600082518060208401526128be816040850160208701612873565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561290257600080fd5b813561145a81612825565b8015158114610b8b57600080fd5b60006020828403121561292d57600080fd5b813561145a8161290d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156129ae576129ae612938565b604052919050565b600067ffffffffffffffff8211156129d0576129d0612938565b5060051b60200190565b600082601f8301126129eb57600080fd5b81356020612a006129fb836129b6565b612967565b82815260059290921b84018101918181019086841115612a1f57600080fd5b8286015b84811015612a43578035612a3681612825565b8352918301918301612a23565b509695505050505050565b600082601f830112612a5f57600080fd5b81356020612a6f6129fb836129b6565b82815260059290921b84018101918181019086841115612a8e57600080fd5b8286015b84811015612a43578035612aa58161290d565b8352918301918301612a92565b600082601f830112612ac357600080fd5b81356020612ad36129fb836129b6565b82815260059290921b84018101918181019086841115612af257600080fd5b8286015b84811015612a435780358352918301918301612af6565b600080600080600080600060e0888a031215612b2857600080fd5b873567ffffffffffffffff80821115612b4057600080fd5b612b4c8b838c016129da565b985060208a0135915080821115612b6257600080fd5b612b6e8b838c01612a4e565b975060408a0135915080821115612b8457600080fd5b612b908b838c01612ab2565b965060608a0135915080821115612ba657600080fd5b612bb28b838c01612ab2565b955060808a0135915080821115612bc857600080fd5b612bd48b838c01612ab2565b945060a08a0135915080821115612bea57600080fd5b612bf68b838c01612ab2565b935060c08a0135915080821115612c0c57600080fd5b50612c198a828b01612ab2565b91505092959891949750929550565b602080825282518282018190526000919060409081850190868401855b82811015612c9f57815180511515855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0908101519085015260e09093019290850190600101612c45565b5091979650505050505050565b60008060008060008060c08789031215612cc557600080fd5b8635612cd081612825565b95506020870135945060408701359350606087013560ff81168114612cf457600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215612d2157600080fd5b8235612d2c81612825565b9150602083013563ffffffff81168114612d4557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612dc157612dc1612d7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612df857612df8612d7f565b5060010190565b600082821015612e1157612e11612d7f565b500390565b600063ffffffff83811690831681811015612e3357612e33612d7f565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff80841680612e8157612e81612e3b565b92169190910492915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215612ece57600080fd5b815161145a81612825565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612f1157612f11612d7f565b500290565b600082612f2557612f25612e3b565b500490565b600063ffffffff808316818516808303821115612f4957612f49612d7f565b01949350505050565b600060208284031215612f6457600080fd5b815161145a8161290d565b60008251612f81818460208701612873565b919091019291505056fea2646970667358221220260e46cf83621352ff07e93a2e933bce8188b91381b8f1da20f338a3f49b32ff64736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061020b5760003560e01c8063782d6fe11161012a578063c3cda520116100bd578063ed361b351161008c578063f1127ed811610071578063f1127ed8146105cb578063f3fef3a314610622578063f851a4401461063557600080fd5b8063ed361b35146105a5578063ef5d9ae8146105b857600080fd5b8063c3cda52014610522578063e7a324dc14610535578063e855060f1461055c578063eaac8c321461059257600080fd5b8063a518488e116100f9578063a518488e146104c9578063b13e4a9d146104e9578063b4b5ea57146104fc578063bb90d9a91461050f57600080fd5b8063782d6fe11461046c5780637ecebe001461047f57806396e9a3eb1461049f5780639d76ea58146104a957600080fd5b80634e71d92d116101a2578063640e116811610171578063640e1168146103ee57806364872f5f1461040b578063657059db1461041e5780636fcfff451461043157600080fd5b80634e71d92d1461037d578063587cde1e146103855780635c19a95c146103bb5780635c60da1b146103ce57600080fd5b806323868491116101de57806323868491146102f0578063267822471461030557806326a4e8d21461034a578063396f7b231461035d57600080fd5b8063010bc33c1461021057806306fdde031461025f5780631dfce5c6146102a857806320606b70146102c9575b600080fd5b61022361021e366004612847565b610655565b6040805197151588526020880196909652948601939093526060850191909152608084015260a083015260c082015260e0015b60405180910390f35b61029b6040518060400160405280600581526020017f7657454c4c00000000000000000000000000000000000000000000000000000081525081565b604051610256919061289f565b6102bb6102b63660046128f0565b6106b3565b604051908152602001610256565b6102bb7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103036102fe36600461291b565b6107af565b005b6002546103259073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610256565b6103036103583660046128f0565b6108af565b6004546103259073ffffffffffffffffffffffffffffffffffffffff1681565b610303610a29565b6103256103933660046128f0565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6103036103c93660046128f0565b610b81565b6003546103259073ffffffffffffffffffffffffffffffffffffffff1681565b600b546103fb9060ff1681565b6040519015158152602001610256565b6102bb6104193660046128f0565b610b8e565b61030361042c366004612b0d565b610bbb565b61045761043f3660046128f0565b60096020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001610256565b6102bb61047a366004612847565b610f33565b6102bb61048d3660046128f0565b600a6020526000908152604090205481565b6102bb622819a081565b6005546103259073ffffffffffffffffffffffffffffffffffffffff1681565b6104dc6104d73660046128f0565b611203565b6040516102569190612c28565b6102bb6104f73660046128f0565b6112ca565b6102bb61050a3660046128f0565b6113bd565b61030361051d3660046128f0565b611461565b610303610530366004612cac565b6115e0565b6102bb7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6102bb61056a3660046128f0565b73ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604090205490565b6103036105a03660046128f0565b611970565b6102bb6105b33660046128f0565b611ad6565b6102bb6105c63660046128f0565b611b6e565b6106066105d9366004612d0e565b60086020908152600092835260408084209091529082529020805460019091015463ffffffff9091169082565b6040805163ffffffff9093168352602083019190915201610256565b610303610630366004612847565b611c06565b6001546103259073ffffffffffffffffffffffffffffffffffffffff1681565b6006602052816000526040600020818154811061067157600080fd5b6000918252602090912060079091020180546001820154600283015460038401546004850154600586015460069096015460ff90951697509295509093909287565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805461078a91908390811061072157610721612d50565b60009182526020918290206040805160e0810182526007909302909101805460ff16151583526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a082015260069091015460c0820152611d3d565b6107949084612dae565b925061079f81612dc6565b90506106dd565b50909392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c790000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600b80548215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00821681179092556040805160ff9283168015158252929093161515602084015290917f18ebc081a3d5a29f7a5be783c402fcf3136f0aa8c9614ad3c39a3877b6ecb14e91015b60405180910390a15050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610930576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60055473ffffffffffffffffffffffffffffffffffffffff16156109b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f6164647265737320616c72656164792073657400000000000000000000000000604482015260640161082c565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ffff847241a814a368b845d49aa06534bae1e893f6c606a681e2d782e8eb98f889060200160405180910390a150565b60026000541415610a96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161082c565b6002600090815533815260066020526040812054815b81811015610b09573360009081526006602052604090208054610aed919083908110610ada57610ada612d50565b9060005260206000209060070201611d57565b610af79084612dae565b9250610b0281612dc6565b9050610aac565b508115610b785760405182815233907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a233600090815260076020526040812054610b789173ffffffffffffffffffffffffffffffffffffffff9091169084611e03565b50506001600055565b610b8b3382611fce565b50565b600080610b9a83611ad6565b90506000610ba784611b6e565b9050610bb38183612dff565b949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b8451875114610c4a57600080fd5b8551875114610c5857600080fd5b8351875114610c6657600080fd5b8251875114610c7457600080fd5b8151875114610c8257600080fd5b8051875114610c9057600080fd5b865160005b81811015610f2857670de0b6b3a7640000848281518110610cb857610cb8612d50565b60200260200101511115610ccb57600080fd5b600660008a8381518110610ce157610ce1612d50565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052808a8481518110610d4057610d40612d50565b602002602001015115158152602001898481518110610d6157610d61612d50565b60200260200101518152602001888481518110610d8057610d80612d50565b60200260200101518152602001878481518110610d9f57610d9f612d50565b60200260200101518152602001868481518110610dbe57610dbe612d50565b60200260200101518152602001858481518110610ddd57610ddd612d50565b602090810291909101810151825260009181018290528354600180820186559483528183208451600792830290910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091178155918401519482019490945560408301516002820155606083015160038201556080830151600482015560a0830151600582015560c0909201516006909201919091558a51610f18929082908d9086908110610e9657610e96612d50565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16858481518110610f0b57610f0b612d50565b6020026020010151611e03565b610f2181612dc6565b9050610c95565b505050505050505050565b6000438210610f9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f74207965742064657465726d696e65640000000000000000000000000000604482015260640161082c565b600b5460ff16610fb0575060006111fd565b73ffffffffffffffffffffffffffffffffffffffff831660009081526009602052604090205463ffffffff1680610feb5760009150506111fd565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600860205260408120849161101d600185612e16565b63ffffffff908116825260208201929092526040016000205416116110935773ffffffffffffffffffffffffffffffffffffffff841660009081526008602052604081209061106d600184612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101549150506111fd565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260086020908152604080832083805290915290205463ffffffff168310156110db5760009150506111fd565b6000806110e9600184612e16565b90505b8163ffffffff168163ffffffff1611156111be576000600261110e8484612e16565b6111189190612e6a565b6111229083612e16565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260086020908152604080832063ffffffff8086168552908352928190208151808301909252805490931680825260019093015491810191909152919250871415611192576020015194506111fd9350505050565b805163ffffffff168711156111a9578193506111b7565b6111b4600183612e16565b92505b50506110ec565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260086020908152604080832063ffffffff909416835292905220600101549150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660209081526040808320805482518185028101850190935280835260609492939192909184015b828210156112bf5760008481526020908190206040805160e08101825260078602909201805460ff1615158352600180820154848601526002820154928401929092526003810154606084015260048101546080840152600581015460a08401526006015460c08301529083529092019101611248565b505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff8516600090815260066020526040902080546113a191908390811061133857611338612d50565b60009182526020918290206040805160e0810182526007909302909101805460ff16151583526001810154938301939093526002830154908201526003820154606082015260048201546080820152600582015460a082015260069091015460c0820152612095565b6113ab9084612dae565b92506113b681612dc6565b90506112f4565b600b5460009060ff166113d257506000919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604090205463ffffffff168061140a57600061145a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526008602052604081209061143b600184612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146114e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60006114ed82610b8e565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260076020526040812054929350611525929091169083611e03565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600660205260408120611553916127a4565b8015611583576001546005546115839173ffffffffffffffffffffffffffffffffffffffff9182169116836121c4565b6005546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681526020810185905292909116908201527fc979c8583dcc6bae4df6f025c882f3e8de7e3622e22d56b997d8061bc0894991906060016108a3565b604080518082018252600581527f7657454c4c00000000000000000000000000000000000000000000000000000060209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527ff8033fc0b97d824d386a6f0ec3d9ac37e8b24a9f281505f79d9f2dfc41bf490681840152466060820152306080808301919091528351808303909101815260a0820184528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c083015273ffffffffffffffffffffffffffffffffffffffff8a1660e0830152610100820189905261012080830189905284518084039091018152610140830185528051908401207f19010000000000000000000000000000000000000000000000000000000000006101608401526101628301829052610182808401829052855180850390910181526101a29093019094528151919092012090919060008061175483898989612251565b9092509050600081600481111561176d5761176d612e8d565b146117d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f696e76616c696420736967000000000000000000000000000000000000000000604482015260640161082c565b73ffffffffffffffffffffffffffffffffffffffff8216611851576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f696e76616c696420736967000000000000000000000000000000000000000000604482015260640161082c565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a6020526040812080549161188283612dc6565b919050558a146118ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f696e76616c6964206e6f6e636500000000000000000000000000000000000000604482015260640161082c565b88421115611958576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f7369676e61747572652065787069726564000000000000000000000000000000604482015260640161082c565b611962828c611fce565b50505050505b505050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119df9190612ebc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6e6f742070726f78792061646d696e0000000000000000000000000000000000604482015260640161082c565b8073ffffffffffffffffffffffffffffffffffffffff166316ec205c6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611abb57600080fd5b505af1158015611acf573d6000803e3d6000fd5b5050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805482908110611b3f57611b3f612d50565b90600052602060002090600702016005015483611b5c9190612dae565b9250611b6781612dc6565b9050611b00565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260408120548190815b818110156107a65773ffffffffffffffffffffffffffffffffffffffff85166000908152600660205260409020805482908110611bd757611bd7612d50565b90600052602060002090600702016006015483611bf49190612dae565b9250611bff81612dc6565b9050611b98565b60015473ffffffffffffffffffffffffffffffffffffffff163314611c87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f61646d696e206f6e6c7900000000000000000000000000000000000000000000604482015260640161082c565b60055473ffffffffffffffffffffffffffffffffffffffff83811691161415611d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f757365207265736574416c6c6f636174696f6e73427955736572000000000000604482015260640161082c565b8015611d3957600154611d399073ffffffffffffffffffffffffffffffffffffffff8481169116836121c4565b5050565b60008160c00151611d4d83612095565b6111fd9190612dff565b6040805160e081018252825460ff1615158152600183015460208201526002830154918101919091526003820154606082015260048201546080820152600582015460a0820152600682015460c08201526000908190611db690611d3d565b905080611dc65750600092915050565b80836006016000828254611dda9190612dae565b90915550506005546111fd9073ffffffffffffffffffffffffffffffffffffffff1633836121c4565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611e3e57508015155b15611fc95773ffffffffffffffffffffffffffffffffffffffff831615611f085773ffffffffffffffffffffffffffffffffffffffff831660009081526009602052604081205463ffffffff169081611e98576000611ee8565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260086020526040812090611ec9600185612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b90506000611ef68483612dff565b9050611f0486848484612369565b5050505b73ffffffffffffffffffffffffffffffffffffffff821615611fc95773ffffffffffffffffffffffffffffffffffffffff821660009081526009602052604081205463ffffffff169081611f5d576000611fad565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260086020526040812090611f8e600185612e16565b63ffffffff1663ffffffff168152602001908152602001600020600101545b90506000611fbb8483612dae565b905061196885848484612369565b505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600760205260408120549091169061200284610b8e565b73ffffffffffffffffffffffffffffffffffffffff85811660008181526007602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016898616908117909155905194955093928616927f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461208f828483611e03565b50505050565b6000816060015182602001516120ab9190612dae565b4210156120ba57506000919050565b6000670de0b6b3a764000083608001518460a001516120d99190612ed9565b6120e39190612f16565b90506000818460a001516120f79190612dff565b9050600084606001518560200151426121109190612dff565b61211a9190612dff565b855190915015612166578460400151811061213a575050505060a0015190565b60408501516121498284612ed9565b6121539190612f16565b61215d9084612dae565b95945050505050565b6000612175622819a083612f16565b9050856040015181106121915750505060a09092015192915050565b60008660400151846121a39190612f16565b90506121af8282612ed9565b6121b99086612dae565b979650505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611fc990849061255c565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156122885750600090506003612360565b8460ff16601b141580156122a057508460ff16601c14155b156122b15750600090506004612360565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612305573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661235957600060019250925050612360565b9150600090505b94509492505050565b4363ffffffff8416158015906123ce575073ffffffffffffffffffffffffffffffffffffffff8516600090815260086020526040812063ffffffff8316916123b2600188612e16565b63ffffffff908116825260208201929092526040016000205416145b156124245773ffffffffffffffffffffffffffffffffffffffff851660009081526008602052604081208391612405600188612e16565b63ffffffff168152602081019190915260400160002060010155612504565b60408051808201825263ffffffff8381168252602080830186815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600883528581208a85168252909252939020915182547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016911617815590516001918201556124ab908590612f2a565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b604080518481526020810184905273ffffffffffffffffffffffffffffffffffffffff8716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b60006125be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126689092919063ffffffff16565b805190915015611fc957808060200190518101906125dc9190612f52565b611fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161082c565b6060610bb3848460008585843b6126db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161082c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516127049190612f6f565b60006040518083038185875af1925050503d8060008114612741576040519150601f19603f3d011682016040523d82523d6000602084013e612746565b606091505b50915091506121b98282866060831561276057508161145a565b8251156127705782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082c919061289f565b5080546000825560070290600052602060002090810190610b8b91905b808211156128215780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681556000600182018190556002820181905560038201819055600482018190556005820181905560068201556007016127c1565b5090565b73ffffffffffffffffffffffffffffffffffffffff81168114610b8b57600080fd5b6000806040838503121561285a57600080fd5b823561286581612825565b946020939093013593505050565b60005b8381101561288e578181015183820152602001612876565b8381111561208f5750506000910152565b60208152600082518060208401526128be816040850160208701612873565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561290257600080fd5b813561145a81612825565b8015158114610b8b57600080fd5b60006020828403121561292d57600080fd5b813561145a8161290d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156129ae576129ae612938565b604052919050565b600067ffffffffffffffff8211156129d0576129d0612938565b5060051b60200190565b600082601f8301126129eb57600080fd5b81356020612a006129fb836129b6565b612967565b82815260059290921b84018101918181019086841115612a1f57600080fd5b8286015b84811015612a43578035612a3681612825565b8352918301918301612a23565b509695505050505050565b600082601f830112612a5f57600080fd5b81356020612a6f6129fb836129b6565b82815260059290921b84018101918181019086841115612a8e57600080fd5b8286015b84811015612a43578035612aa58161290d565b8352918301918301612a92565b600082601f830112612ac357600080fd5b81356020612ad36129fb836129b6565b82815260059290921b84018101918181019086841115612af257600080fd5b8286015b84811015612a435780358352918301918301612af6565b600080600080600080600060e0888a031215612b2857600080fd5b873567ffffffffffffffff80821115612b4057600080fd5b612b4c8b838c016129da565b985060208a0135915080821115612b6257600080fd5b612b6e8b838c01612a4e565b975060408a0135915080821115612b8457600080fd5b612b908b838c01612ab2565b965060608a0135915080821115612ba657600080fd5b612bb28b838c01612ab2565b955060808a0135915080821115612bc857600080fd5b612bd48b838c01612ab2565b945060a08a0135915080821115612bea57600080fd5b612bf68b838c01612ab2565b935060c08a0135915080821115612c0c57600080fd5b50612c198a828b01612ab2565b91505092959891949750929550565b602080825282518282018190526000919060409081850190868401855b82811015612c9f57815180511515855286810151878601528581015186860152606080820151908601526080808201519086015260a0808201519086015260c0908101519085015260e09093019290850190600101612c45565b5091979650505050505050565b60008060008060008060c08789031215612cc557600080fd5b8635612cd081612825565b95506020870135945060408701359350606087013560ff81168114612cf457600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215612d2157600080fd5b8235612d2c81612825565b9150602083013563ffffffff81168114612d4557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612dc157612dc1612d7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612df857612df8612d7f565b5060010190565b600082821015612e1157612e11612d7f565b500390565b600063ffffffff83811690831681811015612e3357612e33612d7f565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff80841680612e8157612e81612e3b565b92169190910492915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215612ece57600080fd5b815161145a81612825565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612f1157612f11612d7f565b500290565b600082612f2557612f25612e3b565b500490565b600063ffffffff808316818516808303821115612f4957612f49612d7f565b01949350505050565b600060208284031215612f6457600080fd5b815161145a8161290d565b60008251612f81818460208701612873565b919091019291505056fea2646970667358221220260e46cf83621352ff07e93a2e933bce8188b91381b8f1da20f338a3f49b32ff64736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.