Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 23 from a total of 23 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw Tokens | 24491333 | 4 days ago | IN | 0 ETH | 0.00008906 | ||||
| Set Referral Rew... | 24491144 | 4 days ago | IN | 0 ETH | 0.00000406 | ||||
| Set Active Round | 24491022 | 4 days ago | IN | 0 ETH | 0.00021772 | ||||
| Add Round | 24491005 | 4 days ago | IN | 0 ETH | 0.00034039 | ||||
| Deactivate Activ... | 24490921 | 4 days ago | IN | 0 ETH | 0.00007233 | ||||
| Set Active Round | 24489974 | 5 days ago | IN | 0 ETH | 0.00026619 | ||||
| Edit Round | 24489965 | 5 days ago | IN | 0 ETH | 0.00013018 | ||||
| Add Round | 24489962 | 5 days ago | IN | 0 ETH | 0.00041162 | ||||
| Add Round | 24489901 | 5 days ago | IN | 0 ETH | 0.00041282 | ||||
| Edit Round | 24489900 | 5 days ago | IN | 0 ETH | 0.00014507 | ||||
| Sync Active Roun... | 24489899 | 5 days ago | IN | 0 ETH | 0.00006106 | ||||
| Edit Round | 24489894 | 5 days ago | IN | 0 ETH | 0.00014509 | ||||
| Edit Round | 24489890 | 5 days ago | IN | 0 ETH | 0.00014529 | ||||
| Edit Round | 24489887 | 5 days ago | IN | 0 ETH | 0.00013784 | ||||
| Add Round | 24489881 | 5 days ago | IN | 0 ETH | 0.0004108 | ||||
| Deactivate Activ... | 24489724 | 5 days ago | IN | 0 ETH | 0.00008499 | ||||
| Set Active Round | 24483929 | 5 days ago | IN | 0 ETH | 0.00026697 | ||||
| Edit Round | 24483889 | 5 days ago | IN | 0 ETH | 0.00013773 | ||||
| Edit Round | 24483881 | 5 days ago | IN | 0 ETH | 0.0001306 | ||||
| Edit Round | 24483879 | 5 days ago | IN | 0 ETH | 0.00013784 | ||||
| Add Round | 24483864 | 5 days ago | IN | 0 ETH | 0.00045441 | ||||
| Transfer Ownersh... | 24483677 | 5 days ago | IN | 0 ETH | 0.0000617 | ||||
| Transfer Ownersh... | 24477219 | 6 days ago | IN | 0 ETH | 0.00006307 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Presale
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title Presale Contract
/// @notice Referral system is intentionally irreversible and owner-controlled.
/// @dev Design decisions:
/// - Referrer can be set only once and cannot be changed
/// - Owner can disable or reactivate referrals
/// - Referral removal permanently disables future rewards
/// This introduces intentional centralized control and is not a vulnerability.
contract Presale is ReentrancyGuard, Pausable, Ownable {
using SafeERC20 for IERC20Metadata;
IERC20Metadata public immutable presaleToken;
IERC20Metadata public immutable usdcToken;
IERC20Permit public immutable usdcPermit;
address public liqHolder;
uint256 public minPurchaseTokens;
uint256 public totalRounds;
uint256 public nextRoundId = 1;
uint256 public constant MAX_REFERRAL_DEPTH = 10;
uint256 public activeRoundId;
uint256 public constant PERCENTAGE_BASE = 10000;
uint256 public referralRewardPercentage = 100;
bool public referralRewardsEnabled = true;
uint256 public totalReferralRewardsGiven = 0;
uint256 public referralCapPercentage = 500;
uint256 public maxReferralRewardsCap;
uint8 public immutable tokenDecimals;
uint8 public immutable usdcDecimals;
address public timelock;
uint256 public totalTokensSold;
uint256 public maxRoundDuration;
/// @notice TIMING FIX: Minimum delay before a round can start (prevents same-block DoS)
uint256 public constant MINIMUM_ACTIVATION_DELAY = 60; // 60 seconds minimum delay
/// @notice Track only active round allocation (not cumulative)
uint256 public activeRoundUnsoldAllocation;
/// @notice Single flag to prevent referrer reassignment
mapping(address => bool) public referrerLocked;
/// @notice Track admin-deactivated referrals
mapping(address => mapping(address => bool)) public adminDeactivated;
enum RoundState {
Pending,
Active,
Ended
}
struct User {
uint256 totalPurchased;
uint256 totalDepositUSDC;
uint256 totalReferralRewards;
uint256 referralCount;
address referrer;
}
struct Round {
uint256 roundId;
uint256 startTime;
uint256 endTime;
uint256 tokenPriceUSDC;
uint256 tokensSold;
uint256 cap;
RoundState state;
}
/// @notice Single source of truth for referral data
struct ReferralInfo {
address referee;
uint256 referredDate;
bool isActive;
uint256 firstPurchaseDate;
// arrayIndex removed - redundant with referralInfoIndex mapping
}
mapping(address => User) public usersInfo;
mapping(uint256 => Round) public rounds;
/// @notice Single referral data structure with proper indexing
mapping(address => ReferralInfo[]) public referralInfoList;
mapping(address => mapping(address => uint256)) private referralInfoIndex; // 1-based index
address[] public referrersList;
mapping(address => bool) public isReferrer;
event RoundAdded(uint256 indexed roundId, uint256 startTime, uint256 endTime, uint256 price, uint256 cap);
event RoundEdited(
uint256 indexed roundId,
uint256 startTime,
uint256 endTime,
uint256 price,
RoundState state,
uint256 cap
);
event TokensPurchased(address indexed buyer, uint256 indexed roundId, uint256 usdcAmount, uint256 tokensBought);
event ReferralRewardPaid(address indexed referrer, address indexed referee, uint256 rewardAmount, uint256 roundId);
event ReferralRewardCapped(address indexed referrer, address indexed referee, uint256 intendedReward, uint256 actualReward);
event ReferralSet(address indexed user, address indexed referrer);
event RoundActivated(uint256 indexed roundId);
event RoundEnded(uint256 indexed roundId);
event ReferralStatusUpdated(address indexed referrer, address indexed referee, bool isActive, uint256 firstPurchaseDate);
event ReferralReactivated(address indexed referrer, address indexed referee);
event ReferralRemoved(address indexed referrer, address indexed referee);
event LiqHolderUpdated(address newLiqHolder);
event Withdraw(address to, uint256 amount);
event TokensRescued(address indexed token, address indexed to, uint256 amount);
event ActiveRoundAllocationUpdated(uint256 newAllocation);
event MinimumActivationDelayUpdated(uint256 newDelay);
modifier onlyOwnerOrTimelock() {
require(msg.sender == owner() || msg.sender == timelock, "Presale: caller is not owner or timelock");
_;
}
constructor(address _liqHolder, address _usdcToken, address _token) Ownable(msg.sender) {
require(_token != address(0), "Presale: Invalid token address");
require(_liqHolder != address(0) && _usdcToken != address(0), "Presale: Invalid address");
require(!_hasCode(_liqHolder), "Presale: liqHolder cannot be a contract");
presaleToken = IERC20Metadata(_token);
usdcToken = IERC20Metadata(_usdcToken);
usdcPermit = IERC20Permit(_usdcToken);
liqHolder = _liqHolder;
uint8 _tokenDecimals = presaleToken.decimals();
uint8 _usdcDecimals = usdcToken.decimals();
require(_tokenDecimals <= 18, "Presale: Token decimals must be <= 18");
require(_usdcDecimals <= 18, "Presale: USDC decimals must be <= 18");
tokenDecimals = _tokenDecimals;
usdcDecimals = _usdcDecimals;
maxRoundDuration = 90 days;
minPurchaseTokens = 100 * (10 ** _tokenDecimals);
_updateReferralCap();
}
/// @notice Referrer assignment is one-time and permanently locked.
/// @dev Once set or skipped, referrer cannot be changed under any circumstance.
function _assignReferrer(address _buyer, address _referrer) internal {
// If no referrer provided or already locked, return
if (_referrer == address(0)) {
if (!referrerLocked[_buyer]) {
referrerLocked[_buyer] = true; // Lock with no referrer
}
return;
}
// Prevent reassignment
if (referrerLocked[_buyer]) {
if (usersInfo[_buyer].referrer == _referrer) {
return; // Same referrer, OK
}
revert("Presale: Referrer already locked");
}
// Validation
require(_referrer != _buyer, "Presale: Cannot refer yourself");
require(!_hasCode(_buyer), "Presale: Buyer cannot be a contract");
require(!_hasCode(_referrer), "Presale: Referrer cannot be a contract");
require(!_wouldCreateReferralCycle(_buyer, _referrer), "Presale: Referral cycle detected");
// Revert if admin deactivated this relationship
require(!adminDeactivated[_referrer][_buyer], "Presale: Referral deactivated by admin");
// Set referrer and lock
usersInfo[_buyer].referrer = _referrer;
referrerLocked[_buyer] = true;
// Update single source of truth with proper indexing
ReferralInfo memory newReferral = ReferralInfo({
referee: _buyer,
referredDate: block.timestamp,
isActive: false,
firstPurchaseDate: 0
});
referralInfoList[_referrer].push(newReferral);
// Use 1-based indexing (0 means not found)
referralInfoIndex[_referrer][_buyer] = referralInfoList[_referrer].length;
if (!isReferrer[_referrer]) {
isReferrer[_referrer] = true;
referrersList.push(_referrer);
}
emit ReferralSet(_buyer, _referrer);
}
/// @notice Returns active referrer or activates on first purchase
/// @return referrer address if active and valid, address(0) otherwise
function _getOrActivateReferrer(address _buyer) internal returns (address) {
address referrer = usersInfo[_buyer].referrer;
// No referrer assigned
if (referrer == address(0)) return address(0);
// Rewards disabled globally
if (!referralRewardsEnabled || referralRewardPercentage == 0) return address(0);
// Admin deactivated
if (adminDeactivated[referrer][_buyer]) return address(0);
uint256 index = referralInfoIndex[referrer][_buyer];
if (index == 0) return address(0); // Not in list
ReferralInfo storage refInfo = referralInfoList[referrer][index - 1];
// Activate on first purchase if not yet active
if (!refInfo.isActive) {
refInfo.isActive = true;
refInfo.firstPurchaseDate = block.timestamp;
emit ReferralStatusUpdated(referrer, _buyer, true, block.timestamp);
}
return referrer;
}
function _normalizeDecimals(uint256 amount, uint8 fromDecimals, uint8 toDecimals) internal pure returns (uint256) {
if (fromDecimals == toDecimals) return amount;
if (fromDecimals < toDecimals) return amount * (10 ** (toDecimals - fromDecimals));
return amount / (10 ** (fromDecimals - toDecimals));
}
function _calculateTokenAmount(uint256 _usdcAmount, uint256 _priceUSDC) internal view returns (uint256) {
require(_usdcAmount > 0 && _priceUSDC > 0, "Presale: Invalid amounts");
uint256 usdcAmount18 = _normalizeDecimals(_usdcAmount, usdcDecimals, 18);
return (usdcAmount18 * (10 ** tokenDecimals)) / _priceUSDC;
}
function _hasCode(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function _wouldCreateReferralCycle(address user, address referrer)
internal view returns (bool)
{
address current = referrer;
// @dev Allow chains up to MAX_REFERRAL_DEPTH inclusive
for (uint256 i = 0; i <= MAX_REFERRAL_DEPTH; i++) {
if (current == address(0)) return false;
if (current == user) return true;
current = usersInfo[current].referrer;
}
return true; // Exceeded allowed depth
}
/// @notice Sync active round and update allocation
function _syncRoundState(uint256 _roundId) internal {
if (_roundId == 0) return;
Round storage r = rounds[_roundId];
if (
r.state == RoundState.Active &&
(block.timestamp > r.endTime || r.tokensSold >= r.cap)
) {
r.state = RoundState.Ended;
activeRoundId = 0;
activeRoundUnsoldAllocation = 0;
emit ActiveRoundAllocationUpdated(0);
emit RoundEnded(_roundId);
}
}
function _buyWithUsdc(uint256 _usdcAmount, address _referrer) private {
Round storage round = _getActiveRoundForPurchase();
require(_usdcAmount > 0, "Presale: Amount must be > 0");
require(
usdcToken.allowance(msg.sender, address(this)) >= _usdcAmount,
"Presale: Insufficient allowance"
);
uint256 tokensToBuy = _calculateTokenAmount(_usdcAmount, round.tokenPriceUSDC);
require(tokensToBuy >= minPurchaseTokens, "Presale: Below minimum purchase");
// USDC goes directly to liquidity holder
usdcToken.safeTransferFrom(msg.sender, liqHolder, _usdcAmount);
usersInfo[msg.sender].totalDepositUSDC += _usdcAmount;
// Assign referrer (one-time)
_assignReferrer(msg.sender, _referrer);
// All cap + referral logic handled here
_purchaseTokens(msg.sender, round, tokensToBuy, _usdcAmount);
}
/// @notice FIX: Corrected purchase logic addressing both CertiK findings
/// @dev Changes:
/// 1. Calculate actual referral reward (after global cap) BEFORE round cap check
/// 2. Validate inventory BEFORE any token transfers
function _purchaseTokens(
address _buyer,
Round storage _round,
uint256 _tokensToBuy,
uint256 _usdcAmount
) private {
// STEP 1: Get or activate referrer
address activeReferrer = _getOrActivateReferrer(_buyer);
// STEP 2: Calculate intended referral reward
uint256 intendedReward = 0;
if (activeReferrer != address(0)) {
intendedReward = (_tokensToBuy * referralRewardPercentage) / PERCENTAGE_BASE;
}
// STEP 3: Apply global referral cap to get ACTUAL referral reward
// FIX #1: Calculate the actual reward amount considering global cap
uint256 referralReward = 0;
if (activeReferrer != address(0) && intendedReward > 0) {
uint256 projected = totalReferralRewardsGiven + intendedReward;
if (projected > maxReferralRewardsCap) {
// Cap the reward to what's remaining in global cap
intendedReward = maxReferralRewardsCap > totalReferralRewardsGiven
? maxReferralRewardsCap - totalReferralRewardsGiven
: 0;
}
referralReward = intendedReward;
}
// STEP 4: Enforce round cap using ACTUAL referral reward (not intended)
// FIX #1: Now using the actual referralReward after global cap adjustment
require(
_round.tokensSold + _tokensToBuy + referralReward <= _round.cap,
"Presale: Exceeds round cap including referral rewards"
);
// STEP 5: Total distributed = buyer + actual referral
uint256 totalDistributed = _tokensToBuy + referralReward;
// STEP 6: Ensure contract has enough tokens BEFORE any transfers
// FIX #2: Check balance before transfers, not after
require(
presaleToken.balanceOf(address(this)) >= totalDistributed,
"Presale: Insufficient balance"
);
// STEP 7: Transfer tokens to buyer
presaleToken.safeTransfer(_buyer, _tokensToBuy);
// STEP 8: Transfer referral reward if applicable
if (referralReward > 0) {
usersInfo[activeReferrer].totalReferralRewards += referralReward;
usersInfo[activeReferrer].referralCount++;
totalReferralRewardsGiven += referralReward;
presaleToken.safeTransfer(activeReferrer, referralReward);
emit ReferralRewardPaid(
activeReferrer,
_buyer,
referralReward,
_round.roundId
);
}
// STEP 9: Update round + global accounting
_round.tokensSold += totalDistributed;
usersInfo[_buyer].totalPurchased += _tokensToBuy;
totalTokensSold += totalDistributed;
// STEP 10: Update active round allocation
require(
activeRoundUnsoldAllocation >= totalDistributed,
"Presale: Insufficient round allocation"
);
activeRoundUnsoldAllocation -= totalDistributed;
emit ActiveRoundAllocationUpdated(activeRoundUnsoldAllocation);
// STEP 11: Emit purchase event
emit TokensPurchased(
_buyer,
_round.roundId,
_usdcAmount,
_tokensToBuy
);
}
function buyWithUsdc(uint256 _usdcAmount) external nonReentrant whenNotPaused {
syncActiveRound();
_buyWithUsdc(_usdcAmount, address(0));
}
function buyWithUsdcWithReferral(uint256 _usdcAmount, address _referrer) external nonReentrant whenNotPaused {
syncActiveRound();
_buyWithUsdc(_usdcAmount, _referrer);
}
function buyWithUsdcPermit(uint256 _usdcAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external nonReentrant whenNotPaused
{
require(deadline >= block.timestamp, "Presale: Permit expired");
syncActiveRound();
_buyWithUsdcPermit(_usdcAmount, address(0), deadline, v, r, s);
}
function buyWithUsdcPermitWithReferral(uint256 _usdcAmount, address _referrer, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external nonReentrant whenNotPaused
{
require(deadline >= block.timestamp, "Presale: Permit expired");
syncActiveRound();
_buyWithUsdcPermit(_usdcAmount, _referrer, deadline, v, r, s);
}
function _buyWithUsdcPermit(uint256 _usdcAmount, address _referrer, uint256 deadline, uint8 v, bytes32 r, bytes32 s) private {
usdcPermit.permit(msg.sender, address(this), _usdcAmount, deadline, v, r, s);
_buyWithUsdc(_usdcAmount, _referrer);
}
/// @notice TIMING FIX: Add round without immediate activation option
/// @dev Rounds must be created with sufficient buffer before start time
function addRound(
uint256 _startTime,
uint256 _endTime,
uint256 _tokenPriceUSDC,
uint256 _cap
) external onlyOwner {
uint256 _roundId = nextRoundId++;
require(rounds[_roundId].roundId == 0, "Presale: Round exists");
require(_startTime < _endTime && _tokenPriceUSDC > 0 && _cap > 0, "Presale: Invalid params");
// TIMING FIX: Enforce minimum delay before round can start
require(
_startTime > block.timestamp + MINIMUM_ACTIVATION_DELAY,
"Presale: Start time must be after minimum delay"
);
require(_endTime > block.timestamp, "Presale: Invalid time");
require(_endTime - _startTime <= maxRoundDuration, "Presale: Duration exceeds max");
// Only check direct balance vs cap (no cross-round accounting)
uint256 contractBal = presaleToken.balanceOf(address(this));
require(_cap <= contractBal, "Presale: Insufficient inventory");
// if (_roundId > 1) {
// require(
// _startTime > rounds[_roundId - 1].endTime,
// "Presale: Round time must be strictly increasing"
// );
// }
rounds[_roundId] = Round({
roundId: _roundId,
startTime: _startTime,
endTime: _endTime,
tokenPriceUSDC: _tokenPriceUSDC,
tokensSold: 0,
cap: _cap,
state: RoundState.Pending
});
totalRounds++;
emit RoundAdded(_roundId, _startTime, _endTime, _tokenPriceUSDC, _cap);
}
function editRound(uint256 _roundId, uint256 _startTime, uint256 _endTime, uint256 _tokenPriceUSDC, uint256 _cap) external onlyOwner {
_editRoundInternal(_roundId, _startTime, _endTime, _tokenPriceUSDC, _cap);
}
function _editRoundInternal(
uint256 _roundId,
uint256 _startTime,
uint256 _endTime,
uint256 _tokenPriceUSDC,
uint256 _cap
) internal {
require(rounds[_roundId].roundId != 0, "Presale: Round not found");
_syncRoundState(_roundId);
Round storage round = rounds[_roundId];
require(
round.state == RoundState.Pending,
"Presale: Only pending rounds editable"
);
require(_startTime < _endTime && _tokenPriceUSDC > 0 && _cap > 0, "Presale: Invalid params");
// TIMING FIX: Enforce minimum delay for edited rounds too
require(
_startTime > block.timestamp + MINIMUM_ACTIVATION_DELAY,
"Presale: Start time must be after minimum delay"
);
require(_endTime - _startTime <= maxRoundDuration, "Presale: Duration exceeds max");
require(_cap >= round.tokensSold, "Presale: Cap below sold tokens");
// Only check direct balance vs new cap (stateless, local)
uint256 contractBal = presaleToken.balanceOf(address(this));
require(_cap <= contractBal, "Presale: Insufficient inventory");
round.cap = _cap;
round.startTime = _startTime;
round.endTime = _endTime;
round.tokenPriceUSDC = _tokenPriceUSDC;
emit RoundEdited(
_roundId,
_startTime,
_endTime,
_tokenPriceUSDC,
round.state,
_cap
);
}
/// @notice TIMING FIX: Separate activation function with proper timing checks
/// @dev Can only activate a pending round within its valid time window
function setActiveRound(uint256 _roundId) external onlyOwner {
require(_roundId > 0 && _roundId < nextRoundId, "Presale: Invalid round id");
Round storage r = rounds[_roundId];
// Enforce monotonic lifecycle - only PENDING rounds can be activated
require(r.state == RoundState.Pending, "Presale: Round already used");
// TIMING FIX: More flexible activation window
// Allow activation if we're past the minimum delay but before end time
require(
block.timestamp >= r.startTime - MINIMUM_ACTIVATION_DELAY &&
block.timestamp <= r.endTime,
"Presale: Round timing invalid for activation"
);
// End currently active round permanently
if (activeRoundId != 0) {
Round storage prev = rounds[activeRoundId];
prev.state = RoundState.Ended;
emit RoundEnded(activeRoundId);
}
// Activate new round
r.state = RoundState.Active;
activeRoundId = _roundId;
// Set allocation strictly from this round
activeRoundUnsoldAllocation = r.cap - r.tokensSold;
emit ActiveRoundAllocationUpdated(activeRoundUnsoldAllocation);
emit RoundActivated(_roundId);
}
/// @notice Clear allocation when deactivating
function deactivateActiveRound() external onlyOwner {
require(activeRoundId != 0, "Presale: No active round");
uint256 old = activeRoundId;
Round storage r = rounds[old];
r.state = RoundState.Ended; // permanently ended
activeRoundId = 0;
activeRoundUnsoldAllocation = 0;
emit ActiveRoundAllocationUpdated(0);
emit RoundEnded(old);
}
function syncActiveRound() public {
if (activeRoundId == 0) return;
Round storage r = rounds[activeRoundId];
if (
r.state == RoundState.Active &&
(block.timestamp > r.endTime || r.tokensSold >= r.cap)
) {
r.state = RoundState.Ended;
activeRoundId = 0;
activeRoundUnsoldAllocation = 0;
emit ActiveRoundAllocationUpdated(0);
emit RoundEnded(r.roundId);
}
}
function _getActiveRoundForPurchase() internal view returns (Round storage) {
require(activeRoundId != 0, "Presale: No active round");
Round storage r = rounds[activeRoundId];
require(
r.state == RoundState.Active &&
block.timestamp >= r.startTime &&
block.timestamp <= r.endTime &&
r.tokensSold < r.cap,
"Presale: Round unavailable"
);
return r;
}
/// @notice Owner can disable a referral relationship.
/// @dev Future rewards will stop; this is a centralized design choice.
function deactivateReferral(address _referrer, address _referee) external onlyOwner {
require(usersInfo[_referee].referrer == _referrer, "Presale: Invalid relationship");
uint256 index = referralInfoIndex[_referrer][_referee];
require(index > 0, "Presale: Referral not found");
ReferralInfo storage info = referralInfoList[_referrer][index - 1];
require(info.referee == _referee, "Presale: Index mismatch");
info.isActive = false;
adminDeactivated[_referrer][_referee] = true;
emit ReferralStatusUpdated(_referrer, _referee, false, 0);
}
/// @notice Admin can reactivate previously deactivated referral
function reactivateReferral(address _referrer, address _referee) external onlyOwner {
require(usersInfo[_referee].referrer == _referrer, "Presale: Invalid relationship");
require(adminDeactivated[_referrer][_referee], "Presale: Not deactivated");
uint256 index = referralInfoIndex[_referrer][_referee];
require(index > 0, "Presale: Referral not found");
ReferralInfo storage info = referralInfoList[_referrer][index - 1];
info.isActive = true;
adminDeactivated[_referrer][_referee] = false;
emit ReferralReactivated(_referrer, _referee);
emit ReferralStatusUpdated(_referrer, _referee, true, info.firstPurchaseDate);
}
/// @notice Permanently disables referral rewards for a referee.
/// @dev Does NOT allow referrer reassignment.
/// This behavior is intentional and owner-controlled.
function removeReferral(address _referrer, address _referee) external onlyOwner {
require(usersInfo[_referee].referrer == _referrer, "Presale: Invalid relationship");
uint256 index = referralInfoIndex[_referrer][_referee];
require(index > 0, "Presale: Referral not found");
ReferralInfo[] storage list = referralInfoList[_referrer];
uint256 arrayIndex = index - 1;
uint256 lastIndex = list.length - 1;
if (arrayIndex != lastIndex) {
ReferralInfo storage lastRef = list[lastIndex];
list[arrayIndex] = lastRef;
// Update mapping to reflect new position (1-based index)
referralInfoIndex[_referrer][lastRef.referee] = arrayIndex + 1;
}
list.pop();
delete referralInfoIndex[_referrer][_referee];
// Full state cleanup
usersInfo[_referee].referrer = address(0);
adminDeactivated[_referrer][_referee] = false;
emit ReferralRemoved(_referrer, _referee);
}
function setMinPurchaseTokens(uint256 _amount) external onlyOwner {
require(_amount > 0, "Presale: Invalid min");
minPurchaseTokens = _amount;
}
function updateLiqHolder(address newLiqHolder) external onlyOwnerOrTimelock {
require(newLiqHolder != address(0) && !_hasCode(newLiqHolder), "Presale: Invalid");
liqHolder = newLiqHolder;
emit LiqHolderUpdated(newLiqHolder);
}
function setTimelock(address _timelock) external onlyOwner {
require(_timelock != address(0), "Presale: Invalid timelock");
timelock = _timelock;
}
function setReferralRewardPercentage(uint256 _percentage) external onlyOwner {
require(_percentage <= 2000, "Presale: Max 20%");
referralRewardPercentage = _percentage;
}
function setReferralRewardsEnabled(bool _enabled) external onlyOwner {
referralRewardsEnabled = _enabled;
}
function setReferralCapPercentage(uint256 _percentage) external onlyOwner {
require(_percentage <= 2000, "Presale: Max 20%");
referralCapPercentage = _percentage;
_updateReferralCap();
}
function setReferralCapManual(uint256 _cap) external onlyOwner {
require(_cap > 0 && _cap >= totalReferralRewardsGiven, "Presale: Invalid cap");
maxReferralRewardsCap = _cap;
}
function _updateReferralCap() internal {
uint256 totalSupply = presaleToken.totalSupply();
uint256 newCap = (totalSupply * referralCapPercentage) / PERCENTAGE_BASE;
require(newCap >= totalReferralRewardsGiven, "Presale: Cap below distributed");
maxReferralRewardsCap = newCap;
}
function setMaxRoundDuration(uint256 _newDuration) external onlyOwner {
require(_newDuration > 0 && _newDuration <= 180 days, "Presale: Invalid duration");
require(activeRoundId == 0, "Presale: Cannot change during active round");
maxRoundDuration = _newDuration;
}
function pause() external onlyOwner { _pause(); }
function unpause() external onlyOwner { _unpause(); }
function withdrawTokens(address _to, uint256 _amount) external onlyOwnerOrTimelock nonReentrant {
require(_to != address(0), "Presale: Invalid address");
uint256 bal = presaleToken.balanceOf(address(this));
require(bal >= _amount, "Presale: Insufficient balance");
presaleToken.safeTransfer(_to, _amount);
emit Withdraw(_to, _amount);
}
/// @notice USDC rescue works because USDC never stays in contract
/// @dev USDC is sent directly to liqHolder, so no conflict with totalUSDCDeposited
function rescueERC20(address token, address to, uint256 amount) external onlyOwnerOrTimelock nonReentrant {
require(to != address(0), "Presale: Invalid address");
require(token != address(presaleToken), "Presale: Cannot rescue presale token");
IERC20 t = IERC20(token);
uint256 bal = t.balanceOf(address(this));
require(amount <= bal, "Presale: Insufficient balance");
SafeERC20.safeTransfer(t, to, amount);
emit TokensRescued(token, to, amount);
}
/// @notice Can only set referrer once, before first purchase
/// @dev Prevents deferred referrer selection and secondary referral markets
function setReferrer(address _referrer) external {
require(_referrer != address(0), "Presale: Invalid referrer");
require(!referrerLocked[msg.sender], "Presale: Referrer already locked");
require(usersInfo[msg.sender].totalPurchased == 0, "Presale: Cannot set after purchase");
_assignReferrer(msg.sender, _referrer);
}
// ============ VIEW FUNCTIONS ============
function getActiveRound() public view returns (Round memory) {
require(activeRoundId != 0, "Presale: No active round");
return rounds[activeRoundId];
}
function getRoundInfo(uint256 _roundId) external view returns (Round memory) {
require(rounds[_roundId].roundId != 0, "Presale: Round not found");
return rounds[_roundId];
}
function isReferralCapReached() public view returns (bool) {
return totalReferralRewardsGiven >= maxReferralRewardsCap;
}
function getRemainingReferralRewards() public view returns (uint256) {
return totalReferralRewardsGiven >= maxReferralRewardsCap
? 0
: maxReferralRewardsCap - totalReferralRewardsGiven;
}
function getReferralCount(address _referrer) external view returns (uint256) {
return referralInfoList[_referrer].length;
}
/// @notice Single source of truth for referral info
function getReferralInfo(address _referrer, address _referee) external view returns (
address referee,
uint256 referredDate,
bool isActive,
uint256 firstPurchaseDate
) {
uint256 index = referralInfoIndex[_referrer][_referee];
require(index > 0, "Presale: Referral not found");
ReferralInfo memory info = referralInfoList[_referrer][index - 1];
require(info.referee == _referee, "Presale: Invalid mapping");
return (info.referee, info.referredDate, info.isActive, info.firstPurchaseDate);
}
function getReferralStatusCounts(address _referrer) external view returns (
uint256 totalReferrals,
uint256 activeReferrals,
uint256 inactiveReferrals
) {
ReferralInfo[] memory infos = referralInfoList[_referrer];
totalReferrals = infos.length;
for (uint256 i = 0; i < infos.length; i++) {
if (infos[i].isActive) {
activeReferrals++;
} else {
inactiveReferrals++;
}
}
return (totalReferrals, activeReferrals, inactiveReferrals);
}
function getAllActiveReferrers() external view onlyOwner returns (
address[] memory referrers,
uint256[] memory totalRewards,
uint256[] memory referralCounts
) {
uint256 count = referrersList.length;
referrers = new address[](count);
totalRewards = new uint256[](count);
referralCounts = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
address referrer = referrersList[i];
referrers[i] = referrer;
totalRewards[i] = usersInfo[referrer].totalReferralRewards;
referralCounts[i] = referralInfoList[referrer].length;
}
return (referrers, totalRewards, referralCounts);
}
function getTotalReferrersCount() external view returns (uint256) {
return referrersList.length;
}
/// @notice Check if a user's referrer is locked (cannot be changed)
function isReferrerLocked(address _user) external view returns (bool) {
return referrerLocked[_user];
}
/// @notice Get the current active round allocation (unsold tokens)
function getActiveRoundAllocation() external view returns (uint256) {
return activeRoundUnsoldAllocation;
}
/// @notice Check if a referral has been admin-deactivated
function isAdminDeactivated(address _referrer, address _referee) external view returns (bool) {
return adminDeactivated[_referrer][_referee];
}
/// @notice Get the minimum activation delay constant
function getMinimumActivationDelay() external pure returns (uint256) {
return MINIMUM_ACTIVATION_DELAY;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @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 {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_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 v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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 v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_liqHolder","type":"address"},{"internalType":"address","name":"_usdcToken","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newAllocation","type":"uint256"}],"name":"ActiveRoundAllocationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newLiqHolder","type":"address"}],"name":"LiqHolderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"MinimumActivationDelayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"}],"name":"ReferralReactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"}],"name":"ReferralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":false,"internalType":"uint256","name":"intendedReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualReward","type":"uint256"}],"name":"ReferralRewardCapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"ReferralRewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"}],"name":"ReferralSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"referee","type":"address"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"},{"indexed":false,"internalType":"uint256","name":"firstPurchaseDate","type":"uint256"}],"name":"ReferralStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"RoundActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"RoundAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"enum Presale.RoundState","name":"state","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"RoundEdited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"}],"name":"RoundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBought","type":"uint256"}],"name":"TokensPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensRescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAX_REFERRAL_DEPTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_ACTIVATION_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENTAGE_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeRoundId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeRoundUnsoldAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"uint256","name":"_tokenPriceUSDC","type":"uint256"},{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"addRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"adminDeactivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usdcAmount","type":"uint256"}],"name":"buyWithUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usdcAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"buyWithUsdcPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usdcAmount","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"buyWithUsdcPermitWithReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usdcAmount","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"buyWithUsdcWithReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deactivateActiveRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_referee","type":"address"}],"name":"deactivateReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"uint256","name":"_endTime","type":"uint256"},{"internalType":"uint256","name":"_tokenPriceUSDC","type":"uint256"},{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"editRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getActiveRound","outputs":[{"components":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"tokenPriceUSDC","type":"uint256"},{"internalType":"uint256","name":"tokensSold","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"},{"internalType":"enum Presale.RoundState","name":"state","type":"uint8"}],"internalType":"struct Presale.Round","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getActiveRoundAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllActiveReferrers","outputs":[{"internalType":"address[]","name":"referrers","type":"address[]"},{"internalType":"uint256[]","name":"totalRewards","type":"uint256[]"},{"internalType":"uint256[]","name":"referralCounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinimumActivationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"}],"name":"getReferralCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_referee","type":"address"}],"name":"getReferralInfo","outputs":[{"internalType":"address","name":"referee","type":"address"},{"internalType":"uint256","name":"referredDate","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"firstPurchaseDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"}],"name":"getReferralStatusCounts","outputs":[{"internalType":"uint256","name":"totalReferrals","type":"uint256"},{"internalType":"uint256","name":"activeReferrals","type":"uint256"},{"internalType":"uint256","name":"inactiveReferrals","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRemainingReferralRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"}],"name":"getRoundInfo","outputs":[{"components":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"tokenPriceUSDC","type":"uint256"},{"internalType":"uint256","name":"tokensSold","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"},{"internalType":"enum Presale.RoundState","name":"state","type":"uint8"}],"internalType":"struct Presale.Round","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalReferrersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_referee","type":"address"}],"name":"isAdminDeactivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isReferralCapReached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReferrer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"isReferrerLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liqHolder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxReferralRewardsCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRoundDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minPurchaseTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextRoundId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_referee","type":"address"}],"name":"reactivateReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referralCapPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referralInfoList","outputs":[{"internalType":"address","name":"referee","type":"address"},{"internalType":"uint256","name":"referredDate","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"firstPurchaseDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralRewardPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralRewardsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrerLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"referrersList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"address","name":"_referee","type":"address"}],"name":"removeReferral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rounds","outputs":[{"internalType":"uint256","name":"roundId","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"tokenPriceUSDC","type":"uint256"},{"internalType":"uint256","name":"tokensSold","type":"uint256"},{"internalType":"uint256","name":"cap","type":"uint256"},{"internalType":"enum Presale.RoundState","name":"state","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_roundId","type":"uint256"}],"name":"setActiveRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newDuration","type":"uint256"}],"name":"setMaxRoundDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinPurchaseTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setReferralCapManual","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setReferralCapPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setReferralRewardPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setReferralRewardsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"}],"name":"setReferrer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_timelock","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncActiveRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReferralRewardsGiven","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLiqHolder","type":"address"}],"name":"updateLiqHolder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdcDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdcPermit","outputs":[{"internalType":"contract IERC20Permit","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdcToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usersInfo","outputs":[{"internalType":"uint256","name":"totalPurchased","type":"uint256"},{"internalType":"uint256","name":"totalDepositUSDC","type":"uint256"},{"internalType":"uint256","name":"totalReferralRewards","type":"uint256"},{"internalType":"uint256","name":"referralCount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
61012060408181523462000534576060826200495a803803809162000025828562000539565b83398101031262000534576200003b8262000573565b91602062000058836200005083850162000573565b930162000573565b916000916001835533156200051c5760018054610100600160a81b0319811633600881811b610100600160a81b0316929092179093558751986001600160a01b0393909290911c83167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08780a3600160055560649384600755600160ff19600854161760085585600955826101f49788600a5516988915620004db57508282169182151580620004cf575b156200048c573b6200043957829089608052168060a05260c05260018060a01b0319600254161760025585519283838163313ce56760e01b9a8b825260049788915afa9081156200040d57869162000417575b50838360a0511699868a51809c819382525afa9889156200040d578699620003d7575b5060ff811690601282116200038757601260ff8b1611620003395760e0526101009889526276a700600e55604d81116200032657600a0a80820291820403620003135760035560805186516318160ddd60e01b8152918391839186918391165afa91821562000309578492620002d1575b5050838102938185041490151715620002be5750506127109004600b55516143b69182620005a483396080518281816103de01528181611198015281816111de015281816113830152818161192f015281816124bb01528181612912015281816129f301528181612dfa015281816139280152818161396e0152613ab7015260a051828181610fe801528181612d4f01526137d3015260c051828181612a7201528181612af60152612c96015260e05182818161107601526128aa01525181818161104a015281816120cc01526138310152f35b634e487b7160e01b825260119052602490fd5b90809250813d831162000301575b620002eb818362000539565b81010312620002fd57513880620001ea565b8280fd5b503d620002df565b86513d86823e3d90fd5b634e487b7160e01b855260118452602485fd5b634e487b7160e01b865260118552602486fd5b885162461bcd60e51b81528087018690526024808201527f50726573616c653a205553444320646563696d616c73206d757374206265203c60448201526307a4062760e31b81850152608490fd5b885162461bcd60e51b8152808701869052602560248201527f50726573616c653a20546f6b656e20646563696d616c73206d757374206265206044820152640787a4062760db1b81850152608490fd5b620003fd919950843d861162000405575b620003f4818362000539565b81019062000588565b973862000179565b503d620003e8565b88513d88823e3d90fd5b620004329150843d86116200040557620003f4818362000539565b3862000156565b875162461bcd60e51b815260048101859052602760248201527f50726573616c653a206c6971486f6c6465722063616e6e6f74206265206120636044820152661bdb9d1c9858dd60ca1b81870152608490fd5b885162461bcd60e51b815260048101869052601860248201527f50726573616c653a20496e76616c69642061646472657373000000000000000060448201528690fd5b50838216151562000103565b62461bcd60e51b815260048101859052601e60248201527f50726573616c653a20496e76616c696420746f6b656e2061646472657373000060448201528590fd5b8451631e4fbdf760e01b815260048101849052602490fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200055d57604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200053457565b9081602091031262000534575160ff8116810362000534579056fe608080604052600436101561001357600080fd5b60003560e01c908163058efc4714612ee05750806305febd701461276f57806306b091f914612da657806306c5b7a014612d7e57806311eac85514612d3957806314ab047c14612c4a57806314d8432e14612bd35780631ca45272146105f05780631dd0aeef14612b915780632049e06f14612aa157806320e7c31c14612a5c57806324acbd6914612a2257806324ffea1a146129dd57806339535865146128ce5780633b97e856146128905780633f4ba83a146128265780634002eda61461280857806345210920146127ea5780634759e67f146127cc5780634ca68001146123105780634cf9dea4146127ae57806355d7bef21461276f5780635c086f4c1461272c5780635c975abb146127095780635d0eaaaf1461269f5780635ee300441461268657806363b201171461266857806369b21366146123e75780636bd10fc81461236c578063701c75e41461232e57806370b6131a14612310578063715018a6146122af57806372d54c651461228c578063753c7a8a1461217b5780637876fa95146120f05780637bf42165146120b25780638456cb59146120595780638788ce0c14611f7957806387c1394314611f5c57806388c3ffb014611eb457806389e59ea014611e985780638a56829914611e7a5780638b77842314611d9d5780638c65c81f14611d255780638da5cb5b14611cf8578063920a253e14611cda5780639f9c769814611b95578063a18a7bfc14611a5e578063b2118a8d146118cc578063b6c39a231461060c578063ba7046c4146118ae578063bdacb30314611821578063c9a2398714611691578063cb81d8e114610f4a578063cedcc6da14610f1b578063d04211a114610eb8578063d33219b414610e8f578063d4adef7014610d40578063d64d696814610d01578063d713c0a714610ce3578063d7e0d89314610ac4578063d86005f614610aa6578063d96a681814610a6d578063e2334ae314610a4a578063e405702b14610a21578063f2fde38b14610988578063f8c9637d1461074c578063fa798bd714610662578063fc503b9c1461060c578063feb6d45b146105f05763ff7603ce1461032c57600080fd5b3461053b57608036600319011261053b57602460043560643560443583356103526136fe565b6005549461035f8661352a565b60055585600052602090601382526040600020546105b557828610806105ac575b806105a3575b61038f90613539565b603c420180421161058e576103a5908711613585565b42831115610553576103c46103ba878561338e565b600e5410156135e9565b6040516370a0823160e01b815230600482015290828282817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa801561054757889260009161050e575b5061042590871115613635565b6006604051610433816130cb565b838152848101898152604082018781526060830189815260808401916000835260a08501938c855260c086019860008a5260005260138a526040600020955186555160018601555160028501555160038401555160048301555160058201550191519060038210156104fa57509160809593917f0b10fedca86de69b0ec988438c48bc6c1a518e1c1e0640f1d98c9d5aa4b6284d97959360ff801983541691161790556104e160045461352a565b60045560405194855284015260408301526060820152a2005b634e487b7160e01b60009081526021600452fd5b809350848092503d8311610540575b6105278183613149565b8101031261053b5761042588925190610418565b600080fd5b503d61051d565b6040513d6000823e3d90fd5b9060156064926040519262461bcd60e51b845260048401528201527450726573616c653a20496e76616c69642074696d6560581b6044820152fd5b50634e487b7160e01b60009081526011600452fd5b50841515610386565b50831515610380565b9060156064926040519262461bcd60e51b845260048401528201527450726573616c653a20526f756e642065786973747360581b6044820152fd5b3461053b57600036600319011261053b576020604051603c8152f35b3461053b57604036600319011261053b57610625612efb565b61062d612f11565b9060018060a01b03809116600052601160205260406000209116600052602052602060ff604060002054166040519015158152f35b3461053b5760208060031936011261053b5761067c612efb565b6001600160a01b031660009081526014825260408120805490919081906106a281613473565b936106b06040519586613149565b8185526000908152858120868087015b84841061072d5750505050508251926000925b81518410156107175760406106e885846134bd565b51015115610704576106fb60019161352a565b935b01926106d3565b929161071160019161352a565b926106fd565b8483606092886040519384528301526040820152f35b60019160049161073c856133e7565b81520192019201919087906106c0565b3461053b5760208060031936011261053b576004359061076a6136fe565b8115158061097d575b1561093957816000526013815260406000206006810160ff8154166003811015610923576108de576001820154603b1981019081116108c857421015806108ba575b156108605760008051602061434183398151915292916107f8916006548061082a575b50600160ff1982541617905584600655600460058201549101549061338e565b80600f55604051908152a17f86ec269b6177409ec7bcbae934b586d42b370d98762fdd2929157217fef4e8b1600080a2005b600052601384526006604060002001600260ff19825416179055600654600080516020614361833981519152600080a2866107d8565b60405162461bcd60e51b815260048101849052602c60248201527f50726573616c653a20526f756e642074696d696e6720696e76616c696420666f60448201526b391030b1ba34bb30ba34b7b760a11b6064820152608490fd5b5060028201544211156107b5565b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b815260048101849052601b60248201527f50726573616c653a20526f756e6420616c7265616479207573656400000000006044820152606490fd5b634e487b7160e01b600052602160045260246000fd5b6064906040519062461bcd60e51b82526004820152601960248201527f50726573616c653a20496e76616c696420726f756e64206964000000000000006044820152fd5b506005548210610773565b3461053b57602036600319011261053b576109a1612efb565b6109a96136fe565b6001600160a01b03818116918215610a085760018054610100600160a81b03198116600893841b610100600160a81b031617909155901c167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b3461053b57600036600319011261053b576002546040516001600160a01b039091168152602090f35b3461053b57600036600319011261053b57602060ff600854166040519015158152f35b3461053b57602036600319011261053b5760043580151580910361053b57610a936136fe565b60ff801960085416911617600855600080f35b3461053b57600036600319011261053b576020600654604051908152f35b3461053b57604036600319011261053b57610add612efb565b610ae5612f11565b90610aee6136fe565b60018060a01b03809216918260005260209060128252610b1d81806004604060002001541694168094146134d1565b8260005260158252604060002084600052825260406000205490610b4282151561339b565b836000526014835260406000209160001991828201908282116108c85784548481019081116108c857808303610c4f575b5050505081548015610c39570190610b8b8282612fd2565b610c2357600381600080935582600182015582600282015501555581600052601581526040600020836000528152600060408120556012815260046040600020016001600160601b0360a01b815416905581600052601181526040600020908360005252604060002060ff1981541690557fcf6da4c63c4a3d4ace6eb0ed1baae25bd4fd92123d59b9cb774b1d100764c6ac600080a3005b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052603160045260246000fd5b610c5c610c649187612fd2565b509286612fd2565b610c2357828103610c95575b5086600052601586526040600020915416600052845260406000205585808080610b73565b818354166001600160601b0360a01b82541617815560018301546001820155610cd460ff600285015416600283019060ff801983541691151516179055565b60038084015491015588610c70565b3461053b57600036600319011261053b576020600b54604051908152f35b3461053b57602036600319011261053b576001600160a01b03610d22612efb565b166000526017602052602060ff604060002054166040519015158152f35b3461053b57604036600319011261053b57610d59612efb565b610d61612f11565b90610d6a6136fe565b60018060a01b03809216918260005260209060128252610d9981806004604060002001541694168094146134d1565b82600052601582526040600020846000528252604060002054610dbd81151561339b565b8360005260148352604060002060001982019182116108c8578591610de191612fd2565b509182541603610e4a577fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd59160026040920160ff1990818154169055846000526011825282600020866000528252600183600020918254161790556000825191818352820152a3005b60405162461bcd60e51b815260048101839052601760248201527f50726573616c653a20496e646578206d69736d617463680000000000000000006044820152606490fd5b3461053b57600036600319011261053b57600c546040516001600160a01b039091168152602090f35b3461053b57602036600319011261053b57600435610ed46136fe565b8015610edf57600355005b60405162461bcd60e51b8152602060048201526014602482015273283932b9b0b6329d1024b73b30b634b21036b4b760611b6044820152606490fd5b3461053b57602036600319011261053b57600435610f376136fe565b610f456107d0821115613293565b600755005b3461053b57602036600319011261053b57610f63613681565b610f6b6136e0565b610f736132d2565b600654610f818115156131ef565b6000526013602052604060002060ff60068201541660038110156109235760011480611683575b80611675575b80611664575b1561161f5760043515908115916115da57604051636eb1769f60e11b81523360048201523060248201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116939091602081604481885afa908115610547576000916115a8575b5060043511611563576003830154908061155a575b15611515576110a5906110a06110717f00000000000000000000000000000000000000000000000000000000000000006004356141c0565b61109a7f0000000000000000000000000000000000000000000000000000000000000000614089565b9061372d565b613740565b9260035484106114d0576110ef90826002541690604051916323b872dd60e01b602084015233602484015260448301526004356064830152606482526110ea8261312d565b61402d565b336000526012602052600160406000200161110d600435825461351d565b90553360005260106020526040600020805460ff8116156114c0575b505061113433614212565b80821615156000816114aa575b600091806114a1575b61145a575b506111678161116287600488015461351d565b61351d565b6005850154106113f75761117b818661351d565b926040516370a0823160e01b8152306004820152602081602481857f0000000000000000000000000000000000000000000000000000000000000000165afa80156105475785906000906113c1575b6111d69250101561316b565b6112038633837f0000000000000000000000000000000000000000000000000000000000000000166136a4565b8161130b575b50505061121a81600484015461351d565b6004830155336000526012602052604060002061123884825461351d565b905561124681600d5461351d565b600d55600f54908082106112b75761126f6020916000805160206143418339815191529361338e565b80600f55604051908152a1549060405190600435825260208201527f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f160403392a36001600055005b60405162461bcd60e51b815260206004820152602660248201527f50726573616c653a20496e73756666696369656e7420726f756e6420616c6c6f60448201526531b0ba34b7b760d11b6064820152608490fd5b6040817fe679beb5d98a54fda65331587d36d13358e8bf295be15e932c482164f8fde95e92851660005260126020526002826000200161134c85825461351d565b905580851660005260126020526003826000200161136a815461352a565b90556113788460095461351d565b6009556113a88486837f0000000000000000000000000000000000000000000000000000000000000000166136a4565b86548251948552602085015233941692a3838080611209565b50506020813d6020116113ef575b816113dc60209383613149565b8101031261053b57846111d691516111ca565b3d91506113cf565b60405162461bcd60e51b815260206004820152603560248201527f50726573616c653a204578636565647320726f756e642063617020696e636c7560448201527464696e6720726566657272616c207265776172647360581b6064820152608490fd5b9050600954611469828261351d565b90600b5480921161147d575b50508561114f565b90915080821115611498576114919161338e565b8580611475565b50506000611491565b5080151561114a565b506127106114ba6007548761372d565b04611141565b60ff191660011790558380611129565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a2042656c6f77206d696e696d756d207075726368617365006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c696420616d6f756e747300000000000000006044820152606490fd5b50801515611039565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a20496e73756666696369656e7420616c6c6f77616e6365006044820152606490fd5b90506020813d6020116115d2575b816115c360209383613149565b8101031261053b575185611024565b3d91506115b6565b60405162461bcd60e51b815260206004820152601b60248201527f50726573616c653a20416d6f756e74206d757374206265203e203000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601a60248201527f50726573616c653a20526f756e6420756e617661696c61626c650000000000006044820152606490fd5b506004810154600582015411610fb4565b506002810154421115610fae565b506001810154421015610fa8565b3461053b57604036600319011261053b576116aa612efb565b6116b2612f11565b906116bb6136fe565b60018060a01b0380921691826000526116e960209160128352806004604060002001541693168093146134d1565b8160005260118152604060002083600052815260ff60406000205416156117dd578160005260158152604060002083600052815260406000205461172e81151561339b565b826000526014825260406000209160001982019182116108c8576117756040927fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd594612fd2565b50906002820160ff199060018282541617905585600052601182528360002087600052825283600020908154169055600383519287877f17d8b82fb3eae0e73737bd7b0a1660b65826c1756c28b8fbc96cf83caeb70fd6600080a301549060018352820152a3005b6064906040519062461bcd60e51b82526004820152601860248201527f50726573616c653a204e6f7420646561637469766174656400000000000000006044820152fd5b3461053b57602036600319011261053b5761183a612efb565b6118426136fe565b6001600160a01b03168015611869576001600160601b0360a01b600c541617600c55600080f35b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c69642074696d656c6f636b000000000000006044820152606490fd5b3461053b57600036600319011261053b576020600354604051908152f35b3461053b57606036600319011261053b576118e5612efb565b6118ed612f11565b6044359060018060a01b03918260015460081c1633148015611a51575b61191390613022565b61191b613681565b828083169461192b86151561307f565b16927f0000000000000000000000000000000000000000000000000000000000000000168314611a00576040516370a0823160e01b8152306004820152602081602481875afa908115610547576000916119ca575b50906119bc817f77023e19c7343ad491fd706c36335ca0e738340a91f29b1fd81e2673d44896c4946119b660209583111561316b565b866136a4565b604051908152a36001600055005b9190506020823d6020116119f8575b816119e660209383613149565b8101031261053b5790516119bc611980565b3d91506119d9565b60405162461bcd60e51b8152602060048201526024808201527f50726573616c653a2043616e6e6f74207265736375652070726573616c65207460448201526337b5b2b760e11b6064820152608490fd5b50600c548316331461190a565b3461053b57602036600319011261053b57611a77612efb565b6001600160a01b03811615611b505733600052601060205260ff60406000205416611b0b57336000526012602052604060002054611abb57611ab99033613bfc565b005b60405162461bcd60e51b815260206004820152602260248201527f50726573616c653a2043616e6e6f742073657420616674657220707572636861604482015261736560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820181905260248201527f50726573616c653a20526566657272657220616c7265616479206c6f636b65646044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c6964207265666572726572000000000000006044820152606490fd5b3461053b57600036600319011261053b57611bae6136fe565b601654611bba81613473565b611bc76040519182613149565b818152611bd382613473565b6020929082840190601f1901368237611beb8261348b565b611bf48361348b565b9260005b818110611c6e5750506040519485946060860190606087525180915260808601939060005b818110611c4e5750505084830390850152611c4a9291611c3c91612fee565b908382036040850152612fee565b0390f35b82516001600160a01b031686528897509483019491830191600101611c1d565b80611c80600192989495969798612f85565b838060a01b0391549060031b1c1680611c99838b6134bd565b528060005260128552600260406000200154611cb583886134bd565b5260005260148452604060002054611ccd82896134bd565b5201959493929195611bf8565b3461053b57600036600319011261053b576020600754604051908152f35b3461053b57600036600319011261053b5760015460405160089190911c6001600160a01b03168152602090f35b3461053b57602036600319011261053b57600435600052601360205260e06040600020611d9b8154916001810154906002810154600382015460048301549160ff600660058601549501541694604051978852602088015260408701526060860152608085015260a084015260c0830190612f27565bf35b3461053b57602036600319011261053b57611db6612efb565b60018060a01b038060015460081c1633148015611e6d575b611dd790613022565b8116908115159081611e63575b5015611e2b576020817fa64c5f87f31d2d7127a1e94aaaff2fbbef101a077120dd59d059d01dead1122e926001600160601b0360a01b6002541617600255604051908152a1005b60405162461bcd60e51b815260206004820152601060248201526f141c995cd85b194e88125b9d985b1a5960821b6044820152606490fd5b90503b1582611de4565b50600c5481163314611dce565b3461053b57600036600319011261053b576020600454604051908152f35b3461053b57600036600319011261053b576020604051600a8152f35b3461053b57602036600319011261053b57600435611ed06131b7565b50806000526013602052611eea6040600020541515613427565b6000526013602052611c4a6040600020611f5060ff600660405193611f0e856130cb565b8054855260018101546020860152600281015460408601526003810154606086015260048101546080860152600581015460a086015201541660c0830161323b565b60405191829182612f34565b3461053b57600036600319011261053b5760206040516127108152f35b3461053b57602036600319011261053b57600435611f956136fe565b8015158061204c575b1561200757600654611faf57600e55005b60405162461bcd60e51b815260206004820152602a60248201527f50726573616c653a2043616e6e6f74206368616e676520647572696e672061636044820152691d1a5d99481c9bdd5b9960b21b6064820152608490fd5b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c6964206475726174696f6e000000000000006044820152606490fd5b5062ed4e00811115611f9e565b3461053b57600036600319011261053b576120726136fe565b61207a6136e0565b600160ff19815416176001557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b3461053b57600036600319011261053b57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461053b57604036600319011261053b57612109612efb565b6001600160a01b03908116600090815260146020526040902080546024359081101561053b5761213891612fd2565b5080546001820154600283015460039093015460408051959093166001600160a01b03168552602085019190915260ff9092161515908301526060820152608090f35b3461053b57604036600319011261053b57612194612efb565b61219c612f11565b9060018060a01b0380911680600052601560205281604060002093169283600052602052604060002054906121d282151561339b565b6000526014602052604060002060001982019182116108c8576121fe916121f891612fd2565b506133e7565b9181835116036122475781516020808401516040808601516060968701518251969095166001600160a01b03168652928501919091529015159083015291810191909152608090f35b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c6964206d617070696e6700000000000000006044820152606490fd5b3461053b57600036600319011261053b576020600954600b541115604051908152f35b3461053b57600036600319011261053b576122c86136fe565b60018054610100600160a81b0319811690915560009060081c6001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461053b57600036600319011261053b576020600f54604051908152f35b3461053b57600036600319011261053b57600954600b5480821061235b575050602060005b604051908152f35b6020916123679161338e565b612353565b3461053b57600036600319011261053b576123856136fe565b6006546123938115156131ef565b8060005260136020526006604060002001600260ff1982541617905560006006556000600f55600080516020614341833981519152602060405160008152a1600080516020614361833981519152600080a2005b3461053b5760a036600319011261053b576004356044356024803590608435906064356124126136fe565b856000526020946013865261242d6040600020541515613427565b6124368761409a565b8660005260138652604060002060ff6006820154169360038510156104fa5784612617578287108061260e575b80612605575b61247290613539565b603c420180421161058e57612488908811613585565b6124956103ba888561338e565b600482015486106125c2576040516370a0823160e01b81523060048201529088908290817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561054757600091612565575b50917f6901e2dccc1386be04abc9d013bc80c946841529a7350f612eb3a34a1f33968a9784600361255d96946125318a999760a09c9b1115613635565b886005820155896001820155846002820155015560405196875286015260408501526060840190612f27565b6080820152a2005b93919695949290508784813d83116125bb575b6125828183613149565b8101031261053b5792519495939491939092917f6901e2dccc1386be04abc9d013bc80c946841529a7350f612eb3a34a1f33968a6124f4565b503d612578565b87601e6064926040519262461bcd60e51b845260048401528201527f50726573616c653a204361702062656c6f7720736f6c6420746f6b656e7300006044820152fd5b50851515612469565b50831515612463565b8760256084926040519262461bcd60e51b845260048401528201527f50726573616c653a204f6e6c792070656e64696e6720726f756e6473206564696044820152647461626c6560d81b6064820152fd5b3461053b57600036600319011261053b576020600d54604051908152f35b3461053b57600036600319011261053b57611ab96132d2565b3461053b57602036600319011261053b5760a06001600160a01b03806126c3612efb565b1660005260126020526040600020908154916001810154916002820154906004600384015493015416926040519485526020850152604084015260608301526080820152f35b3461053b57600036600319011261053b57602060ff600154166040519015158152f35b3461053b57604036600319011261053b57612768612748612f11565b612750613681565b6127586136e0565b6127606132d2565b600435613760565b6001600055005b3461053b57602036600319011261053b576001600160a01b03612790612efb565b166000526010602052602060ff604060002054166040519015158152f35b3461053b57600036600319011261053b576020600954604051908152f35b3461053b57600036600319011261053b576020601654604051908152f35b3461053b57600036600319011261053b576020600e54604051908152f35b3461053b57600036600319011261053b576020600554604051908152f35b3461053b57600036600319011261053b5761283f6136fe565b60015460ff81161561287e5760ff19166001557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b604051638dfc202b60e01b8152600490fd5b3461053b57600036600319011261053b57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461053b5760208060031936011261053b576004356128eb6136fe565b6128f96107d0821115613293565b600a8190556040516318160ddd60e01b815282816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610547576000916129ae575b50612710916129599161372d565b0490600954821061296a5750600b55005b6064906040519062461bcd60e51b82526004820152601e60248201527f50726573616c653a204361702062656c6f7720646973747269627574656400006044820152fd5b90508281813d83116129d6575b6129c58183613149565b8101031261053b575161271061294b565b503d6129bb565b3461053b57600036600319011261053b576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461053b57602036600319011261053b576001600160a01b03612a43612efb565b1660005260146020526020604060002054604051908152f35b3461053b57600036600319011261053b576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461053b5760c036600319011261053b57600435612abd612f11565b604435916064359260ff841680940361053b57612ad8613681565b612ae06136e0565b612aec42821015613247565b612af46132d2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031693843b1561053b5760e460009283604051978894859363d505accf60e01b85523360048601523060248601528860448601526064850152608484015260843560a484015260a43560c48401525af19283156105475761276893612b82575b50613760565b612b8b90613119565b83612b7c565b3461053b57602036600319011261053b5760043560165481101561053b57612bba602091612f85565b905460405160039290921b1c6001600160a01b03168152f35b3461053b57602036600319011261053b57600435612bef6136fe565b80151580612c3e575b15612c0257600b55005b60405162461bcd60e51b8152602060048201526014602482015273050726573616c653a20496e76616c6964206361760641b6044820152606490fd5b50600954811015612bf8565b3461053b5760a036600319011261053b576004356024356044359160ff831680930361053b57612c78613681565b612c806136e0565b612c8c42831015613247565b612c946132d2565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169260009290843b1561053b5760e460009283604051978894859363d505accf60e01b85523360048601523060248601528860448601526064850152608484015260643560a484015260843560c48401525af19283156105475761276893612d255750613760565b612d30919250613119565b60009083612b7c565b3461053b57600036600319011261053b576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461053b57600036600319011261053b57612d976131b7565b50600654611eea8115156131ef565b3461053b57604036600319011261053b57612dbf612efb565b60243560018060a01b038060015460081c1633148015612ed3575b612de390613022565b612deb613681565b612df8818416151561307f565b7f000000000000000000000000000000000000000000000000000000000000000016916040516370a0823160e01b8152306004820152602081602481875afa90811561054757600091612ea1575b5082827f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436495612e7a83612e7f95101561316b565b6136a4565b604080516001600160a01b039290921682526020820192909252a16001600055005b90506020813d602011612ecb575b81612ebc60209383613149565b8101031261053b575182612e46565b3d9150612eaf565b50600c5481163314612dda565b3461053b57600036600319011261053b57602090600a548152f35b600435906001600160a01b038216820361053b57565b602435906001600160a01b038216820361053b57565b9060038210156109235752565b612f839092919260c08060e0830195805184526020810151602085015260408101516040850152606081015160608501526080810151608085015260a081015160a08501520151910190612f27565b565b601654811015612fbc5760166000527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b51242890190600090565b634e487b7160e01b600052603260045260246000fd5b8054821015612fbc5760005260206000209060021b0190600090565b90815180825260208080930193019160005b82811061300e575050505090565b835185529381019392810192600101613000565b1561302957565b60405162461bcd60e51b815260206004820152602860248201527f50726573616c653a2063616c6c6572206973206e6f74206f776e6572206f722060448201526774696d656c6f636b60c01b6064820152608490fd5b1561308657565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c6964206164647265737300000000000000006044820152606490fd5b60e0810190811067ffffffffffffffff8211176130e757604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176130e757604052565b67ffffffffffffffff81116130e757604052565b60a0810190811067ffffffffffffffff8211176130e757604052565b90601f8019910116810190811067ffffffffffffffff8211176130e757604052565b1561317257565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a20496e73756666696369656e742062616c616e63650000006044820152606490fd5b604051906131c4826130cb565b8160c06000918281528260208201528260408201528260608201528260808201528260a08201520152565b156131f657565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a204e6f2061637469766520726f756e6400000000000000006044820152606490fd5b60038210156109235752565b1561324e57565b60405162461bcd60e51b815260206004820152601760248201527f50726573616c653a205065726d697420657870697265640000000000000000006044820152606490fd5b1561329a57565b60405162461bcd60e51b815260206004820152601060248201526f50726573616c653a204d61782032302560801b6044820152606490fd5b600654801561338b576000908152601360205260408120600681019081549160ff831660038110156133775760011480613358575b613312575b50505050565b60026000805160206143618339815191529360ff19161790558260065582600f556000805160206143418339815191526020604051858152a1549180a23880808061330c565b5060028201544211806133075750600482015460058301541115613307565b634e487b7160e01b85526021600452602485fd5b50565b919082039182116108c857565b156133a257565b60405162461bcd60e51b815260206004820152601b60248201527f50726573616c653a20526566657272616c206e6f7420666f756e6400000000006044820152606490fd5b906040516133f4816130fd565b82546001600160a01b0316815260018301546020820152600283015460ff16151560408201526003909201546060830152565b1561342e57565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20526f756e64206e6f7420666f756e6400000000000000006044820152606490fd5b67ffffffffffffffff81116130e75760051b60200190565b9061349582613473565b6134a26040519182613149565b82815280926134b3601f1991613473565b0190602036910137565b8051821015612fbc5760209160051b010190565b156134d857565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a20496e76616c69642072656c6174696f6e736869700000006044820152606490fd5b919082018092116108c857565b60001981146108c85760010190565b1561354057565b60405162461bcd60e51b815260206004820152601760248201527f50726573616c653a20496e76616c696420706172616d730000000000000000006044820152606490fd5b1561358c57565b60405162461bcd60e51b815260206004820152602f60248201527f50726573616c653a2053746172742074696d65206d757374206265206166746560448201526e72206d696e696d756d2064656c617960881b6064820152608490fd5b156135f057565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a204475726174696f6e2065786365656473206d61780000006044820152606490fd5b1561363c57565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a20496e73756666696369656e7420696e76656e746f7279006044820152606490fd5b600260005414613692576002600055565b604051633ee5aeb560e01b8152600490fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152612f83916110ea606483613149565b60ff600154166136ec57565b60405163d93c066560e01b8152600490fd5b60015460081c6001600160a01b0316330361371557565b60405163118cdaa760e01b8152336004820152602490fd5b818102929181159184041417156108c857565b811561374a570490565b634e487b7160e01b600052601260045260246000fd5b60065461376e8115156131ef565b6000526013602052604060002060ff60068201541660038110156109235760011480613bee575b80613be0575b80613bcf575b1561161f5781158015906115da57604051636eb1769f60e11b81523360048201523060248201526001600160a01b03917f0000000000000000000000000000000000000000000000000000000000000000831691602081604481865afa8015610547578691600091613b9a575b50106115635760038401549080613b91575b1561151557613856906110a06110717f0000000000000000000000000000000000000000000000000000000000000000886141c0565b9460035486106114d05761389c6138c092846002541690604051916323b872dd60e01b60208401523360248401526044830152876064830152606482526110ea8261312d565b33600052601260205260016040600020016138b886825461351d565b905533613bfc565b6138c933614212565b8082161515600081613b7b575b60009180613b72575b613b2b575b506138f78161116288600488015461351d565b6005850154106113f75761390b818761351d565b926040516370a0823160e01b8152306004820152602081602481857f0000000000000000000000000000000000000000000000000000000000000000165afa8015610547578590600090613af5575b6139669250101561316b565b6139938733837f0000000000000000000000000000000000000000000000000000000000000000166136a4565b81613a3f575b5050506139aa81600484015461351d565b600483015533600052601260205260406000206139c885825461351d565b90556139d681600d5461351d565b600d55600f54908082106112b7576139ff6020916000805160206143418339815191529361338e565b80600f55604051908152a1549160405191825260208201527f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f160403392a3565b6040817fe679beb5d98a54fda65331587d36d13358e8bf295be15e932c482164f8fde95e928516600052601260205260028260002001613a8085825461351d565b9055808516600052601260205260038260002001613a9e815461352a565b9055613aac8460095461351d565b600955613adc8486837f0000000000000000000000000000000000000000000000000000000000000000166136a4565b86548251948552602085015233941692a3388080613999565b50506020813d602011613b23575b81613b1060209383613149565b8101031261053b5784613966915161395a565b3d9150613b03565b9050600954613b3a828261351d565b90600b54809211613b4e575b5050386138e4565b90915080821115613b6957613b629161338e565b3880613b46565b50506000613b62565b508015156138df565b50612710613b8b6007548861372d565b046138d6565b50801515613820565b9150506020813d602011613bc7575b81613bb660209383613149565b8101031261053b578590513861380e565b3d9150613ba9565b5060048101546005820154116137a1565b50600281015442111561379b565b506001810154421015613795565b6001600160a01b038281169290831561400257808316926000928484526020906010825260409260ff8487205416613fa257868814613f5e57803b613f0e57813b613ebb5790613c4b9161415b565b613e7a5785845260118152818420858552815260ff8285205416613e295784845260128152600482852001916001600160601b0360a01b928784825416179055601082528085209160ff19926001848254161790558151613cab816130fd565b87815281810142815283820188815260608301918983528b8a5260148552858a2097885468010000000000000000998a821015613e155790613cf291600182018155612fd2565b959095613e015792601796959492613d2f928c600396511690875416178655516001860155511515600285019060ff801983541691151516179055565b5191015588875260148152828720546015825283882089895282528388205588875252842090815460ff811615613d8c575b5050505050807fdf63218877cb126f6c003f2b7f77327674cd6a0b53ad51deac392548ec12b0ed91a3565b16600117905560165490811015613ded5790613dd08260017fdf63218877cb126f6c003f2b7f77327674cd6a0b53ad51deac392548ec12b0ed959401601655612f85565b819291549060031b9187831b921b19161790559038808080613d61565b634e487b7160e01b83526041600452602483fd5b634e487b7160e01b8c5260048c905260248cfd5b634e487b7160e01b8d52604160045260248dfd5b608491519062461bcd60e51b82526004820152602660248201527f50726573616c653a20526566657272616c2064656163746976617465642062796044820152651030b236b4b760d11b6064820152fd5b606491519062461bcd60e51b825280600483015260248201527f50726573616c653a20526566657272616c206379636c652064657465637465646044820152fd5b835162461bcd60e51b815260048101849052602660248201527f50726573616c653a2052656665727265722063616e6e6f74206265206120636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b835162461bcd60e51b815260048101849052602360248201527f50726573616c653a2042757965722063616e6e6f74206265206120636f6e74726044820152621858dd60ea1b6064820152608490fd5b835162461bcd60e51b815260048101849052601e60248201527f50726573616c653a2043616e6e6f7420726566657220796f757273656c6600006044820152606490fd5b5050819695945092601260049394522001541614613ffe57505162461bcd60e51b815260206004820181905260248201527f50726573616c653a20526566657272657220616c7265616479206c6f636b65646044820152606490fd5b9050565b9250501660005260106020526040600020805460ff811615614022575050565b60ff19166001179055565b906000602091828151910182855af115610547576000513d61408057506001600160a01b0381163b155b61405e5750565b604051635274afe760e01b81526001600160a01b039091166004820152602490fd5b60011415614057565b60ff16604d81116108c857600a0a90565b801561338b576000818152601360205260408120906006820180549260ff8416600381101561414757600114908161411c575b506140d85750505050565b60026000805160206143618339815191529360ff19161790558060065580600f556000805160206143418339815191526020604051838152a180a23880808061330c565b6002810154421191508115614133575b50386140cd565b90506005600482015491015411153861412c565b634e487b7160e01b84526021600452602484fd5b906000905b600a82111561417157505050600190565b6001600160a01b039081169081156141b75780841682146141ae576141a8916000526012602052600460406000200154169161352a565b90614160565b50505050600190565b50505050600090565b9060ff166012811461420e57601281106141f657601119019060ff82116108c8576141ed6141f392614089565b90613740565b90565b6012039060ff82116108c85761109a6141f392614089565b5090565b6001600160a01b03908116600081815260126020908152604080832060040154909416939091841561432e5760ff60085416158015614336575b61432e5784815260118352818120848252835260ff828220541661432e578481526015835281812084825283528181205490811561432557858152601484528281209060001983019283116143115750859392916142a991612fd2565b5091600283019283549360ff8516156142c7575b5050505050505090565b60017fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd59560ff1916179055600342910155815190600182524290820152a3388181808080806142bd565b634e487b7160e01b81526011600452602490fd5b94505050505090565b935050505090565b506007541561424c56fe7e9c0e320e234667f81e817ec078e4b6f73c2cfe90ddda113cdc742931b16633aa97d4a7b3afec5f55c25ca8593dde6929d4455fad650a16fa4334004293a618a2646970667358221220645b87737c0babd2132ee13577b4851661a71883f535c38de6d9793081845a6b64736f6c6343000818003300000000000000000000000047ced79fd38e1c77739891aab40e5f66e6deb157000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c908163058efc4714612ee05750806305febd701461276f57806306b091f914612da657806306c5b7a014612d7e57806311eac85514612d3957806314ab047c14612c4a57806314d8432e14612bd35780631ca45272146105f05780631dd0aeef14612b915780632049e06f14612aa157806320e7c31c14612a5c57806324acbd6914612a2257806324ffea1a146129dd57806339535865146128ce5780633b97e856146128905780633f4ba83a146128265780634002eda61461280857806345210920146127ea5780634759e67f146127cc5780634ca68001146123105780634cf9dea4146127ae57806355d7bef21461276f5780635c086f4c1461272c5780635c975abb146127095780635d0eaaaf1461269f5780635ee300441461268657806363b201171461266857806369b21366146123e75780636bd10fc81461236c578063701c75e41461232e57806370b6131a14612310578063715018a6146122af57806372d54c651461228c578063753c7a8a1461217b5780637876fa95146120f05780637bf42165146120b25780638456cb59146120595780638788ce0c14611f7957806387c1394314611f5c57806388c3ffb014611eb457806389e59ea014611e985780638a56829914611e7a5780638b77842314611d9d5780638c65c81f14611d255780638da5cb5b14611cf8578063920a253e14611cda5780639f9c769814611b95578063a18a7bfc14611a5e578063b2118a8d146118cc578063b6c39a231461060c578063ba7046c4146118ae578063bdacb30314611821578063c9a2398714611691578063cb81d8e114610f4a578063cedcc6da14610f1b578063d04211a114610eb8578063d33219b414610e8f578063d4adef7014610d40578063d64d696814610d01578063d713c0a714610ce3578063d7e0d89314610ac4578063d86005f614610aa6578063d96a681814610a6d578063e2334ae314610a4a578063e405702b14610a21578063f2fde38b14610988578063f8c9637d1461074c578063fa798bd714610662578063fc503b9c1461060c578063feb6d45b146105f05763ff7603ce1461032c57600080fd5b3461053b57608036600319011261053b57602460043560643560443583356103526136fe565b6005549461035f8661352a565b60055585600052602090601382526040600020546105b557828610806105ac575b806105a3575b61038f90613539565b603c420180421161058e576103a5908711613585565b42831115610553576103c46103ba878561338e565b600e5410156135e9565b6040516370a0823160e01b815230600482015290828282817f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b76001600160a01b03165afa801561054757889260009161050e575b5061042590871115613635565b6006604051610433816130cb565b838152848101898152604082018781526060830189815260808401916000835260a08501938c855260c086019860008a5260005260138a526040600020955186555160018601555160028501555160038401555160048301555160058201550191519060038210156104fa57509160809593917f0b10fedca86de69b0ec988438c48bc6c1a518e1c1e0640f1d98c9d5aa4b6284d97959360ff801983541691161790556104e160045461352a565b60045560405194855284015260408301526060820152a2005b634e487b7160e01b60009081526021600452fd5b809350848092503d8311610540575b6105278183613149565b8101031261053b5761042588925190610418565b600080fd5b503d61051d565b6040513d6000823e3d90fd5b9060156064926040519262461bcd60e51b845260048401528201527450726573616c653a20496e76616c69642074696d6560581b6044820152fd5b50634e487b7160e01b60009081526011600452fd5b50841515610386565b50831515610380565b9060156064926040519262461bcd60e51b845260048401528201527450726573616c653a20526f756e642065786973747360581b6044820152fd5b3461053b57600036600319011261053b576020604051603c8152f35b3461053b57604036600319011261053b57610625612efb565b61062d612f11565b9060018060a01b03809116600052601160205260406000209116600052602052602060ff604060002054166040519015158152f35b3461053b5760208060031936011261053b5761067c612efb565b6001600160a01b031660009081526014825260408120805490919081906106a281613473565b936106b06040519586613149565b8185526000908152858120868087015b84841061072d5750505050508251926000925b81518410156107175760406106e885846134bd565b51015115610704576106fb60019161352a565b935b01926106d3565b929161071160019161352a565b926106fd565b8483606092886040519384528301526040820152f35b60019160049161073c856133e7565b81520192019201919087906106c0565b3461053b5760208060031936011261053b576004359061076a6136fe565b8115158061097d575b1561093957816000526013815260406000206006810160ff8154166003811015610923576108de576001820154603b1981019081116108c857421015806108ba575b156108605760008051602061434183398151915292916107f8916006548061082a575b50600160ff1982541617905584600655600460058201549101549061338e565b80600f55604051908152a17f86ec269b6177409ec7bcbae934b586d42b370d98762fdd2929157217fef4e8b1600080a2005b600052601384526006604060002001600260ff19825416179055600654600080516020614361833981519152600080a2866107d8565b60405162461bcd60e51b815260048101849052602c60248201527f50726573616c653a20526f756e642074696d696e6720696e76616c696420666f60448201526b391030b1ba34bb30ba34b7b760a11b6064820152608490fd5b5060028201544211156107b5565b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b815260048101849052601b60248201527f50726573616c653a20526f756e6420616c7265616479207573656400000000006044820152606490fd5b634e487b7160e01b600052602160045260246000fd5b6064906040519062461bcd60e51b82526004820152601960248201527f50726573616c653a20496e76616c696420726f756e64206964000000000000006044820152fd5b506005548210610773565b3461053b57602036600319011261053b576109a1612efb565b6109a96136fe565b6001600160a01b03818116918215610a085760018054610100600160a81b03198116600893841b610100600160a81b031617909155901c167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b3461053b57600036600319011261053b576002546040516001600160a01b039091168152602090f35b3461053b57600036600319011261053b57602060ff600854166040519015158152f35b3461053b57602036600319011261053b5760043580151580910361053b57610a936136fe565b60ff801960085416911617600855600080f35b3461053b57600036600319011261053b576020600654604051908152f35b3461053b57604036600319011261053b57610add612efb565b610ae5612f11565b90610aee6136fe565b60018060a01b03809216918260005260209060128252610b1d81806004604060002001541694168094146134d1565b8260005260158252604060002084600052825260406000205490610b4282151561339b565b836000526014835260406000209160001991828201908282116108c85784548481019081116108c857808303610c4f575b5050505081548015610c39570190610b8b8282612fd2565b610c2357600381600080935582600182015582600282015501555581600052601581526040600020836000528152600060408120556012815260046040600020016001600160601b0360a01b815416905581600052601181526040600020908360005252604060002060ff1981541690557fcf6da4c63c4a3d4ace6eb0ed1baae25bd4fd92123d59b9cb774b1d100764c6ac600080a3005b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052603160045260246000fd5b610c5c610c649187612fd2565b509286612fd2565b610c2357828103610c95575b5086600052601586526040600020915416600052845260406000205585808080610b73565b818354166001600160601b0360a01b82541617815560018301546001820155610cd460ff600285015416600283019060ff801983541691151516179055565b60038084015491015588610c70565b3461053b57600036600319011261053b576020600b54604051908152f35b3461053b57602036600319011261053b576001600160a01b03610d22612efb565b166000526017602052602060ff604060002054166040519015158152f35b3461053b57604036600319011261053b57610d59612efb565b610d61612f11565b90610d6a6136fe565b60018060a01b03809216918260005260209060128252610d9981806004604060002001541694168094146134d1565b82600052601582526040600020846000528252604060002054610dbd81151561339b565b8360005260148352604060002060001982019182116108c8578591610de191612fd2565b509182541603610e4a577fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd59160026040920160ff1990818154169055846000526011825282600020866000528252600183600020918254161790556000825191818352820152a3005b60405162461bcd60e51b815260048101839052601760248201527f50726573616c653a20496e646578206d69736d617463680000000000000000006044820152606490fd5b3461053b57600036600319011261053b57600c546040516001600160a01b039091168152602090f35b3461053b57602036600319011261053b57600435610ed46136fe565b8015610edf57600355005b60405162461bcd60e51b8152602060048201526014602482015273283932b9b0b6329d1024b73b30b634b21036b4b760611b6044820152606490fd5b3461053b57602036600319011261053b57600435610f376136fe565b610f456107d0821115613293565b600755005b3461053b57602036600319011261053b57610f63613681565b610f6b6136e0565b610f736132d2565b600654610f818115156131ef565b6000526013602052604060002060ff60068201541660038110156109235760011480611683575b80611675575b80611664575b1561161f5760043515908115916115da57604051636eb1769f60e11b81523360048201523060248201526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488116939091602081604481885afa908115610547576000916115a8575b5060043511611563576003830154908061155a575b15611515576110a5906110a06110717f00000000000000000000000000000000000000000000000000000000000000066004356141c0565b61109a7f0000000000000000000000000000000000000000000000000000000000000009614089565b9061372d565b613740565b9260035484106114d0576110ef90826002541690604051916323b872dd60e01b602084015233602484015260448301526004356064830152606482526110ea8261312d565b61402d565b336000526012602052600160406000200161110d600435825461351d565b90553360005260106020526040600020805460ff8116156114c0575b505061113433614212565b80821615156000816114aa575b600091806114a1575b61145a575b506111678161116287600488015461351d565b61351d565b6005850154106113f75761117b818661351d565b926040516370a0823160e01b8152306004820152602081602481857f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7165afa80156105475785906000906113c1575b6111d69250101561316b565b6112038633837f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7166136a4565b8161130b575b50505061121a81600484015461351d565b6004830155336000526012602052604060002061123884825461351d565b905561124681600d5461351d565b600d55600f54908082106112b75761126f6020916000805160206143418339815191529361338e565b80600f55604051908152a1549060405190600435825260208201527f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f160403392a36001600055005b60405162461bcd60e51b815260206004820152602660248201527f50726573616c653a20496e73756666696369656e7420726f756e6420616c6c6f60448201526531b0ba34b7b760d11b6064820152608490fd5b6040817fe679beb5d98a54fda65331587d36d13358e8bf295be15e932c482164f8fde95e92851660005260126020526002826000200161134c85825461351d565b905580851660005260126020526003826000200161136a815461352a565b90556113788460095461351d565b6009556113a88486837f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7166136a4565b86548251948552602085015233941692a3838080611209565b50506020813d6020116113ef575b816113dc60209383613149565b8101031261053b57846111d691516111ca565b3d91506113cf565b60405162461bcd60e51b815260206004820152603560248201527f50726573616c653a204578636565647320726f756e642063617020696e636c7560448201527464696e6720726566657272616c207265776172647360581b6064820152608490fd5b9050600954611469828261351d565b90600b5480921161147d575b50508561114f565b90915080821115611498576114919161338e565b8580611475565b50506000611491565b5080151561114a565b506127106114ba6007548761372d565b04611141565b60ff191660011790558380611129565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a2042656c6f77206d696e696d756d207075726368617365006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c696420616d6f756e747300000000000000006044820152606490fd5b50801515611039565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a20496e73756666696369656e7420616c6c6f77616e6365006044820152606490fd5b90506020813d6020116115d2575b816115c360209383613149565b8101031261053b575185611024565b3d91506115b6565b60405162461bcd60e51b815260206004820152601b60248201527f50726573616c653a20416d6f756e74206d757374206265203e203000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601a60248201527f50726573616c653a20526f756e6420756e617661696c61626c650000000000006044820152606490fd5b506004810154600582015411610fb4565b506002810154421115610fae565b506001810154421015610fa8565b3461053b57604036600319011261053b576116aa612efb565b6116b2612f11565b906116bb6136fe565b60018060a01b0380921691826000526116e960209160128352806004604060002001541693168093146134d1565b8160005260118152604060002083600052815260ff60406000205416156117dd578160005260158152604060002083600052815260406000205461172e81151561339b565b826000526014825260406000209160001982019182116108c8576117756040927fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd594612fd2565b50906002820160ff199060018282541617905585600052601182528360002087600052825283600020908154169055600383519287877f17d8b82fb3eae0e73737bd7b0a1660b65826c1756c28b8fbc96cf83caeb70fd6600080a301549060018352820152a3005b6064906040519062461bcd60e51b82526004820152601860248201527f50726573616c653a204e6f7420646561637469766174656400000000000000006044820152fd5b3461053b57602036600319011261053b5761183a612efb565b6118426136fe565b6001600160a01b03168015611869576001600160601b0360a01b600c541617600c55600080f35b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c69642074696d656c6f636b000000000000006044820152606490fd5b3461053b57600036600319011261053b576020600354604051908152f35b3461053b57606036600319011261053b576118e5612efb565b6118ed612f11565b6044359060018060a01b03918260015460081c1633148015611a51575b61191390613022565b61191b613681565b828083169461192b86151561307f565b16927f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7168314611a00576040516370a0823160e01b8152306004820152602081602481875afa908115610547576000916119ca575b50906119bc817f77023e19c7343ad491fd706c36335ca0e738340a91f29b1fd81e2673d44896c4946119b660209583111561316b565b866136a4565b604051908152a36001600055005b9190506020823d6020116119f8575b816119e660209383613149565b8101031261053b5790516119bc611980565b3d91506119d9565b60405162461bcd60e51b8152602060048201526024808201527f50726573616c653a2043616e6e6f74207265736375652070726573616c65207460448201526337b5b2b760e11b6064820152608490fd5b50600c548316331461190a565b3461053b57602036600319011261053b57611a77612efb565b6001600160a01b03811615611b505733600052601060205260ff60406000205416611b0b57336000526012602052604060002054611abb57611ab99033613bfc565b005b60405162461bcd60e51b815260206004820152602260248201527f50726573616c653a2043616e6e6f742073657420616674657220707572636861604482015261736560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820181905260248201527f50726573616c653a20526566657272657220616c7265616479206c6f636b65646044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c6964207265666572726572000000000000006044820152606490fd5b3461053b57600036600319011261053b57611bae6136fe565b601654611bba81613473565b611bc76040519182613149565b818152611bd382613473565b6020929082840190601f1901368237611beb8261348b565b611bf48361348b565b9260005b818110611c6e5750506040519485946060860190606087525180915260808601939060005b818110611c4e5750505084830390850152611c4a9291611c3c91612fee565b908382036040850152612fee565b0390f35b82516001600160a01b031686528897509483019491830191600101611c1d565b80611c80600192989495969798612f85565b838060a01b0391549060031b1c1680611c99838b6134bd565b528060005260128552600260406000200154611cb583886134bd565b5260005260148452604060002054611ccd82896134bd565b5201959493929195611bf8565b3461053b57600036600319011261053b576020600754604051908152f35b3461053b57600036600319011261053b5760015460405160089190911c6001600160a01b03168152602090f35b3461053b57602036600319011261053b57600435600052601360205260e06040600020611d9b8154916001810154906002810154600382015460048301549160ff600660058601549501541694604051978852602088015260408701526060860152608085015260a084015260c0830190612f27565bf35b3461053b57602036600319011261053b57611db6612efb565b60018060a01b038060015460081c1633148015611e6d575b611dd790613022565b8116908115159081611e63575b5015611e2b576020817fa64c5f87f31d2d7127a1e94aaaff2fbbef101a077120dd59d059d01dead1122e926001600160601b0360a01b6002541617600255604051908152a1005b60405162461bcd60e51b815260206004820152601060248201526f141c995cd85b194e88125b9d985b1a5960821b6044820152606490fd5b90503b1582611de4565b50600c5481163314611dce565b3461053b57600036600319011261053b576020600454604051908152f35b3461053b57600036600319011261053b576020604051600a8152f35b3461053b57602036600319011261053b57600435611ed06131b7565b50806000526013602052611eea6040600020541515613427565b6000526013602052611c4a6040600020611f5060ff600660405193611f0e856130cb565b8054855260018101546020860152600281015460408601526003810154606086015260048101546080860152600581015460a086015201541660c0830161323b565b60405191829182612f34565b3461053b57600036600319011261053b5760206040516127108152f35b3461053b57602036600319011261053b57600435611f956136fe565b8015158061204c575b1561200757600654611faf57600e55005b60405162461bcd60e51b815260206004820152602a60248201527f50726573616c653a2043616e6e6f74206368616e676520647572696e672061636044820152691d1a5d99481c9bdd5b9960b21b6064820152608490fd5b60405162461bcd60e51b815260206004820152601960248201527f50726573616c653a20496e76616c6964206475726174696f6e000000000000006044820152606490fd5b5062ed4e00811115611f9e565b3461053b57600036600319011261053b576120726136fe565b61207a6136e0565b600160ff19815416176001557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b3461053b57600036600319011261053b57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000006168152f35b3461053b57604036600319011261053b57612109612efb565b6001600160a01b03908116600090815260146020526040902080546024359081101561053b5761213891612fd2565b5080546001820154600283015460039093015460408051959093166001600160a01b03168552602085019190915260ff9092161515908301526060820152608090f35b3461053b57604036600319011261053b57612194612efb565b61219c612f11565b9060018060a01b0380911680600052601560205281604060002093169283600052602052604060002054906121d282151561339b565b6000526014602052604060002060001982019182116108c8576121fe916121f891612fd2565b506133e7565b9181835116036122475781516020808401516040808601516060968701518251969095166001600160a01b03168652928501919091529015159083015291810191909152608090f35b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c6964206d617070696e6700000000000000006044820152606490fd5b3461053b57600036600319011261053b576020600954600b541115604051908152f35b3461053b57600036600319011261053b576122c86136fe565b60018054610100600160a81b0319811690915560009060081c6001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461053b57600036600319011261053b576020600f54604051908152f35b3461053b57600036600319011261053b57600954600b5480821061235b575050602060005b604051908152f35b6020916123679161338e565b612353565b3461053b57600036600319011261053b576123856136fe565b6006546123938115156131ef565b8060005260136020526006604060002001600260ff1982541617905560006006556000600f55600080516020614341833981519152602060405160008152a1600080516020614361833981519152600080a2005b3461053b5760a036600319011261053b576004356044356024803590608435906064356124126136fe565b856000526020946013865261242d6040600020541515613427565b6124368761409a565b8660005260138652604060002060ff6006820154169360038510156104fa5784612617578287108061260e575b80612605575b61247290613539565b603c420180421161058e57612488908811613585565b6124956103ba888561338e565b600482015486106125c2576040516370a0823160e01b81523060048201529088908290817f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b76001600160a01b03165afa90811561054757600091612565575b50917f6901e2dccc1386be04abc9d013bc80c946841529a7350f612eb3a34a1f33968a9784600361255d96946125318a999760a09c9b1115613635565b886005820155896001820155846002820155015560405196875286015260408501526060840190612f27565b6080820152a2005b93919695949290508784813d83116125bb575b6125828183613149565b8101031261053b5792519495939491939092917f6901e2dccc1386be04abc9d013bc80c946841529a7350f612eb3a34a1f33968a6124f4565b503d612578565b87601e6064926040519262461bcd60e51b845260048401528201527f50726573616c653a204361702062656c6f7720736f6c6420746f6b656e7300006044820152fd5b50851515612469565b50831515612463565b8760256084926040519262461bcd60e51b845260048401528201527f50726573616c653a204f6e6c792070656e64696e6720726f756e6473206564696044820152647461626c6560d81b6064820152fd5b3461053b57600036600319011261053b576020600d54604051908152f35b3461053b57600036600319011261053b57611ab96132d2565b3461053b57602036600319011261053b5760a06001600160a01b03806126c3612efb565b1660005260126020526040600020908154916001810154916002820154906004600384015493015416926040519485526020850152604084015260608301526080820152f35b3461053b57600036600319011261053b57602060ff600154166040519015158152f35b3461053b57604036600319011261053b57612768612748612f11565b612750613681565b6127586136e0565b6127606132d2565b600435613760565b6001600055005b3461053b57602036600319011261053b576001600160a01b03612790612efb565b166000526010602052602060ff604060002054166040519015158152f35b3461053b57600036600319011261053b576020600954604051908152f35b3461053b57600036600319011261053b576020601654604051908152f35b3461053b57600036600319011261053b576020600e54604051908152f35b3461053b57600036600319011261053b576020600554604051908152f35b3461053b57600036600319011261053b5761283f6136fe565b60015460ff81161561287e5760ff19166001557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b604051638dfc202b60e01b8152600490fd5b3461053b57600036600319011261053b57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000009168152f35b3461053b5760208060031936011261053b576004356128eb6136fe565b6128f96107d0821115613293565b600a8190556040516318160ddd60e01b815282816004817f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b76001600160a01b03165afa908115610547576000916129ae575b50612710916129599161372d565b0490600954821061296a5750600b55005b6064906040519062461bcd60e51b82526004820152601e60248201527f50726573616c653a204361702062656c6f7720646973747269627574656400006044820152fd5b90508281813d83116129d6575b6129c58183613149565b8101031261053b575161271061294b565b503d6129bb565b3461053b57600036600319011261053b576040517f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b76001600160a01b03168152602090f35b3461053b57602036600319011261053b576001600160a01b03612a43612efb565b1660005260146020526020604060002054604051908152f35b3461053b57600036600319011261053b576040517f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b03168152602090f35b3461053b5760c036600319011261053b57600435612abd612f11565b604435916064359260ff841680940361053b57612ad8613681565b612ae06136e0565b612aec42821015613247565b612af46132d2565b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b031693843b1561053b5760e460009283604051978894859363d505accf60e01b85523360048601523060248601528860448601526064850152608484015260843560a484015260a43560c48401525af19283156105475761276893612b82575b50613760565b612b8b90613119565b83612b7c565b3461053b57602036600319011261053b5760043560165481101561053b57612bba602091612f85565b905460405160039290921b1c6001600160a01b03168152f35b3461053b57602036600319011261053b57600435612bef6136fe565b80151580612c3e575b15612c0257600b55005b60405162461bcd60e51b8152602060048201526014602482015273050726573616c653a20496e76616c6964206361760641b6044820152606490fd5b50600954811015612bf8565b3461053b5760a036600319011261053b576004356024356044359160ff831680930361053b57612c78613681565b612c806136e0565b612c8c42831015613247565b612c946132d2565b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b03169260009290843b1561053b5760e460009283604051978894859363d505accf60e01b85523360048601523060248601528860448601526064850152608484015260643560a484015260843560c48401525af19283156105475761276893612d255750613760565b612d30919250613119565b60009083612b7c565b3461053b57600036600319011261053b576040517f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b03168152602090f35b3461053b57600036600319011261053b57612d976131b7565b50600654611eea8115156131ef565b3461053b57604036600319011261053b57612dbf612efb565b60243560018060a01b038060015460081c1633148015612ed3575b612de390613022565b612deb613681565b612df8818416151561307f565b7f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b716916040516370a0823160e01b8152306004820152602081602481875afa90811561054757600091612ea1575b5082827f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436495612e7a83612e7f95101561316b565b6136a4565b604080516001600160a01b039290921682526020820192909252a16001600055005b90506020813d602011612ecb575b81612ebc60209383613149565b8101031261053b575182612e46565b3d9150612eaf565b50600c5481163314612dda565b3461053b57600036600319011261053b57602090600a548152f35b600435906001600160a01b038216820361053b57565b602435906001600160a01b038216820361053b57565b9060038210156109235752565b612f839092919260c08060e0830195805184526020810151602085015260408101516040850152606081015160608501526080810151608085015260a081015160a08501520151910190612f27565b565b601654811015612fbc5760166000527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b51242890190600090565b634e487b7160e01b600052603260045260246000fd5b8054821015612fbc5760005260206000209060021b0190600090565b90815180825260208080930193019160005b82811061300e575050505090565b835185529381019392810192600101613000565b1561302957565b60405162461bcd60e51b815260206004820152602860248201527f50726573616c653a2063616c6c6572206973206e6f74206f776e6572206f722060448201526774696d656c6f636b60c01b6064820152608490fd5b1561308657565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20496e76616c6964206164647265737300000000000000006044820152606490fd5b60e0810190811067ffffffffffffffff8211176130e757604052565b634e487b7160e01b600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176130e757604052565b67ffffffffffffffff81116130e757604052565b60a0810190811067ffffffffffffffff8211176130e757604052565b90601f8019910116810190811067ffffffffffffffff8211176130e757604052565b1561317257565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a20496e73756666696369656e742062616c616e63650000006044820152606490fd5b604051906131c4826130cb565b8160c06000918281528260208201528260408201528260608201528260808201528260a08201520152565b156131f657565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a204e6f2061637469766520726f756e6400000000000000006044820152606490fd5b60038210156109235752565b1561324e57565b60405162461bcd60e51b815260206004820152601760248201527f50726573616c653a205065726d697420657870697265640000000000000000006044820152606490fd5b1561329a57565b60405162461bcd60e51b815260206004820152601060248201526f50726573616c653a204d61782032302560801b6044820152606490fd5b600654801561338b576000908152601360205260408120600681019081549160ff831660038110156133775760011480613358575b613312575b50505050565b60026000805160206143618339815191529360ff19161790558260065582600f556000805160206143418339815191526020604051858152a1549180a23880808061330c565b5060028201544211806133075750600482015460058301541115613307565b634e487b7160e01b85526021600452602485fd5b50565b919082039182116108c857565b156133a257565b60405162461bcd60e51b815260206004820152601b60248201527f50726573616c653a20526566657272616c206e6f7420666f756e6400000000006044820152606490fd5b906040516133f4816130fd565b82546001600160a01b0316815260018301546020820152600283015460ff16151560408201526003909201546060830152565b1561342e57565b60405162461bcd60e51b815260206004820152601860248201527f50726573616c653a20526f756e64206e6f7420666f756e6400000000000000006044820152606490fd5b67ffffffffffffffff81116130e75760051b60200190565b9061349582613473565b6134a26040519182613149565b82815280926134b3601f1991613473565b0190602036910137565b8051821015612fbc5760209160051b010190565b156134d857565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a20496e76616c69642072656c6174696f6e736869700000006044820152606490fd5b919082018092116108c857565b60001981146108c85760010190565b1561354057565b60405162461bcd60e51b815260206004820152601760248201527f50726573616c653a20496e76616c696420706172616d730000000000000000006044820152606490fd5b1561358c57565b60405162461bcd60e51b815260206004820152602f60248201527f50726573616c653a2053746172742074696d65206d757374206265206166746560448201526e72206d696e696d756d2064656c617960881b6064820152608490fd5b156135f057565b60405162461bcd60e51b815260206004820152601d60248201527f50726573616c653a204475726174696f6e2065786365656473206d61780000006044820152606490fd5b1561363c57565b60405162461bcd60e51b815260206004820152601f60248201527f50726573616c653a20496e73756666696369656e7420696e76656e746f7279006044820152606490fd5b600260005414613692576002600055565b604051633ee5aeb560e01b8152600490fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152612f83916110ea606483613149565b60ff600154166136ec57565b60405163d93c066560e01b8152600490fd5b60015460081c6001600160a01b0316330361371557565b60405163118cdaa760e01b8152336004820152602490fd5b818102929181159184041417156108c857565b811561374a570490565b634e487b7160e01b600052601260045260246000fd5b60065461376e8115156131ef565b6000526013602052604060002060ff60068201541660038110156109235760011480613bee575b80613be0575b80613bcf575b1561161f5781158015906115da57604051636eb1769f60e11b81523360048201523060248201526001600160a01b03917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48831691602081604481865afa8015610547578691600091613b9a575b50106115635760038401549080613b91575b1561151557613856906110a06110717f0000000000000000000000000000000000000000000000000000000000000006886141c0565b9460035486106114d05761389c6138c092846002541690604051916323b872dd60e01b60208401523360248401526044830152876064830152606482526110ea8261312d565b33600052601260205260016040600020016138b886825461351d565b905533613bfc565b6138c933614212565b8082161515600081613b7b575b60009180613b72575b613b2b575b506138f78161116288600488015461351d565b6005850154106113f75761390b818761351d565b926040516370a0823160e01b8152306004820152602081602481857f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7165afa8015610547578590600090613af5575b6139669250101561316b565b6139938733837f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7166136a4565b81613a3f575b5050506139aa81600484015461351d565b600483015533600052601260205260406000206139c885825461351d565b90556139d681600d5461351d565b600d55600f54908082106112b7576139ff6020916000805160206143418339815191529361338e565b80600f55604051908152a1549160405191825260208201527f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f160403392a3565b6040817fe679beb5d98a54fda65331587d36d13358e8bf295be15e932c482164f8fde95e928516600052601260205260028260002001613a8085825461351d565b9055808516600052601260205260038260002001613a9e815461352a565b9055613aac8460095461351d565b600955613adc8486837f000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7166136a4565b86548251948552602085015233941692a3388080613999565b50506020813d602011613b23575b81613b1060209383613149565b8101031261053b5784613966915161395a565b3d9150613b03565b9050600954613b3a828261351d565b90600b54809211613b4e575b5050386138e4565b90915080821115613b6957613b629161338e565b3880613b46565b50506000613b62565b508015156138df565b50612710613b8b6007548861372d565b046138d6565b50801515613820565b9150506020813d602011613bc7575b81613bb660209383613149565b8101031261053b578590513861380e565b3d9150613ba9565b5060048101546005820154116137a1565b50600281015442111561379b565b506001810154421015613795565b6001600160a01b038281169290831561400257808316926000928484526020906010825260409260ff8487205416613fa257868814613f5e57803b613f0e57813b613ebb5790613c4b9161415b565b613e7a5785845260118152818420858552815260ff8285205416613e295784845260128152600482852001916001600160601b0360a01b928784825416179055601082528085209160ff19926001848254161790558151613cab816130fd565b87815281810142815283820188815260608301918983528b8a5260148552858a2097885468010000000000000000998a821015613e155790613cf291600182018155612fd2565b959095613e015792601796959492613d2f928c600396511690875416178655516001860155511515600285019060ff801983541691151516179055565b5191015588875260148152828720546015825283882089895282528388205588875252842090815460ff811615613d8c575b5050505050807fdf63218877cb126f6c003f2b7f77327674cd6a0b53ad51deac392548ec12b0ed91a3565b16600117905560165490811015613ded5790613dd08260017fdf63218877cb126f6c003f2b7f77327674cd6a0b53ad51deac392548ec12b0ed959401601655612f85565b819291549060031b9187831b921b19161790559038808080613d61565b634e487b7160e01b83526041600452602483fd5b634e487b7160e01b8c5260048c905260248cfd5b634e487b7160e01b8d52604160045260248dfd5b608491519062461bcd60e51b82526004820152602660248201527f50726573616c653a20526566657272616c2064656163746976617465642062796044820152651030b236b4b760d11b6064820152fd5b606491519062461bcd60e51b825280600483015260248201527f50726573616c653a20526566657272616c206379636c652064657465637465646044820152fd5b835162461bcd60e51b815260048101849052602660248201527f50726573616c653a2052656665727265722063616e6e6f74206265206120636f6044820152651b9d1c9858dd60d21b6064820152608490fd5b835162461bcd60e51b815260048101849052602360248201527f50726573616c653a2042757965722063616e6e6f74206265206120636f6e74726044820152621858dd60ea1b6064820152608490fd5b835162461bcd60e51b815260048101849052601e60248201527f50726573616c653a2043616e6e6f7420726566657220796f757273656c6600006044820152606490fd5b5050819695945092601260049394522001541614613ffe57505162461bcd60e51b815260206004820181905260248201527f50726573616c653a20526566657272657220616c7265616479206c6f636b65646044820152606490fd5b9050565b9250501660005260106020526040600020805460ff811615614022575050565b60ff19166001179055565b906000602091828151910182855af115610547576000513d61408057506001600160a01b0381163b155b61405e5750565b604051635274afe760e01b81526001600160a01b039091166004820152602490fd5b60011415614057565b60ff16604d81116108c857600a0a90565b801561338b576000818152601360205260408120906006820180549260ff8416600381101561414757600114908161411c575b506140d85750505050565b60026000805160206143618339815191529360ff19161790558060065580600f556000805160206143418339815191526020604051838152a180a23880808061330c565b6002810154421191508115614133575b50386140cd565b90506005600482015491015411153861412c565b634e487b7160e01b84526021600452602484fd5b906000905b600a82111561417157505050600190565b6001600160a01b039081169081156141b75780841682146141ae576141a8916000526012602052600460406000200154169161352a565b90614160565b50505050600190565b50505050600090565b9060ff166012811461420e57601281106141f657601119019060ff82116108c8576141ed6141f392614089565b90613740565b90565b6012039060ff82116108c85761109a6141f392614089565b5090565b6001600160a01b03908116600081815260126020908152604080832060040154909416939091841561432e5760ff60085416158015614336575b61432e5784815260118352818120848252835260ff828220541661432e578481526015835281812084825283528181205490811561432557858152601484528281209060001983019283116143115750859392916142a991612fd2565b5091600283019283549360ff8516156142c7575b5050505050505090565b60017fc860b5cda3190d9c7509acc31e40b42a3a12756b1d00d31d67f570bc845c3fd59560ff1916179055600342910155815190600182524290820152a3388181808080806142bd565b634e487b7160e01b81526011600452602490fd5b94505050505090565b935050505090565b506007541561424c56fe7e9c0e320e234667f81e817ec078e4b6f73c2cfe90ddda113cdc742931b16633aa97d4a7b3afec5f55c25ca8593dde6929d4455fad650a16fa4334004293a618a2646970667358221220645b87737c0babd2132ee13577b4851661a71883f535c38de6d9793081845a6b64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000047ced79fd38e1c77739891aab40e5f66e6deb157000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7
-----Decoded View---------------
Arg [0] : _liqHolder (address): 0x47cED79fD38E1C77739891Aab40E5F66E6deb157
Arg [1] : _usdcToken (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [2] : _token (address): 0x102897Eeac4e88FEa1e852ba5D7370415A5235B7
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000047ced79fd38e1c77739891aab40e5f66e6deb157
Arg [1] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [2] : 000000000000000000000000102897eeac4e88fea1e852ba5d7370415a5235b7
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.