Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Authorized F... | 38486182 | 8 hrs ago | IN | 0 ETH | 0.00000006 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 38486869 | 7 hrs ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {TokenVestingFactory} from "./TokenVestingFactory.sol";
/// @title TokenVestingFactoryDeployer
/// @notice Deploys TokenVestingFactory contracts for TokenLaunchFactory
contract TokenVestingFactoryDeployer {
address public authorizedFactory;
address public immutable admin;
error UnauthorizedCaller();
constructor(address _admin) {
if (_admin == address(0)) revert UnauthorizedCaller();
admin = _admin;
}
function setAuthorizedFactory(address factory) external {
if (msg.sender != admin) revert UnauthorizedCaller();
if (authorizedFactory != address(0)) revert UnauthorizedCaller();
authorizedFactory = factory;
}
function deploy(address token, address creator) external returns (address vestingFactory) {
if (msg.sender != authorizedFactory) revert UnauthorizedCaller();
vestingFactory = address(new TokenVestingFactory(token, creator));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {TokenVesting} from "./TokenVesting.sol";
/// @title TokenVestingFactory
/// @notice Holds vesting allocation and deploys per-member schedules with minimums enforced by TokenVesting.
contract TokenVestingFactory is AccessControl {
using SafeERC20 for IERC20;
bytes32 public constant SCHEDULER_ROLE = keccak256("SCHEDULER_ROLE");
struct VestingInfo {
address vesting;
address beneficiary;
uint256 amount;
uint256 cliff;
uint256 end;
uint256 createdAt;
}
address public immutable token;
VestingInfo[] internal _allVestings;
mapping(address => uint256[]) internal _beneficiaryToIndices;
event VestingCreated(address indexed vesting, address indexed beneficiary, uint256 amount, uint256 cliff, uint256 end);
error InvalidAddress();
error InvalidAmount();
error InsufficientBalance();
constructor(address _token, address admin) {
if (_token == address(0) || admin == address(0)) revert InvalidAddress();
token = _token;
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(SCHEDULER_ROLE, admin);
}
function createVesting(address beneficiary, uint256 amount, uint256 cliff, uint256 end)
external
onlyRole(SCHEDULER_ROLE)
returns (address vesting)
{
if (beneficiary == address(0)) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
if (IERC20(token).balanceOf(address(this)) < amount) revert InsufficientBalance();
vesting = address(new TokenVesting(token, beneficiary, amount, cliff, end));
IERC20(token).safeTransfer(vesting, amount);
_allVestings.push(
VestingInfo({
vesting: vesting,
beneficiary: beneficiary,
amount: amount,
cliff: cliff,
end: end,
createdAt: block.timestamp
})
);
_beneficiaryToIndices[beneficiary].push(_allVestings.length - 1);
emit VestingCreated(vesting, beneficiary, amount, cliff, end);
}
function createVestings(
address[] calldata beneficiaries,
uint256[] calldata amounts,
uint256[] calldata cliffs,
uint256[] calldata ends
) external onlyRole(SCHEDULER_ROLE) returns (address[] memory vestings) {
uint256 count = beneficiaries.length;
if (count == 0) revert InvalidAmount();
if (amounts.length != count || cliffs.length != count || ends.length != count) revert InvalidAmount();
vestings = new address[](count);
for (uint256 i = 0; i < count; i++) {
address beneficiary = beneficiaries[i];
uint256 amount = amounts[i];
uint256 cliff = cliffs[i];
uint256 end = ends[i];
if (beneficiary == address(0)) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
if (IERC20(token).balanceOf(address(this)) < amount) revert InsufficientBalance();
address vesting = address(new TokenVesting(token, beneficiary, amount, cliff, end));
IERC20(token).safeTransfer(vesting, amount);
_allVestings.push(
VestingInfo({
vesting: vesting,
beneficiary: beneficiary,
amount: amount,
cliff: cliff,
end: end,
createdAt: block.timestamp
})
);
_beneficiaryToIndices[beneficiary].push(_allVestings.length - 1);
vestings[i] = vesting;
emit VestingCreated(vesting, beneficiary, amount, cliff, end);
}
}
function getVestingsPaginated(uint256 offset, uint256 limit)
external
view
returns (VestingInfo[] memory vestings, uint256 totalCount)
{
totalCount = _allVestings.length;
if (offset == 0 && limit == 0) {
vestings = _allVestings;
return (vestings, totalCount);
}
if (limit == 0) limit = totalCount;
if (offset >= totalCount) return (new VestingInfo[](0), totalCount);
uint256 count = (offset + limit > totalCount) ? (totalCount - offset) : limit;
vestings = new VestingInfo[](count);
for (uint256 i = 0; i < count; i++) {
vestings[i] = _allVestings[offset + i];
}
}
function getVestingsByBeneficiaryPaginated(address beneficiary, uint256 offset, uint256 limit)
external
view
returns (VestingInfo[] memory vestings, uint256 totalCount)
{
uint256[] storage indices = _beneficiaryToIndices[beneficiary];
totalCount = indices.length;
if (offset == 0 && limit == 0) {
vestings = new VestingInfo[](totalCount);
for (uint256 i = 0; i < totalCount; i++) {
vestings[i] = _allVestings[indices[i]];
}
return (vestings, totalCount);
}
if (limit == 0) limit = totalCount;
if (offset >= totalCount) return (new VestingInfo[](0), totalCount);
uint256 count = (offset + limit > totalCount) ? (totalCount - offset) : limit;
vestings = new VestingInfo[](count);
for (uint256 i = 0; i < count; i++) {
vestings[i] = _allVestings[indices[offset + i]];
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title TokenVesting
/// @notice Linear vesting with team-controlled schedule updates subject to minimums
contract TokenVesting {
using SafeERC20 for IERC20;
uint256 public constant MIN_CLIFF = 180 days;
uint256 public constant MIN_DURATION = 730 days;
address public immutable token;
address public team;
uint256 public immutable vestingAmount;
uint256 public immutable vestingBegin;
uint256 public vestingCliff;
uint256 public vestingEnd;
uint256 public lastUpdate;
event TeamUpdated(address indexed oldTeam, address indexed newTeam);
event ScheduleUpdated(uint256 newCliff, uint256 newEnd);
event TokensClaimed(address indexed recipient, uint256 amount);
error InvalidAddress();
error InvalidSchedule();
error Unauthorized();
error StillInCliff();
error NoTokens();
constructor(
address _token,
address _team,
uint256 _vestingAmount,
uint256 _vestingCliff,
uint256 _vestingEnd
) {
if (_token == address(0) || _team == address(0)) revert InvalidAddress();
if (_vestingCliff < block.timestamp + MIN_CLIFF) revert InvalidSchedule();
if (_vestingEnd < block.timestamp + MIN_DURATION) revert InvalidSchedule();
if (_vestingEnd < _vestingCliff) revert InvalidSchedule();
token = _token;
team = _team;
vestingAmount = _vestingAmount;
vestingBegin = block.timestamp;
vestingCliff = _vestingCliff;
vestingEnd = _vestingEnd;
lastUpdate = block.timestamp;
}
function updateTeam(address newTeam) external {
if (msg.sender != team) revert Unauthorized();
if (newTeam == address(0)) revert InvalidAddress();
address old = team;
team = newTeam;
emit TeamUpdated(old, newTeam);
}
function claim() external {
if (msg.sender != team) revert Unauthorized();
if (block.timestamp < vestingCliff) revert StillInCliff();
uint256 amount;
if (block.timestamp >= vestingEnd) {
amount = IERC20(token).balanceOf(address(this));
} else {
uint256 elapsed = block.timestamp - lastUpdate;
uint256 duration = vestingEnd - vestingBegin;
amount = (vestingAmount * elapsed) / duration;
lastUpdate = block.timestamp;
}
if (amount == 0) revert NoTokens();
IERC20(token).safeTransfer(team, amount);
emit TokensClaimed(team, amount);
}
function claimableAmount() external view returns (uint256) {
if (block.timestamp < vestingCliff) return 0;
if (block.timestamp >= vestingEnd) return IERC20(token).balanceOf(address(this));
uint256 elapsed = block.timestamp - lastUpdate;
uint256 duration = vestingEnd - vestingBegin;
return (vestingAmount * elapsed) / duration;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";{
"remappings": [
"@ensdomains/=lib/v4-periphery/lib/v4-core/node_modules/@ensdomains/",
"@openzeppelin/=lib/liquidity-launcher/lib/openzeppelin-contracts/",
"@openzeppelin/contracts/=lib/liquidity-launcher/lib/openzeppelin-contracts/contracts/",
"@openzeppelin-latest/=lib/liquidity-launcher/lib/openzeppelin-contracts/",
"@optimism/=lib/liquidity-launcher/lib/optimism/packages/contracts-bedrock/",
"@solady/=lib/liquidity-launcher/lib/solady/",
"@uniswap/v4-core/=lib/v4-periphery/lib/v4-core/",
"@uniswap/v4-periphery/=lib/v4-periphery/",
"@uniswap/uerc20-factory/=lib/liquidity-launcher/lib/uerc20-factory/src/",
"blocknumberish/=lib/liquidity-launcher/lib/blocknumberish/",
"ds-test/=lib/v4-periphery/lib/v4-core/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/liquidity-launcher/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-gas-snapshot/=lib/v4-periphery/lib/forge-gas-snapshot/src/",
"forge-std/=lib/forge-std/src/",
"hardhat/=lib/v4-periphery/lib/v4-core/node_modules/hardhat/",
"openzeppelin-contracts/=lib/liquidity-launcher/lib/openzeppelin-contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"permit2/=lib/v4-periphery/lib/permit2/",
"solady/=lib/liquidity-launcher/lib/solady/src/",
"solmate/=lib/v4-periphery/lib/v4-core/lib/solmate/",
"v4-core/=lib/v4-periphery/lib/v4-core/src/",
"v4-periphery/=lib/v4-periphery/",
"scripts/=lib/liquidity-launcher/lib/optimism/packages/contracts-bedrock/scripts/",
"liquidity-launcher/src/token-factories/uerc20-factory/=lib/liquidity-launcher/lib/uerc20-factory/src/",
"liquidity-launcher/src/=lib/liquidity-launcher/src/",
"liquidity-launcher/=lib/liquidity-launcher/",
"periphery/=lib/liquidity-launcher/src/periphery/",
"continuous-clearing-auction/=lib/liquidity-launcher/lib/continuous-clearing-auction/",
"ll/=lib/liquidity-launcher/src/"
],
"optimizer": {
"enabled": true,
"runs": 800
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"UnauthorizedCaller","type":"error"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authorizedFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"creator","type":"address"}],"name":"deploy","outputs":[{"internalType":"address","name":"vestingFactory","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"factory","type":"address"}],"name":"setAuthorizedFactory","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a0604052348015600e575f80fd5b50604051612709380380612709833981016040819052602b916061565b6001600160a01b038116605157604051635c427cd960e01b815260040160405180910390fd5b6001600160a01b0316608052608c565b5f602082840312156070575f80fd5b81516001600160a01b03811681146085575f80fd5b9392505050565b6080516126606100a95f395f818160a9015260d601526126605ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630852f9f31461004e5780632625dbae1461007c578063545e7c6114610091578063f851a440146100a4575b5f80fd5b5f54610060906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61008f61008a36600461020f565b6100cb565b005b61006061009f36600461022f565b610176565b6100607f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461011457604051635c427cd960e01b815260040160405180910390fd5b5f546001600160a01b03161561013d57604051635c427cd960e01b815260040160405180910390fd5b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b5f80546001600160a01b031633146101a157604051635c427cd960e01b815260040160405180910390fd5b82826040516101af906101e7565b6001600160a01b03928316815291166020820152604001604051809103905ff0801580156101df573d5f803e3d5ffd5b509392505050565b6123ca8061026183390190565b80356001600160a01b038116811461020a575f80fd5b919050565b5f6020828403121561021f575f80fd5b610228826101f4565b9392505050565b5f8060408385031215610240575f80fd5b610249836101f4565b9150610257602084016101f4565b9050925092905056fe60a060405234801561000f575f80fd5b506040516123ca3803806123ca83398101604081905261002e91610177565b6001600160a01b038216158061004b57506001600160a01b038116155b156100695760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0382166080526100805f826100b3565b506100ab7f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b82826100b3565b5050506101a8565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16610153575f838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561010b3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610156565b505f5b92915050565b80516001600160a01b0381168114610172575f80fd5b919050565b5f8060408385031215610188575f80fd5b6101918361015c565b915061019f6020840161015c565b90509250929050565b6080516121e06101ea5f395f81816102590152818161033a015281816103cc0152818161044f0152818161080a0152818161089d015261092001526121e05ff3fe608060405234801561000f575f80fd5b50600436106100da575f3560e01c80635c8ab63d11610088578063d547741f11610063578063d547741f1461020d578063d91e60f214610220578063f7cde11314610241578063fc0c546a14610254575f80fd5b80635c8ab63d146101a957806391d14854146101d0578063a217fddf14610206575f80fd5b8063248a9ca3116100b8578063248a9ca3146101515780632f2ff15d1461018157806336568abe14610196575f80fd5b806301ffc9a7146100de5780630665a06f146101065780630c45e22814610131575b5f80fd5b6100f16100ec36600461149c565b61027b565b60405190151581526020015b60405180910390f35b6101196101143660046114e5565b6102b1565b6040516001600160a01b0390911681526020016100fd565b61014461013f36600461155c565b610657565b6040516100fd919061162a565b61017361015f366004611675565b5f9081526020819052604090206001015490565b6040519081526020016100fd565b61019461018f36600461168c565b610b67565b005b6101946101a436600461168c565b610b91565b6101737f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b8281565b6100f16101de36600461168c565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101735f81565b61019461021b36600461168c565b610bc9565b61023361022e3660046116b6565b610bed565b6040516100fd9291906116e6565b61023361024f36600461177e565b610f81565b6101197f000000000000000000000000000000000000000000000000000000000000000081565b5f6001600160e01b03198216637965db0b60e01b14806102ab57506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f7f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b826102dc8161122c565b6001600160a01b0386166103035760405163e6c4247b60e01b815260040160405180910390fd5b845f036103235760405163162908e360e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015285907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610387573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ab919061179e565b10156103ca57604051631e9acf1760e31b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000868686866040516103fb9061148f565b6001600160a01b03958616815294909316602085015260408401919091526060830152608082015260a001604051809103905ff08015801561043f573d5f803e3d5ffd5b5091506104766001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168387611239565b6040805160c0810182526001600160a01b03808516825288811660208084018281528486018b8152606086018b8152608087018b81524260a089019081526001805480820182555f8281529a5160069091027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054928c1673ffffffffffffffffffffffffffffffffffffffff1993841617905596517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78801805491909b1691161790985592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf885015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa830155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb9091015590835260029052919020815490916105eb916117c9565b81546001810183555f92835260209283902001556040805187815291820186905281018490526001600160a01b0387811691908416907f66a644acab4366c0125120794335c517775a2b44b4315b5d90f0d163dae07fea9060600160405180910390a350949350505050565b60607f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b826106838161122c565b885f8190036106a55760405163162908e360e11b815260040160405180910390fd5b87811415806106b45750858114155b806106bf5750838114155b156106dd5760405163162908e360e11b815260040160405180910390fd5b8067ffffffffffffffff8111156106f6576106f66117dc565b60405190808252806020026020018201604052801561071f578160200160208202803683370190505b5092505f5b81811015610b58575f8c8c8381811061073f5761073f6117f0565b90506020020160208101906107549190611804565b90505f8b8b84818110610769576107696117f0565b9050602002013590505f8a8a85818110610785576107856117f0565b9050602002013590505f8989868181106107a1576107a16117f0565b60200291909101359150506001600160a01b0384166107d35760405163e6c4247b60e01b815260040160405180910390fd5b825f036107f35760405163162908e360e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087b919061179e565b101561089a57604051631e9acf1760e31b815260040160405180910390fd5b5f7f0000000000000000000000000000000000000000000000000000000000000000858585856040516108cc9061148f565b6001600160a01b03958616815294909316602085015260408401919091526060830152608082015260a001604051809103905ff080158015610910573d5f803e3d5ffd5b5090506109476001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168286611239565b6040805160c0810182526001600160a01b03808416825287811660208084018281528486018a8152606086018a8152608087018a81524260a089019081526001805480820182555f8281529a5160069091027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054928c1673ffffffffffffffffffffffffffffffffffffffff1993841617905596517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78801805491909b1691161790985592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf885015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa830155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb909101559083526002905291902081549091610abc916117c9565b81546001810183555f928352602090922090910155885181908a9088908110610ae757610ae76117f0565b6001600160a01b03928316602091820292909201810191909152604080518781529182018690528101849052868216918316907f66a644acab4366c0125120794335c517775a2b44b4315b5d90f0d163dae07fea9060600160405180910390a3505060019093019250610724915050565b50505098975050505050505050565b5f82815260208190526040902060010154610b818161122c565b610b8b83836112a0565b50505050565b6001600160a01b0381163314610bba5760405163334bd91960e11b815260040160405180910390fd5b610bc48282611347565b505050565b5f82815260208190526040902060010154610be38161122c565b610b8b8383611347565b6001600160a01b0383165f908152600260205260409020805460609184158015610c15575083155b15610d71578167ffffffffffffffff811115610c3357610c336117dc565b604051908082528060200260200182016040528015610ca957816020015b610c966040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610c515790505b5092505f5b82811015610d6a576001828281548110610cca57610cca6117f0565b905f5260205f20015481548110610ce357610ce36117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a08201528451859083908110610d5757610d576117f0565b6020908102919091010152600101610cae565b5050610f79565b835f03610d7c578193505b818510610df957604080515f8082526020820190925290610df0565b610ddd6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610d985790505b50925050610f79565b5f82610e05868861181d565b11610e105784610e1a565b610e1a86846117c9565b90508067ffffffffffffffff811115610e3557610e356117dc565b604051908082528060200260200182016040528015610eab57816020015b610e986040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610e535790505b5093505f5b81811015610f7557600183610ec5838a61181d565b81548110610ed557610ed56117f0565b905f5260205f20015481548110610eee57610eee6117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a08201528551869083908110610f6257610f626117f0565b6020908102919091010152600101610eb0565b5050505b935093915050565b60015460609083158015610f93575082155b15611039576001805480602002602001604051908101604052809291908181526020015f905b8282101561102e575f8481526020908190206040805160c0810182526006860290920180546001600160a01b0390811684526001808301549091168486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101610fb9565b505050509150611225565b825f03611044578092505b8084106110c057604080515f80825260208201909252906110b8565b6110a56040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b8152602001906001900390816110605790505b509150611225565b5f816110cc858761181d565b116110d757836110e1565b6110e185836117c9565b90508067ffffffffffffffff8111156110fc576110fc6117dc565b60405190808252806020026020018201604052801561117257816020015b61115f6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b81526020019060019003908161111a5790505b5092505f5b8181101561122257600161118b828861181d565b8154811061119b5761119b6117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a0820152845185908390811061120f5761120f6117f0565b6020908102919091010152600101611177565b50505b9250929050565b61123681336113c8565b50565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052610bc4908490611423565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16611340575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556112f83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016102ab565b505f6102ab565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1615611340575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016102ab565b5f828152602081815260408083206001600160a01b038516845290915290205460ff1661141f5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b5050565b5f8060205f8451602086015f885af180611442576040513d5f823e3d81fd5b50505f513d91508115611459578060011415611466565b6001600160a01b0384163b155b15610b8b57604051635274afe760e01b81526001600160a01b0385166004820152602401611416565b61097a8061183183390190565b5f602082840312156114ac575f80fd5b81356001600160e01b0319811681146114c3575f80fd5b9392505050565b80356001600160a01b03811681146114e0575f80fd5b919050565b5f805f80608085870312156114f8575f80fd5b611501856114ca565b966020860135965060408601359560600135945092505050565b5f8083601f84011261152b575f80fd5b50813567ffffffffffffffff811115611542575f80fd5b6020830191508360208260051b8501011115611225575f80fd5b5f805f805f805f806080898b031215611573575f80fd5b883567ffffffffffffffff811115611589575f80fd5b6115958b828c0161151b565b909950975050602089013567ffffffffffffffff8111156115b4575f80fd5b6115c08b828c0161151b565b909750955050604089013567ffffffffffffffff8111156115df575f80fd5b6115eb8b828c0161151b565b909550935050606089013567ffffffffffffffff81111561160a575f80fd5b6116168b828c0161151b565b999c989b5096995094979396929594505050565b602080825282518282018190525f918401906040840190835b8181101561166a5783516001600160a01b0316835260209384019390920191600101611643565b509095945050505050565b5f60208284031215611685575f80fd5b5035919050565b5f806040838503121561169d575f80fd5b823591506116ad602084016114ca565b90509250929050565b5f805f606084860312156116c8575f80fd5b6116d1846114ca565b95602085013595506040909401359392505050565b604080825283519082018190525f9060208501906060840190835b8181101561176b5783516001600160a01b0381511684526001600160a01b03602082015116602085015260408101516040850152606081015160608501526080810151608085015260a081015160a08501525060c083019250602084019350600181019050611701565b5050602093909301939093525092915050565b5f806040838503121561178f575f80fd5b50508035926020909101359150565b5f602082840312156117ae575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156102ab576102ab6117b5565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611814575f80fd5b6114c3826114ca565b808201808211156102ab576102ab6117b556fe60e060405234801561000f575f80fd5b5060405161097a38038061097a83398101604081905261002e91610140565b6001600160a01b038516158061004b57506001600160a01b038416155b156100695760405163e6c4247b60e01b815260040160405180910390fd5b61007662ed4e004261018a565b82101561009657604051631b742d9d60e31b815260040160405180910390fd5b6100a46303c267004261018a565b8110156100c457604051631b742d9d60e31b815260040160405180910390fd5b818110156100e557604051631b742d9d60e31b815260040160405180910390fd5b6001600160a01b039485166080525f80546001600160a01b031916949095169390931790935560a0524260c08190526001929092556002556003556101af565b80516001600160a01b038116811461013b575f80fd5b919050565b5f805f805f60a08688031215610154575f80fd5b61015d86610125565b945061016b60208701610125565b6040870151606088015160809098015196999198509695945092505050565b808201808211156101a957634e487b7160e01b5f52601160045260245ffd5b92915050565b60805160a05160c0516107716102095f395f8181610187015281816102d0015261049101525f818160d70152818161030501526104c601525f81816101b7015281816102440152818161036c015261040701526107715ff3fe608060405234801561000f575f80fd5b50600436106100ce575f3560e01c8063b23f35941161007d578063e29bc68b11610058578063e29bc68b14610182578063f3640e74146101a9578063fc0c546a146101b2575f80fd5b8063b23f35941461015b578063b6a6d1771461016e578063c046371114610179575f80fd5b806384a1931f116100ad57806384a1931f1461012057806385f2aef214610129578063a556f84614610153575f80fd5b8062728f76146100d25780630ef31a9b1461010c5780634e71d92d14610116575b5f80fd5b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100f962ed4e0081565b61011e6101d9565b005b6100f960025481565b5f5461013b906001600160a01b031681565b6040516001600160a01b039091168152602001610103565b6100f96103d9565b61011e610169366004610694565b6104fb565b6100f96303c2670081565b6100f960035481565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f960015481565b61013b7f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b03163314610202576040516282b42960e81b815260040160405180910390fd5b600154421015610225576040516343523d3f60e11b815260040160405180910390fd5b5f60025442106102bc576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610291573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b591906106c1565b905061033c565b5f600354426102cb91906106ec565b90505f7f00000000000000000000000000000000000000000000000000000000000000006002546102fc91906106ec565b905080610329837f0000000000000000000000000000000000000000000000000000000000000000610705565b610333919061071c565b42600355925050505b805f0361035c5760405163df95788360e01b815260040160405180910390fd5b5f54610395906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836105b2565b5f546040518281526001600160a01b03909116907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a250565b5f6001544210156103e957505f90565b600254421061047d576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610454573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047891906106c1565b905090565b5f6003544261048c91906106ec565b90505f7f00000000000000000000000000000000000000000000000000000000000000006002546104bd91906106ec565b9050806104ea837f0000000000000000000000000000000000000000000000000000000000000000610705565b6104f4919061071c565b9250505090565b5f546001600160a01b03163314610524576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811661054b5760405163e6c4247b60e01b815260040160405180910390fd5b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f607e753d2dade5906d41862e6512bba104d36715c1f18d4110d26443bf2655f69190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905261061990849061061e565b505050565b5f8060205f8451602086015f885af18061063d576040513d5f823e3d81fd5b50505f513d91508115610654578060011415610661565b6001600160a01b0384163b155b1561068e57604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b50505050565b5f602082840312156106a4575f80fd5b81356001600160a01b03811681146106ba575f80fd5b9392505050565b5f602082840312156106d1575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ff576106ff6106d8565b92915050565b80820281158282048414176106ff576106ff6106d8565b5f8261073657634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220765bbd5baf0087eea1b420799b4627b141382250d656f523e02779b2e098aaf064736f6c634300081a0033a2646970667358221220189b096f211dbcaadb031789e6076b4aa8d9c460dfe04a9ca987bd5d0eb64c8464736f6c634300081a0033a264697066735822122055ef0687e61a08ac3865ce9e4812e2b95d14441de361686acc654b780d7f2f7664736f6c634300081a0033000000000000000000000000e911f518449ba0011d84b047b4cde50daa081ec1
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630852f9f31461004e5780632625dbae1461007c578063545e7c6114610091578063f851a440146100a4575b5f80fd5b5f54610060906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61008f61008a36600461020f565b6100cb565b005b61006061009f36600461022f565b610176565b6100607f000000000000000000000000e911f518449ba0011d84b047b4cde50daa081ec181565b336001600160a01b037f000000000000000000000000e911f518449ba0011d84b047b4cde50daa081ec1161461011457604051635c427cd960e01b815260040160405180910390fd5b5f546001600160a01b03161561013d57604051635c427cd960e01b815260040160405180910390fd5b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b5f80546001600160a01b031633146101a157604051635c427cd960e01b815260040160405180910390fd5b82826040516101af906101e7565b6001600160a01b03928316815291166020820152604001604051809103905ff0801580156101df573d5f803e3d5ffd5b509392505050565b6123ca8061026183390190565b80356001600160a01b038116811461020a575f80fd5b919050565b5f6020828403121561021f575f80fd5b610228826101f4565b9392505050565b5f8060408385031215610240575f80fd5b610249836101f4565b9150610257602084016101f4565b9050925092905056fe60a060405234801561000f575f80fd5b506040516123ca3803806123ca83398101604081905261002e91610177565b6001600160a01b038216158061004b57506001600160a01b038116155b156100695760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0382166080526100805f826100b3565b506100ab7f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b82826100b3565b5050506101a8565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16610153575f838152602081815260408083206001600160a01b03861684529091529020805460ff1916600117905561010b3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610156565b505f5b92915050565b80516001600160a01b0381168114610172575f80fd5b919050565b5f8060408385031215610188575f80fd5b6101918361015c565b915061019f6020840161015c565b90509250929050565b6080516121e06101ea5f395f81816102590152818161033a015281816103cc0152818161044f0152818161080a0152818161089d015261092001526121e05ff3fe608060405234801561000f575f80fd5b50600436106100da575f3560e01c80635c8ab63d11610088578063d547741f11610063578063d547741f1461020d578063d91e60f214610220578063f7cde11314610241578063fc0c546a14610254575f80fd5b80635c8ab63d146101a957806391d14854146101d0578063a217fddf14610206575f80fd5b8063248a9ca3116100b8578063248a9ca3146101515780632f2ff15d1461018157806336568abe14610196575f80fd5b806301ffc9a7146100de5780630665a06f146101065780630c45e22814610131575b5f80fd5b6100f16100ec36600461149c565b61027b565b60405190151581526020015b60405180910390f35b6101196101143660046114e5565b6102b1565b6040516001600160a01b0390911681526020016100fd565b61014461013f36600461155c565b610657565b6040516100fd919061162a565b61017361015f366004611675565b5f9081526020819052604090206001015490565b6040519081526020016100fd565b61019461018f36600461168c565b610b67565b005b6101946101a436600461168c565b610b91565b6101737f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b8281565b6100f16101de36600461168c565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101735f81565b61019461021b36600461168c565b610bc9565b61023361022e3660046116b6565b610bed565b6040516100fd9291906116e6565b61023361024f36600461177e565b610f81565b6101197f000000000000000000000000000000000000000000000000000000000000000081565b5f6001600160e01b03198216637965db0b60e01b14806102ab57506301ffc9a760e01b6001600160e01b03198316145b92915050565b5f7f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b826102dc8161122c565b6001600160a01b0386166103035760405163e6c4247b60e01b815260040160405180910390fd5b845f036103235760405163162908e360e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015285907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610387573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ab919061179e565b10156103ca57604051631e9acf1760e31b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000868686866040516103fb9061148f565b6001600160a01b03958616815294909316602085015260408401919091526060830152608082015260a001604051809103905ff08015801561043f573d5f803e3d5ffd5b5091506104766001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168387611239565b6040805160c0810182526001600160a01b03808516825288811660208084018281528486018b8152606086018b8152608087018b81524260a089019081526001805480820182555f8281529a5160069091027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054928c1673ffffffffffffffffffffffffffffffffffffffff1993841617905596517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78801805491909b1691161790985592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf885015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa830155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb9091015590835260029052919020815490916105eb916117c9565b81546001810183555f92835260209283902001556040805187815291820186905281018490526001600160a01b0387811691908416907f66a644acab4366c0125120794335c517775a2b44b4315b5d90f0d163dae07fea9060600160405180910390a350949350505050565b60607f2c0e86ef42968f843b5fc3a6f6d421401da96923e1a6a2299b016956535a3b826106838161122c565b885f8190036106a55760405163162908e360e11b815260040160405180910390fd5b87811415806106b45750858114155b806106bf5750838114155b156106dd5760405163162908e360e11b815260040160405180910390fd5b8067ffffffffffffffff8111156106f6576106f66117dc565b60405190808252806020026020018201604052801561071f578160200160208202803683370190505b5092505f5b81811015610b58575f8c8c8381811061073f5761073f6117f0565b90506020020160208101906107549190611804565b90505f8b8b84818110610769576107696117f0565b9050602002013590505f8a8a85818110610785576107856117f0565b9050602002013590505f8989868181106107a1576107a16117f0565b60200291909101359150506001600160a01b0384166107d35760405163e6c4247b60e01b815260040160405180910390fd5b825f036107f35760405163162908e360e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087b919061179e565b101561089a57604051631e9acf1760e31b815260040160405180910390fd5b5f7f0000000000000000000000000000000000000000000000000000000000000000858585856040516108cc9061148f565b6001600160a01b03958616815294909316602085015260408401919091526060830152608082015260a001604051809103905ff080158015610910573d5f803e3d5ffd5b5090506109476001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168286611239565b6040805160c0810182526001600160a01b03808416825287811660208084018281528486018a8152606086018a8152608087018a81524260a089019081526001805480820182555f8281529a5160069091027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054928c1673ffffffffffffffffffffffffffffffffffffffff1993841617905596517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78801805491909b1691161790985592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf885015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa830155517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb909101559083526002905291902081549091610abc916117c9565b81546001810183555f928352602090922090910155885181908a9088908110610ae757610ae76117f0565b6001600160a01b03928316602091820292909201810191909152604080518781529182018690528101849052868216918316907f66a644acab4366c0125120794335c517775a2b44b4315b5d90f0d163dae07fea9060600160405180910390a3505060019093019250610724915050565b50505098975050505050505050565b5f82815260208190526040902060010154610b818161122c565b610b8b83836112a0565b50505050565b6001600160a01b0381163314610bba5760405163334bd91960e11b815260040160405180910390fd5b610bc48282611347565b505050565b5f82815260208190526040902060010154610be38161122c565b610b8b8383611347565b6001600160a01b0383165f908152600260205260409020805460609184158015610c15575083155b15610d71578167ffffffffffffffff811115610c3357610c336117dc565b604051908082528060200260200182016040528015610ca957816020015b610c966040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610c515790505b5092505f5b82811015610d6a576001828281548110610cca57610cca6117f0565b905f5260205f20015481548110610ce357610ce36117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a08201528451859083908110610d5757610d576117f0565b6020908102919091010152600101610cae565b5050610f79565b835f03610d7c578193505b818510610df957604080515f8082526020820190925290610df0565b610ddd6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610d985790505b50925050610f79565b5f82610e05868861181d565b11610e105784610e1a565b610e1a86846117c9565b90508067ffffffffffffffff811115610e3557610e356117dc565b604051908082528060200260200182016040528015610eab57816020015b610e986040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b815260200190600190039081610e535790505b5093505f5b81811015610f7557600183610ec5838a61181d565b81548110610ed557610ed56117f0565b905f5260205f20015481548110610eee57610eee6117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a08201528551869083908110610f6257610f626117f0565b6020908102919091010152600101610eb0565b5050505b935093915050565b60015460609083158015610f93575082155b15611039576001805480602002602001604051908101604052809291908181526020015f905b8282101561102e575f8481526020908190206040805160c0810182526006860290920180546001600160a01b0390811684526001808301549091168486015260028201549284019290925260038101546060840152600481015460808401526005015460a08301529083529092019101610fb9565b505050509150611225565b825f03611044578092505b8084106110c057604080515f80825260208201909252906110b8565b6110a56040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b8152602001906001900390816110605790505b509150611225565b5f816110cc858761181d565b116110d757836110e1565b6110e185836117c9565b90508067ffffffffffffffff8111156110fc576110fc6117dc565b60405190808252806020026020018201604052801561117257816020015b61115f6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b81526020019060019003908161111a5790505b5092505f5b8181101561122257600161118b828861181d565b8154811061119b5761119b6117f0565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608082015260059091015460a0820152845185908390811061120f5761120f6117f0565b6020908102919091010152600101611177565b50505b9250929050565b61123681336113c8565b50565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052610bc4908490611423565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16611340575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556112f83390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016102ab565b505f6102ab565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1615611340575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016102ab565b5f828152602081815260408083206001600160a01b038516845290915290205460ff1661141f5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b5050565b5f8060205f8451602086015f885af180611442576040513d5f823e3d81fd5b50505f513d91508115611459578060011415611466565b6001600160a01b0384163b155b15610b8b57604051635274afe760e01b81526001600160a01b0385166004820152602401611416565b61097a8061183183390190565b5f602082840312156114ac575f80fd5b81356001600160e01b0319811681146114c3575f80fd5b9392505050565b80356001600160a01b03811681146114e0575f80fd5b919050565b5f805f80608085870312156114f8575f80fd5b611501856114ca565b966020860135965060408601359560600135945092505050565b5f8083601f84011261152b575f80fd5b50813567ffffffffffffffff811115611542575f80fd5b6020830191508360208260051b8501011115611225575f80fd5b5f805f805f805f806080898b031215611573575f80fd5b883567ffffffffffffffff811115611589575f80fd5b6115958b828c0161151b565b909950975050602089013567ffffffffffffffff8111156115b4575f80fd5b6115c08b828c0161151b565b909750955050604089013567ffffffffffffffff8111156115df575f80fd5b6115eb8b828c0161151b565b909550935050606089013567ffffffffffffffff81111561160a575f80fd5b6116168b828c0161151b565b999c989b5096995094979396929594505050565b602080825282518282018190525f918401906040840190835b8181101561166a5783516001600160a01b0316835260209384019390920191600101611643565b509095945050505050565b5f60208284031215611685575f80fd5b5035919050565b5f806040838503121561169d575f80fd5b823591506116ad602084016114ca565b90509250929050565b5f805f606084860312156116c8575f80fd5b6116d1846114ca565b95602085013595506040909401359392505050565b604080825283519082018190525f9060208501906060840190835b8181101561176b5783516001600160a01b0381511684526001600160a01b03602082015116602085015260408101516040850152606081015160608501526080810151608085015260a081015160a08501525060c083019250602084019350600181019050611701565b5050602093909301939093525092915050565b5f806040838503121561178f575f80fd5b50508035926020909101359150565b5f602082840312156117ae575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156102ab576102ab6117b5565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611814575f80fd5b6114c3826114ca565b808201808211156102ab576102ab6117b556fe60e060405234801561000f575f80fd5b5060405161097a38038061097a83398101604081905261002e91610140565b6001600160a01b038516158061004b57506001600160a01b038416155b156100695760405163e6c4247b60e01b815260040160405180910390fd5b61007662ed4e004261018a565b82101561009657604051631b742d9d60e31b815260040160405180910390fd5b6100a46303c267004261018a565b8110156100c457604051631b742d9d60e31b815260040160405180910390fd5b818110156100e557604051631b742d9d60e31b815260040160405180910390fd5b6001600160a01b039485166080525f80546001600160a01b031916949095169390931790935560a0524260c08190526001929092556002556003556101af565b80516001600160a01b038116811461013b575f80fd5b919050565b5f805f805f60a08688031215610154575f80fd5b61015d86610125565b945061016b60208701610125565b6040870151606088015160809098015196999198509695945092505050565b808201808211156101a957634e487b7160e01b5f52601160045260245ffd5b92915050565b60805160a05160c0516107716102095f395f8181610187015281816102d0015261049101525f818160d70152818161030501526104c601525f81816101b7015281816102440152818161036c015261040701526107715ff3fe608060405234801561000f575f80fd5b50600436106100ce575f3560e01c8063b23f35941161007d578063e29bc68b11610058578063e29bc68b14610182578063f3640e74146101a9578063fc0c546a146101b2575f80fd5b8063b23f35941461015b578063b6a6d1771461016e578063c046371114610179575f80fd5b806384a1931f116100ad57806384a1931f1461012057806385f2aef214610129578063a556f84614610153575f80fd5b8062728f76146100d25780630ef31a9b1461010c5780634e71d92d14610116575b5f80fd5b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100f962ed4e0081565b61011e6101d9565b005b6100f960025481565b5f5461013b906001600160a01b031681565b6040516001600160a01b039091168152602001610103565b6100f96103d9565b61011e610169366004610694565b6104fb565b6100f96303c2670081565b6100f960035481565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f960015481565b61013b7f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b03163314610202576040516282b42960e81b815260040160405180910390fd5b600154421015610225576040516343523d3f60e11b815260040160405180910390fd5b5f60025442106102bc576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610291573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b591906106c1565b905061033c565b5f600354426102cb91906106ec565b90505f7f00000000000000000000000000000000000000000000000000000000000000006002546102fc91906106ec565b905080610329837f0000000000000000000000000000000000000000000000000000000000000000610705565b610333919061071c565b42600355925050505b805f0361035c5760405163df95788360e01b815260040160405180910390fd5b5f54610395906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116836105b2565b5f546040518281526001600160a01b03909116907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a250565b5f6001544210156103e957505f90565b600254421061047d576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610454573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047891906106c1565b905090565b5f6003544261048c91906106ec565b90505f7f00000000000000000000000000000000000000000000000000000000000000006002546104bd91906106ec565b9050806104ea837f0000000000000000000000000000000000000000000000000000000000000000610705565b6104f4919061071c565b9250505090565b5f546001600160a01b03163314610524576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811661054b5760405163e6c4247b60e01b815260040160405180910390fd5b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f607e753d2dade5906d41862e6512bba104d36715c1f18d4110d26443bf2655f69190a35050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905261061990849061061e565b505050565b5f8060205f8451602086015f885af18061063d576040513d5f823e3d81fd5b50505f513d91508115610654578060011415610661565b6001600160a01b0384163b155b1561068e57604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b50505050565b5f602082840312156106a4575f80fd5b81356001600160a01b03811681146106ba575f80fd5b9392505050565b5f602082840312156106d1575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ff576106ff6106d8565b92915050565b80820281158282048414176106ff576106ff6106d8565b5f8261073657634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220765bbd5baf0087eea1b420799b4627b141382250d656f523e02779b2e098aaf064736f6c634300081a0033a2646970667358221220189b096f211dbcaadb031789e6076b4aa8d9c460dfe04a9ca987bd5d0eb64c8464736f6c634300081a0033a264697066735822122055ef0687e61a08ac3865ce9e4812e2b95d14441de361686acc654b780d7f2f7664736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e911f518449ba0011d84b047b4cde50daa081ec1
-----Decoded View---------------
Arg [0] : _admin (address): 0xe911f518449ba0011D84b047B4cde50dAA081eC1
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000e911f518449ba0011d84b047b4cde50daa081ec1
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.