Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 1,650 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Claim | 23115260 | 207 days ago | IN | 0 ETH | 0.00019419 | ||||
| Claim | 22371735 | 311 days ago | IN | 0 ETH | 0.00008764 | ||||
| Claim | 22063762 | 354 days ago | IN | 0 ETH | 0.00008783 | ||||
| Claim | 21810805 | 390 days ago | IN | 0 ETH | 0.00008308 | ||||
| Claim | 21309645 | 460 days ago | IN | 0 ETH | 0.00208195 | ||||
| Claim | 21161534 | 480 days ago | IN | 0 ETH | 0.00157088 | ||||
| Claim | 21100075 | 489 days ago | IN | 0 ETH | 0.00049789 | ||||
| Claim | 21074195 | 492 days ago | IN | 0 ETH | 0.00079836 | ||||
| Claim | 21070836 | 493 days ago | IN | 0 ETH | 0.0006856 | ||||
| Claim | 21070469 | 493 days ago | IN | 0 ETH | 0.00071235 | ||||
| Claim | 21069145 | 493 days ago | IN | 0 ETH | 0.00113979 | ||||
| Claim | 21068968 | 493 days ago | IN | 0 ETH | 0.00079776 | ||||
| Claim | 21068541 | 493 days ago | IN | 0 ETH | 0.00156993 | ||||
| Claim | 21068514 | 493 days ago | IN | 0 ETH | 0.00129866 | ||||
| Claim | 21065719 | 494 days ago | IN | 0 ETH | 0.00140312 | ||||
| Claim | 21063125 | 494 days ago | IN | 0 ETH | 0.00057688 | ||||
| Claim | 21063078 | 494 days ago | IN | 0 ETH | 0.00083503 | ||||
| Claim | 21063056 | 494 days ago | IN | 0 ETH | 0.00061702 | ||||
| Claim | 21060360 | 494 days ago | IN | 0 ETH | 0.00055556 | ||||
| Claim | 21058991 | 495 days ago | IN | 0 ETH | 0.00065332 | ||||
| Claim | 21058441 | 495 days ago | IN | 0 ETH | 0.00067306 | ||||
| Claim | 21056603 | 495 days ago | IN | 0 ETH | 0.00057178 | ||||
| Claim | 21056131 | 495 days ago | IN | 0 ETH | 0.00057559 | ||||
| Claim | 21054396 | 495 days ago | IN | 0 ETH | 0.00026614 | ||||
| Claim | 21054389 | 495 days ago | IN | 0 ETH | 0.00025151 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
TrufVesting
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {IVotingEscrow} from "../interfaces/IVotingEscrow.sol";
/**
* @title TRUF vesting contract
* @author Ryuhei Matsuda
* @notice Admin registers vesting information for users,
* and users could claim or lock vesting to veTRUF to get voting power and TRUF staking rewards
*/
contract TrufVesting is Ownable2Step {
using SafeERC20 for IERC20;
using SafeCast for uint256;
using SafeCast for int256;
error ZeroAddress();
error ZeroAmount();
error Forbidden(address sender);
error InvalidTimestamp();
error InvalidAmount();
error VestingStarted(uint64 tge);
error InvalidVestingCategory(uint256 id);
error InvalidEmissions();
error InvalidVestingInfo(uint256 categoryIdx, uint256 id);
error InvalidUserVesting();
error ClaimAmountExceed();
error UserVestingAlreadySet(uint256 categoryIdx, uint256 vestingId, address user);
error UserVestingDoesNotExists(uint256 categoryIdx, uint256 vestingId, address user);
error MaxAllocationExceed();
error AlreadyVested(uint256 categoryIdx, uint256 vestingId, address user);
error LockExist();
error LockDoesNotExist();
error InvalidInitialReleasePct();
error InvalidInitialReleasePeriod();
error InvalidCliff();
error InvalidPeriod();
error InvalidUnit();
error InvalidArray();
error Initialized();
/// @dev Emitted when vesting category is set
event VestingCategorySet(uint256 indexed id, string category, uint256 maxAllocation, bool adminClaimable);
/// @dev Emitted when emission schedule is set
event EmissionScheduleSet(uint256 indexed categoryId, uint256[] emissions);
/// @dev Emitted when vesting info is set
event VestingInfoSet(uint256 indexed categoryId, uint256 indexed id, VestingInfo info);
/// @dev Emitted when user vesting info is set
event UserVestingSet(
uint256 indexed categoryId, uint256 indexed vestingId, address indexed user, uint256 amount, uint64 startTime
);
/// @dev Emitted when admin migrates user's vesting to another address
event MigrateUser(
uint256 indexed categoryId, uint256 indexed vestingId, address prevUser, address newUser, uint256 newLockupId
);
/// @dev Emitted when admin cancel user's vesting
event CancelVesting(
uint256 indexed categoryId, uint256 indexed vestingId, address indexed user, bool giveUnclaimed
);
/// @dev Emitted when admin has been set
event AdminSet(address indexed admin, bool indexed flag);
/// @dev Emitted when user claimed vested TRUF tokens
event Claimed(uint256 indexed categoryId, uint256 indexed vestingId, address indexed user, uint256 amount);
/// @dev Emitted when veTRUF token has been set
event VeTrufSet(address indexed veTRUF);
/// @dev Emitted when user stakes vesting to veTRUF
event Staked(
uint256 indexed categoryId,
uint256 indexed vestingId,
address indexed user,
uint256 amount,
uint256 duration,
uint256 lockupId
);
/// @dev Emitted when user extended veTRUF staking period or increased amount
event ExtendedStaking(
uint256 indexed categoryId, uint256 indexed vestingId, address indexed user, uint256 amount, uint256 duration
);
/// @dev Emitted when user unstakes from veTRUF
event Unstaked(uint256 indexed categoryId, uint256 indexed vestingId, address indexed user, uint256 amount);
/// @dev Vesting Category struct
struct VestingCategory {
string category; // Category name
uint256 maxAllocation; // Maximum allocation for this category
uint256 allocated; // Current allocated amount
bool adminClaimable; // Allow admin to claim if value is true
uint256 totalClaimed; // Total claimed amount
}
/// @dev Vesting info struct
struct VestingInfo {
uint64 initialReleasePct; // Initial Release percentage
uint64 initialReleasePeriod; // Initial release period after TGE
uint64 cliff; // Cliff period
uint64 period; // Total period
uint64 unit; // The period to claim. ex. monthly or 6 monthly
}
/// @dev User vesting info struct
struct UserVesting {
uint256 amount; // Total vesting amount
uint256 claimed; // Total claimed amount
uint256 locked; // Locked amount at VotingEscrow
uint64 startTime; // Vesting start time
}
uint256 public constant DENOMINATOR = 1e18;
uint64 public constant ONE_MONTH = 30 days;
/// @dev Is category initialized
mapping(uint256 => bool) public isInitialized;
/// @dev TRUF token address
IERC20 public immutable trufToken;
/// @dev veTRUF token address
IVotingEscrow public veTRUF;
/// @dev TGE timestamp
uint64 public immutable tgeTime;
/// @dev Vesting categories
VestingCategory[] public categories;
// @dev Emission schedule per category. x index item of array indicates emission limit on x+1 months after TGE time.
mapping(uint256 => uint256[]) public emissionSchedule;
/// @dev Vesting info per category
mapping(uint256 => VestingInfo[]) public vestingInfos;
/// @dev User vesting information (category => info => user address => user vesting)
mapping(uint256 => mapping(uint256 => mapping(address => UserVesting))) public userVestings;
/// @dev Vesting lockup ids (category => info => user address => lockup id)
mapping(uint256 => mapping(uint256 => mapping(address => uint256))) public lockupIds;
/// @dev True if account has admin permission
mapping(address => bool) public isAdmin;
modifier onlyAdmin() {
if (!isAdmin[msg.sender] && msg.sender != owner()) {
revert Forbidden(msg.sender);
}
_;
}
/**
* @notice TRUF Vesting constructor
* @param _trufToken TRUF token address
*/
constructor(IERC20 _trufToken, uint64 _tgeTime) {
if (address(_trufToken) == address(0)) revert ZeroAddress();
trufToken = _trufToken;
if (_tgeTime < block.timestamp) {
revert InvalidTimestamp();
}
tgeTime = _tgeTime;
}
/**
* @notice Calculate claimable amount (total vested amount - previously claimed amount - locked amount)
* @param categoryId Vesting category id
* @param vestingId Vesting id
* @param user user address
* @return claimableAmount Claimable amount
*/
function claimable(uint256 categoryId, uint256 vestingId, address user)
public
view
returns (uint256 claimableAmount)
{
if (isInitialized[categoryId] == false) revert Initialized();
UserVesting memory userVesting = userVestings[categoryId][vestingId][user];
VestingInfo memory info = vestingInfos[categoryId][vestingId];
uint64 startTime = userVesting.startTime + info.initialReleasePeriod;
if (startTime > block.timestamp) {
return 0;
}
uint256 totalAmount = userVesting.amount;
uint256 initialRelease = (totalAmount * info.initialReleasePct) / DENOMINATOR;
startTime += info.cliff;
uint256 vestedAmount;
if (startTime > block.timestamp) {
vestedAmount = initialRelease;
} else {
uint64 timeElapsed = ((uint64(block.timestamp) - startTime) / info.unit) * info.unit;
vestedAmount = ((totalAmount - initialRelease) * timeElapsed) / info.period + initialRelease;
}
uint256 maxClaimable = userVesting.amount - userVesting.locked;
if (vestedAmount > maxClaimable) {
vestedAmount = maxClaimable;
}
if (vestedAmount <= userVesting.claimed) {
return 0;
}
claimableAmount = vestedAmount - userVesting.claimed;
uint256 emissionLeft = getEmission(categoryId) - categories[categoryId].totalClaimed;
if (claimableAmount > emissionLeft) {
claimableAmount = emissionLeft;
}
}
/**
* @notice Claim available amount
* @dev Owner is able to claim for admin claimable categories.
* @param user user account(For non-admin claimable categories, it must be msg.sender)
* @param categoryId category id
* @param vestingId vesting id
* @param claimAmount token amount to claim
*/
function claim(address user, uint256 categoryId, uint256 vestingId, uint256 claimAmount) public {
if (isInitialized[categoryId] == false) revert Initialized();
if (user != msg.sender && (!categories[categoryId].adminClaimable || !isAdmin[msg.sender])) {
revert Forbidden(msg.sender);
}
uint256 claimableAmount = claimable(categoryId, vestingId, user);
if (claimAmount == type(uint256).max) {
claimAmount = claimableAmount;
} else if (claimAmount > claimableAmount) {
revert ClaimAmountExceed();
}
if (claimAmount == 0) {
revert ZeroAmount();
}
categories[categoryId].totalClaimed += claimAmount;
userVestings[categoryId][vestingId][user].claimed += claimAmount;
trufToken.safeTransfer(user, claimAmount);
emit Claimed(categoryId, vestingId, user, claimAmount);
}
/**
* @notice Stake vesting to veTRUF to get voting power and get staking TRUF rewards
* @param categoryId category id
* @param vestingId vesting id
* @param amount amount to stake
* @param duration lock period in seconds
*/
function stake(uint256 categoryId, uint256 vestingId, uint256 amount, uint256 duration) external {
if (isInitialized[categoryId] == false) revert Initialized();
if (amount == 0) {
revert ZeroAmount();
}
if (lockupIds[categoryId][vestingId][msg.sender] != 0) {
revert LockExist();
}
UserVesting storage userVesting = userVestings[categoryId][vestingId][msg.sender];
if (amount > userVesting.amount - userVesting.claimed - userVesting.locked) {
revert InvalidAmount();
}
userVesting.locked += amount;
trufToken.safeIncreaseAllowance(address(veTRUF), amount);
uint256 lockupId = veTRUF.stakeVesting(amount, duration, msg.sender) + 1;
lockupIds[categoryId][vestingId][msg.sender] = lockupId;
emit Staked(categoryId, vestingId, msg.sender, amount, duration, lockupId);
}
/**
* @notice Extend veTRUF staking period and increase amount
* @param categoryId category id
* @param vestingId vesting id
* @param amount token amount to increase
* @param duration lock period from now
*/
function extendStaking(uint256 categoryId, uint256 vestingId, uint256 amount, uint256 duration) external {
if (isInitialized[categoryId] == false) revert Initialized();
uint256 lockupId = lockupIds[categoryId][vestingId][msg.sender];
if (lockupId == 0) {
revert LockDoesNotExist();
}
if (amount != 0) {
UserVesting storage userVesting = userVestings[categoryId][vestingId][msg.sender];
if (amount > userVesting.amount - userVesting.claimed - userVesting.locked) {
revert InvalidAmount();
}
userVesting.locked += amount;
trufToken.safeIncreaseAllowance(address(veTRUF), amount);
}
veTRUF.extendVestingLock(msg.sender, lockupId - 1, amount, duration);
emit ExtendedStaking(categoryId, vestingId, msg.sender, amount, duration);
}
/**
* @notice Unstake vesting from veTRUF
* @param categoryId category id
* @param vestingId vesting id
*/
function unstake(uint256 categoryId, uint256 vestingId) external {
if (isInitialized[categoryId] == false) revert Initialized();
uint256 lockupId = lockupIds[categoryId][vestingId][msg.sender];
if (lockupId == 0) {
revert LockDoesNotExist();
}
uint256 amount = veTRUF.unstakeVesting(msg.sender, lockupId - 1, false);
UserVesting storage userVesting = userVestings[categoryId][vestingId][msg.sender];
userVesting.locked -= amount;
delete lockupIds[categoryId][vestingId][msg.sender];
emit Unstaked(categoryId, vestingId, msg.sender, amount);
}
/**
* @notice Migrate owner of vesting. Used when user lost his private key
* @dev Only admin can migrate users vesting
* @param categoryId Category id
* @param vestingId Vesting id
* @param prevUser previous user address
* @param newUser new user address
*/
function migrateUser(uint256 categoryId, uint256 vestingId, address prevUser, address newUser) external onlyAdmin {
if (newUser == address(0)) {
revert ZeroAddress();
}
UserVesting storage prevVesting = userVestings[categoryId][vestingId][prevUser];
UserVesting storage newVesting = userVestings[categoryId][vestingId][newUser];
if (newVesting.amount != 0) {
revert UserVestingAlreadySet(categoryId, vestingId, newUser);
}
if (prevVesting.amount == 0) {
revert UserVestingDoesNotExists(categoryId, vestingId, prevUser);
}
newVesting.amount = prevVesting.amount;
newVesting.claimed = prevVesting.claimed;
newVesting.startTime = prevVesting.startTime;
uint256 lockupId = lockupIds[categoryId][vestingId][prevUser];
uint256 newLockupId;
if (lockupId != 0) {
newLockupId = veTRUF.migrateVestingLock(prevUser, newUser, lockupId - 1) + 1;
lockupIds[categoryId][vestingId][newUser] = newLockupId;
delete lockupIds[categoryId][vestingId][prevUser];
newVesting.locked = prevVesting.locked;
}
delete userVestings[categoryId][vestingId][prevUser];
emit MigrateUser(categoryId, vestingId, prevUser, newUser, newLockupId);
}
/**
* @notice Cancel vesting and force cancel from voting escrow
* @dev Only admin can cancel users vesting
* @param categoryId Category id
* @param vestingId Vesting id
* @param user user address
* @param giveUnclaimed Send currently vested, but unclaimed amount to use or not
*/
function cancelVesting(uint256 categoryId, uint256 vestingId, address user, bool giveUnclaimed)
external
onlyAdmin
{
UserVesting storage userVesting = userVestings[categoryId][vestingId][user];
if (userVesting.amount == 0) {
revert UserVestingDoesNotExists(categoryId, vestingId, user);
}
VestingInfo memory vestingInfo = vestingInfos[categoryId][vestingId];
if (
userVesting.startTime + vestingInfo.initialReleasePeriod + vestingInfo.cliff + vestingInfo.period
<= block.timestamp
) {
revert AlreadyVested(categoryId, vestingId, user);
}
uint256 lockupId = lockupIds[categoryId][vestingId][user];
if (lockupId != 0) {
veTRUF.unstakeVesting(user, lockupId - 1, true);
delete lockupIds[categoryId][vestingId][user];
userVesting.locked = 0;
}
VestingCategory storage category = categories[categoryId];
uint256 claimableAmount = claimable(categoryId, vestingId, user);
uint256 unvested = userVesting.amount - (userVesting.claimed + (giveUnclaimed ? claimableAmount : 0));
delete userVestings[categoryId][vestingId][user];
category.allocated -= unvested;
if (giveUnclaimed && claimableAmount != 0) {
trufToken.safeTransfer(user, claimableAmount);
category.totalClaimed += claimableAmount;
emit Claimed(categoryId, vestingId, user, claimableAmount);
}
emit CancelVesting(categoryId, vestingId, user, giveUnclaimed);
}
/**
* @notice Add or modify vesting category
* @dev Only admin can set vesting category
* @param id id to modify or uint256.max to add new category
* @param category new vesting category
* @param maxAllocation Max allocation amount for this category
* @param adminClaimable Admin claimable flag
*/
function setVestingCategory(uint256 id, string calldata category, uint256 maxAllocation, bool adminClaimable)
public
onlyOwner
{
if (id != type(uint256).max && isInitialized[id]) {
revert Initialized();
}
if (maxAllocation == 0) {
revert ZeroAmount();
}
int256 tokenMove;
if (id == type(uint256).max) {
if (block.timestamp >= tgeTime) {
revert VestingStarted(tgeTime);
}
id = categories.length;
categories.push(VestingCategory(category, maxAllocation, 0, adminClaimable, 0));
tokenMove = maxAllocation.toInt256();
} else {
if (categories[id].allocated > maxAllocation) {
revert MaxAllocationExceed();
}
tokenMove = maxAllocation.toInt256() - categories[id].maxAllocation.toInt256();
categories[id].maxAllocation = maxAllocation;
categories[id].category = category;
categories[id].adminClaimable = adminClaimable;
}
emit VestingCategorySet(id, category, maxAllocation, adminClaimable);
}
/**
* @notice Set emission schedule
* @dev Only admin can set emission schedule
* @param categoryId category id
* @param emissions Emission schedule
*/
function setEmissionSchedule(uint256 categoryId, uint256[] memory emissions) public onlyOwner {
if (block.timestamp >= tgeTime) {
revert VestingStarted(tgeTime);
}
uint256 maxAllocation = categories[categoryId].maxAllocation;
if (emissions.length == 0 || emissions[emissions.length - 1] != maxAllocation) {
revert InvalidEmissions();
}
delete emissionSchedule[categoryId];
emissionSchedule[categoryId] = emissions;
emit EmissionScheduleSet(categoryId, emissions);
}
/**
* @notice Add or modify vesting information
* @dev Only admin can set vesting info
* @param categoryIdx category id
* @param id id to modify or uint256.max to add new info
* @param info new vesting info
*/
function setVestingInfo(uint256 categoryIdx, uint256 id, VestingInfo calldata info) public onlyAdmin {
if (info.initialReleasePct > DENOMINATOR) {
revert InvalidInitialReleasePct();
} else if (info.initialReleasePeriod > info.period) {
revert InvalidInitialReleasePeriod();
} else if (info.cliff > 365 days) {
revert InvalidCliff();
} else if (info.period > 8 * 365 days) {
revert InvalidPeriod();
} else if (info.period % info.unit != 0) {
revert InvalidUnit();
}
if (id == type(uint256).max) {
id = vestingInfos[categoryIdx].length;
vestingInfos[categoryIdx].push(info);
} else {
vestingInfos[categoryIdx][id] = info;
}
emit VestingInfoSet(categoryIdx, id, info);
}
/**
* @notice Set user vesting amount
* @dev Only admin can set user vesting
* @dev It will be failed if it exceeds max allocation
* @param categoryId category id
* @param vestingId vesting id
* @param user user address
* @param startTime zero to start from TGE or non-zero to set up custom start time
* @param amount vesting amount
*/
function setUserVesting(uint256 categoryId, uint256 vestingId, address user, uint64 startTime, uint256 amount)
public
onlyAdmin
{
if (user == address(0)) {
revert ZeroAddress();
}
if (amount == 0) {
revert ZeroAmount();
}
if (categoryId >= categories.length) {
revert InvalidVestingCategory(categoryId);
}
if (vestingId >= vestingInfos[categoryId].length) {
revert InvalidVestingInfo(categoryId, vestingId);
}
VestingCategory storage category = categories[categoryId];
UserVesting storage userVesting = userVestings[categoryId][vestingId][user];
category.allocated += amount;
category.allocated -= userVesting.amount;
if (category.allocated > category.maxAllocation) {
revert MaxAllocationExceed();
}
if (amount < userVesting.claimed + userVesting.locked) {
revert InvalidUserVesting();
}
if (startTime != 0 && startTime < tgeTime) revert InvalidTimestamp();
userVesting.amount = amount;
userVesting.startTime = startTime == 0 ? tgeTime : startTime;
emit UserVestingSet(categoryId, vestingId, user, amount, userVesting.startTime);
}
/**
* @notice Set multiple user vestings
* @dev Only admin can set user vestings
* @dev It will fail if it exceeds max allocation
* @param categoryId category id
* @param vestingId vesting id
* @param users users address
* @param amounts vesting amounts
*/
function setUsersVestings(uint256 categoryId, uint256 vestingId, address[] memory users, uint256[] memory amounts)
public
onlyAdmin
{
if (users.length != amounts.length) {
revert InvalidArray();
}
for (uint256 i = 0; i < users.length; i++) {
setUserVesting(categoryId, vestingId, users[i], 0, amounts[i]);
}
}
/**
* @notice Set veTRUF token
* @dev Only admin can set veTRUF
* @param _veTRUF veTRUF token address
*/
function setVeTruf(address _veTRUF) external onlyOwner {
if (_veTRUF == address(0)) {
revert ZeroAddress();
}
veTRUF = IVotingEscrow(_veTRUF);
emit VeTrufSet(_veTRUF);
}
/**
* @notice Set admin
* @dev Only owner can set
* @param _admin admin address
* @param _flag true to set, false to remove
*/
function setAdmin(address _admin, bool _flag) external onlyOwner {
isAdmin[_admin] = _flag;
emit AdminSet(_admin, _flag);
}
/**
* @notice Initialize category by transferring TRUF tokens
* @param _categoryId category to initialize
*/
function initialize(uint256 _categoryId) external {
if (isInitialized[_categoryId]) {
revert Initialized();
}
isInitialized[_categoryId] = true;
trufToken.safeTransferFrom(msg.sender, address(this), categories[_categoryId].maxAllocation);
}
/**
* @notice Multicall several functions in single transaction
* @dev Could be for setting vesting categories, vesting info, and user vesting in single transaction at once
* @param payloads list of payloads
*/
function multicall(bytes[] calldata payloads) external {
uint256 len = payloads.length;
for (uint256 i; i < len;) {
(bool success, bytes memory result) = address(this).delegatecall(payloads[i]);
if (!success) {
if (result.length < 68) revert();
assembly {
result := add(result, 0x04)
}
revert(abi.decode(result, (string)));
}
unchecked {
i += 1;
}
}
}
/**
* @return emissions returns emission schedule of category
*/
function getEmissionSchedule(uint256 categoryId) external view returns (uint256[] memory emissions) {
emissions = emissionSchedule[categoryId];
}
/**
* @return emissionLimit returns current emission limit of category
*/
function getEmission(uint256 categoryId) public view returns (uint256 emissionLimit) {
uint64 _tgeTime = tgeTime;
if (block.timestamp >= _tgeTime) {
uint256 maxAllocation = categories[categoryId].maxAllocation;
if (emissionSchedule[categoryId].length == 0) {
return maxAllocation;
}
uint64 elapsedTime = uint64(block.timestamp) - _tgeTime + ONE_MONTH;
uint64 elapsedMonth = elapsedTime / ONE_MONTH;
if (elapsedMonth >= emissionSchedule[categoryId].length) {
return maxAllocation;
}
uint256 lastMonthEmission = elapsedMonth == 0 ? 0 : emissionSchedule[categoryId][elapsedMonth - 1];
uint256 thisMonthEmission = emissionSchedule[categoryId][elapsedMonth];
uint64 elapsedTimeOfLastMonth = elapsedTime % ONE_MONTH;
emissionLimit =
(thisMonthEmission - lastMonthEmission) * elapsedTimeOfLastMonth / ONE_MONTH + lastMonthEmission;
if (emissionLimit > maxAllocation) {
emissionLimit = maxAllocation;
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
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 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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/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;
/**
* @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.encodeWithSelector(token.transfer.selector, 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.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 Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @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.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @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");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @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 silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// 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 cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;
interface IVotingEscrow {
/// @dev Lockup struct
struct Lockup {
uint128 amount; // Locked amount
uint128 duration; // Lock duration in seconds
uint128 end; // Lock end timestamp in seconds
uint256 points; // veTRUF points
bool isVesting; // True if locked from vesting
}
function stakeVesting(uint256 amount, uint256 duration, address to) external returns (uint256 lockupId);
function unstakeVesting(address user, uint256 lockupId, bool force) external returns (uint256 amount);
function migrateVestingLock(address oldUser, address newUser, uint256 lockupId)
external
returns (uint256 newLockupId);
function extendVestingLock(address user, uint256 lockupId, uint256 amount, uint256 duration) external;
// Events
/// Emitted when user staked TRUF or vesting
event Stake(
address indexed user, bool indexed isVesting, uint256 lockupId, uint256 amount, uint256 end, uint256 points
);
/// Emitted when user unstaked
event Unstake(
address indexed user, bool indexed isVesting, uint256 lockupId, uint256 amount, uint256 end, uint256 points
);
/// Emitted when lockup migrated to another user (for vesting only)
event Migrated(address indexed oldUser, address indexed newUser, uint256 oldLockupId, uint256 newLockupId);
/// Emitted when lockup cancelled (for vesting only)
event Cancelled(address indexed user, uint256 lockupId, uint256 amount, uint256 points);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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.
return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with 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;
}
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@uniswap/v2-periphery/=lib/uniswap-v2-periphery/contracts/",
"murky/src/=lib/murky/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IERC20","name":"_trufToken","type":"address"},{"internalType":"uint64","name":"_tgeTime","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"categoryIdx","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"AlreadyVested","type":"error"},{"inputs":[],"name":"ClaimAmountExceed","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"Forbidden","type":"error"},{"inputs":[],"name":"Initialized","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidArray","type":"error"},{"inputs":[],"name":"InvalidCliff","type":"error"},{"inputs":[],"name":"InvalidEmissions","type":"error"},{"inputs":[],"name":"InvalidInitialReleasePct","type":"error"},{"inputs":[],"name":"InvalidInitialReleasePeriod","type":"error"},{"inputs":[],"name":"InvalidPeriod","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"InvalidUnit","type":"error"},{"inputs":[],"name":"InvalidUserVesting","type":"error"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"InvalidVestingCategory","type":"error"},{"inputs":[{"internalType":"uint256","name":"categoryIdx","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"InvalidVestingInfo","type":"error"},{"inputs":[],"name":"LockDoesNotExist","type":"error"},{"inputs":[],"name":"LockExist","type":"error"},{"inputs":[],"name":"MaxAllocationExceed","type":"error"},{"inputs":[{"internalType":"uint256","name":"categoryIdx","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"UserVestingAlreadySet","type":"error"},{"inputs":[{"internalType":"uint256","name":"categoryIdx","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"UserVestingDoesNotExists","type":"error"},{"inputs":[{"internalType":"uint64","name":"tge","type":"uint64"}],"name":"VestingStarted","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":true,"internalType":"bool","name":"flag","type":"bool"}],"name":"AdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"giveUnclaimed","type":"bool"}],"name":"CancelVesting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"emissions","type":"uint256[]"}],"name":"EmissionScheduleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"ExtendedStaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":false,"internalType":"address","name":"prevUser","type":"address"},{"indexed":false,"internalType":"address","name":"newUser","type":"address"},{"indexed":false,"internalType":"uint256","name":"newLockupId","type":"uint256"}],"name":"MigrateUser","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockupId","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vestingId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"startTime","type":"uint64"}],"name":"UserVestingSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"veTRUF","type":"address"}],"name":"VeTrufSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"category","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxAllocation","type":"uint256"},{"indexed":false,"internalType":"bool","name":"adminClaimable","type":"bool"}],"name":"VestingCategorySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"categoryId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint64","name":"initialReleasePct","type":"uint64"},{"internalType":"uint64","name":"initialReleasePeriod","type":"uint64"},{"internalType":"uint64","name":"cliff","type":"uint64"},{"internalType":"uint64","name":"period","type":"uint64"},{"internalType":"uint64","name":"unit","type":"uint64"}],"indexed":false,"internalType":"struct TrufVesting.VestingInfo","name":"info","type":"tuple"}],"name":"VestingInfoSet","type":"event"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_MONTH","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"giveUnclaimed","type":"bool"}],"name":"cancelVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"categories","outputs":[{"internalType":"string","name":"category","type":"string"},{"internalType":"uint256","name":"maxAllocation","type":"uint256"},{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"bool","name":"adminClaimable","type":"bool"},{"internalType":"uint256","name":"totalClaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"uint256","name":"claimAmount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"claimableAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"emissionSchedule","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"extendStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"}],"name":"getEmission","outputs":[{"internalType":"uint256","name":"emissionLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"}],"name":"getEmissionSchedule","outputs":[{"internalType":"uint256[]","name":"emissions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_categoryId","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"lockupIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"prevUser","type":"address"},{"internalType":"address","name":"newUser","type":"address"}],"name":"migrateUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"payloads","type":"bytes[]"}],"name":"multicall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256[]","name":"emissions","type":"uint256[]"}],"name":"setEmissionSchedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setUserVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"setUsersVestings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_veTRUF","type":"address"}],"name":"setVeTruf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"category","type":"string"},{"internalType":"uint256","name":"maxAllocation","type":"uint256"},{"internalType":"bool","name":"adminClaimable","type":"bool"}],"name":"setVestingCategory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryIdx","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint64","name":"initialReleasePct","type":"uint64"},{"internalType":"uint64","name":"initialReleasePeriod","type":"uint64"},{"internalType":"uint64","name":"cliff","type":"uint64"},{"internalType":"uint64","name":"period","type":"uint64"},{"internalType":"uint64","name":"unit","type":"uint64"}],"internalType":"struct TrufVesting.VestingInfo","name":"info","type":"tuple"}],"name":"setVestingInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tgeTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trufToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"categoryId","type":"uint256"},{"internalType":"uint256","name":"vestingId","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userVestings","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"claimed","type":"uint256"},{"internalType":"uint256","name":"locked","type":"uint256"},{"internalType":"uint64","name":"startTime","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veTRUF","outputs":[{"internalType":"contract IVotingEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"vestingInfos","outputs":[{"internalType":"uint64","name":"initialReleasePct","type":"uint64"},{"internalType":"uint64","name":"initialReleasePeriod","type":"uint64"},{"internalType":"uint64","name":"cliff","type":"uint64"},{"internalType":"uint64","name":"period","type":"uint64"},{"internalType":"uint64","name":"unit","type":"uint64"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b50604051613dec380380613dec83398101604081905261002f91610114565b610038336100a8565b6001600160a01b03821661005f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216608052426001600160401b03821610156100965760405163b7d0949760e01b815260040160405180910390fd5b6001600160401b031660a05250610166565b600180546001600160a01b03191690556100c1816100c4565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000806040838503121561012757600080fd5b82516001600160a01b038116811461013e57600080fd5b60208401519092506001600160401b038116811461015b57600080fd5b809150509250929050565b60805160a051613c0d6101df60003960008181610374015281816107eb01528181610857015281816108ef01528181610ef101528181610f36015281816116c2015261170701526000818161025501528181610e0c015281816115db015281816123f90152818161262001526129090152613c0d6000f3fe608060405234801561001057600080fd5b50600436106102105760003560e01c80638358a04811610125578063d2673bbf116100ad578063ef15259f1161007c578063ef15259f14610566578063efc07c5514610579578063f01e59d2146105c6578063f2fde38b146105d9578063fe4b84df146105ec57600080fd5b8063d2673bbf146104ee578063d82fdf1c14610501578063d9a845d814610532578063e30c39781461055557600080fd5b80639e2c8a5b116100f45780639e2c8a5b1461047e578063ac9650d814610491578063c6cdbe5e146104a4578063ce2fbd97146104c8578063ce93a882146104db57600080fd5b80638358a0481461042b578063866d50071461043e5780638da5cb5b1461045e578063918f86741461046f57600080fd5b8063339f2b90116101a8578063715018a611610177578063715018a6146103e257806377b1f713146103ea57806378481566146103fd578063796d2c3c1461041057806379ba50971461042357600080fd5b8063339f2b901461039657806341100a45146103a95780634b0bddd2146103bc5780634dcb2546146103cf57600080fd5b806324d7806c116101e457806324d7806c146102b157806326f73a2e146102e45780632d80e2881461035c5780633163e3a81461036f57600080fd5b8062b03e051461021557806303e7b4e91461022a57806312c5422a1461025057806320988cef1461028f575b600080fd5b610228610223366004612ecf565b6105ff565b005b61023d610238366004612f1f565b6108eb565b6040519081526020015b60405180910390f35b6102777f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610247565b61029962278d0081565b6040516001600160401b039091168152602001610247565b6102d46102bf366004612f38565b60096020526000908152604090205460ff1681565b6040519015158152602001610247565b6103336102f2366004612f53565b60076020908152600093845260408085208252928452828420905282529020805460018201546002830154600390930154919290916001600160401b031684565b604080519485526020850193909352918301526001600160401b03166060820152608001610247565b61022861036a366004612f96565b610aaa565b6102997f000000000000000000000000000000000000000000000000000000000000000081565b6102286103a43660046130b6565b610ee7565b6102286103b73660046130fc565b611054565b6102286103ca3660046131d0565b61111c565b61023d6103dd366004612f53565b611178565b61022861142f565b6102286103f8366004613207565b611443565b600354610277906001600160a01b031681565b61022861041e366004613240565b61164e565b610228611962565b6102286104393660046132da565b6119dc565b61045161044c366004612f1f565b611c40565b604051610247919061331b565b6000546001600160a01b0316610277565b61023d670de0b6b3a764000081565b61022861048c36600461335f565b611ca2565b61022861049f366004613381565b611e44565b6104b76104b2366004612f1f565b611f22565b604051610247959493929190613445565b6102286104d636600461347c565b611ff7565b6102286104e93660046134c2565b6122da565b6102286104fc3660046134c2565b612519565b61023d61050f366004612f53565b600860209081526000938452604080852082529284528284209052825290205481565b6102d4610540366004612f1f565b60026020526000908152604090205460ff1681565b6001546001600160a01b0316610277565b610228610574366004612f38565b612710565b61058c61058736600461335f565b612789565b604080516001600160401b03968716815294861660208601529285169284019290925283166060830152909116608082015260a001610247565b61023d6105d436600461335f565b6127ed565b6102286105e7366004612f38565b61281e565b6102286105fa366004612f1f565b61288f565b3360009081526009602052604090205460ff1615801561062a57506000546001600160a01b03163314155b1561064f5760405163a59d7f4d60e01b81523360048201526024015b60405180910390fd5b6001600160a01b0383166106765760405163d92e233d60e01b815260040160405180910390fd5b8060000361069757604051631f2a200560e01b815260040160405180910390fd5b60045485106106bc57604051630ef78d7d60e41b815260048101869052602401610646565b60008581526006602052604090205484106106f4576040516366ee880560e01b81526004810186905260248101859052604401610646565b600060048681548110610709576107096134f4565b600091825260208083208984526007825260408085208a865283528085206001600160a01b038a168652909252908320600592909202016002810180549194509192859291610759908490613520565b90915550508054600283018054600090610774908490613539565b90915550506001820154600283015411156107a25760405163a4052f5760e01b815260040160405180910390fd5b806002015481600101546107b69190613520565b8310156107d657604051630c07527360e31b815260040160405180910390fd5b6001600160401b0384161580159061081f57507f00000000000000000000000000000000000000000000000000000000000000006001600160401b0316846001600160401b0316105b1561083d5760405163b7d0949760e01b815260040160405180910390fd5b8281556001600160401b038416156108555783610877565b7f00000000000000000000000000000000000000000000000000000000000000005b60038201805467ffffffffffffffff19166001600160401b039290921691821790556040805185815260208101929092526001600160a01b0387169188918a917f6efec3f1cc0e7e3f8127f9dff5d9ef4dd3c09342d44eec43e8160944f8e6366a910160405180910390a450505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160401b0381164210610aa457600060048481548110610933576109336134f4565b600091825260208083206005928302016001015487845291905260408220549092509003610962579392505050565b600062278d00610972844261354c565b61097c9190613573565b9050600061098d62278d00836135a9565b6000878152600560205260409020549091506001600160401b038216106109b8575090949350505050565b60006001600160401b03821615610a0b5760008781526005602052604090206109e260018461354c565b6001600160401b0316815481106109fb576109fb6134f4565b9060005260206000200154610a0e565b60005b6000888152600560205260408120805492935090916001600160401b038516908110610a3c57610a3c6134f4565b60009182526020822001549150610a5662278d00866135cf565b90508262278d006001600160401b038316610a718386613539565b610a7b91906135f5565b610a85919061360c565b610a8f9190613520565b975085881115610a9d578597505b5050505050505b50919050565b3360009081526009602052604090205460ff16158015610ad557506000546001600160a01b03163314155b15610af55760405163a59d7f4d60e01b8152336004820152602401610646565b600084815260076020908152604080832086845282528083206001600160a01b038616845290915281208054909103610b4a578484846040516001620dfdb360e01b0319815260040161064693929190613620565b6000858152600660205260408120805486908110610b6a57610b6a6134f4565b60009182526020918290206040805160a081018252600290930290910180546001600160401b038082168552600160401b82048116958501869052600160801b82048116938501849052600160c01b90910481166060850181905260019092015481166080850152600387015493955042949193610be9929116613573565b610bf39190613573565b610bfd9190613573565b6001600160401b031611610c2a57858585604051633b96c3a160e21b815260040161064693929190613620565b600086815260086020908152604080832088845282528083206001600160a01b03881684529091529020548015610d22576003546001600160a01b031663bb1405df86610c78600185613539565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152600160448201526064016020604051808303816000875af1158015610cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cee919061363f565b50600087815260086020908152604080832089845282528083206001600160a01b0389168452909152812081905560028401555b600060048881548110610d3757610d376134f4565b906000526020600020906005020190506000610d54898989611178565b9050600086610d64576000610d66565b815b8660010154610d759190613520565b8654610d819190613539565b60008b81526007602090815260408083208d845282528083206001600160a01b038d16845290915281208181556001810182905560028082018390556003909101805467ffffffffffffffff19169055850180549293508392909190610de8908490613539565b909155508790508015610dfa57508115155b15610e9457610e336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168984612941565b81836004016000828254610e479190613520565b92505081905550876001600160a01b0316898b7fb94bf7f9302edf52a596286915a69b4b0685574cffdedd0712e3c62f2550f0ba85604051610e8b91815260200190565b60405180910390a45b876001600160a01b0316898b7f29ff2b9c3d0121132b158b2f2dd19d17c3cb466efdfdbaa1ba7ee2c50fcc41728a604051610ed3911515815260200190565b60405180910390a450505050505050505050565b610eef6129a9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b03164210610f63576040516355ecc8a760e11b81526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602401610646565b600060048381548110610f7857610f786134f4565b9060005260206000209060050201600101549050815160001480610fc25750808260018451610fa79190613539565b81518110610fb757610fb76134f4565b602002602001015114155b15610fe057604051632238b26160e01b815260040160405180910390fd5b6000838152600560205260408120610ff791612e28565b6000838152600560209081526040909120835161101692850190612e46565b50827f91d1473fd427151d93d77055a94438bae10b534c81a00beb2931d6f81d4ac6e483604051611047919061331b565b60405180910390a2505050565b3360009081526009602052604090205460ff1615801561107f57506000546001600160a01b03163314155b1561109f5760405163a59d7f4d60e01b8152336004820152602401610646565b80518251146110c157604051631ec5aa5160e01b815260040160405180910390fd5b60005b82518110156111155761110d85858584815181106110e4576110e46134f4565b60200260200101516000868681518110611100576111006134f4565b60200260200101516105ff565b6001016110c4565b5050505050565b6111246129a9565b6001600160a01b038216600081815260096020526040808220805460ff191685151590811790915590519092917fe68d2c359a771606c400cf8b87000cf5864010363d6a736e98f5047b7bbe18e991a35050565b60008381526002602052604081205460ff16151581036111ab576040516302ed543d60e51b815260040160405180910390fd5b600084815260076020908152604080832086845282528083206001600160a01b038616845282528083208151608081018352815481526001820154818501526002820154818401526003909101546001600160401b0316606082015287845260069092528220805491929186908110611226576112266134f4565b600091825260208083206040805160a081018252600290940290910180546001600160401b038082168652600160401b82048116948601859052600160801b8204811693860193909352600160c01b90048216606080860191909152600190910154909116608084015285015191935061129f91613573565b905042816001600160401b031611156112be5760009350505050611428565b82518251600090670de0b6b3a7640000906112e2906001600160401b0316846135f5565b6112ec919061360c565b90508360400151836112fe9190613573565b9250600042846001600160401b0316111561131a57508061138a565b60808501516000908061132d874261354c565b61133791906135a9565b6113419190613658565b90508286606001516001600160401b0316826001600160401b031685876113689190613539565b61137291906135f5565b61137c919061360c565b6113869190613520565b9150505b6040860151865160009161139d91613539565b9050808211156113ab578091505b866020015182116113c6576000975050505050505050611428565b60208701516113d59083613539565b9750600060048c815481106113ec576113ec6134f4565b9060005260206000209060050201600401546114078d6108eb565b6114119190613539565b90508089111561141f578098505b50505050505050505b9392505050565b6114376129a9565b6114416000612a03565b565b60008381526002602052604081205460ff1615159003611476576040516302ed543d60e51b815260040160405180910390fd5b6001600160a01b03841633148015906114d057506004838154811061149d5761149d6134f4565b600091825260209091206003600590920201015460ff1615806114d057503360009081526009602052604090205460ff16155b156114f05760405163a59d7f4d60e01b8152336004820152602401610646565b60006114fd848487611178565b9050600019820361151057809150611531565b80821115611531576040516333ade54560e11b815260040160405180910390fd5b8160000361155257604051631f2a200560e01b815260040160405180910390fd5b8160048581548110611566576115666134f4565b906000526020600020906005020160040160008282546115869190613520565b9091555050600084815260076020908152604080832086845282528083206001600160a01b0389168452909152812060010180548492906115c8908490613520565b9091555061160290506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168684612941565b846001600160a01b031683857fb94bf7f9302edf52a596286915a69b4b0685574cffdedd0712e3c62f2550f0ba8560405161163f91815260200190565b60405180910390a45050505050565b6116566129a9565b6000198514158015611676575060008581526002602052604090205460ff165b15611694576040516302ed543d60e51b815260040160405180910390fd5b816000036116b557604051631f2a200560e01b815260040160405180910390fd5b60006000198603611801577f00000000000000000000000000000000000000000000000000000000000000006001600160401b03164210611734576040516355ecc8a760e11b81526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166004820152602401610646565b600480546040805160c06020601f8a01819004028201810190925260a08101888152929950918291899089908190850183828082843760009201829052509385525050506020808301889052604083018290528615156060840152608090920181905283546001810185559381522081519192600502019081906117b89082613707565b506020820151600182015560408201516002820155606082015160038201805460ff19169115159190911790556080909101516004909101556117fa83612a1c565b905061191c565b8260048781548110611815576118156134f4565b90600052602060002090600502016002015411156118465760405163a4052f5760e01b815260040160405180910390fd5b6118736004878154811061185c5761185c6134f4565b906000526020600020906005020160010154612a1c565b61187c84612a1c565b61188691906137c6565b9050826004878154811061189c5761189c6134f4565b9060005260206000209060050201600101819055508484600488815481106118c6576118c66134f4565b906000526020600020906005020160000191826118e49291906137e6565b5081600487815481106118f9576118f96134f4565b60009182526020909120600590910201600301805460ff19169115159190911790555b857f2102d51f93820332058f58bd7e7142f0cfd8bbfb6109b57f14ee479f5a9adf3a8686868660405161195294939291906138a5565b60405180910390a2505050505050565b60015433906001600160a01b031681146119d05760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610646565b6119d981612a03565b50565b3360009081526009602052604090205460ff16158015611a0757506000546001600160a01b03163314155b15611a275760405163a59d7f4d60e01b8152336004820152602401610646565b670de0b6b3a7640000611a3d60208301836138e7565b6001600160401b03161115611a6557604051634b8ce6a360e11b815260040160405180910390fd5b611a7560808201606083016138e7565b6001600160401b0316611a8e60408301602084016138e7565b6001600160401b03161115611ab65760405163799547e960e11b815260040160405180910390fd5b6301e13380611acb60608301604084016138e7565b6001600160401b03161115611af357604051630a15cca960e21b815260040160405180910390fd5b630f099c00611b0860808301606084016138e7565b6001600160401b03161115611b30576040516302e8f35960e31b815260040160405180910390fd5b611b4060a08201608083016138e7565b611b5060808301606084016138e7565b611b5a91906135cf565b6001600160401b031615611b815760405163265f13bd60e21b815260040160405180910390fd5b6000198203611bc257600083815260066020908152604082208054600181018255908352912090925081906002840201611bbb8282613911565b5050611c02565b6000838152600660205260409020805482919084908110611be557611be56134f4565b90600052602060002090600202018181611bff9190613911565b50505b81837f03d87beedebfab89b17c593a654fdae3e6a916f19fb66ab32ad3d9ab2db5fa7083604051611c339190613a1b565b60405180910390a3505050565b600081815260056020908152604091829020805483518184028101840190945280845260609392830182828015611c9657602002820191906000526020600020905b815481526020019060010190808311611c82575b50505050509050919050565b60008281526002602052604081205460ff1615159003611cd5576040516302ed543d60e51b815260040160405180910390fd5b6000828152600860209081526040808320848452825280832033845290915281205490819003611d1857604051630b58543560e11b815260040160405180910390fd5b6003546000906001600160a01b031663bb1405df33611d38600186613539565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152600060448201526064016020604051808303816000875af1158015611d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dae919061363f565b6000858152600760209081526040808320878452825280832033845290915281206002810180549394509092849290611de8908490613539565b909155505060008581526008602090815260408083208784528252808320338085529083528184209390935551848152869188917fb904b5088e8442bdbf73b7777734a35451036f567f8487e489c62d6bbb401255910161163f565b8060005b81811015611f1c5760008030868685818110611e6657611e666134f4565b9050602002810190611e789190613a9b565b604051611e86929190613ae8565b600060405180830381855af49150503d8060008114611ec1576040519150601f19603f3d011682016040523d82523d6000602084013e611ec6565b606091505b509150915081611f1257604481511015611edf57600080fd5b60048101905080806020019051810190611ef99190613af8565b60405162461bcd60e51b81526004016106469190613b8b565b5050600101611e48565b50505050565b60048181548110611f3257600080fd5b9060005260206000209060050201600091509050806000018054611f5590613683565b80601f0160208091040260200160405190810160405280929190818152602001828054611f8190613683565b8015611fce5780601f10611fa357610100808354040283529160200191611fce565b820191906000526020600020905b815481529060010190602001808311611fb157829003601f168201915b5050506001840154600285015460038601546004909601549495919490935060ff909116915085565b3360009081526009602052604090205460ff1615801561202257506000546001600160a01b03163314155b156120425760405163a59d7f4d60e01b8152336004820152602401610646565b6001600160a01b0381166120695760405163d92e233d60e01b815260040160405180910390fd5b600084815260076020908152604080832086845282528083206001600160a01b038681168552925280832091841683529091208054156120c25785858460405163a4b28b6760e01b815260040161064693929190613620565b81546000036120ed578585856040516001620dfdb360e01b0319815260040161064693929190613620565b8154815560018083015490820155600380830154908201805467ffffffffffffffff19166001600160401b03909216919091179055600086815260086020908152604080832088845282528083206001600160a01b0388168452909152812054908115612238576003546001600160a01b031663551268928787612172600187613539565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156121c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ea919061363f565b6121f5906001613520565b60008981526008602090815260408083208b845282528083206001600160a01b038a81168552925280832084905590891682528120556002858101549085015590505b60008881526007602090815260408083208a845282528083206001600160a01b038a81168086529184528285208581556001810186905560028101959095556003909401805467ffffffffffffffff191690558151908152928816918301919091528101829052879089907f2c1c254c5f909c052d5ee899e1f47d0c63c05046d6ba71645f65884c72e92e0b9060600160405180910390a35050505050505050565b60008481526002602052604081205460ff161515900361230d576040516302ed543d60e51b815260040160405180910390fd5b8160000361232e57604051631f2a200560e01b815260040160405180910390fd5b600084815260086020908152604080832086845282528083203384529091529020541561236e57604051635ef6934f60e11b815260040160405180910390fd5b6000848152600760209081526040808320868452825280832033845290915290206002810154600182015482546123a59190613539565b6123af9190613539565b8311156123cf5760405163162908e360e11b815260040160405180910390fd5b828160020160008282546123e39190613520565b9091555050600354612422906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911685612a8a565b60035460405163136b901760e11b81526000916001600160a01b0316906326d7202e9061245790879087903390600401613620565b6020604051808303816000875af1158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a919061363f565b6124a5906001613520565b6000878152600860209081526040808320898452825280832033808552908352928190208490558051888152918201879052810183905291925090869088907f0206c6fc83cce751511b5967bcd8ce71e05610271791c0a7a66c09914c12b4b59060600160405180910390a4505050505050565b60008481526002602052604081205460ff161515900361254c576040516302ed543d60e51b815260040160405180910390fd5b600084815260086020908152604080832086845282528083203384529091528120549081900361258f57604051630b58543560e11b815260040160405180910390fd5b821561264b576000858152600760209081526040808320878452825280832033845290915290206002810154600182015482546125cc9190613539565b6125d69190613539565b8411156125f65760405163162908e360e11b815260040160405180910390fd5b8381600201600082825461260a9190613520565b9091555050600354612649906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911686612a8a565b505b6003546001600160a01b031663e495087e33612668600185613539565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044810186905260648101859052608401600060405180830381600087803b1580156126bc57600080fd5b505af11580156126d0573d6000803e3d6000fd5b5050604080518681526020810186905233935087925088917fdee550df05d371dc88ce21066779b6d45b37523c79b367598954e70fc6ce852b910161163f565b6127186129a9565b6001600160a01b03811661273f5760405163d92e233d60e01b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040517f2274320fe0c4e3ae6dcee56cccecc83bc6ae62bdc7690f7d4cf5026b5761e0e290600090a250565b600660205281600052604060002081815481106127a557600080fd5b6000918252602090912060029091020180546001909101546001600160401b038083169450600160401b830481169350600160801b8304811692600160c01b90048116911685565b6005602052816000526040600020818154811061280957600080fd5b90600052602060002001600091509150505481565b6128266129a9565b600180546001600160a01b0383166001600160a01b031990911681179091556128576000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60008181526002602052604090205460ff16156128bf576040516302ed543d60e51b815260040160405180910390fd5b6000818152600260205260409020805460ff19166001179055600480546119d9913391309190859081106128f5576128f56134f4565b9060005260206000209060050201600101547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612b37909392919063ffffffff16565b6040516001600160a01b0383166024820152604481018290526129a490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b6f565b505050565b6000546001600160a01b031633146114415760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610646565b600180546001600160a01b03191690556119d981612c44565b60006001600160ff1b03821115612a865760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610646565b5090565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612ada573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afe919061363f565b9050611f1c8463095ea7b360e01b85612b178686613520565b6040516001600160a01b039092166024830152604482015260640161296d565b6040516001600160a01b0380851660248301528316604482015260648101829052611f1c9085906323b872dd60e01b9060840161296d565b6000612bc4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c949092919063ffffffff16565b9050805160001480612be5575080806020019051810190612be59190613b9e565b6129a45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610646565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060612ca38484600085612cab565b949350505050565b606082471015612d0c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610646565b600080866001600160a01b03168587604051612d289190613bbb565b60006040518083038185875af1925050503d8060008114612d65576040519150601f19603f3d011682016040523d82523d6000602084013e612d6a565b606091505b5091509150612d7b87838387612d86565b979650505050505050565b60608315612df5578251600003612dee576001600160a01b0385163b612dee5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610646565b5081612ca3565b612ca38383815115612e0a5781518083602001fd5b8060405162461bcd60e51b81526004016106469190613b8b565b5050565b50805460008255906000526020600020908101906119d99190612e89565b828054828255906000526020600020908101928215612e81579160200282015b82811115612e81578251825591602001919060010190612e66565b50612a869291505b5b80821115612a865760008155600101612e8a565b80356001600160a01b0381168114612eb557600080fd5b919050565b6001600160401b03811681146119d957600080fd5b600080600080600060a08688031215612ee757600080fd5b8535945060208601359350612efe60408701612e9e565b92506060860135612f0e81612eba565b949793965091946080013592915050565b600060208284031215612f3157600080fd5b5035919050565b600060208284031215612f4a57600080fd5b61142882612e9e565b600080600060608486031215612f6857600080fd5b8335925060208401359150612f7f60408501612e9e565b90509250925092565b80151581146119d957600080fd5b60008060008060808587031215612fac57600080fd5b8435935060208501359250612fc360408601612e9e565b91506060850135612fd381612f88565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561301c5761301c612fde565b604052919050565b60006001600160401b0382111561303d5761303d612fde565b5060051b60200190565b600082601f83011261305857600080fd5b8135602061306d61306883613024565b612ff4565b8083825260208201915060208460051b87010193508684111561308f57600080fd5b602086015b848110156130ab5780358352918301918301613094565b509695505050505050565b600080604083850312156130c957600080fd5b8235915060208301356001600160401b038111156130e657600080fd5b6130f285828601613047565b9150509250929050565b6000806000806080858703121561311257600080fd5b84359350602080860135935060408601356001600160401b038082111561313857600080fd5b818801915088601f83011261314c57600080fd5b813561315a61306882613024565b81815260059190911b8301840190848101908b83111561317957600080fd5b938501935b8285101561319e5761318f85612e9e565b8252938501939085019061317e565b9650505060608801359250808311156131b657600080fd5b50506131c487828801613047565b91505092959194509250565b600080604083850312156131e357600080fd5b6131ec83612e9e565b915060208301356131fc81612f88565b809150509250929050565b6000806000806080858703121561321d57600080fd5b61322685612e9e565b966020860135965060408601359560600135945092505050565b60008060008060006080868803121561325857600080fd5b8535945060208601356001600160401b038082111561327657600080fd5b818801915088601f83011261328a57600080fd5b81358181111561329957600080fd5b8960208285010111156132ab57600080fd5b6020830196508095505050506040860135915060608601356132cc81612f88565b809150509295509295909350565b600080600083850360e08112156132f057600080fd5b843593506020850135925060a0603f198201121561330d57600080fd5b506040840190509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561335357835183529284019291840191600101613337565b50909695505050505050565b6000806040838503121561337257600080fd5b50508035926020909101359150565b6000806020838503121561339457600080fd5b82356001600160401b03808211156133ab57600080fd5b818501915085601f8301126133bf57600080fd5b8135818111156133ce57600080fd5b8660208260051b85010111156133e357600080fd5b60209290920196919550909350505050565b60005b838110156134105781810151838201526020016133f8565b50506000910152565b600081518084526134318160208601602086016133f5565b601f01601f19169290920160200192915050565b60a08152600061345860a0830188613419565b60208301969096525060408101939093529015156060830152608090910152919050565b6000806000806080858703121561349257600080fd5b84359350602085013592506134a960408601612e9e565b91506134b760608601612e9e565b905092959194509250565b600080600080608085870312156134d857600080fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156135335761353361350a565b92915050565b818103818111156135335761353361350a565b6001600160401b0382811682821603908082111561356c5761356c61350a565b5092915050565b6001600160401b0381811683821601908082111561356c5761356c61350a565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806135c3576135c3613593565b92169190910492915050565b60006001600160401b03808416806135e9576135e9613593565b92169190910692915050565b80820281158282048414176135335761353361350a565b60008261361b5761361b613593565b500490565b92835260208301919091526001600160a01b0316604082015260600190565b60006020828403121561365157600080fd5b5051919050565b6001600160401b0381811683821602808216919082811461367b5761367b61350a565b505092915050565b600181811c9082168061369757607f821691505b602082108103610aa457634e487b7160e01b600052602260045260246000fd5b601f8211156129a4576000816000526020600020601f850160051c810160208610156136e05750805b601f850160051c820191505b818110156136ff578281556001016136ec565b505050505050565b81516001600160401b0381111561372057613720612fde565b6137348161372e8454613683565b846136b7565b602080601f83116001811461376957600084156137515750858301515b600019600386901b1c1916600185901b1785556136ff565b600085815260208120601f198616915b8281101561379857888601518255948401946001909101908401613779565b50858210156137b65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b818103600083128015838313168383128216171561356c5761356c61350a565b6001600160401b038311156137fd576137fd612fde565b6138118361380b8354613683565b836136b7565b6000601f841160018114613845576000851561382d5750838201355b600019600387901b1c1916600186901b178355611115565b600083815260209020601f19861690835b828110156138765786850135825560209485019460019092019101613856565b50868210156138935760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b606081528360608201528385608083013760006080858301015260006080601f19601f8701168301019050836020830152821515604083015295945050505050565b6000602082840312156138f957600080fd5b813561142881612eba565b6000813561353381612eba565b813561391c81612eba565b815467ffffffffffffffff19166001600160401b03821617825550602082013561394581612eba565b81546fffffffffffffffff0000000000000000604092831b166fffffffffffffffff0000000000000000198216811784559184013561398381612eba565b67ffffffffffffffff60801b60809190911b1677ffffffffffffffffffffffffffffffff000000000000000019821683178117845560608501356139c681612eba565b6001600160401b0360c01b8160c01b16846001600160401b03851617831717855550505050612e246139fa60808401613904565b600183016001600160401b0382166001600160401b03198254161781555050565b60a081018235613a2a81612eba565b6001600160401b039081168352602084013590613a4682612eba565b9081166020840152604084013590613a5d82612eba565b9081166040840152606084013590613a7482612eba565b9081166060840152608084013590613a8b82612eba565b8082166080850152505092915050565b6000808335601e19843603018112613ab257600080fd5b8301803591506001600160401b03821115613acc57600080fd5b602001915036819003821315613ae157600080fd5b9250929050565b8183823760009101908152919050565b600060208284031215613b0a57600080fd5b81516001600160401b0380821115613b2157600080fd5b818401915084601f830112613b3557600080fd5b815181811115613b4757613b47612fde565b613b5a601f8201601f1916602001612ff4565b9150808252856020828501011115613b7157600080fd5b613b828160208401602086016133f5565b50949350505050565b6020815260006114286020830184613419565b600060208284031215613bb057600080fd5b815161142881612f88565b60008251613bcd8184602087016133f5565b919091019291505056fea2646970667358221220830f4c15214df0150645cede5a39e95078ac7f327345969a1b33dfd92d2a098164736f6c6343000819003300000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca0000000000000000000000000000000000000000000000000000000066659940
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102105760003560e01c80638358a04811610125578063d2673bbf116100ad578063ef15259f1161007c578063ef15259f14610566578063efc07c5514610579578063f01e59d2146105c6578063f2fde38b146105d9578063fe4b84df146105ec57600080fd5b8063d2673bbf146104ee578063d82fdf1c14610501578063d9a845d814610532578063e30c39781461055557600080fd5b80639e2c8a5b116100f45780639e2c8a5b1461047e578063ac9650d814610491578063c6cdbe5e146104a4578063ce2fbd97146104c8578063ce93a882146104db57600080fd5b80638358a0481461042b578063866d50071461043e5780638da5cb5b1461045e578063918f86741461046f57600080fd5b8063339f2b90116101a8578063715018a611610177578063715018a6146103e257806377b1f713146103ea57806378481566146103fd578063796d2c3c1461041057806379ba50971461042357600080fd5b8063339f2b901461039657806341100a45146103a95780634b0bddd2146103bc5780634dcb2546146103cf57600080fd5b806324d7806c116101e457806324d7806c146102b157806326f73a2e146102e45780632d80e2881461035c5780633163e3a81461036f57600080fd5b8062b03e051461021557806303e7b4e91461022a57806312c5422a1461025057806320988cef1461028f575b600080fd5b610228610223366004612ecf565b6105ff565b005b61023d610238366004612f1f565b6108eb565b6040519081526020015b60405180910390f35b6102777f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca81565b6040516001600160a01b039091168152602001610247565b61029962278d0081565b6040516001600160401b039091168152602001610247565b6102d46102bf366004612f38565b60096020526000908152604090205460ff1681565b6040519015158152602001610247565b6103336102f2366004612f53565b60076020908152600093845260408085208252928452828420905282529020805460018201546002830154600390930154919290916001600160401b031684565b604080519485526020850193909352918301526001600160401b03166060820152608001610247565b61022861036a366004612f96565b610aaa565b6102997f000000000000000000000000000000000000000000000000000000006665994081565b6102286103a43660046130b6565b610ee7565b6102286103b73660046130fc565b611054565b6102286103ca3660046131d0565b61111c565b61023d6103dd366004612f53565b611178565b61022861142f565b6102286103f8366004613207565b611443565b600354610277906001600160a01b031681565b61022861041e366004613240565b61164e565b610228611962565b6102286104393660046132da565b6119dc565b61045161044c366004612f1f565b611c40565b604051610247919061331b565b6000546001600160a01b0316610277565b61023d670de0b6b3a764000081565b61022861048c36600461335f565b611ca2565b61022861049f366004613381565b611e44565b6104b76104b2366004612f1f565b611f22565b604051610247959493929190613445565b6102286104d636600461347c565b611ff7565b6102286104e93660046134c2565b6122da565b6102286104fc3660046134c2565b612519565b61023d61050f366004612f53565b600860209081526000938452604080852082529284528284209052825290205481565b6102d4610540366004612f1f565b60026020526000908152604090205460ff1681565b6001546001600160a01b0316610277565b610228610574366004612f38565b612710565b61058c61058736600461335f565b612789565b604080516001600160401b03968716815294861660208601529285169284019290925283166060830152909116608082015260a001610247565b61023d6105d436600461335f565b6127ed565b6102286105e7366004612f38565b61281e565b6102286105fa366004612f1f565b61288f565b3360009081526009602052604090205460ff1615801561062a57506000546001600160a01b03163314155b1561064f5760405163a59d7f4d60e01b81523360048201526024015b60405180910390fd5b6001600160a01b0383166106765760405163d92e233d60e01b815260040160405180910390fd5b8060000361069757604051631f2a200560e01b815260040160405180910390fd5b60045485106106bc57604051630ef78d7d60e41b815260048101869052602401610646565b60008581526006602052604090205484106106f4576040516366ee880560e01b81526004810186905260248101859052604401610646565b600060048681548110610709576107096134f4565b600091825260208083208984526007825260408085208a865283528085206001600160a01b038a168652909252908320600592909202016002810180549194509192859291610759908490613520565b90915550508054600283018054600090610774908490613539565b90915550506001820154600283015411156107a25760405163a4052f5760e01b815260040160405180910390fd5b806002015481600101546107b69190613520565b8310156107d657604051630c07527360e31b815260040160405180910390fd5b6001600160401b0384161580159061081f57507f00000000000000000000000000000000000000000000000000000000666599406001600160401b0316846001600160401b0316105b1561083d5760405163b7d0949760e01b815260040160405180910390fd5b8281556001600160401b038416156108555783610877565b7f00000000000000000000000000000000000000000000000000000000666599405b60038201805467ffffffffffffffff19166001600160401b039290921691821790556040805185815260208101929092526001600160a01b0387169188918a917f6efec3f1cc0e7e3f8127f9dff5d9ef4dd3c09342d44eec43e8160944f8e6366a910160405180910390a450505050505050565b60007f00000000000000000000000000000000000000000000000000000000666599406001600160401b0381164210610aa457600060048481548110610933576109336134f4565b600091825260208083206005928302016001015487845291905260408220549092509003610962579392505050565b600062278d00610972844261354c565b61097c9190613573565b9050600061098d62278d00836135a9565b6000878152600560205260409020549091506001600160401b038216106109b8575090949350505050565b60006001600160401b03821615610a0b5760008781526005602052604090206109e260018461354c565b6001600160401b0316815481106109fb576109fb6134f4565b9060005260206000200154610a0e565b60005b6000888152600560205260408120805492935090916001600160401b038516908110610a3c57610a3c6134f4565b60009182526020822001549150610a5662278d00866135cf565b90508262278d006001600160401b038316610a718386613539565b610a7b91906135f5565b610a85919061360c565b610a8f9190613520565b975085881115610a9d578597505b5050505050505b50919050565b3360009081526009602052604090205460ff16158015610ad557506000546001600160a01b03163314155b15610af55760405163a59d7f4d60e01b8152336004820152602401610646565b600084815260076020908152604080832086845282528083206001600160a01b038616845290915281208054909103610b4a578484846040516001620dfdb360e01b0319815260040161064693929190613620565b6000858152600660205260408120805486908110610b6a57610b6a6134f4565b60009182526020918290206040805160a081018252600290930290910180546001600160401b038082168552600160401b82048116958501869052600160801b82048116938501849052600160c01b90910481166060850181905260019092015481166080850152600387015493955042949193610be9929116613573565b610bf39190613573565b610bfd9190613573565b6001600160401b031611610c2a57858585604051633b96c3a160e21b815260040161064693929190613620565b600086815260086020908152604080832088845282528083206001600160a01b03881684529091529020548015610d22576003546001600160a01b031663bb1405df86610c78600185613539565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152600160448201526064016020604051808303816000875af1158015610cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cee919061363f565b50600087815260086020908152604080832089845282528083206001600160a01b0389168452909152812081905560028401555b600060048881548110610d3757610d376134f4565b906000526020600020906005020190506000610d54898989611178565b9050600086610d64576000610d66565b815b8660010154610d759190613520565b8654610d819190613539565b60008b81526007602090815260408083208d845282528083206001600160a01b038d16845290915281208181556001810182905560028082018390556003909101805467ffffffffffffffff19169055850180549293508392909190610de8908490613539565b909155508790508015610dfa57508115155b15610e9457610e336001600160a01b037f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca168984612941565b81836004016000828254610e479190613520565b92505081905550876001600160a01b0316898b7fb94bf7f9302edf52a596286915a69b4b0685574cffdedd0712e3c62f2550f0ba85604051610e8b91815260200190565b60405180910390a45b876001600160a01b0316898b7f29ff2b9c3d0121132b158b2f2dd19d17c3cb466efdfdbaa1ba7ee2c50fcc41728a604051610ed3911515815260200190565b60405180910390a450505050505050505050565b610eef6129a9565b7f00000000000000000000000000000000000000000000000000000000666599406001600160401b03164210610f63576040516355ecc8a760e11b81526001600160401b037f0000000000000000000000000000000000000000000000000000000066659940166004820152602401610646565b600060048381548110610f7857610f786134f4565b9060005260206000209060050201600101549050815160001480610fc25750808260018451610fa79190613539565b81518110610fb757610fb76134f4565b602002602001015114155b15610fe057604051632238b26160e01b815260040160405180910390fd5b6000838152600560205260408120610ff791612e28565b6000838152600560209081526040909120835161101692850190612e46565b50827f91d1473fd427151d93d77055a94438bae10b534c81a00beb2931d6f81d4ac6e483604051611047919061331b565b60405180910390a2505050565b3360009081526009602052604090205460ff1615801561107f57506000546001600160a01b03163314155b1561109f5760405163a59d7f4d60e01b8152336004820152602401610646565b80518251146110c157604051631ec5aa5160e01b815260040160405180910390fd5b60005b82518110156111155761110d85858584815181106110e4576110e46134f4565b60200260200101516000868681518110611100576111006134f4565b60200260200101516105ff565b6001016110c4565b5050505050565b6111246129a9565b6001600160a01b038216600081815260096020526040808220805460ff191685151590811790915590519092917fe68d2c359a771606c400cf8b87000cf5864010363d6a736e98f5047b7bbe18e991a35050565b60008381526002602052604081205460ff16151581036111ab576040516302ed543d60e51b815260040160405180910390fd5b600084815260076020908152604080832086845282528083206001600160a01b038616845282528083208151608081018352815481526001820154818501526002820154818401526003909101546001600160401b0316606082015287845260069092528220805491929186908110611226576112266134f4565b600091825260208083206040805160a081018252600290940290910180546001600160401b038082168652600160401b82048116948601859052600160801b8204811693860193909352600160c01b90048216606080860191909152600190910154909116608084015285015191935061129f91613573565b905042816001600160401b031611156112be5760009350505050611428565b82518251600090670de0b6b3a7640000906112e2906001600160401b0316846135f5565b6112ec919061360c565b90508360400151836112fe9190613573565b9250600042846001600160401b0316111561131a57508061138a565b60808501516000908061132d874261354c565b61133791906135a9565b6113419190613658565b90508286606001516001600160401b0316826001600160401b031685876113689190613539565b61137291906135f5565b61137c919061360c565b6113869190613520565b9150505b6040860151865160009161139d91613539565b9050808211156113ab578091505b866020015182116113c6576000975050505050505050611428565b60208701516113d59083613539565b9750600060048c815481106113ec576113ec6134f4565b9060005260206000209060050201600401546114078d6108eb565b6114119190613539565b90508089111561141f578098505b50505050505050505b9392505050565b6114376129a9565b6114416000612a03565b565b60008381526002602052604081205460ff1615159003611476576040516302ed543d60e51b815260040160405180910390fd5b6001600160a01b03841633148015906114d057506004838154811061149d5761149d6134f4565b600091825260209091206003600590920201015460ff1615806114d057503360009081526009602052604090205460ff16155b156114f05760405163a59d7f4d60e01b8152336004820152602401610646565b60006114fd848487611178565b9050600019820361151057809150611531565b80821115611531576040516333ade54560e11b815260040160405180910390fd5b8160000361155257604051631f2a200560e01b815260040160405180910390fd5b8160048581548110611566576115666134f4565b906000526020600020906005020160040160008282546115869190613520565b9091555050600084815260076020908152604080832086845282528083206001600160a01b0389168452909152812060010180548492906115c8908490613520565b9091555061160290506001600160a01b037f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca168684612941565b846001600160a01b031683857fb94bf7f9302edf52a596286915a69b4b0685574cffdedd0712e3c62f2550f0ba8560405161163f91815260200190565b60405180910390a45050505050565b6116566129a9565b6000198514158015611676575060008581526002602052604090205460ff165b15611694576040516302ed543d60e51b815260040160405180910390fd5b816000036116b557604051631f2a200560e01b815260040160405180910390fd5b60006000198603611801577f00000000000000000000000000000000000000000000000000000000666599406001600160401b03164210611734576040516355ecc8a760e11b81526001600160401b037f0000000000000000000000000000000000000000000000000000000066659940166004820152602401610646565b600480546040805160c06020601f8a01819004028201810190925260a08101888152929950918291899089908190850183828082843760009201829052509385525050506020808301889052604083018290528615156060840152608090920181905283546001810185559381522081519192600502019081906117b89082613707565b506020820151600182015560408201516002820155606082015160038201805460ff19169115159190911790556080909101516004909101556117fa83612a1c565b905061191c565b8260048781548110611815576118156134f4565b90600052602060002090600502016002015411156118465760405163a4052f5760e01b815260040160405180910390fd5b6118736004878154811061185c5761185c6134f4565b906000526020600020906005020160010154612a1c565b61187c84612a1c565b61188691906137c6565b9050826004878154811061189c5761189c6134f4565b9060005260206000209060050201600101819055508484600488815481106118c6576118c66134f4565b906000526020600020906005020160000191826118e49291906137e6565b5081600487815481106118f9576118f96134f4565b60009182526020909120600590910201600301805460ff19169115159190911790555b857f2102d51f93820332058f58bd7e7142f0cfd8bbfb6109b57f14ee479f5a9adf3a8686868660405161195294939291906138a5565b60405180910390a2505050505050565b60015433906001600160a01b031681146119d05760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610646565b6119d981612a03565b50565b3360009081526009602052604090205460ff16158015611a0757506000546001600160a01b03163314155b15611a275760405163a59d7f4d60e01b8152336004820152602401610646565b670de0b6b3a7640000611a3d60208301836138e7565b6001600160401b03161115611a6557604051634b8ce6a360e11b815260040160405180910390fd5b611a7560808201606083016138e7565b6001600160401b0316611a8e60408301602084016138e7565b6001600160401b03161115611ab65760405163799547e960e11b815260040160405180910390fd5b6301e13380611acb60608301604084016138e7565b6001600160401b03161115611af357604051630a15cca960e21b815260040160405180910390fd5b630f099c00611b0860808301606084016138e7565b6001600160401b03161115611b30576040516302e8f35960e31b815260040160405180910390fd5b611b4060a08201608083016138e7565b611b5060808301606084016138e7565b611b5a91906135cf565b6001600160401b031615611b815760405163265f13bd60e21b815260040160405180910390fd5b6000198203611bc257600083815260066020908152604082208054600181018255908352912090925081906002840201611bbb8282613911565b5050611c02565b6000838152600660205260409020805482919084908110611be557611be56134f4565b90600052602060002090600202018181611bff9190613911565b50505b81837f03d87beedebfab89b17c593a654fdae3e6a916f19fb66ab32ad3d9ab2db5fa7083604051611c339190613a1b565b60405180910390a3505050565b600081815260056020908152604091829020805483518184028101840190945280845260609392830182828015611c9657602002820191906000526020600020905b815481526020019060010190808311611c82575b50505050509050919050565b60008281526002602052604081205460ff1615159003611cd5576040516302ed543d60e51b815260040160405180910390fd5b6000828152600860209081526040808320848452825280832033845290915281205490819003611d1857604051630b58543560e11b815260040160405180910390fd5b6003546000906001600160a01b031663bb1405df33611d38600186613539565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152600060448201526064016020604051808303816000875af1158015611d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dae919061363f565b6000858152600760209081526040808320878452825280832033845290915281206002810180549394509092849290611de8908490613539565b909155505060008581526008602090815260408083208784528252808320338085529083528184209390935551848152869188917fb904b5088e8442bdbf73b7777734a35451036f567f8487e489c62d6bbb401255910161163f565b8060005b81811015611f1c5760008030868685818110611e6657611e666134f4565b9050602002810190611e789190613a9b565b604051611e86929190613ae8565b600060405180830381855af49150503d8060008114611ec1576040519150601f19603f3d011682016040523d82523d6000602084013e611ec6565b606091505b509150915081611f1257604481511015611edf57600080fd5b60048101905080806020019051810190611ef99190613af8565b60405162461bcd60e51b81526004016106469190613b8b565b5050600101611e48565b50505050565b60048181548110611f3257600080fd5b9060005260206000209060050201600091509050806000018054611f5590613683565b80601f0160208091040260200160405190810160405280929190818152602001828054611f8190613683565b8015611fce5780601f10611fa357610100808354040283529160200191611fce565b820191906000526020600020905b815481529060010190602001808311611fb157829003601f168201915b5050506001840154600285015460038601546004909601549495919490935060ff909116915085565b3360009081526009602052604090205460ff1615801561202257506000546001600160a01b03163314155b156120425760405163a59d7f4d60e01b8152336004820152602401610646565b6001600160a01b0381166120695760405163d92e233d60e01b815260040160405180910390fd5b600084815260076020908152604080832086845282528083206001600160a01b038681168552925280832091841683529091208054156120c25785858460405163a4b28b6760e01b815260040161064693929190613620565b81546000036120ed578585856040516001620dfdb360e01b0319815260040161064693929190613620565b8154815560018083015490820155600380830154908201805467ffffffffffffffff19166001600160401b03909216919091179055600086815260086020908152604080832088845282528083206001600160a01b0388168452909152812054908115612238576003546001600160a01b031663551268928787612172600187613539565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156121c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ea919061363f565b6121f5906001613520565b60008981526008602090815260408083208b845282528083206001600160a01b038a81168552925280832084905590891682528120556002858101549085015590505b60008881526007602090815260408083208a845282528083206001600160a01b038a81168086529184528285208581556001810186905560028101959095556003909401805467ffffffffffffffff191690558151908152928816918301919091528101829052879089907f2c1c254c5f909c052d5ee899e1f47d0c63c05046d6ba71645f65884c72e92e0b9060600160405180910390a35050505050505050565b60008481526002602052604081205460ff161515900361230d576040516302ed543d60e51b815260040160405180910390fd5b8160000361232e57604051631f2a200560e01b815260040160405180910390fd5b600084815260086020908152604080832086845282528083203384529091529020541561236e57604051635ef6934f60e11b815260040160405180910390fd5b6000848152600760209081526040808320868452825280832033845290915290206002810154600182015482546123a59190613539565b6123af9190613539565b8311156123cf5760405163162908e360e11b815260040160405180910390fd5b828160020160008282546123e39190613520565b9091555050600354612422906001600160a01b037f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca8116911685612a8a565b60035460405163136b901760e11b81526000916001600160a01b0316906326d7202e9061245790879087903390600401613620565b6020604051808303816000875af1158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a919061363f565b6124a5906001613520565b6000878152600860209081526040808320898452825280832033808552908352928190208490558051888152918201879052810183905291925090869088907f0206c6fc83cce751511b5967bcd8ce71e05610271791c0a7a66c09914c12b4b59060600160405180910390a4505050505050565b60008481526002602052604081205460ff161515900361254c576040516302ed543d60e51b815260040160405180910390fd5b600084815260086020908152604080832086845282528083203384529091528120549081900361258f57604051630b58543560e11b815260040160405180910390fd5b821561264b576000858152600760209081526040808320878452825280832033845290915290206002810154600182015482546125cc9190613539565b6125d69190613539565b8411156125f65760405163162908e360e11b815260040160405180910390fd5b8381600201600082825461260a9190613520565b9091555050600354612649906001600160a01b037f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca8116911686612a8a565b505b6003546001600160a01b031663e495087e33612668600185613539565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044810186905260648101859052608401600060405180830381600087803b1580156126bc57600080fd5b505af11580156126d0573d6000803e3d6000fd5b5050604080518681526020810186905233935087925088917fdee550df05d371dc88ce21066779b6d45b37523c79b367598954e70fc6ce852b910161163f565b6127186129a9565b6001600160a01b03811661273f5760405163d92e233d60e01b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040517f2274320fe0c4e3ae6dcee56cccecc83bc6ae62bdc7690f7d4cf5026b5761e0e290600090a250565b600660205281600052604060002081815481106127a557600080fd5b6000918252602090912060029091020180546001909101546001600160401b038083169450600160401b830481169350600160801b8304811692600160c01b90048116911685565b6005602052816000526040600020818154811061280957600080fd5b90600052602060002001600091509150505481565b6128266129a9565b600180546001600160a01b0383166001600160a01b031990911681179091556128576000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60008181526002602052604090205460ff16156128bf576040516302ed543d60e51b815260040160405180910390fd5b6000818152600260205260409020805460ff19166001179055600480546119d9913391309190859081106128f5576128f56134f4565b9060005260206000209060050201600101547f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca6001600160a01b0316612b37909392919063ffffffff16565b6040516001600160a01b0383166024820152604481018290526129a490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b6f565b505050565b6000546001600160a01b031633146114415760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610646565b600180546001600160a01b03191690556119d981612c44565b60006001600160ff1b03821115612a865760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610646565b5090565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015612ada573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afe919061363f565b9050611f1c8463095ea7b360e01b85612b178686613520565b6040516001600160a01b039092166024830152604482015260640161296d565b6040516001600160a01b0380851660248301528316604482015260648101829052611f1c9085906323b872dd60e01b9060840161296d565b6000612bc4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612c949092919063ffffffff16565b9050805160001480612be5575080806020019051810190612be59190613b9e565b6129a45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610646565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060612ca38484600085612cab565b949350505050565b606082471015612d0c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610646565b600080866001600160a01b03168587604051612d289190613bbb565b60006040518083038185875af1925050503d8060008114612d65576040519150601f19603f3d011682016040523d82523d6000602084013e612d6a565b606091505b5091509150612d7b87838387612d86565b979650505050505050565b60608315612df5578251600003612dee576001600160a01b0385163b612dee5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610646565b5081612ca3565b612ca38383815115612e0a5781518083602001fd5b8060405162461bcd60e51b81526004016106469190613b8b565b5050565b50805460008255906000526020600020908101906119d99190612e89565b828054828255906000526020600020908101928215612e81579160200282015b82811115612e81578251825591602001919060010190612e66565b50612a869291505b5b80821115612a865760008155600101612e8a565b80356001600160a01b0381168114612eb557600080fd5b919050565b6001600160401b03811681146119d957600080fd5b600080600080600060a08688031215612ee757600080fd5b8535945060208601359350612efe60408701612e9e565b92506060860135612f0e81612eba565b949793965091946080013592915050565b600060208284031215612f3157600080fd5b5035919050565b600060208284031215612f4a57600080fd5b61142882612e9e565b600080600060608486031215612f6857600080fd5b8335925060208401359150612f7f60408501612e9e565b90509250925092565b80151581146119d957600080fd5b60008060008060808587031215612fac57600080fd5b8435935060208501359250612fc360408601612e9e565b91506060850135612fd381612f88565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561301c5761301c612fde565b604052919050565b60006001600160401b0382111561303d5761303d612fde565b5060051b60200190565b600082601f83011261305857600080fd5b8135602061306d61306883613024565b612ff4565b8083825260208201915060208460051b87010193508684111561308f57600080fd5b602086015b848110156130ab5780358352918301918301613094565b509695505050505050565b600080604083850312156130c957600080fd5b8235915060208301356001600160401b038111156130e657600080fd5b6130f285828601613047565b9150509250929050565b6000806000806080858703121561311257600080fd5b84359350602080860135935060408601356001600160401b038082111561313857600080fd5b818801915088601f83011261314c57600080fd5b813561315a61306882613024565b81815260059190911b8301840190848101908b83111561317957600080fd5b938501935b8285101561319e5761318f85612e9e565b8252938501939085019061317e565b9650505060608801359250808311156131b657600080fd5b50506131c487828801613047565b91505092959194509250565b600080604083850312156131e357600080fd5b6131ec83612e9e565b915060208301356131fc81612f88565b809150509250929050565b6000806000806080858703121561321d57600080fd5b61322685612e9e565b966020860135965060408601359560600135945092505050565b60008060008060006080868803121561325857600080fd5b8535945060208601356001600160401b038082111561327657600080fd5b818801915088601f83011261328a57600080fd5b81358181111561329957600080fd5b8960208285010111156132ab57600080fd5b6020830196508095505050506040860135915060608601356132cc81612f88565b809150509295509295909350565b600080600083850360e08112156132f057600080fd5b843593506020850135925060a0603f198201121561330d57600080fd5b506040840190509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561335357835183529284019291840191600101613337565b50909695505050505050565b6000806040838503121561337257600080fd5b50508035926020909101359150565b6000806020838503121561339457600080fd5b82356001600160401b03808211156133ab57600080fd5b818501915085601f8301126133bf57600080fd5b8135818111156133ce57600080fd5b8660208260051b85010111156133e357600080fd5b60209290920196919550909350505050565b60005b838110156134105781810151838201526020016133f8565b50506000910152565b600081518084526134318160208601602086016133f5565b601f01601f19169290920160200192915050565b60a08152600061345860a0830188613419565b60208301969096525060408101939093529015156060830152608090910152919050565b6000806000806080858703121561349257600080fd5b84359350602085013592506134a960408601612e9e565b91506134b760608601612e9e565b905092959194509250565b600080600080608085870312156134d857600080fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156135335761353361350a565b92915050565b818103818111156135335761353361350a565b6001600160401b0382811682821603908082111561356c5761356c61350a565b5092915050565b6001600160401b0381811683821601908082111561356c5761356c61350a565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806135c3576135c3613593565b92169190910492915050565b60006001600160401b03808416806135e9576135e9613593565b92169190910692915050565b80820281158282048414176135335761353361350a565b60008261361b5761361b613593565b500490565b92835260208301919091526001600160a01b0316604082015260600190565b60006020828403121561365157600080fd5b5051919050565b6001600160401b0381811683821602808216919082811461367b5761367b61350a565b505092915050565b600181811c9082168061369757607f821691505b602082108103610aa457634e487b7160e01b600052602260045260246000fd5b601f8211156129a4576000816000526020600020601f850160051c810160208610156136e05750805b601f850160051c820191505b818110156136ff578281556001016136ec565b505050505050565b81516001600160401b0381111561372057613720612fde565b6137348161372e8454613683565b846136b7565b602080601f83116001811461376957600084156137515750858301515b600019600386901b1c1916600185901b1785556136ff565b600085815260208120601f198616915b8281101561379857888601518255948401946001909101908401613779565b50858210156137b65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b818103600083128015838313168383128216171561356c5761356c61350a565b6001600160401b038311156137fd576137fd612fde565b6138118361380b8354613683565b836136b7565b6000601f841160018114613845576000851561382d5750838201355b600019600387901b1c1916600186901b178355611115565b600083815260209020601f19861690835b828110156138765786850135825560209485019460019092019101613856565b50868210156138935760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b606081528360608201528385608083013760006080858301015260006080601f19601f8701168301019050836020830152821515604083015295945050505050565b6000602082840312156138f957600080fd5b813561142881612eba565b6000813561353381612eba565b813561391c81612eba565b815467ffffffffffffffff19166001600160401b03821617825550602082013561394581612eba565b81546fffffffffffffffff0000000000000000604092831b166fffffffffffffffff0000000000000000198216811784559184013561398381612eba565b67ffffffffffffffff60801b60809190911b1677ffffffffffffffffffffffffffffffff000000000000000019821683178117845560608501356139c681612eba565b6001600160401b0360c01b8160c01b16846001600160401b03851617831717855550505050612e246139fa60808401613904565b600183016001600160401b0382166001600160401b03198254161781555050565b60a081018235613a2a81612eba565b6001600160401b039081168352602084013590613a4682612eba565b9081166020840152604084013590613a5d82612eba565b9081166040840152606084013590613a7482612eba565b9081166060840152608084013590613a8b82612eba565b8082166080850152505092915050565b6000808335601e19843603018112613ab257600080fd5b8301803591506001600160401b03821115613acc57600080fd5b602001915036819003821315613ae157600080fd5b9250929050565b8183823760009101908152919050565b600060208284031215613b0a57600080fd5b81516001600160401b0380821115613b2157600080fd5b818401915084601f830112613b3557600080fd5b815181811115613b4757613b47612fde565b613b5a601f8201601f1916602001612ff4565b9150808252856020828501011115613b7157600080fd5b613b828160208401602086016133f5565b50949350505050565b6020815260006114286020830184613419565b600060208284031215613bb057600080fd5b815161142881612f88565b60008251613bcd8184602087016133f5565b919091019291505056fea2646970667358221220830f4c15214df0150645cede5a39e95078ac7f327345969a1b33dfd92d2a098164736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca0000000000000000000000000000000000000000000000000000000066659940
-----Decoded View---------------
Arg [0] : _trufToken (address): 0x38C2a4a7330b22788374B8Ff70BBa513C8D848cA
Arg [1] : _tgeTime (uint64): 1717934400
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca
Arg [1] : 0000000000000000000000000000000000000000000000000000000066659940
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.