Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StakingEngineLinear
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 300 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// Top‐level pool interface
interface IPool {
function transferTokens(uint256 amount) external returns (bool);
function receiveTokens(address from, uint256 amount) external returns (bool);
}
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "../governance/libraries/ProposalTypes.sol";
import "hardhat/console.sol";
/*
Staking Periods and Rewards
User cannot claim rewards before the staking priod is over
| Lock Period | Duration | Fixed APY | Referrer Reward |
|-------------|----------|-----------|-----------------|
| LOCK_PERIOD_1 | 90 days | 2% | 0% |
| LOCK_PERIOD_2 | 180 days | 6% | 1% |
| LOCK_PERIOD_3 | 365 days | 15% | 4% |
*/
/*
Maximum and Minimum Limits
| Limit | Value | Description |
|-------|-------|-------------|
| Minimum Stake Amount | > 0 | The amount staked must be greater than zero |
| MAX_STAKES_TO_PROCESS | 100 | Maximum number of stakes that can be processed in a single operation (for gas efficiency) |
| PRECISION_FACTOR | 1e18 | Used for precision in calculations to avoid rounding errors |
*/
/// @title StakingEngine
/// @notice Handles token staking with different lock periods and rewards
/// @dev Non-upgradeable version of the staking contract with separate stake and reward pool addresses
contract StakingEngineLinear is AccessControl, ReentrancyGuard, Pausable {
using SafeERC20 for IERC20;
// Define roles for access control
// bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE");
// Lock periods in seconds
uint32 public constant LOCK_PERIOD_1 = 90 days;
uint32 public constant LOCK_PERIOD_2 = 180 days;
uint32 public constant LOCK_PERIOD_3 = 365 days;
// Fixed APY percentages for each lock period
uint256 public constant FIXED_APY_90_DAYS = 2; // 2% for 90 days
uint256 public constant FIXED_APY_180_DAYS = 6; // 6% for 180 days
uint256 public constant FIXED_APY_365_DAYS = 15; // 15% for 365 days
// Referrer reward percentages for each lock period
uint256 public constant REFERRER_REWARD_PERCENT_90_DAYS = 0; // 0% for 90 days
uint256 public constant REFERRER_REWARD_PERCENT_180_DAYS = 1; // 1% for 180 days
uint256 public constant REFERRER_REWARD_PERCENT_365_DAYS = 4; // 4% for 365 days
// Precision factor for calculations to avoid rounding errors
uint256 public constant PRECISION_FACTOR = 1e18;
// Maximum number of stakes to process in a single operation
uint256 public constant MAX_STAKES_TO_PROCESS = 100;
// Referrer reward claim period
uint256 public constant REFERRER_CLAIM_PERIOD = 1 days;
struct StakeInfo {
uint256 amount;
uint256 rewardDebt; // Tracks user's share of accumulated rewards
uint256 lockPeriod;
uint256 startTime; // Track when the stake was created
address referrer; // Address of the referrer (if any)
bool isActive; // Whether the stake is still active
}
struct ReferrerInfo {
uint256 totalReferred; // Total amount of tokens referred
uint256 totalReferrerRewards; // Total rewards earned by the referrer
uint256 unclaimedRewards; // Unclaimed rewards
uint256 lastClaimTime; // Last time rewards were claimed
uint256 referredStakersCount; // Number of unique stakers referred
uint256 activeReferredStakersCount; // Number of active stakers referred
uint256 totalActiveStaked; // Total amount of tokens currently staked by referees
uint256 totalUnstaked; // Total amount of tokens unstaked by referees
uint256 totalActiveStaked90Days; // Total active staked for 90 days
uint256 totalActiveStaked180Days; // Total active staked for 180 days
uint256 totalActiveStaked365Days; // Total active staked for 365 days
}
struct ReferrerRewardInfo {
uint256 stakeId; // ID of the stake
uint256 amount; // Amount of the stake
uint256 lockPeriod; // Lock period of the stake
uint256 startTime; // Start time of the stake
uint256 endTime; // End time of the stake (startTime + lockPeriod)
uint256 totalReward; // Total reward for the referrer
uint256 claimedReward; // Amount of reward already claimed
uint256 nextClaimTime; // Next time rewards can be claimed
bool isActive; // Whether the stake is still active
address referee; // Address of the referee
}
// Mapping from referrer to array of referred stakers
mapping(address => address[]) public referredStakers;
// Mapping from referrer to mapping of staker to whether they are referred
mapping(address => mapping(address => bool)) public isReferred;
// Mapping from referrer to array of referrer reward info
mapping(address => ReferrerRewardInfo[]) public referrerRewards;
mapping(address => StakeInfo[]) public stakes;
mapping(address => ReferrerInfo) public referrers;
mapping(address => mapping(uint256 => uint256)) public referrerRewardsByPeriod;
uint256 public totalStaked;
uint256 public lastUpdateTime;
IERC20 public token;
// CHANGE: Separate stake and reward pool addresses instead of single tokenPool
address public stakePool;
address public rewardPool;
IPool public stakePoolContract;
IPool public rewardPoolContract;
// Tracking variables for internal accounting
uint256 public accRewardPerToken90Days;
uint256 public accRewardPerToken180Days;
uint256 public accRewardPerToken365Days;
uint256 public totalStaked90Days;
uint256 public totalStaked180Days;
uint256 public totalStaked365Days;
// --- New variables for global queries ---
// List of all staker addresses (unique, append-only)
address[] private allStakerAddresses;
mapping(address => bool) private isKnownStaker;
// For each lock period, a list of staker addresses (unique, append-only)
mapping(uint256 => address[]) private stakerAddressesByPeriod;
mapping(uint256 => mapping(address => bool)) private isStakerInPeriod;
// List of all referrer addresses (unique, append-only)
address[] private allReferrerAddresses;
mapping(address => bool) private isKnownReferrer;
// For each lock period, a list of referrer addresses (unique, append-only)
mapping(uint256 => address[]) private referrerAddressesByPeriod;
mapping(uint256 => mapping(address => bool)) private isReferrerInPeriod;
event RewardsAdded(uint256 amount);
event RewardsWithdrawn(uint256 amount);
event Staked(address indexed user, uint256 amount, uint256 lockPeriod);
event StakedWithReferrer(address indexed user, address indexed referrer, uint256 amount, uint256 lockPeriod);
event Unstaked(address indexed user, uint256 amount, uint256 distributedReward, uint256 penalty);
event MissedRewards(address indexed user, uint256 amount);
event ReferrerRewardsClaimed(address indexed referrer, uint256 amount);
event ReferrerRewardUpdated(address indexed referrer, address indexed referee, uint256 stakeId, uint256 amount, uint256 lockPeriod);
event TokensTransferredToStorageToken(address indexed from, uint256 amount);
event RewardDistributionLog(
address indexed user,
uint256 amount,
uint256 pendingRewards,
uint256 penalty,
uint256 rewardPoolBalance,
uint256 lockPeriod,
uint256 elapsedTime
);
event UnableToDistributeRewards(address indexed user, uint256 rewardPoolBalance, uint256 stakedAmount, uint256 finalRewards, uint256 lockPeriod);
event EmergencyAction(string action, uint256 timestamp);
event PoolBalanceReconciled(uint256 amount, bool isExcess);
error OperationFailed(uint256 code);
error TotalStakedTooLow(uint256 totalStaked, uint256 required);
error APYCannotBeSatisfied(uint8 stakingPeriod, uint256 projectedAPY, uint256 minimumAPY);
error InvalidStorageTokenAddress();
error NoReferrerRewardsAvailable();
error InvalidTokenAddress();
error InvalidReferrerAddress();
error InsufficientApproval();
error NoClaimableRewards();
error ClaimPeriodNotReached();
/**
* @notice Constructor for the non-upgradeable contract
* @param _token Address of the StorageToken
* @param _stakePool Address of the stake pool
* @param _rewardPool Address of the reward pool
* @param initialOwner Address of the initial owner
* @param initialAdmin Address of the initial admin
*/
constructor(
address _token,
address _stakePool,
address _rewardPool,
address initialOwner,
address initialAdmin
) {
require(
_token != address(0) &&
_stakePool != address(0) &&
_rewardPool != address(0) &&
initialOwner != address(0) &&
initialAdmin != address(0),
"Invalid address"
);
// Validate that the token address is a valid ERC20 token
try IERC20(_token).totalSupply() returns (uint256) {
// Token implements totalSupply, likely a valid ERC20
} catch {
revert InvalidTokenAddress();
}
// Initialize roles
_grantRole(OWNER_ROLE, initialOwner);
_grantRole(ProposalTypes.ADMIN_ROLE, initialOwner); // Grant ADMIN_ROLE to owner as well
_grantRole(ProposalTypes.ADMIN_ROLE, initialAdmin);
_setRoleAdmin(ProposalTypes.ADMIN_ROLE, OWNER_ROLE);
token = IERC20(_token);
stakePool = _stakePool;
rewardPool = _rewardPool;
stakePoolContract = IPool(_stakePool);
rewardPoolContract = IPool(_rewardPool);
// Initialize tracking variables
lastUpdateTime = block.timestamp;
}
/**
* @notice Emergency pause reward distribution
* @dev Can only be called by admin
*/
function emergencyPauseRewardDistribution() external onlyRole(ProposalTypes.ADMIN_ROLE) {
_pause();
emit EmergencyAction("Rewards Distribution paused", block.timestamp);
}
/**
* @notice Emergency unpause reward distribution
* @dev Can only be called by admin
*/
function emergencyUnpauseRewardDistribution() external onlyRole(ProposalTypes.ADMIN_ROLE) {
_unpause();
emit EmergencyAction("Rewards Distribution unpaused", block.timestamp);
}
/**
* @notice Add rewards to the pool
* @param amount Amount of rewards to add
*/
function addRewardsToPool(uint256 amount) external onlyRole(ProposalTypes.ADMIN_ROLE) {
// Transfer tokens from sender to pool
token.safeTransferFrom(msg.sender, rewardPool, amount);
rewardPoolContract.receiveTokens(msg.sender, amount);
emit RewardsAdded(amount);
}
/**
* @notice Get excess rewards (rewards beyond what's needed for current stakes)
* @return Amount of excess rewards
*/
function getExcessRewards() public view returns (uint256) {
uint256 requiredRewards = calculateRequiredRewards();
uint256 poolBalance = token.balanceOf(rewardPool);
if (poolBalance > requiredRewards) {
return poolBalance - requiredRewards;
}
return 0;
}
/**
* @notice Calculate rewards required for current stakes
* @return Amount of rewards required
*/
function calculateRequiredRewards() public view returns (uint256) {
// Calculate required rewards based on current stakes and APY
uint256 required90Days = (totalStaked90Days * FIXED_APY_90_DAYS) / 100;
uint256 required180Days = (totalStaked180Days * FIXED_APY_180_DAYS) / 100;
uint256 required365Days = (totalStaked365Days * FIXED_APY_365_DAYS) / 100;
return required90Days + required180Days + required365Days;
}
/**
* @notice Get detailed pool status
* @return totalPoolBalance Expected total balance in pool
* @return stakedAmount Amount of staked tokens
* @return rewardsAmount Amount of reward tokens
*/
function getPoolStatus() external view returns (
uint256 totalPoolBalance,
uint256 stakedAmount,
uint256 rewardsAmount
) {
totalPoolBalance = token.balanceOf(stakePool) + token.balanceOf(rewardPool);
stakedAmount = token.balanceOf(stakePool);
rewardsAmount = token.balanceOf(rewardPool);
return (totalPoolBalance, stakedAmount, rewardsAmount);
}
/**
* @notice Get all stakes for a user
* @param user Address of the user
* @return Array of StakeInfo structs
*/
function getUserStakes(address user) external view returns (StakeInfo[] memory) {
return stakes[user];
}
/**
* @notice Get total staked amount by a user
* @param user Address of the user
* @return Total staked amount
*/
function getUserTotalStaked(address user) external view returns (uint256) {
uint256 total = 0;
StakeInfo[] memory userStakes = stakes[user];
for (uint256 i = 0; i < userStakes.length; i++) {
if (userStakes[i].isActive) {
total += userStakes[i].amount;
}
}
return total;
}
/**
* @notice Get total staked amount across all users
* @return Total staked amount
*/
function getTotalStaked() external view returns (uint256) {
return totalStaked;
}
/**
* @notice Get all referrer statistics
* @param referrer Address of the referrer
* @return ReferrerInfo struct with all statistics
*/
function getReferrerStats(address referrer) external view returns (ReferrerInfo memory) {
return referrers[referrer];
}
/**
* @notice Get all referred stakers for a referrer
* @param referrer Address of the referrer
* @return Array of referred staker addresses
*/
function getReferredStakers(address referrer) external view returns (address[] memory) {
return referredStakers[referrer];
}
/**
* @notice Get all referrer rewards
* @param referrer Address of the referrer
* @return Array of ReferrerRewardInfo structs
*/
function getReferrerRewards(address referrer) external view returns (ReferrerRewardInfo[] memory) {
return referrerRewards[referrer];
}
/**
* @notice Get claimable rewards for a referrer
* @param referrer Address of the referrer
* @return Claimable rewards amount
*/
function getClaimableReferrerRewards(address referrer) public view returns (uint256) {
uint256 claimable = 0;
ReferrerRewardInfo[] memory rewards = referrerRewards[referrer];
for (uint256 i = 0; i < rewards.length; i++) {
if (rewards[i].isActive && block.timestamp >= rewards[i].nextClaimTime) {
// Calculate how many claim periods have passed since last claim
uint256 timeSinceLastClaim = block.timestamp - (rewards[i].nextClaimTime - REFERRER_CLAIM_PERIOD);
uint256 claimPeriodsPassed = timeSinceLastClaim / REFERRER_CLAIM_PERIOD;
// Only proceed if at least one period has passed
if (claimPeriodsPassed > 0) {
// Calculate total time from start to now
uint256 totalTimeElapsed = block.timestamp - rewards[i].startTime;
// Calculate total reward per day
uint256 rewardPerDay = rewards[i].totalReward / (rewards[i].lockPeriod / 1 days);
// Calculate reward for the claim periods
uint256 daysToReward = claimPeriodsPassed * (REFERRER_CLAIM_PERIOD / 1 days);
// Ensure we don't exceed the lock period
if (totalTimeElapsed > rewards[i].lockPeriod) {
daysToReward = (rewards[i].lockPeriod / 1 days) - (rewards[i].claimedReward / rewardPerDay);
}
uint256 periodReward = rewardPerDay * daysToReward;
// Ensure we don't exceed the total reward
if (rewards[i].claimedReward + periodReward > rewards[i].totalReward) {
periodReward = rewards[i].totalReward - rewards[i].claimedReward;
}
claimable += periodReward;
}
}
}
return claimable;
}
/**
* @notice Update accumulated rewards
* @dev Updates the accumulated rewards per token for each lock period
*/
function updateRewards() public {
if (block.timestamp <= lastUpdateTime) {
return;
}
uint256 timeElapsed = block.timestamp - lastUpdateTime;
// Update accumulated rewards for each lock period
if (totalStaked90Days > 0) {
uint256 rewardsForPeriod = calculateElapsedRewards(totalStaked90Days, FIXED_APY_90_DAYS, timeElapsed);
accRewardPerToken90Days += (rewardsForPeriod * PRECISION_FACTOR) / totalStaked90Days;
}
if (totalStaked180Days > 0) {
uint256 rewardsForPeriod = calculateElapsedRewards(totalStaked180Days, FIXED_APY_180_DAYS, timeElapsed);
accRewardPerToken180Days += (rewardsForPeriod * PRECISION_FACTOR) / totalStaked180Days;
}
if (totalStaked365Days > 0) {
uint256 rewardsForPeriod = calculateElapsedRewards(totalStaked365Days, FIXED_APY_365_DAYS, timeElapsed);
accRewardPerToken365Days += (rewardsForPeriod * PRECISION_FACTOR) / totalStaked365Days;
}
lastUpdateTime = block.timestamp;
}
/**
* @notice Internal function to stake tokens
* @param amount The amount to stake
* @param lockPeriod The lock period (90, 180, or 365 days)
* @param referrer Optional address of the referrer
*/
function _stakeTokenInternal(uint256 amount, uint256 lockPeriod, address referrer) internal {
// Update rewards before processing the stake
updateRewards();
// Calculate pending rewards for existing stakes
uint256 pendingRewards = 0;
for (uint256 i = 0; i < stakes[msg.sender].length; i++) {
StakeInfo storage stake = stakes[msg.sender][i];
if (stake.isActive) {
uint256 accRewardPerToken1 = getAccRewardPerTokenForLockPeriod(stake.lockPeriod);
uint256 pendingReward = (stake.amount * (accRewardPerToken1 - stake.rewardDebt)) / PRECISION_FACTOR;
pendingRewards += pendingReward;
// Update reward debt to current accumulated rewards
stake.rewardDebt = accRewardPerToken1;
}
}
// Add new stake
uint256 accRewardPerToken = getAccRewardPerTokenForLockPeriod(lockPeriod);
stakes[msg.sender].push(
StakeInfo({
amount: amount,
rewardDebt: accRewardPerToken,
lockPeriod: lockPeriod,
startTime: block.timestamp,
referrer: referrer,
isActive: true
})
);
// Update total staked amounts
totalStaked += amount;
if (lockPeriod == LOCK_PERIOD_1) {
totalStaked90Days += amount;
} else if (lockPeriod == LOCK_PERIOD_2) {
totalStaked180Days += amount;
} else if (lockPeriod == LOCK_PERIOD_3) {
totalStaked365Days += amount;
}
// Update referrer information if provided
if (referrer != address(0)) {
ReferrerInfo storage referrerInfo = referrers[referrer];
// If this is a new referee for this referrer
if (!isReferred[referrer][msg.sender]) {
isReferred[referrer][msg.sender] = true;
referredStakers[referrer].push(msg.sender);
referrerInfo.referredStakersCount++;
referrerInfo.activeReferredStakersCount++;
}
referrerInfo.totalReferred += amount;
referrerInfo.totalActiveStaked += amount;
if (lockPeriod == LOCK_PERIOD_1) {
referrerInfo.totalActiveStaked90Days += amount;
} else if (lockPeriod == LOCK_PERIOD_2) {
referrerInfo.totalActiveStaked180Days += amount;
} else if (lockPeriod == LOCK_PERIOD_3) {
referrerInfo.totalActiveStaked365Days += amount;
}
// Calculate referrer reward based on lock period
uint256 referrerRewardPercent = 0;
if (lockPeriod == LOCK_PERIOD_1) {
referrerRewardPercent = REFERRER_REWARD_PERCENT_90_DAYS;
} else if (lockPeriod == LOCK_PERIOD_2) {
referrerRewardPercent = REFERRER_REWARD_PERCENT_180_DAYS;
} else if (lockPeriod == LOCK_PERIOD_3) {
referrerRewardPercent = REFERRER_REWARD_PERCENT_365_DAYS;
}
if (referrerRewardPercent > 0) {
uint256 totalReferrerReward = (amount * referrerRewardPercent) / 100;
// Add to referrer rewards
referrerRewards[referrer].push(
ReferrerRewardInfo({
stakeId: stakes[msg.sender].length - 1,
amount: amount,
lockPeriod: lockPeriod,
startTime: block.timestamp,
endTime: block.timestamp + lockPeriod,
totalReward: totalReferrerReward,
claimedReward: 0,
nextClaimTime: block.timestamp + REFERRER_CLAIM_PERIOD,
isActive: true,
referee: msg.sender
})
);
// Update unclaimed rewards
referrerInfo.unclaimedRewards += totalReferrerReward;
// Update rewards by period
referrerRewardsByPeriod[referrer][lockPeriod] += totalReferrerReward;
emit ReferrerRewardUpdated(referrer, msg.sender, stakes[msg.sender].length - 1, totalReferrerReward, lockPeriod);
}
}
// --- Track all stakers globally and per period ---
if (!isKnownStaker[msg.sender]) {
isKnownStaker[msg.sender] = true;
allStakerAddresses.push(msg.sender);
}
if (!isStakerInPeriod[lockPeriod][msg.sender]) {
isStakerInPeriod[lockPeriod][msg.sender] = true;
stakerAddressesByPeriod[lockPeriod].push(msg.sender);
}
// --- Track all referrers globally and per period ---
if (referrer != address(0)) {
if (!isKnownReferrer[referrer]) {
isKnownReferrer[referrer] = true;
allReferrerAddresses.push(referrer);
}
if (!isReferrerInPeriod[lockPeriod][referrer]) {
isReferrerInPeriod[lockPeriod][referrer] = true;
referrerAddressesByPeriod[lockPeriod].push(referrer);
}
}
// Check if the user has sufficient allowance for this contract
if (token.allowance(msg.sender, address(this)) < amount) {
revert InsufficientApproval();
}
// Check if there are sufficient rewards available for the APY
uint256 projectedAPY = calculateProjectedAPY(amount, lockPeriod);
uint256 minimumAPY = 0;
if (lockPeriod == LOCK_PERIOD_1) {
minimumAPY = FIXED_APY_90_DAYS;
} else if (lockPeriod == LOCK_PERIOD_2) {
minimumAPY = FIXED_APY_180_DAYS;
} else if (lockPeriod == LOCK_PERIOD_3) {
minimumAPY = FIXED_APY_365_DAYS;
}
if (projectedAPY < minimumAPY) {
revert APYCannotBeSatisfied(uint8(lockPeriod / (30 days)), projectedAPY, minimumAPY);
}
// Execute external interactions after state changes
// Transfer staked tokens to pool
token.safeTransferFrom(msg.sender, stakePool, amount);
stakePoolContract.receiveTokens(msg.sender, amount);
if (pendingRewards > 0) {
// Check if the pool has sufficient balance for rewards
uint256 poolBalance = token.balanceOf(rewardPool);
uint256 availableForRewards = poolBalance;
if (availableForRewards < pendingRewards) {
emit UnableToDistributeRewards(msg.sender, availableForRewards, amount, pendingRewards, lockPeriod);
} else {
// Transfer rewards
rewardPoolContract.transferTokens(pendingRewards);
token.safeTransfer(msg.sender, pendingRewards);
}
}
}
/**
* @dev Stakes tokens with an optional referrer
* @param amount The amount to stake
* @param lockPeriod The lock period (90, 180, or 365 days)
* @param referrer Optional address of the referrer
*/
function stakeTokenWithReferrer(uint256 amount, uint256 lockPeriod, address referrer) external nonReentrant whenNotPaused {
require(amount > 0, "Amount must be greater than zero");
require(
lockPeriod == LOCK_PERIOD_1 || lockPeriod == LOCK_PERIOD_2 || lockPeriod == LOCK_PERIOD_3,
"Invalid lock period"
);
// Limit the number of active stakes per user
uint256 activeStakes = 0;
for (uint256 i = 0; i < stakes[msg.sender].length; i++) {
if (stakes[msg.sender][i].isActive) {
activeStakes++;
}
}
require(activeStakes < 100, "Maximum number of active stakes reached");
// Make the zero address handling explicit
if (referrer == address(0)) {
// Zero address is treated as "no referrer"
_stakeTokenInternal(amount, lockPeriod, address(0));
emit Staked(msg.sender, amount, lockPeriod);
return;
}
// Referrer cannot be the same as the staker
require(referrer != msg.sender, "Cannot refer yourself");
// Additional validation to check referrer is not a contract
uint256 size;
assembly { size := extcodesize(referrer) }
require(size == 0, "Referrer cannot be a contract");
_stakeTokenInternal(amount, lockPeriod, referrer);
emit StakedWithReferrer(msg.sender, referrer, amount, lockPeriod);
}
/**
* @notice Stake tokens without a referrer
* @param amount The amount to stake
* @param lockPeriod The lock period (90, 180, or 365 days)
*/
function stakeToken(uint256 amount, uint256 lockPeriod) external nonReentrant whenNotPaused {
require(amount > 0, "Amount must be greater than zero");
require(
lockPeriod == LOCK_PERIOD_1 || lockPeriod == LOCK_PERIOD_2 || lockPeriod == LOCK_PERIOD_3,
"Invalid lock period"
);
// Limit the number of active stakes per user
uint256 activeStakes = 0;
for (uint256 i = 0; i < stakes[msg.sender].length; i++) {
if (stakes[msg.sender][i].isActive) {
activeStakes++;
}
}
require(activeStakes < 100, "Maximum number of active stakes reached");
_stakeTokenInternal(amount, lockPeriod, address(0));
emit Staked(msg.sender, amount, lockPeriod);
}
/**
* @notice Calculate rewards based on staked amount, APY, and time elapsed
* @param stakedAmount Amount staked
* @param fixedAPY Annual percentage yield
* @param timeElapsed Time elapsed in seconds
* @return Calculated rewards
*/
function calculateElapsedRewards(
uint256 stakedAmount,
uint256 fixedAPY,
uint256 timeElapsed
) internal pure returns (uint256) {
if (stakedAmount == 0) {
return 0; // No rewards if nothing is staked
}
// Calculate annualized rewards based on fixed APY
uint256 annualRewards = (stakedAmount * fixedAPY * PRECISION_FACTOR) / 100;
// Adjust rewards proportionally to elapsed time (in seconds)
if (timeElapsed == 0) {
return 0;
}
// Improved precision by using adding half divisor for rounding
return (annualRewards * timeElapsed + (365 days * PRECISION_FACTOR / 2)) / (365 days * PRECISION_FACTOR);
}
/**
* @notice Get accumulated reward per token for a specific lock period
* @param lockPeriod The lock period
* @return Accumulated reward per token
*/
function getAccRewardPerTokenForLockPeriod(uint256 lockPeriod) internal view returns (uint256) {
if (lockPeriod == LOCK_PERIOD_1) {
return accRewardPerToken90Days;
} else if (lockPeriod == LOCK_PERIOD_2) {
return accRewardPerToken180Days;
} else if (lockPeriod == LOCK_PERIOD_3) {
return accRewardPerToken365Days;
}
return 0; // Default case; should never occur due to earlier validation
}
/**
* @notice Unstake tokens and claim rewards
* @param index Index of the stake to unstake
*/
function unstakeToken(uint256 index) external nonReentrant whenNotPaused {
require(index < stakes[msg.sender].length, "Invalid stake index");
StakeInfo storage stake = stakes[msg.sender][index];
require(stake.isActive, "Stake already unstaked");
require(block.timestamp >= stake.startTime + stake.lockPeriod, "Cannot unstake before lock period ends");
updateRewards();
uint256 stakedAmount = stake.amount;
uint256 lockPeriod = stake.lockPeriod;
address referrer = stake.referrer;
// Mark stake as inactive
stake.isActive = false;
// Update total staked amounts
totalStaked -= stakedAmount;
if (lockPeriod == LOCK_PERIOD_1) {
totalStaked90Days -= stakedAmount;
} else if (lockPeriod == LOCK_PERIOD_2) {
totalStaked180Days -= stakedAmount;
} else if (lockPeriod == LOCK_PERIOD_3) {
totalStaked365Days -= stakedAmount;
}
// Update referrer info if any
if (referrer != address(0)) {
ReferrerInfo storage referrerInfo = referrers[referrer];
referrerInfo.totalActiveStaked -= stakedAmount;
referrerInfo.totalUnstaked += stakedAmount;
if (lockPeriod == LOCK_PERIOD_1) {
referrerInfo.totalActiveStaked90Days -= stakedAmount;
} else if (lockPeriod == LOCK_PERIOD_2) {
referrerInfo.totalActiveStaked180Days -= stakedAmount;
} else if (lockPeriod == LOCK_PERIOD_3) {
referrerInfo.totalActiveStaked365Days -= stakedAmount;
}
// Mark all referrer rewards for this stake as inactive
for (uint256 i = 0; i < referrerRewards[referrer].length; i++) {
if (referrerRewards[referrer][i].referee == msg.sender && referrerRewards[referrer][i].stakeId == index) {
referrerRewards[referrer][i].isActive = false;
break;
}
}
}
// Transfer staked tokens back to user
stakePoolContract.transferTokens(stakedAmount);
token.safeTransfer(msg.sender, stakedAmount);
emit Unstaked(msg.sender, stakedAmount, 0, 0);
}
/**
* @notice Claim staker rewards linearly up to lock period
* @param stakeIndex Index of the stake to claim rewards for
*/
function claimStakerReward(uint256 stakeIndex) external nonReentrant whenNotPaused {
require(stakeIndex < stakes[msg.sender].length, "Invalid stake index");
StakeInfo storage stake = stakes[msg.sender][stakeIndex];
require(stake.isActive, "Stake not active");
uint256 lockEnd = stake.startTime + stake.lockPeriod;
uint256 nowOrEnd = block.timestamp < lockEnd ? block.timestamp : lockEnd;
uint256 timeElapsed = nowOrEnd - stake.startTime;
uint256 fixedAPY = 0;
if (stake.lockPeriod == LOCK_PERIOD_1) fixedAPY = FIXED_APY_90_DAYS;
else if (stake.lockPeriod == LOCK_PERIOD_2) fixedAPY = FIXED_APY_180_DAYS;
else if (stake.lockPeriod == LOCK_PERIOD_3) fixedAPY = FIXED_APY_365_DAYS;
uint256 totalReward = (stake.amount * fixedAPY * stake.lockPeriod) / (100 * 365 days);
uint256 claimable = (totalReward * timeElapsed) / stake.lockPeriod;
// Track claimed rewards in rewardDebt
uint256 alreadyClaimed = stake.rewardDebt;
require(claimable > alreadyClaimed, "No claimable rewards");
uint256 toClaim = claimable - alreadyClaimed;
// Update rewardDebt
stake.rewardDebt = claimable;
// Transfer rewards
require(token.balanceOf(rewardPool) >= toClaim, "Insufficient rewards in pool");
rewardPoolContract.transferTokens(toClaim);
token.safeTransfer(msg.sender, toClaim);
emit RewardDistributionLog(msg.sender, stake.amount, toClaim, 0, token.balanceOf(rewardPool), stake.lockPeriod, timeElapsed);
}
/**
* @notice Claim referrer rewards linearly up to lock period
* @param rewardIndex Index of the referrer reward to claim
*/
function claimReferrerReward(uint256 rewardIndex) external nonReentrant whenNotPaused {
ReferrerRewardInfo storage info = referrerRewards[msg.sender][rewardIndex];
require(info.isActive, "Referrer reward not active");
uint256 lockEnd = info.startTime + info.lockPeriod;
uint256 nowOrEnd = block.timestamp < lockEnd ? block.timestamp : lockEnd;
uint256 timeElapsed = nowOrEnd - info.startTime;
uint256 claimable = (info.totalReward * timeElapsed) / info.lockPeriod;
uint256 alreadyClaimed = info.claimedReward;
require(claimable > alreadyClaimed, "No claimable rewards");
uint256 toClaim = claimable - alreadyClaimed;
info.claimedReward = claimable;
require(token.balanceOf(rewardPool) >= toClaim, "Insufficient rewards in pool");
rewardPoolContract.transferTokens(toClaim);
token.safeTransfer(msg.sender, toClaim);
emit ReferrerRewardsClaimed(msg.sender, toClaim);
}
/**
* @notice Calculate projected APY based on available rewards
* @param additionalStake Additional amount to be staked
* @param lockPeriod Lock period
* @return Projected APY
*/
function calculateProjectedAPY(uint256 additionalStake, uint256 lockPeriod) public view returns (uint256) {
uint256 fixedAPY = 0;
uint256 totalNeededRewards = 0;
uint256 totalStakedForPeriod = 0;
if (lockPeriod == LOCK_PERIOD_1) {
fixedAPY = FIXED_APY_90_DAYS;
totalStakedForPeriod = totalStaked90Days;
} else if (lockPeriod == LOCK_PERIOD_2) {
fixedAPY = FIXED_APY_180_DAYS;
totalStakedForPeriod = totalStaked180Days;
} else if (lockPeriod == LOCK_PERIOD_3) {
fixedAPY = FIXED_APY_365_DAYS;
totalStakedForPeriod = totalStaked365Days;
}
// Calculate total staked amount including the additional stake
uint256 newTotalStaked = totalStakedForPeriod + additionalStake;
// Calculate rewards needed for the fixed APY
totalNeededRewards = (newTotalStaked * fixedAPY) / 100;
// Get available rewards in the reward pool
uint256 availableRewards = token.balanceOf(rewardPool);
// Calculate projected APY based on available rewards
if (availableRewards >= totalNeededRewards) {
return fixedAPY; // Can satisfy the fixed APY
} else if (newTotalStaked == 0) {
return 0; // Avoid division by zero
} else {
// Ensure we return at least 1 (0.01%) if there are any available rewards
uint256 calculatedAPY = (availableRewards * 100) / newTotalStaked;
return calculatedAPY > 0 ? calculatedAPY : (availableRewards > 0 ? 1 : 0);
}
}
/**
* @notice Check if the reward pool has sufficient balance to satisfy the fixed APY
* @param lockPeriod Lock period to check
* @return Whether the reward pool has sufficient balance
*/
function canSatisfyFixedAPY(uint256 lockPeriod) external view returns (bool) {
uint256 fixedAPY = 0;
uint256 totalStakedForPeriod = 0;
if (lockPeriod == LOCK_PERIOD_1) {
fixedAPY = FIXED_APY_90_DAYS;
totalStakedForPeriod = totalStaked90Days;
} else if (lockPeriod == LOCK_PERIOD_2) {
fixedAPY = FIXED_APY_180_DAYS;
totalStakedForPeriod = totalStaked180Days;
} else if (lockPeriod == LOCK_PERIOD_3) {
fixedAPY = FIXED_APY_365_DAYS;
totalStakedForPeriod = totalStaked365Days;
}
// Calculate rewards needed for the fixed APY
uint256 totalNeededRewards = (totalStakedForPeriod * fixedAPY) / 100;
// Get available rewards in the reward pool
uint256 availableRewards = token.balanceOf(rewardPool);
return availableRewards >= totalNeededRewards;
}
/**
* @notice Check pending rewards for a user
* @param user Address of the user
* @return Total pending rewards
*/
function checkPendingRewards(address user) external view returns (uint256) {
uint256 totalPendingRewards = 0;
// Calculate pending rewards for each stake
for (uint256 i = 0; i < stakes[user].length; i++) {
StakeInfo storage stake = stakes[user][i];
if (stake.isActive) {
uint256 accRewardPerToken = getAccRewardPerTokenForLockPeriod(stake.lockPeriod);
uint256 pendingReward = (stake.amount * (accRewardPerToken - stake.rewardDebt)) / PRECISION_FACTOR;
totalPendingRewards += pendingReward;
}
}
if (totalPendingRewards > 0) {
// Check if pool has sufficient balance for rewards
uint256 poolBalance = token.balanceOf(rewardPool);
uint256 availableForRewards = poolBalance;
if (availableForRewards < totalPendingRewards) {
return 0;
} else {
return totalPendingRewards;
}
}
return 0;
}
/**
* @notice Get a single referrer reward by index
* @param referrer Address of the referrer
* @param index Index of the referrer reward
* @return ReferrerRewardInfo struct for the given index
*/
function getReferrerRewardByIndex(address referrer, uint256 index) external view returns (ReferrerRewardInfo memory) {
require(index < referrerRewards[referrer].length, "Invalid reward index");
return referrerRewards[referrer][index];
}
/**
* @notice Get a single staker reward (stake info) by index
* @param staker Address of the staker
* @param index Index of the stake
* @return StakeInfo struct for the given index
*/
function getStakerRewardByIndex(address staker, uint256 index) external view returns (StakeInfo memory) {
require(index < stakes[staker].length, "Invalid stake index");
return stakes[staker][index];
}
/**
* @notice View the claimable staker reward for a given stake index (does not transfer)
* @param staker Address of the staker
* @param stakeIndex Index of the stake to view rewards for
* @return toClaim Amount of claimable rewards for the given stake
*/
function getClaimableStakerReward(address staker, uint256 stakeIndex) external view returns (uint256 toClaim) {
require(stakeIndex < stakes[staker].length, "Invalid stake index");
StakeInfo storage stake = stakes[staker][stakeIndex];
if (!stake.isActive) return 0;
uint256 lockEnd = stake.startTime + stake.lockPeriod;
uint256 nowOrEnd = block.timestamp < lockEnd ? block.timestamp : lockEnd;
uint256 timeElapsed = nowOrEnd - stake.startTime;
uint256 fixedAPY = 0;
if (stake.lockPeriod == LOCK_PERIOD_1) fixedAPY = FIXED_APY_90_DAYS;
else if (stake.lockPeriod == LOCK_PERIOD_2) fixedAPY = FIXED_APY_180_DAYS;
else if (stake.lockPeriod == LOCK_PERIOD_3) fixedAPY = FIXED_APY_365_DAYS;
uint256 totalReward = (stake.amount * fixedAPY * stake.lockPeriod) / (100 * 365 days);
uint256 claimable = (totalReward * timeElapsed) / stake.lockPeriod;
uint256 alreadyClaimed = stake.rewardDebt;
if (claimable > alreadyClaimed) {
toClaim = claimable - alreadyClaimed;
} else {
toClaim = 0;
}
}
// --- View functions for global queries ---
/**
* @notice Get all staker addresses
*/
function getAllStakerAddresses() external view returns (address[] memory) {
return allStakerAddresses;
}
/**
* @notice Get all staker addresses for a specific period
* @param lockPeriod The lock period (use LOCK_PERIOD_1, _2, or _3)
*/
function getStakerAddressesByPeriod(uint256 lockPeriod) external view returns (address[] memory) {
return stakerAddressesByPeriod[lockPeriod];
}
/**
* @notice Get staked amounts for each staker for a specific period
* @param lockPeriod The lock period (use LOCK_PERIOD_1, _2, or _3)
* @return stakerAddresses, amounts arrays
*/
function getStakedAmountsByPeriod(uint256 lockPeriod) external view returns (address[] memory, uint256[] memory) {
address[] memory stakers = stakerAddressesByPeriod[lockPeriod];
uint256[] memory amounts = new uint256[](stakers.length);
for (uint256 i = 0; i < stakers.length; i++) {
uint256 total = 0;
StakeInfo[] storage s = stakes[stakers[i]];
for (uint256 j = 0; j < s.length; j++) {
if (s[j].lockPeriod == lockPeriod && s[j].isActive) {
total += s[j].amount;
}
}
amounts[i] = total;
}
return (stakers, amounts);
}
/**
* @notice Get all referrer addresses
*/
function getAllReferrerAddresses() external view returns (address[] memory) {
return allReferrerAddresses;
}
/**
* @notice Get all referrer addresses for a specific period
* @param lockPeriod The lock period (use LOCK_PERIOD_1, _2, or _3)
*/
function getReferrerAddressesByPeriod(uint256 lockPeriod) external view returns (address[] memory) {
return referrerAddressesByPeriod[lockPeriod];
}
/**
* @notice Get referrers who referred someone in a specific period
* @param lockPeriod The lock period (use LOCK_PERIOD_1, _2, or _3)
* @return referrers array (only those who actually referred at least one staker in that period)
*/
function getActiveReferrersByPeriod(uint256 lockPeriod) external view returns (address[] memory) {
address[] memory referrers = referrerAddressesByPeriod[lockPeriod];
// Optionally filter to only those with at least one active referral in this period
// (already handled by tracking in _stakeTokenInternal)
return referrers;
}
/**
* @notice View all stakes for a user (for testing)
*/
function getStakes(address user) external view returns (StakeInfo[] memory) {
return stakes[user];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
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.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.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 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.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (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 Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @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;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title ProposalTypes Library
/// @notice Library containing shared types and constants for governance proposals
/// @dev This library is used by both StorageToken and TokenDistributionEngine contracts
library ProposalTypes {
/// @notice Enum representing different types of proposals
enum ProposalType {
NA,
AddRole, // For adding or removing roles
RemoveRole,
Upgrade, // For contract upgrades
Recovery, // For token recovery operations
AddWhitelist, // For whitelist management
RemoveWhitelist,
AddDistributionWallets, //Adding wallet to distribution cap
RemoveDistributionWallet,
AddToBlacklist, // Adding a wallet address to Blacklist for restrictions
RemoveFromBlacklist, // Removing a wallet from blacklist
ChangeTreasuryFee // change hte fee that goes to treasury from transfers
}
/// @notice Time-related constants for proposal lifecycle
uint32 constant MIN_PROPOSAL_EXECUTION_DELAY = 24 hours;
uint32 constant PROPOSAL_TIMEOUT = 3 days;
uint32 constant ROLE_CHANGE_DELAY = 1 days;
bytes32 public constant BRIDGE_OPERATOR_ROLE = keccak256("BRIDGE_OPERATOR_ROLE");
bytes32 public constant CONTRACT_OPERATOR_ROLE = keccak256("CONTRACT_OPERATOR_ROLE");
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
// Time Constants
uint32 public constant INACTIVITY_THRESHOLD = 365 days;
uint32 public constant EMERGENCY_COOLDOWN = 30 minutes;
uint8 public constant EMERGENCY_THRESHOLD = 3;
/// @notice Structure for proposal configuration
struct ProposalConfig {
uint64 expiryTime; // Timestamp when proposal expires
uint64 executionTime; // Earliest timestamp when proposal can be executed
uint16 approvals; // Number of approvals received
uint8 status; // 1: executed
}
struct UnifiedProposal {
// Basic proposal info
uint8 proposalType;
address target; //multi-purpose for both role recipient in AddRole Proposals and Add token recipient wallet Vesting Wallet proposal and token recipient in Recovery
uint40 id; //multi-purpose for capId in add vesting wallet
bytes32 role; //multi-purpose for both role in AddRole Proposals and Add wallet name Vesting Wallet proposal
address tokenAddress; // Address of token for recovery
uint96 amount; //Multi-purpose for both amount in whitelist proposal and allocated amount in add vesting wallet
// Packed configuration
ProposalConfig config;
// Approval tracking
mapping(address => bool) hasApproved;
}
/// @notice Structure for time-related configurations
struct TimeConfig {
uint64 lastActivityTime; // Last activity timestamp
uint64 roleChangeTimeLock; // Timelock for role changes
uint64 whitelistLockTime; // Timelock for whitelist operations
}
/// @notice Structure for role-related configurations
struct RoleConfig {
uint16 quorum; // Required number of approvals
uint240 transactionLimit; // Transaction limit for role
}
/// @notice Structure for pending proposal tracking
struct PendingProposals {
uint8 proposalType; // Flags indicating pending proposal types
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS =
0x000000000000000000636F6e736F6c652e6c6f67;
function _sendLogPayloadImplementation(bytes memory payload) internal view {
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
pop(
staticcall(
gas(),
consoleAddress,
add(payload, 32),
mload(payload),
0,
0
)
)
}
}
function _castToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castToPure(_sendLogPayloadImplementation)(payload);
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}{
"optimizer": {
"enabled": true,
"runs": 300
},
"viaIR": true,
"evmVersion": "shanghai",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_stakePool","type":"address"},{"internalType":"address","name":"_rewardPool","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"address","name":"initialAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"stakingPeriod","type":"uint8"},{"internalType":"uint256","name":"projectedAPY","type":"uint256"},{"internalType":"uint256","name":"minimumAPY","type":"uint256"}],"name":"APYCannotBeSatisfied","type":"error"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ClaimPeriodNotReached","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InsufficientApproval","type":"error"},{"inputs":[],"name":"InvalidReferrerAddress","type":"error"},{"inputs":[],"name":"InvalidStorageTokenAddress","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[],"name":"NoClaimableRewards","type":"error"},{"inputs":[],"name":"NoReferrerRewardsAvailable","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"OperationFailed","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"TotalStakedTooLow","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"action","type":"string"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"EmergencyAction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MissedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isExcess","type":"bool"}],"name":"PoolBalanceReconciled","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":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"ReferrerRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReferrerRewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pendingRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPoolBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"elapsedTime","type":"uint256"}],"name":"RewardDistributionLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"StakedWithReferrer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensTransferredToStorageToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardPoolBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"finalRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"UnableToDistributeRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"distributedReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIXED_APY_180_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIXED_APY_365_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIXED_APY_90_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK_PERIOD_1","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK_PERIOD_2","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK_PERIOD_3","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKES_TO_PROCESS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OWNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRER_CLAIM_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRER_REWARD_PERCENT_180_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRER_REWARD_PERCENT_365_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRER_REWARD_PERCENT_90_DAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardPerToken180Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardPerToken365Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardPerToken90Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addRewardsToPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"additionalStake","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"calculateProjectedAPY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateRequiredRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"canSatisfyFixedAPY","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"checkPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rewardIndex","type":"uint256"}],"name":"claimReferrerReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakeIndex","type":"uint256"}],"name":"claimStakerReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyPauseRewardDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyUnpauseRewardDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"getActiveReferrersByPeriod","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllReferrerAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakerAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getClaimableReferrerRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"stakeIndex","type":"uint256"}],"name":"getClaimableStakerReward","outputs":[{"internalType":"uint256","name":"toClaim","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolStatus","outputs":[{"internalType":"uint256","name":"totalPoolBalance","type":"uint256"},{"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferredStakers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"getReferrerAddressesByPeriod","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getReferrerRewardByIndex","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"uint256","name":"claimedReward","type":"uint256"},{"internalType":"uint256","name":"nextClaimTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"address","name":"referee","type":"address"}],"internalType":"struct StakingEngineLinear.ReferrerRewardInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferrerRewards","outputs":[{"components":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"uint256","name":"claimedReward","type":"uint256"},{"internalType":"uint256","name":"nextClaimTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"address","name":"referee","type":"address"}],"internalType":"struct StakingEngineLinear.ReferrerRewardInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferrerStats","outputs":[{"components":[{"internalType":"uint256","name":"totalReferred","type":"uint256"},{"internalType":"uint256","name":"totalReferrerRewards","type":"uint256"},{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"referredStakersCount","type":"uint256"},{"internalType":"uint256","name":"activeReferredStakersCount","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked","type":"uint256"},{"internalType":"uint256","name":"totalUnstaked","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked90Days","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked180Days","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked365Days","type":"uint256"}],"internalType":"struct StakingEngineLinear.ReferrerInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"getStakedAmountsByPeriod","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"getStakerAddressesByPeriod","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getStakerRewardByIndex","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"internalType":"struct StakingEngineLinear.StakeInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getStakes","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"internalType":"struct StakingEngineLinear.StakeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserStakes","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"internalType":"struct StakingEngineLinear.StakeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserTotalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isReferred","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referredStakers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referrerRewards","outputs":[{"internalType":"uint256","name":"stakeId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"uint256","name":"claimedReward","type":"uint256"},{"internalType":"uint256","name":"nextClaimTime","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"address","name":"referee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referrerRewardsByPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrers","outputs":[{"internalType":"uint256","name":"totalReferred","type":"uint256"},{"internalType":"uint256","name":"totalReferrerRewards","type":"uint256"},{"internalType":"uint256","name":"unclaimedRewards","type":"uint256"},{"internalType":"uint256","name":"lastClaimTime","type":"uint256"},{"internalType":"uint256","name":"referredStakersCount","type":"uint256"},{"internalType":"uint256","name":"activeReferredStakersCount","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked","type":"uint256"},{"internalType":"uint256","name":"totalUnstaked","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked90Days","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked180Days","type":"uint256"},{"internalType":"uint256","name":"totalActiveStaked365Days","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPoolContract","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakePoolContract","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"stakeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"stakeTokenWithReferrer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakes","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked180Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked365Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked90Days","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"unstakeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604081815234620001d45760a08262004971803803809162000024828562000246565b833981010312620001d4576200003a826200027e565b6020926200004a8482016200027e565b91620000588483016200027e565b926200007560806200006d606086016200027e565b94016200027e565b600180556002805460ff191690556001600160a01b0392831693841515806200023a575b806200022e575b8062000222575b8062000216575b15620001e05786516318160ddd60e01b81528880826004818a5afa9182620001ad575b5050620000e9578651630f58058360e11b8152600490fd5b8394959691620001026200010992620001028162000293565b5062000321565b505f5f805160206200495183398151915297888252526001815f2001908154905f805160206200493183398151915280935551977fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff5f80a460018060a01b03199384600b541617600b5516928383600c541617600c5516918282600d541617600d5581600e541617600e55600f541617600f5542600a556145679081620003aa8239f35b813d8311620001d8575b620001c3818362000246565b81010312620001d457885f620000d1565b5f80fd5b503d620001b7565b865162461bcd60e51b815260048101899052600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b508382161515620000ae565b508381161515620000a7565b508386161515620000a0565b50838316151562000099565b601f909101601f19168101906001600160401b038211908210176200026a57604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203620001d457565b6001600160a01b03165f8181527fd329ff8a035c3ce5df2b0dae604d660c0d8783bf7e64be00c1d10db96c0b87b460205260409020545f8051602062004931833981519152919060ff166200031b57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533915f80516020620049118339815191525f80a4600190565b50505f90565b6001600160a01b03165f8181527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec60205260409020545f8051602062004951833981519152919060ff166200031b57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533915f80516020620049118339815191525f80a460019056fe60808060405260049081361015610014575f80fd5b5f3560e01c908162976412146124e7575080630113cd79146124ca57806301ffc9a71461247557806304693989146124585780630563733414610e89578063069695ff146122b25780630917e776146113615780630c541e5d1461228c57806313f5d2f21461226f57806321824a78146121ee578063248a9ca3146121c357806326322833146121a65780632cfb668814611e555780632e58923614611dd45780632e7f4f3814611dad5780632f2ff15d14611d71578063337de9bf14611d1f57806336568abe14611cdb578063369ba15e14611b0b578063377c8b3514611ab3578063379e6bc714611a965780633e158b0c14611a7e578063437938c914611a11578063440da66a146119f45780634a3b68cc1461194a57806354fa1cd61461192d578063563b05f014611914578063584b62a1146118865780635c975abb146118645780635ebb23c81461183e57806361febce81461177b57806366666aa9146117555780636e2f16961461168d5780637ba6f4581461135c5780637e396110146115315780637f79496c1461137e578063817b1cd214611361578063842e29811461135c578063856ea385146112cd57806389310f221461106957806391d148541461102057806392407c5214610ffd578063979358a914610f405780639e0976f614610ef75780639ef5c6aa14610edb578063a217fddf146104a3578063a86fea2114610ec0578063ae96230614610e89578063b536dcaf14610e6b578063b7b9b70314610b80578063b972ad2a14610aaf578063bb2cecb1146109c9578063c41e69b4146109ac578063c85ec056146108f5578063c8f33c91146108d8578063cb889847146108bd578063ccd34cd51461089b578063ced3bebd146107d4578063d33b3b96146106dd578063d547741f1461069f578063e4f5fe3b14610682578063e58378bb14610648578063e68811d614610551578063ed6e7f9814610536578063ed84c22b1461051c578063f269bb97146104d8578063f2c475a2146104bd578063f2e44622146104a3578063f5f8018114610481578063f8ea47561461045b578063fc0c546a146104355763ffab4bd914610335575f80fd5b346104315761034336612591565b61034b613be5565b610353613c08565b61035e821515612ec9565b6276a70081148015610425575b8015610418575b61037b90612f14565b5f905f5b335f52600660205260405f2080548210156103c957856103a18360ff936125a7565b50015460a01c166103b5575b60010161037f565b916103c1600191612f56565b9290506103ad565b84836103d760648710612f64565b6103e18183613fd0565b60405191825260208201527f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee9060403392a260018055005b506301e133808114610372565b5062ed4e00811461036b565b5f80fd5b34610431575f3660031901126104315760206001600160a01b03600b5416604051908152f35b34610431575f3660031901126104315760206001600160a01b03600c5416604051908152f35b34610431575f36600319011261043157602061049b613b8d565b604051908152f35b34610431575f3660031901126104315760206040515f8152f35b34610431575f36600319011261043157602060405160648152f35b34610431576040366003190112610431576001600160a01b036104f961253c565b165f52600860205260405f206024355f52602052602060405f2054604051908152f35b34610431575f36600319011261043157602061049b613afd565b34610431575f36600319011261043157602060405160028152f35b50346104315760403660031901126104315761056b61253c565b906001600160a01b03602435925f61012060405161058881612791565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015201521690815f52600560205260405f2054831015610604576101406105f56105ef85855f52600560205260405f2061272b565b50612cdc565b61060260405180926125c0565bf35b60649060206040519162461bcd60e51b8352820152601460248201527f496e76616c69642072657761726420696e6465780000000000000000000000006044820152fd5b34610431575f3660031901126104315760206040517fb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e8152f35b34610431575f366003190112610431576020601154604051908152f35b5034610431576040366003190112610431576106db90356106be612552565b90805f525f6020526106d6600160405f200154613ce2565b613d7a565b005b50346104315760209081600319360112610431575f8082356276a700810361079457505050606461071260026013545b612901565b04826001600160a01b0392602484600b541694600d54169160405195869384926370a0823160e01b84528301525afa918215610789575f9261075a575b506040519110158152f35b9091508281813d8311610782575b61077281836127ae565b810103126104315751905f61074f565b503d610768565b6040513d5f823e3d90fd5b62ed4e0081036107b05750505060646107126006601454612901565b6301e13380146107c7575b60649161071291612901565b5050601554600f906107bb565b5034610431575f366003190112610431576107ed613c69565b6002549060ff82161561088c575060ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a17f88313a379cb5333a1379fba0719d9d3a734fe6625681e0651edf4c8c105b5178608060405160408152601d60408201527f5265776172647320446973747269627574696f6e20756e7061757365640000006060820152426020820152a1005b604051638dfc202b60e01b8152fd5b34610431575f366003190112610431576020604051670de0b6b3a76400008152f35b34610431575f36600319011261043157602060405160018152f35b34610431575f366003190112610431576020600a54604051908152f35b34610431575f3660031901126104315761090d613c69565b610915613c08565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a17f88313a379cb5333a1379fba0719d9d3a734fe6625681e0651edf4c8c105b5178608060405160408152601b60408201527f5265776172647320446973747269627574696f6e2070617573656400000000006060820152426020820152a1005b34610431575f366003190112610431576020601254604051908152f35b503461043157602036600319011261043157806020610a43923580926109ed613c69565b6001600160a01b03610a0b8382600b541683600d5416903390614485565b600f5416905f604051809781958294630357291360e41b845233908401602090939291936001600160a01b0360408201951681520152565b03925af1908115610789577ff8fad42e780bfa5459be3fe691e8ba1aec70342250112139c5771c3fd155f31292602092610a82575b50604051908152a1005b610aa190833d8511610aa8575b610a9981836127ae565b8101906128e9565b505f610a78565b503d610a8f565b346104315760403660031901126104315760c0610b36610b30610ad061253c565b6001600160a01b03602435915f60a0604051610aeb81612775565b828152826020820152826040820152826060820152826080820152015216805f526006602052610b2060405f2054831061289a565b5f52600660205260405f206125a7565b50612d59565b610602604051809260a08091805184526020810151602085015260408101516040850152606081015160608501526001600160a01b03608082015116608085015201511515910152565b5034610431576020908160031936011261043157610bcf8135610ba1613be5565b610ba9613c08565b335f5260068452610bbf60405f2054821061289a565b335f526006845260405f206125a7565b509160ff8284015460a01c1615610e355760038301549160028401610c3f610c0d825495610bfd878261288d565b8042105f14610e305750426128dc565b945f6276a7008203610de25750610c3a8663bbf81e00610c348461070d60025b8d54612901565b04612901565b612914565b906001860191610c5b8354610c55818411612a0e565b826128dc565b925560246001600160a01b039384600b5416978686600d541699604051948580926370a0823160e01b9d8e8352878301525afa80156107895785935f91610daf575b505f93610cab911015612a5a565b8686600f541660246040518096819363fd9a4e6160e01b83528a888401525af1908115610789578793602492610d92575b50610cec863389600b5416613c26565b549886600b541696600d541696604051978894859384528301525afa928315610789575f93610d63575b5054926040519586528501525f60408501526060840152608083015260a08201527fc6898a8a292c754c3783ceac66fdc8562d79798f08dd40d8012e2b54d975926660c03392a260018055005b9092508381813d8311610d8b575b610d7b81836127ae565b810103126104315751915f610d16565b503d610d71565b610da890853d8711610aa857610a9981836127ae565b505f610cdc565b809450888092503d8311610ddb575b610dc881836127ae565b810103126104315791518492905f610c9d565b503d610dbe565b62ed4e008203610e045750610c3a8663bbf81e00610c348461070d6006610c2d565b86826301e133808114610e27575b610c3463bbf81e009161070d610c3a95610c2d565b600f9250610e12565b6128dc565b60405162461bcd60e51b815291820152601060248201526f5374616b65206e6f742061637469766560801b604482015260649150fd5b34610431575f3660031901126104315760206040516301e133808152f35b503461043157602036600319011261043157610ea8610ebc91356127d0565b604051918291602083526020830190612500565b0390f35b34610431575f366003190112610431576020604051600f8152f35b5034610431575f36600319011261043157602090604051908152f35b5034610431576060366003190112610431576044356001600160a01b038116810361043157610f3a91610f28613be5565b610f30613c08565b6024359035612fc0565b60018055005b503461043157604036600319011261043157610f5a61253c565b90602435916001600160a01b038091165f52600560205260405f2080548410156104315761014093610f8b9161272b565b50918254926001810154916002820154906003830154908301546005840154916006850154936008600787015496015496604051998a5260208a015260408901526060880152608087015260a086015260c085015260e084015260ff8116151561010084015260081c16610120820152f35b3461043157602036600319011261043157602061049b61101b61253c565b612dab565b50346104315760403660031901126104315761103a612552565b90355f525f6020526001600160a01b0360405f2091165f52602052602060ff60405f2054166040519015158152f35b5034610431576020806003193601126104315761108461253c565b6001600160a01b035f91165f526005825260405f2080546110a481612835565b916110b260405193846127ae565b8183525f908152848120858085015b8484106112ae5750505050505f5b81518110156112a4576101006110e5828461284d565b51015115158061128c575b6110fd575b6001016110cf565b60e0611109828461284d565b5101516201517f1981019081116112795761112b9062015180918291426128dc565b04908115801561113e575b5050506110f5565b61115a606061115186889996979961284d565b510151426128dc565b9160a0946111868661116c8a8a61284d565b51015183604061117c8c8c61284d565b5101510490612914565b92818004600114171561126657926111f394926111bd92600197959260406111ae8c8c61284d565b5101511061122b575b50612901565b9160c0906111d884836111d08b8b61284d565b51015161288d565b816111e38a8a61284d565b510151106111fc575b505061288d565b92905f80611136565b61122392935061120c888861284d565b5101519061121a888861284d565b510151906128dc565b905f806111ec565b61125f919250604061123d8b8b61284d565b510151046112598360c06112518d8d61284d565b510151612914565b906128dc565b905f6111b7565b60118a634e487b7160e01b5f525260245ffd5b601186634e487b7160e01b5f525260245ffd5b5060e0611299828461284d565b5101514210156110f0565b5050604051908152f35b6001916009916112bd85612cdc565b81520192019201919086906110c1565b3461043157602080600319360112610431576001600160a01b0390816112f161253c565b165f526003815260405f2091604051809384918482549182815201915f52845f20935f905b8683831061134057859061132c828703836127ae565b610ebc604051928284938452830190612500565b8654821685526001968701968996509401939190910190611316565b61262c565b34610431575f366003190112610431576020600954604051908152f35b5034610431575f366003190112610431576001600160a01b039081600b54169082600c541692604051916370a0823160e01b80845285828501526020928385602481895afa948515610789575f95611502575b50600d54169360405190828252858483015284826024818a5afa908115610789575f916114d1575b611403925061288d565b9460405196828852838801528387602481845afa968715610789575f9761149c575b50839291602491604051968794859384528301525afa908115610789575f9161146c575b50610ebc9150604051938493846040919493926060820195825260208201520152565b905081813d8311611495575b61148281836127ae565b8101031261043157610ebc90515f611449565b503d611478565b9096508381819493943d83116114ca575b6114b781836127ae565b8101031261043157519590919083611425565b503d6114ad565b90508482813d83116114fb575b6114e881836127ae565b81010312610431576114039151906113f9565b503d6114de565b9094508381813d831161152a575b61151a81836127ae565b810103126104315751935f6113d1565b503d611510565b5034610431576020366003190112610431576101609061014061155261253c565b60405161155e81612744565b5f81525f60208201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201526001600160a01b03610100925f848401525f856101209482868201520152165f52600760205260405f2091600a604051936115c585612744565b8054968786526001820154602087015260028201546040870152600382015460608701528101546080860152600581015460a0860152600681015460c0860152600781015460e08601526008810154838601526009810154848601520154848401526040519485526020830151602086015260408301516040860152606083015160608601526080830151608086015260a083015160a086015260c083015160c086015260e083015160e0860152808301519085015280820151908401520151610140820152f35b3461043157602080600319360112610431576116a761253c565b6001600160a01b035f91165f526006825260405f2080546116c781612835565b916116d560405193846127ae565b8183525f908152848120858085015b848410611736575085855f5b81518110156112a45760a0611705828461284d565b510151611715575b6001016116f0565b9161172e600191611726858561284d565b51519061288d565b92905061170d565b60019160059161174585612d59565b81520192019201919086906116e4565b34610431575f3660031901126104315760206001600160a01b03600d5416604051908152f35b3461043157602080600319360112610431576001600160a01b0361179d61253c565b165f526005815260405f209081546117b481612835565b906117c260405192836127ae565b80825282820180945f52835f205f915b838310611821576040805187815286518189018190528992820190895f5b8281106117fd5784840385f35b90919282610140826118126001948a516125c0565b019601910194929190946117f0565b60098660019261183085612cdc565b8152019201920191906117d2565b34610431575f3660031901126104315760206001600160a01b03600e5416604051908152f35b34610431575f36600319011261043157602060ff600254166040519015158152f35b5034610431576040366003190112610431576118a061253c565b6024356001600160a01b038092165f52600660205260405f20928354821015610431576118d160ff9260c0956125a7565b50928354936001810154926002820154906003830154920154936040519687526020870152604086015260608501528116608084015260a01c16151560a0820152f35b3461043157602061049b61192736612591565b90612bab565b34610431575f366003190112610431576020601054604051908152f35b503461043157602036600319011261043157610160906001600160a01b0361197061253c565b165f52600760205260405f20908154916001810154916002820154906003830154908301546005840154600685015491600786015493600887015495600a6009890154980154986040519a8b5260208b015260408a01526060890152608088015260a087015260c086015260e0850152610100840152610120830152610140820152f35b34610431575f366003190112610431576020604051620151808152f35b5034610431576020908160031936011261043157355f526018815260405f20906040518083838295549384815201905f52835f20925f5b85828210611a5f5750505061132c925003836127ae565b85546001600160a01b0316845260019586019588955093019201611a48565b34610431575f366003190112610431576106db612aa6565b34610431575f366003190112610431576020601454604051908152f35b3461043157604036600319011261043157611acc61253c565b602435906001600160a01b038091165f52600360205260405f20805483101561043157602092611afb91612568565b90549060031b1c16604051908152f35b5034610431576020908160031936011261043157611b27613be5565b611b2f613c08565b335f5260058252611b44813560405f2061272b565b509160ff60088401541615611c98576006611b7d6003850154610c3a611b73600288015492610bfd848261288d565b6005880154612901565b930192611b908454610c55818411612a0e565b93556001600160a01b039182600b54168284600d54166024604051809481936370a0823160e01b8352878301525afa80156107895785905f90611c67575b611bda92501015612a5a565b8184602485600f5416935f604051958694859363fd9a4e6160e01b85528401525af18015610789577f25deb48f8299e9863bda34f0d343d51341ac7ac30bf63dbeb2e8212bc4a20bf193611c3b928692611c4a575b503390600b5416613c26565b6040519283523392a260018055005b611c6090853d8711610aa857610a9981836127ae565b505f611c2f565b50508281813d8311611c91575b611c7e81836127ae565b810103126104315784611bda9151611bce565b503d611c74565b60405162461bcd60e51b815291820152601a60248201527f526566657272657220726577617264206e6f7420616374697665000000000000604482015260649150fd5b503461043157604036600319011261043157611cf5612552565b336001600160a01b03821603611d0f576106db9135613d7a565b5060405163334bd91960e11b8152fd5b503461043157604036600319011261043157611d3961253c565b611d41612552565b916001600160a01b038092165f5260205260405f2091165f52602052602060ff60405f2054166040519015158152f35b5034610431576040366003190112610431576106db9035611d90612552565b90805f525f602052611da8600160405f200154613ce2565b613d03565b3461043157604036600319011261043157602061049b611dcb61253c565b60243590612932565b34610431575f36600319011261043157604051806016549182815260208091019260165f527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289915f905b828210611e3557610ebc85610ea8818903826127ae565b83546001600160a01b031686529485019460019384019390910190611e1e565b5034610431576020908160031936011261043157803590611e74613be5565b611e7c613c08565b335f5260068352611e9260405f2054831061289a565b335f5260068352611ea68260405f206125a7565b50928184019160ff835460a01c161561216457600385015494611ecf600282019687549061288d565b421061211257611edd612aa6565b549454938354946001600160a01b03948587169660ff60a01b19169055611f06876009546128dc565b6009556276a70081149081156120d557611f22886013546128dc565b6013555b86611fae575b505050908293508460248294600e5416935f604051958694859363fd9a4e6160e01b85528401525af18015610789575f93611f73928692611c4a57503390600b5416613c26565b6040519283528201525f60408201527f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de0060603392a260018055005b865f526007855260405f209160068301611fc98a82546128dc565b905560078301611fda8a825461288d565b90551561208e5750600801611ff08782546128dc565b90555b5f5b855f52600580855260405f20805483101561208157826120149161272b565b5090600891878333920154841c161480612064575b612037575050600101611ff5565b909394959661204e93505f52855260405f2061272b565b5001805460ff191690555b9082915f8080611f2c565b50875f52808652836120798460405f2061272b565b505414612029565b5050505090919250612059565b62ed4e0081036120ae57506009016120a78782546128dc565b9055611ff3565b6301e13380146120bf575b50611ff3565b600a016120cd8782546128dc565b90555f6120b9565b62ed4e0081036120f3576120eb886014546128dc565b601455611f26565b6301e133808103611f265761210a886015546128dc565b601555611f26565b506084916040519162461bcd60e51b8352820152602660248201527f43616e6e6f7420756e7374616b65206265666f7265206c6f636b20706572696f6044820152656420656e647360d01b6064820152fd5b6064916040519162461bcd60e51b8352820152601660248201527f5374616b6520616c726561647920756e7374616b6564000000000000000000006044820152fd5b34610431575f3660031901126104315760206040516276a7008152f35b503461043157602036600319011261043157355f525f6020526020600160405f200154604051908152f35b34610431575f3660031901126104315760405180601a5491828152602080910192601a5f527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e915f905b82821061224f57610ebc85610ea8818903826127ae565b83546001600160a01b031686529485019460019384019390910190612238565b34610431575f366003190112610431576020601354604051908152f35b34610431575f3660031901126104315760206001600160a01b03600f5416604051908152f35b50346104315760209081600319360112610431578035805f526018835260405f20906040518083868295549384815201905f52865f20925f5b8882821061243957505050612302925003836127ae565b81519061232761231183612835565b9261231f60405194856127ae565b808452612835565b8286019490601f19013686375f5b84518110156123e1575f6001600160a01b03612351838861284d565b51165f526006885260405f205f908054915b828110612382575050509060019161237b828761284d565b5201612335565b86600261238f83856125a7565b50015414806123c7575b6123a6575b600101612363565b926123bf6001916123b786856125a7565b50549061288d565b93905061239e565b5060ff866123d583856125a7565b50015460a01c16612399565b505050926124019392919281604051958695604087526040870190612500565b918583038287015251918281520192915f5b82811061242257505050500390f35b835185528695509381019392810192600101612413565b85546001600160a01b03168452600195860195889550930192016122eb565b34610431575f366003190112610431576020601554604051908152f35b5034610431576020366003190112610431573563ffffffff60e01b811680910361043157602090637965db0b60e01b81149081156124b9575b506040519015158152f35b6301ffc9a760e01b1490505f6124ae565b34610431575f36600319011261043157602060405162ed4e008152f35b34610431575f3660031901126104315780600660209252f35b9081518082526020808093019301915f5b82811061251f575050505090565b83516001600160a01b031685529381019392810192600101612511565b600435906001600160a01b038216820361043157565b602435906001600160a01b038216820361043157565b805482101561257d575f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b6040906003190112610431576004359060243590565b805482101561257d575f52600560205f20910201905f90565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201511515908301526001600160a01b036101208092015116910152565b3461043157602080600319360112610431576001600160a01b0361264e61253c565b165f526006815260405f2090815461266581612835565b9061267360405192836127ae565b80825282820180945f52835f205f915b83831061270e576040805187815286518189018190528992820190895f5b8281106126ae5784840385f35b9091928260c0826126ff6001948a5160a08091805184526020810151602085015260408101516040850152606081015160608501526001600160a01b03608082015116608085015201511515910152565b019601910194929190946126a1565b60058660019261271d85612d59565b815201920192019190612683565b805482101561257d575f52600960205f20910201905f90565b610160810190811067ffffffffffffffff82111761276157604052565b634e487b7160e01b5f52604160045260245ffd5b60c0810190811067ffffffffffffffff82111761276157604052565b610140810190811067ffffffffffffffff82111761276157604052565b90601f8019910116810190811067ffffffffffffffff82111761276157604052565b5f526020601c60205260405f209060405180928391602082549182815201915f5260205f20935f905b8282106128125750505061280f925003826127ae565b90565b85546001600160a01b0316845260019586019587955093810193909101906127f9565b67ffffffffffffffff81116127615760051b60200190565b805182101561257d5760209160051b010190565b906a0d0b00fe2753884f000000820180921161287957565b634e487b7160e01b5f52601160045260245ffd5b9190820180921161287957565b156128a157565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606490fd5b9190820391821161287957565b90816020910312610431575180151581036104315790565b8181029291811591840414171561287957565b811561291e570490565b634e487b7160e01b5f52601260045260245ffd5b906001600160a01b036129579216805f526006602052610b2060405f2054831061289a565b5060ff600482015460a01c1615612a095760016129ab6003830154610c3a612988600286015492610bfd848261288d565b825f6276a70082036129c55750610c3463bbf81e009161070d60025b8a54612901565b910154808211156129bf5761280f916128dc565b50505f90565b62ed4e0082036129e35750610c3463bbf81e009161070d60066129a4565b6301e133808214612a01575b63bbf81e009161070d610c34926129a4565b50600f6129ef565b505f90565b15612a1557565b60405162461bcd60e51b815260206004820152601460248201527f4e6f20636c61696d61626c6520726577617264730000000000000000000000006044820152606490fd5b15612a6157565b60405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e74207265776172647320696e20706f6f6c000000006044820152606490fd5b600a5480421115612ba857612abb90426128dc565b60135480612b66575b5060145480612b24575b506015549081612ae1575b505042600a55565b612aeb9082613e9f565b670de0b6b3a76400009081810291818304149015171561287957612b1a91612b1291612914565b60125461288d565b6012555f80612ad9565b612b2e8282613e47565b670de0b6b3a76400009081810291818304149015171561287957612b5d91612b5591612914565b60115461288d565b6011555f612ace565b612b708282613ded565b670de0b6b3a76400009081810291818304149015171561287957612b9f91612b9791612914565b60105461288d565b6010555f612ac4565b50565b5f9182906276a7008103612c9e5750509050612bcc6002916013545b61288d565b6064612bd88383612901565b04906001600160a01b0391602083600b541693600d54166024604051809681936370a0823160e01b835260048301525afa928315610789575f93612c6a575b508210612c2357505090565b90915080612c315750505f90565b6064820290821592820460641483171561287957612c4e91612914565b908115612c59575090565b15159050612c6657600190565b5f90565b9092506020813d602011612c96575b81612c86602093836127ae565b810103126104315751915f612c17565b3d9150612c79565b62ed4e008103612cba5750509050612bcc60069160145461288d565b6301e1338014612ccf575b90612bcc9161288d565b50601554600f9250612cc5565b90604051612ce981612791565b6101206001600160a01b03600883958054855260018101546020860152600281015460408601526003810154606086015260048101546080860152600581015460a0860152600681015460c0860152600781015460e0860152015460ff8116151561010085015260081c16910152565b90604051612d6681612775565b60a060ff600483958054855260018101546020860152600281015460408601526003810154606086015201546001600160a01b0381166080850152821c161515910152565b5f805b6001600160a01b0383165f52600660205260405f208054821015612e3d5781612dd6916125a7565b5060ff600482015460a01c16612df0575b50600101612dae565b612e356001600160a01b039293670de0b6b3a7640000612e2e84612e28612e1c60026001980154613ef7565b878354930154906128dc565b90612901565b049061288d565b929150612de7565b5050905080612e4b57505f90565b6001600160a01b03602081600b541691600d54166024604051809481936370a0823160e01b835260048301525afa80156107895782915f91612e94575b50101561280f57505f90565b9150506020813d602011612ec1575b81612eb0602093836127ae565b81010312610431578190515f612e88565b3d9150612ea3565b15612ed057565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b15612f1b57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b1bd8dac81c195c9a5bd9606a1b6044820152606490fd5b5f1981146128795760010190565b15612f6b57565b60405162461bcd60e51b815260206004820152602760248201527f4d6178696d756d206e756d626572206f6620616374697665207374616b6573206044820152661c995858da195960ca1b6064820152608490fd5b929190612fce841515612ec9565b6276a700811490818015613af1575b8015613ae4575b612fed90612f14565b5f925f5b335f52600660205260405f20805482101561303c5760046130148360ff936125a7565b50015460a01c16613028575b600101612ff1565b93613034600191612f56565b949050613020565b505092606461305091969295939610612f64565b6001600160a01b03831615613aa157336001600160a01b03841614613a5c57823b613a175761307d612aa6565b5f925f5b335f52600660205260405f2080548210156130f557816130a0916125a7565b5060ff600482015460a01c166130ba575b50600101613081565b94906001916130ed6130cf6002890154613ef7565b91670de0b6b3a7640000612e2e868b549b019a612e288c54876128dc565b9655906130b1565b5050919493909361310582613ef7565b335f52600660205260405f20906040519061311f82612775565b87825260208201908152604082019085825260608301934285526001600160a01b0388166080850152600160a08501528054600160401b8110156127615761316c916001820181556125a7565b6138fb57835181559051600182015590516002820155915160038301556080810151600492909201805460a0928301516001600160a81b03199091166001600160a01b03949094169390931792151590911b60ff60a01b169190911790556131d68560095461288d565b60095580156139da576131eb8560135461288d565b6013555b6001600160a01b0383165f52600760205260405f20600460205260405f20335f5260205260ff60405f2054161561396d575b61322c86825461288d565b81556006810161323d87825461288d565b90558115613933576008810161325487825461288d565b90555b5f821561390e57505f5b806136f7575b5050335f52601760205260405f20805460ff8116156136de575b5050815f52601960205260405f20335f5260205260ff60405f205416156136a3575b6001600160a01b0383165f52601b60205260405f20805460ff81161561362d575b5050815f52601d60205260405f206001600160a01b0384165f5260205260ff60405f205416156135e9575b6001600160a01b03600b541690604051636eb1769f60e11b8152336004820152306024820152602081604481865afa80156107895787915f916135b4575b50106135a25761333d8387612bab565b905f901561357a57506002905b81811061354e5750508461336c916001600160a01b03600c5416903390614485565b600e54604051630357291360e41b81523360048201526024810186905290602090829060449082905f906001600160a01b03165af180156107895761352f575b50826133f2575b6001600160a01b039250604051938452602084015216907f172c3663ecda69252c295c57b21597ed84111f500d212738f9479e14c044e7ef60403392a3565b6001600160a01b03600b541660206001600160a01b03600d54166024604051809481936370a0823160e01b835260048301525afa908115610789575f916134fd575b5083811015613488576001600160a01b039360405191825285602083015260408201528160608201527fbdb6a732b5b8efedf7b869b61fb57aa4414b99363435312d554e374a90582fde60803392a26133b3565b505f9260206001600160a01b03600f541660246040518097819363fd9a4e6160e01b83528660048401525af1908115610789576001600160a01b03946134d9926134de575b503385600b5416613c26565b6133b3565b6134f69060203d602011610aa857610a9981836127ae565b505f6134cd565b90506020813d602011613527575b81613518602093836127ae565b8101031261043157515f613434565b3d915061350b565b6135479060203d602011610aa857610a9981836127ae565b505f6133ac565b6040516319860d2960e31b815262278d0090940460ff1660048501526024840152604483015250606490fd5b62ed4e00840361358d575060069061334a565b906301e13380840361334a57600f915061334a565b604051630fdc9bab60e21b8152600490fd5b9150506020813d6020116135e1575b816135d0602093836127ae565b81010312610431578690515f61332d565b3d91506135c3565b815f52601d60205260405f206001600160a01b0384165f5260205260405f20600160ff19825416179055815f52601c6020526136288360405f20613f94565b6132ef565b60ff19166001179055601a54600160401b811015612761576001810180601a5581101561257d577f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790555f806132c4565b815f52601960205260405f20335f5260205260405f20600160ff19825416179055815f5260186020526136d93360405f20613f94565b6132a3565b60ff191660011790556136f033613f2d565b5f80613281565b61370360649188612901565b04906001600160a01b0385165f52600560205260405f2090335f52600660205260405f205491825f198101116128795761373d864261288d565b6201518042014211612879576040519361375685612791565b5f1901845289602085015286604085015242606085015260808401528360a08401525f60c084015262015180420160e08401526001610100840152336101208401528054600160401b811015612761576137b59160018201815561272b565b9290926138fb5760086002938251815560208301516001820155604083015185820155606083015160038201556080830151600482015560a0830151600582015560c0830151600682015560e08301516007820155019061010081015115159060ff74ffffffffffffffffffffffffffffffffffffffff00610120855493015160081b169216906affffffffffffffffffffff60a81b16171790550161385c82825461288d565b90556001600160a01b0384165f52600860205260405f20835f5260205260405f2061388882825461288d565b9055335f52600660205260405f2054805f19810111612879577f24289ca1591b507f51bd1eff2bd77df898f07293b9b2750f2122394d57851685604051806138f18733966001600160a01b038b16965f1901846040919493926060820195825260208201520152565b0390a35f80613267565b634e487b7160e01b5f525f60045260245ffd5b62ed4e00840361392057506001613261565b6301e13380840361326157506004613261565b62ed4e008303613953576009810161394c87825461288d565b9055613257565b6301e13380830361325757600a810161394c87825461288d565b6001600160a01b0384165f52600460205260405f20335f5260205260405f20600160ff198254161790556001600160a01b0384165f5260036020526139b53360405f20613f94565b600481016139c38154612f56565b9055600581016139d38154612f56565b9055613221565b62ed4e0082036139f8576139f08560145461288d565b6014556131ef565b6301e1338082036131ef57613a0f8560155461288d565b6015556131ef565b60405162461bcd60e51b815260206004820152601d60248201527f52656665727265722063616e6e6f74206265206120636f6e74726163740000006044820152606490fd5b60405162461bcd60e51b815260206004820152601560248201527f43616e6e6f7420726566657220796f757273656c6600000000000000000000006044820152606490fd5b92613ab191945080925083613fd0565b60405191825260208201527f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee9060403392a2565b506301e133808114612fe4565b5062ed4e008114612fdd565b613b05613b8d565b6001600160a01b0390602082600b541692600d54166024604051809581936370a0823160e01b835260048301525afa918215610789575f92613b59575b50808211613b505750505f90565b61280f916128dc565b9091506020813d602011613b85575b81613b75602093836127ae565b810103126104315751905f613b42565b3d9150613b68565b6013548060011b90808204600214901517156128795760145460068102908082046006149015171561287957601554600f810290808204600f14901517156128795761280f9260648080612bc794049404910461288d565b600260015414613bf6576002600155565b604051633ee5aeb560e01b8152600490fd5b60ff60025416613c1457565b60405163d93c066560e01b8152600490fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152613c6791613c626064836127ae565b6144d7565b565b335f9081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec60205260409020547fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217759060ff1615613cc45750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b805f525f60205260405f20335f5260205260ff60405f20541615613cc45750565b90815f525f6020526001600160a01b0360405f20911690815f5260205260ff60405f205416155f146129bf57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b90815f525f6020526001600160a01b0360405f20911690815f5260205260ff60405f2054165f146129bf57815f525f60205260405f20815f5260205260405f2060ff19815416905533917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b9081156129bf578160011b91820460020361287957670de0b6b3a7640000918281029281840414901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b612861565b0490565b9081156129bf576006820291808304600603612879576753444835ec5800000291808304670de0b6b3a764000014901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b9081156129bf57600f820291808304600f036128795767d02ab486cedc00000291808304670de0b6b3a764000014901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b6276a7008103613f08575060105490565b62ed4e008103613f19575060115490565b6301e1338014613f27575f90565b60125490565b601654600160401b81101561276157600181018060165581101561257d576001600160a01b039060165f527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b51242890191166bffffffffffffffffffffffff60a01b825416179055565b8054600160401b81101561276157613fb191600182018155612568565b6001600160a01b039291928084549260031b9316831b921b1916179055565b90613fd9612aa6565b5f925f5b335f52600660205260405f2080548210156140335781613ffc916125a7565b5060ff600482015460a01c16614016575b50600101613fdd565b949060019161402b6130cf6002890154613ef7565b96559061400d565b50509261403f82613ef7565b92335f5260209060068252604091825f20835161405b81612775565b838152828101978852848101918783526060820142815260808301935f855260a0840192600184528054600160401b811015612761576140a0916001820181556125a7565b9b909b6138fb5793518b55925160018b0155915160028a01559051600389015590516004978801805492516001600160a81b03199093166001600160a01b039283161792151560a01b60ff60a01b16929092179091556141028360095461288d565b6009556276a700861480156144485761411d8460135461288d565b6013555b335f5260178352845f20805460ff81161561442f575b5050865f5260198352845f20335f52835260ff855f205416156143fa575b81600b5416908551636eb1769f60e11b8152338a8201523060248201528481604481865afa9081156143f0579086915f916143bf575b50106143af5761419b8886612bab565b905f901561438757506002905b81811061435c575050836141c39183600c5416903390614485565b600e548451630357291360e41b815233818a019081526020810186905290918491839185169082905f90829060400103925af180156143355761433f575b5084614211575b50505050505050565b80600b5416968282600d541660248751809b81936370a0823160e01b8352868301525afa978815614335575f98614306575b5085881015614291575050825195865285015283015260608201527fbdb6a732b5b8efedf7b869b61fb57aa4414b99363435312d554e374a90582fde60803392a25b5f808080808080614208565b9250938193979650809550602485600f5416935f8a51958694859363fd9a4e6160e01b85528401525af180156142fc576142d99596506142de575b50503390600b5416613c26565b614285565b816142f492903d10610aa857610a9981836127ae565b505f806142cc565b86513d5f823e3d90fd5b9097508281813d831161432e575b61431e81836127ae565b810103126104315751965f614243565b503d614314565b85513d5f823e3d90fd5b61435590833d8511610aa857610a9981836127ae565b505f614201565b60649189918b60ff62278d008b51956319860d2960e31b875204169084015260248301526044820152fd5b62ed4e00890361439a57506006906141a8565b906301e1338089036141a857600f91506141a8565b8551630fdc9bab60e21b81528990fd5b809250868092503d83116143e9575b6143d881836127ae565b81010312610431578590515f61418b565b503d6143ce565b87513d5f823e3d90fd5b865f5260198352845f20335f528352845f20600160ff19825416179055865f526018835261442a33865f20613f94565b614155565b60ff1916600117905561444133613f2d565b5f80614137565b62ed4e0087036144665761445e8460145461288d565b601455614121565b6301e1338087036141215761447d8460155461288d565b601555614121565b9290604051926323b872dd60e01b60208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff84111761276157613c67926040525b905f602091828151910182855af115610789575f513d61452857506001600160a01b0381163b155b6145065750565b604051635274afe760e01b81526001600160a01b039091166004820152602490fd5b600114156144ff56fea26469706673582212201d34b6a6d51f05dd17e2cdadea7d5577af8423566f27345793edee18da8e6b6864736f6c634300081800332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0db19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214ea49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217750000000000000000000000009e12735d77c72c5c3670636d428f2f3815d8a4cb0000000000000000000000001275ec313fb4011542add8d4237ed64e08266a870000000000000000000000009c30979fb141f24674bff0a908f785e000b0aaa4000000000000000000000000383a6a34c623c02dcf9bb7069fae4482967fb713000000000000000000000000fa8b02596a84f3b81b4144ea2f30482f8c33d446
Deployed Bytecode
0x60808060405260049081361015610014575f80fd5b5f3560e01c908162976412146124e7575080630113cd79146124ca57806301ffc9a71461247557806304693989146124585780630563733414610e89578063069695ff146122b25780630917e776146113615780630c541e5d1461228c57806313f5d2f21461226f57806321824a78146121ee578063248a9ca3146121c357806326322833146121a65780632cfb668814611e555780632e58923614611dd45780632e7f4f3814611dad5780632f2ff15d14611d71578063337de9bf14611d1f57806336568abe14611cdb578063369ba15e14611b0b578063377c8b3514611ab3578063379e6bc714611a965780633e158b0c14611a7e578063437938c914611a11578063440da66a146119f45780634a3b68cc1461194a57806354fa1cd61461192d578063563b05f014611914578063584b62a1146118865780635c975abb146118645780635ebb23c81461183e57806361febce81461177b57806366666aa9146117555780636e2f16961461168d5780637ba6f4581461135c5780637e396110146115315780637f79496c1461137e578063817b1cd214611361578063842e29811461135c578063856ea385146112cd57806389310f221461106957806391d148541461102057806392407c5214610ffd578063979358a914610f405780639e0976f614610ef75780639ef5c6aa14610edb578063a217fddf146104a3578063a86fea2114610ec0578063ae96230614610e89578063b536dcaf14610e6b578063b7b9b70314610b80578063b972ad2a14610aaf578063bb2cecb1146109c9578063c41e69b4146109ac578063c85ec056146108f5578063c8f33c91146108d8578063cb889847146108bd578063ccd34cd51461089b578063ced3bebd146107d4578063d33b3b96146106dd578063d547741f1461069f578063e4f5fe3b14610682578063e58378bb14610648578063e68811d614610551578063ed6e7f9814610536578063ed84c22b1461051c578063f269bb97146104d8578063f2c475a2146104bd578063f2e44622146104a3578063f5f8018114610481578063f8ea47561461045b578063fc0c546a146104355763ffab4bd914610335575f80fd5b346104315761034336612591565b61034b613be5565b610353613c08565b61035e821515612ec9565b6276a70081148015610425575b8015610418575b61037b90612f14565b5f905f5b335f52600660205260405f2080548210156103c957856103a18360ff936125a7565b50015460a01c166103b5575b60010161037f565b916103c1600191612f56565b9290506103ad565b84836103d760648710612f64565b6103e18183613fd0565b60405191825260208201527f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee9060403392a260018055005b506301e133808114610372565b5062ed4e00811461036b565b5f80fd5b34610431575f3660031901126104315760206001600160a01b03600b5416604051908152f35b34610431575f3660031901126104315760206001600160a01b03600c5416604051908152f35b34610431575f36600319011261043157602061049b613b8d565b604051908152f35b34610431575f3660031901126104315760206040515f8152f35b34610431575f36600319011261043157602060405160648152f35b34610431576040366003190112610431576001600160a01b036104f961253c565b165f52600860205260405f206024355f52602052602060405f2054604051908152f35b34610431575f36600319011261043157602061049b613afd565b34610431575f36600319011261043157602060405160028152f35b50346104315760403660031901126104315761056b61253c565b906001600160a01b03602435925f61012060405161058881612791565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015201521690815f52600560205260405f2054831015610604576101406105f56105ef85855f52600560205260405f2061272b565b50612cdc565b61060260405180926125c0565bf35b60649060206040519162461bcd60e51b8352820152601460248201527f496e76616c69642072657761726420696e6465780000000000000000000000006044820152fd5b34610431575f3660031901126104315760206040517fb19546dff01e856fb3f010c267a7b1c60363cf8a4664e21cc89c26224620214e8152f35b34610431575f366003190112610431576020601154604051908152f35b5034610431576040366003190112610431576106db90356106be612552565b90805f525f6020526106d6600160405f200154613ce2565b613d7a565b005b50346104315760209081600319360112610431575f8082356276a700810361079457505050606461071260026013545b612901565b04826001600160a01b0392602484600b541694600d54169160405195869384926370a0823160e01b84528301525afa918215610789575f9261075a575b506040519110158152f35b9091508281813d8311610782575b61077281836127ae565b810103126104315751905f61074f565b503d610768565b6040513d5f823e3d90fd5b62ed4e0081036107b05750505060646107126006601454612901565b6301e13380146107c7575b60649161071291612901565b5050601554600f906107bb565b5034610431575f366003190112610431576107ed613c69565b6002549060ff82161561088c575060ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a17f88313a379cb5333a1379fba0719d9d3a734fe6625681e0651edf4c8c105b5178608060405160408152601d60408201527f5265776172647320446973747269627574696f6e20756e7061757365640000006060820152426020820152a1005b604051638dfc202b60e01b8152fd5b34610431575f366003190112610431576020604051670de0b6b3a76400008152f35b34610431575f36600319011261043157602060405160018152f35b34610431575f366003190112610431576020600a54604051908152f35b34610431575f3660031901126104315761090d613c69565b610915613c08565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a17f88313a379cb5333a1379fba0719d9d3a734fe6625681e0651edf4c8c105b5178608060405160408152601b60408201527f5265776172647320446973747269627574696f6e2070617573656400000000006060820152426020820152a1005b34610431575f366003190112610431576020601254604051908152f35b503461043157602036600319011261043157806020610a43923580926109ed613c69565b6001600160a01b03610a0b8382600b541683600d5416903390614485565b600f5416905f604051809781958294630357291360e41b845233908401602090939291936001600160a01b0360408201951681520152565b03925af1908115610789577ff8fad42e780bfa5459be3fe691e8ba1aec70342250112139c5771c3fd155f31292602092610a82575b50604051908152a1005b610aa190833d8511610aa8575b610a9981836127ae565b8101906128e9565b505f610a78565b503d610a8f565b346104315760403660031901126104315760c0610b36610b30610ad061253c565b6001600160a01b03602435915f60a0604051610aeb81612775565b828152826020820152826040820152826060820152826080820152015216805f526006602052610b2060405f2054831061289a565b5f52600660205260405f206125a7565b50612d59565b610602604051809260a08091805184526020810151602085015260408101516040850152606081015160608501526001600160a01b03608082015116608085015201511515910152565b5034610431576020908160031936011261043157610bcf8135610ba1613be5565b610ba9613c08565b335f5260068452610bbf60405f2054821061289a565b335f526006845260405f206125a7565b509160ff8284015460a01c1615610e355760038301549160028401610c3f610c0d825495610bfd878261288d565b8042105f14610e305750426128dc565b945f6276a7008203610de25750610c3a8663bbf81e00610c348461070d60025b8d54612901565b04612901565b612914565b906001860191610c5b8354610c55818411612a0e565b826128dc565b925560246001600160a01b039384600b5416978686600d541699604051948580926370a0823160e01b9d8e8352878301525afa80156107895785935f91610daf575b505f93610cab911015612a5a565b8686600f541660246040518096819363fd9a4e6160e01b83528a888401525af1908115610789578793602492610d92575b50610cec863389600b5416613c26565b549886600b541696600d541696604051978894859384528301525afa928315610789575f93610d63575b5054926040519586528501525f60408501526060840152608083015260a08201527fc6898a8a292c754c3783ceac66fdc8562d79798f08dd40d8012e2b54d975926660c03392a260018055005b9092508381813d8311610d8b575b610d7b81836127ae565b810103126104315751915f610d16565b503d610d71565b610da890853d8711610aa857610a9981836127ae565b505f610cdc565b809450888092503d8311610ddb575b610dc881836127ae565b810103126104315791518492905f610c9d565b503d610dbe565b62ed4e008203610e045750610c3a8663bbf81e00610c348461070d6006610c2d565b86826301e133808114610e27575b610c3463bbf81e009161070d610c3a95610c2d565b600f9250610e12565b6128dc565b60405162461bcd60e51b815291820152601060248201526f5374616b65206e6f742061637469766560801b604482015260649150fd5b34610431575f3660031901126104315760206040516301e133808152f35b503461043157602036600319011261043157610ea8610ebc91356127d0565b604051918291602083526020830190612500565b0390f35b34610431575f366003190112610431576020604051600f8152f35b5034610431575f36600319011261043157602090604051908152f35b5034610431576060366003190112610431576044356001600160a01b038116810361043157610f3a91610f28613be5565b610f30613c08565b6024359035612fc0565b60018055005b503461043157604036600319011261043157610f5a61253c565b90602435916001600160a01b038091165f52600560205260405f2080548410156104315761014093610f8b9161272b565b50918254926001810154916002820154906003830154908301546005840154916006850154936008600787015496015496604051998a5260208a015260408901526060880152608087015260a086015260c085015260e084015260ff8116151561010084015260081c16610120820152f35b3461043157602036600319011261043157602061049b61101b61253c565b612dab565b50346104315760403660031901126104315761103a612552565b90355f525f6020526001600160a01b0360405f2091165f52602052602060ff60405f2054166040519015158152f35b5034610431576020806003193601126104315761108461253c565b6001600160a01b035f91165f526005825260405f2080546110a481612835565b916110b260405193846127ae565b8183525f908152848120858085015b8484106112ae5750505050505f5b81518110156112a4576101006110e5828461284d565b51015115158061128c575b6110fd575b6001016110cf565b60e0611109828461284d565b5101516201517f1981019081116112795761112b9062015180918291426128dc565b04908115801561113e575b5050506110f5565b61115a606061115186889996979961284d565b510151426128dc565b9160a0946111868661116c8a8a61284d565b51015183604061117c8c8c61284d565b5101510490612914565b92818004600114171561126657926111f394926111bd92600197959260406111ae8c8c61284d565b5101511061122b575b50612901565b9160c0906111d884836111d08b8b61284d565b51015161288d565b816111e38a8a61284d565b510151106111fc575b505061288d565b92905f80611136565b61122392935061120c888861284d565b5101519061121a888861284d565b510151906128dc565b905f806111ec565b61125f919250604061123d8b8b61284d565b510151046112598360c06112518d8d61284d565b510151612914565b906128dc565b905f6111b7565b60118a634e487b7160e01b5f525260245ffd5b601186634e487b7160e01b5f525260245ffd5b5060e0611299828461284d565b5101514210156110f0565b5050604051908152f35b6001916009916112bd85612cdc565b81520192019201919086906110c1565b3461043157602080600319360112610431576001600160a01b0390816112f161253c565b165f526003815260405f2091604051809384918482549182815201915f52845f20935f905b8683831061134057859061132c828703836127ae565b610ebc604051928284938452830190612500565b8654821685526001968701968996509401939190910190611316565b61262c565b34610431575f366003190112610431576020600954604051908152f35b5034610431575f366003190112610431576001600160a01b039081600b54169082600c541692604051916370a0823160e01b80845285828501526020928385602481895afa948515610789575f95611502575b50600d54169360405190828252858483015284826024818a5afa908115610789575f916114d1575b611403925061288d565b9460405196828852838801528387602481845afa968715610789575f9761149c575b50839291602491604051968794859384528301525afa908115610789575f9161146c575b50610ebc9150604051938493846040919493926060820195825260208201520152565b905081813d8311611495575b61148281836127ae565b8101031261043157610ebc90515f611449565b503d611478565b9096508381819493943d83116114ca575b6114b781836127ae565b8101031261043157519590919083611425565b503d6114ad565b90508482813d83116114fb575b6114e881836127ae565b81010312610431576114039151906113f9565b503d6114de565b9094508381813d831161152a575b61151a81836127ae565b810103126104315751935f6113d1565b503d611510565b5034610431576020366003190112610431576101609061014061155261253c565b60405161155e81612744565b5f81525f60208201525f60408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201526001600160a01b03610100925f848401525f856101209482868201520152165f52600760205260405f2091600a604051936115c585612744565b8054968786526001820154602087015260028201546040870152600382015460608701528101546080860152600581015460a0860152600681015460c0860152600781015460e08601526008810154838601526009810154848601520154848401526040519485526020830151602086015260408301516040860152606083015160608601526080830151608086015260a083015160a086015260c083015160c086015260e083015160e0860152808301519085015280820151908401520151610140820152f35b3461043157602080600319360112610431576116a761253c565b6001600160a01b035f91165f526006825260405f2080546116c781612835565b916116d560405193846127ae565b8183525f908152848120858085015b848410611736575085855f5b81518110156112a45760a0611705828461284d565b510151611715575b6001016116f0565b9161172e600191611726858561284d565b51519061288d565b92905061170d565b60019160059161174585612d59565b81520192019201919086906116e4565b34610431575f3660031901126104315760206001600160a01b03600d5416604051908152f35b3461043157602080600319360112610431576001600160a01b0361179d61253c565b165f526005815260405f209081546117b481612835565b906117c260405192836127ae565b80825282820180945f52835f205f915b838310611821576040805187815286518189018190528992820190895f5b8281106117fd5784840385f35b90919282610140826118126001948a516125c0565b019601910194929190946117f0565b60098660019261183085612cdc565b8152019201920191906117d2565b34610431575f3660031901126104315760206001600160a01b03600e5416604051908152f35b34610431575f36600319011261043157602060ff600254166040519015158152f35b5034610431576040366003190112610431576118a061253c565b6024356001600160a01b038092165f52600660205260405f20928354821015610431576118d160ff9260c0956125a7565b50928354936001810154926002820154906003830154920154936040519687526020870152604086015260608501528116608084015260a01c16151560a0820152f35b3461043157602061049b61192736612591565b90612bab565b34610431575f366003190112610431576020601054604051908152f35b503461043157602036600319011261043157610160906001600160a01b0361197061253c565b165f52600760205260405f20908154916001810154916002820154906003830154908301546005840154600685015491600786015493600887015495600a6009890154980154986040519a8b5260208b015260408a01526060890152608088015260a087015260c086015260e0850152610100840152610120830152610140820152f35b34610431575f366003190112610431576020604051620151808152f35b5034610431576020908160031936011261043157355f526018815260405f20906040518083838295549384815201905f52835f20925f5b85828210611a5f5750505061132c925003836127ae565b85546001600160a01b0316845260019586019588955093019201611a48565b34610431575f366003190112610431576106db612aa6565b34610431575f366003190112610431576020601454604051908152f35b3461043157604036600319011261043157611acc61253c565b602435906001600160a01b038091165f52600360205260405f20805483101561043157602092611afb91612568565b90549060031b1c16604051908152f35b5034610431576020908160031936011261043157611b27613be5565b611b2f613c08565b335f5260058252611b44813560405f2061272b565b509160ff60088401541615611c98576006611b7d6003850154610c3a611b73600288015492610bfd848261288d565b6005880154612901565b930192611b908454610c55818411612a0e565b93556001600160a01b039182600b54168284600d54166024604051809481936370a0823160e01b8352878301525afa80156107895785905f90611c67575b611bda92501015612a5a565b8184602485600f5416935f604051958694859363fd9a4e6160e01b85528401525af18015610789577f25deb48f8299e9863bda34f0d343d51341ac7ac30bf63dbeb2e8212bc4a20bf193611c3b928692611c4a575b503390600b5416613c26565b6040519283523392a260018055005b611c6090853d8711610aa857610a9981836127ae565b505f611c2f565b50508281813d8311611c91575b611c7e81836127ae565b810103126104315784611bda9151611bce565b503d611c74565b60405162461bcd60e51b815291820152601a60248201527f526566657272657220726577617264206e6f7420616374697665000000000000604482015260649150fd5b503461043157604036600319011261043157611cf5612552565b336001600160a01b03821603611d0f576106db9135613d7a565b5060405163334bd91960e11b8152fd5b503461043157604036600319011261043157611d3961253c565b611d41612552565b916001600160a01b038092165f5260205260405f2091165f52602052602060ff60405f2054166040519015158152f35b5034610431576040366003190112610431576106db9035611d90612552565b90805f525f602052611da8600160405f200154613ce2565b613d03565b3461043157604036600319011261043157602061049b611dcb61253c565b60243590612932565b34610431575f36600319011261043157604051806016549182815260208091019260165f527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289915f905b828210611e3557610ebc85610ea8818903826127ae565b83546001600160a01b031686529485019460019384019390910190611e1e565b5034610431576020908160031936011261043157803590611e74613be5565b611e7c613c08565b335f5260068352611e9260405f2054831061289a565b335f5260068352611ea68260405f206125a7565b50928184019160ff835460a01c161561216457600385015494611ecf600282019687549061288d565b421061211257611edd612aa6565b549454938354946001600160a01b03948587169660ff60a01b19169055611f06876009546128dc565b6009556276a70081149081156120d557611f22886013546128dc565b6013555b86611fae575b505050908293508460248294600e5416935f604051958694859363fd9a4e6160e01b85528401525af18015610789575f93611f73928692611c4a57503390600b5416613c26565b6040519283528201525f60408201527f204fccf0d92ed8d48f204adb39b2e81e92bad0dedb93f5716ca9478cfb57de0060603392a260018055005b865f526007855260405f209160068301611fc98a82546128dc565b905560078301611fda8a825461288d565b90551561208e5750600801611ff08782546128dc565b90555b5f5b855f52600580855260405f20805483101561208157826120149161272b565b5090600891878333920154841c161480612064575b612037575050600101611ff5565b909394959661204e93505f52855260405f2061272b565b5001805460ff191690555b9082915f8080611f2c565b50875f52808652836120798460405f2061272b565b505414612029565b5050505090919250612059565b62ed4e0081036120ae57506009016120a78782546128dc565b9055611ff3565b6301e13380146120bf575b50611ff3565b600a016120cd8782546128dc565b90555f6120b9565b62ed4e0081036120f3576120eb886014546128dc565b601455611f26565b6301e133808103611f265761210a886015546128dc565b601555611f26565b506084916040519162461bcd60e51b8352820152602660248201527f43616e6e6f7420756e7374616b65206265666f7265206c6f636b20706572696f6044820152656420656e647360d01b6064820152fd5b6064916040519162461bcd60e51b8352820152601660248201527f5374616b6520616c726561647920756e7374616b6564000000000000000000006044820152fd5b34610431575f3660031901126104315760206040516276a7008152f35b503461043157602036600319011261043157355f525f6020526020600160405f200154604051908152f35b34610431575f3660031901126104315760405180601a5491828152602080910192601a5f527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e915f905b82821061224f57610ebc85610ea8818903826127ae565b83546001600160a01b031686529485019460019384019390910190612238565b34610431575f366003190112610431576020601354604051908152f35b34610431575f3660031901126104315760206001600160a01b03600f5416604051908152f35b50346104315760209081600319360112610431578035805f526018835260405f20906040518083868295549384815201905f52865f20925f5b8882821061243957505050612302925003836127ae565b81519061232761231183612835565b9261231f60405194856127ae565b808452612835565b8286019490601f19013686375f5b84518110156123e1575f6001600160a01b03612351838861284d565b51165f526006885260405f205f908054915b828110612382575050509060019161237b828761284d565b5201612335565b86600261238f83856125a7565b50015414806123c7575b6123a6575b600101612363565b926123bf6001916123b786856125a7565b50549061288d565b93905061239e565b5060ff866123d583856125a7565b50015460a01c16612399565b505050926124019392919281604051958695604087526040870190612500565b918583038287015251918281520192915f5b82811061242257505050500390f35b835185528695509381019392810192600101612413565b85546001600160a01b03168452600195860195889550930192016122eb565b34610431575f366003190112610431576020601554604051908152f35b5034610431576020366003190112610431573563ffffffff60e01b811680910361043157602090637965db0b60e01b81149081156124b9575b506040519015158152f35b6301ffc9a760e01b1490505f6124ae565b34610431575f36600319011261043157602060405162ed4e008152f35b34610431575f3660031901126104315780600660209252f35b9081518082526020808093019301915f5b82811061251f575050505090565b83516001600160a01b031685529381019392810192600101612511565b600435906001600160a01b038216820361043157565b602435906001600160a01b038216820361043157565b805482101561257d575f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b6040906003190112610431576004359060243590565b805482101561257d575f52600560205f20910201905f90565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201511515908301526001600160a01b036101208092015116910152565b3461043157602080600319360112610431576001600160a01b0361264e61253c565b165f526006815260405f2090815461266581612835565b9061267360405192836127ae565b80825282820180945f52835f205f915b83831061270e576040805187815286518189018190528992820190895f5b8281106126ae5784840385f35b9091928260c0826126ff6001948a5160a08091805184526020810151602085015260408101516040850152606081015160608501526001600160a01b03608082015116608085015201511515910152565b019601910194929190946126a1565b60058660019261271d85612d59565b815201920192019190612683565b805482101561257d575f52600960205f20910201905f90565b610160810190811067ffffffffffffffff82111761276157604052565b634e487b7160e01b5f52604160045260245ffd5b60c0810190811067ffffffffffffffff82111761276157604052565b610140810190811067ffffffffffffffff82111761276157604052565b90601f8019910116810190811067ffffffffffffffff82111761276157604052565b5f526020601c60205260405f209060405180928391602082549182815201915f5260205f20935f905b8282106128125750505061280f925003826127ae565b90565b85546001600160a01b0316845260019586019587955093810193909101906127f9565b67ffffffffffffffff81116127615760051b60200190565b805182101561257d5760209160051b010190565b906a0d0b00fe2753884f000000820180921161287957565b634e487b7160e01b5f52601160045260245ffd5b9190820180921161287957565b156128a157565b60405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e6e8c2d6ca40d2dcc8caf606b1b6044820152606490fd5b9190820391821161287957565b90816020910312610431575180151581036104315790565b8181029291811591840414171561287957565b811561291e570490565b634e487b7160e01b5f52601260045260245ffd5b906001600160a01b036129579216805f526006602052610b2060405f2054831061289a565b5060ff600482015460a01c1615612a095760016129ab6003830154610c3a612988600286015492610bfd848261288d565b825f6276a70082036129c55750610c3463bbf81e009161070d60025b8a54612901565b910154808211156129bf5761280f916128dc565b50505f90565b62ed4e0082036129e35750610c3463bbf81e009161070d60066129a4565b6301e133808214612a01575b63bbf81e009161070d610c34926129a4565b50600f6129ef565b505f90565b15612a1557565b60405162461bcd60e51b815260206004820152601460248201527f4e6f20636c61696d61626c6520726577617264730000000000000000000000006044820152606490fd5b15612a6157565b60405162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e74207265776172647320696e20706f6f6c000000006044820152606490fd5b600a5480421115612ba857612abb90426128dc565b60135480612b66575b5060145480612b24575b506015549081612ae1575b505042600a55565b612aeb9082613e9f565b670de0b6b3a76400009081810291818304149015171561287957612b1a91612b1291612914565b60125461288d565b6012555f80612ad9565b612b2e8282613e47565b670de0b6b3a76400009081810291818304149015171561287957612b5d91612b5591612914565b60115461288d565b6011555f612ace565b612b708282613ded565b670de0b6b3a76400009081810291818304149015171561287957612b9f91612b9791612914565b60105461288d565b6010555f612ac4565b50565b5f9182906276a7008103612c9e5750509050612bcc6002916013545b61288d565b6064612bd88383612901565b04906001600160a01b0391602083600b541693600d54166024604051809681936370a0823160e01b835260048301525afa928315610789575f93612c6a575b508210612c2357505090565b90915080612c315750505f90565b6064820290821592820460641483171561287957612c4e91612914565b908115612c59575090565b15159050612c6657600190565b5f90565b9092506020813d602011612c96575b81612c86602093836127ae565b810103126104315751915f612c17565b3d9150612c79565b62ed4e008103612cba5750509050612bcc60069160145461288d565b6301e1338014612ccf575b90612bcc9161288d565b50601554600f9250612cc5565b90604051612ce981612791565b6101206001600160a01b03600883958054855260018101546020860152600281015460408601526003810154606086015260048101546080860152600581015460a0860152600681015460c0860152600781015460e0860152015460ff8116151561010085015260081c16910152565b90604051612d6681612775565b60a060ff600483958054855260018101546020860152600281015460408601526003810154606086015201546001600160a01b0381166080850152821c161515910152565b5f805b6001600160a01b0383165f52600660205260405f208054821015612e3d5781612dd6916125a7565b5060ff600482015460a01c16612df0575b50600101612dae565b612e356001600160a01b039293670de0b6b3a7640000612e2e84612e28612e1c60026001980154613ef7565b878354930154906128dc565b90612901565b049061288d565b929150612de7565b5050905080612e4b57505f90565b6001600160a01b03602081600b541691600d54166024604051809481936370a0823160e01b835260048301525afa80156107895782915f91612e94575b50101561280f57505f90565b9150506020813d602011612ec1575b81612eb0602093836127ae565b81010312610431578190515f612e88565b3d9150612ea3565b15612ed057565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b15612f1b57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b1bd8dac81c195c9a5bd9606a1b6044820152606490fd5b5f1981146128795760010190565b15612f6b57565b60405162461bcd60e51b815260206004820152602760248201527f4d6178696d756d206e756d626572206f6620616374697665207374616b6573206044820152661c995858da195960ca1b6064820152608490fd5b929190612fce841515612ec9565b6276a700811490818015613af1575b8015613ae4575b612fed90612f14565b5f925f5b335f52600660205260405f20805482101561303c5760046130148360ff936125a7565b50015460a01c16613028575b600101612ff1565b93613034600191612f56565b949050613020565b505092606461305091969295939610612f64565b6001600160a01b03831615613aa157336001600160a01b03841614613a5c57823b613a175761307d612aa6565b5f925f5b335f52600660205260405f2080548210156130f557816130a0916125a7565b5060ff600482015460a01c166130ba575b50600101613081565b94906001916130ed6130cf6002890154613ef7565b91670de0b6b3a7640000612e2e868b549b019a612e288c54876128dc565b9655906130b1565b5050919493909361310582613ef7565b335f52600660205260405f20906040519061311f82612775565b87825260208201908152604082019085825260608301934285526001600160a01b0388166080850152600160a08501528054600160401b8110156127615761316c916001820181556125a7565b6138fb57835181559051600182015590516002820155915160038301556080810151600492909201805460a0928301516001600160a81b03199091166001600160a01b03949094169390931792151590911b60ff60a01b169190911790556131d68560095461288d565b60095580156139da576131eb8560135461288d565b6013555b6001600160a01b0383165f52600760205260405f20600460205260405f20335f5260205260ff60405f2054161561396d575b61322c86825461288d565b81556006810161323d87825461288d565b90558115613933576008810161325487825461288d565b90555b5f821561390e57505f5b806136f7575b5050335f52601760205260405f20805460ff8116156136de575b5050815f52601960205260405f20335f5260205260ff60405f205416156136a3575b6001600160a01b0383165f52601b60205260405f20805460ff81161561362d575b5050815f52601d60205260405f206001600160a01b0384165f5260205260ff60405f205416156135e9575b6001600160a01b03600b541690604051636eb1769f60e11b8152336004820152306024820152602081604481865afa80156107895787915f916135b4575b50106135a25761333d8387612bab565b905f901561357a57506002905b81811061354e5750508461336c916001600160a01b03600c5416903390614485565b600e54604051630357291360e41b81523360048201526024810186905290602090829060449082905f906001600160a01b03165af180156107895761352f575b50826133f2575b6001600160a01b039250604051938452602084015216907f172c3663ecda69252c295c57b21597ed84111f500d212738f9479e14c044e7ef60403392a3565b6001600160a01b03600b541660206001600160a01b03600d54166024604051809481936370a0823160e01b835260048301525afa908115610789575f916134fd575b5083811015613488576001600160a01b039360405191825285602083015260408201528160608201527fbdb6a732b5b8efedf7b869b61fb57aa4414b99363435312d554e374a90582fde60803392a26133b3565b505f9260206001600160a01b03600f541660246040518097819363fd9a4e6160e01b83528660048401525af1908115610789576001600160a01b03946134d9926134de575b503385600b5416613c26565b6133b3565b6134f69060203d602011610aa857610a9981836127ae565b505f6134cd565b90506020813d602011613527575b81613518602093836127ae565b8101031261043157515f613434565b3d915061350b565b6135479060203d602011610aa857610a9981836127ae565b505f6133ac565b6040516319860d2960e31b815262278d0090940460ff1660048501526024840152604483015250606490fd5b62ed4e00840361358d575060069061334a565b906301e13380840361334a57600f915061334a565b604051630fdc9bab60e21b8152600490fd5b9150506020813d6020116135e1575b816135d0602093836127ae565b81010312610431578690515f61332d565b3d91506135c3565b815f52601d60205260405f206001600160a01b0384165f5260205260405f20600160ff19825416179055815f52601c6020526136288360405f20613f94565b6132ef565b60ff19166001179055601a54600160401b811015612761576001810180601a5581101561257d577f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e01805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790555f806132c4565b815f52601960205260405f20335f5260205260405f20600160ff19825416179055815f5260186020526136d93360405f20613f94565b6132a3565b60ff191660011790556136f033613f2d565b5f80613281565b61370360649188612901565b04906001600160a01b0385165f52600560205260405f2090335f52600660205260405f205491825f198101116128795761373d864261288d565b6201518042014211612879576040519361375685612791565b5f1901845289602085015286604085015242606085015260808401528360a08401525f60c084015262015180420160e08401526001610100840152336101208401528054600160401b811015612761576137b59160018201815561272b565b9290926138fb5760086002938251815560208301516001820155604083015185820155606083015160038201556080830151600482015560a0830151600582015560c0830151600682015560e08301516007820155019061010081015115159060ff74ffffffffffffffffffffffffffffffffffffffff00610120855493015160081b169216906affffffffffffffffffffff60a81b16171790550161385c82825461288d565b90556001600160a01b0384165f52600860205260405f20835f5260205260405f2061388882825461288d565b9055335f52600660205260405f2054805f19810111612879577f24289ca1591b507f51bd1eff2bd77df898f07293b9b2750f2122394d57851685604051806138f18733966001600160a01b038b16965f1901846040919493926060820195825260208201520152565b0390a35f80613267565b634e487b7160e01b5f525f60045260245ffd5b62ed4e00840361392057506001613261565b6301e13380840361326157506004613261565b62ed4e008303613953576009810161394c87825461288d565b9055613257565b6301e13380830361325757600a810161394c87825461288d565b6001600160a01b0384165f52600460205260405f20335f5260205260405f20600160ff198254161790556001600160a01b0384165f5260036020526139b53360405f20613f94565b600481016139c38154612f56565b9055600581016139d38154612f56565b9055613221565b62ed4e0082036139f8576139f08560145461288d565b6014556131ef565b6301e1338082036131ef57613a0f8560155461288d565b6015556131ef565b60405162461bcd60e51b815260206004820152601d60248201527f52656665727265722063616e6e6f74206265206120636f6e74726163740000006044820152606490fd5b60405162461bcd60e51b815260206004820152601560248201527f43616e6e6f7420726566657220796f757273656c6600000000000000000000006044820152606490fd5b92613ab191945080925083613fd0565b60405191825260208201527f1449c6dd7851abc30abf37f57715f492010519147cc2652fbc38202c18a6ee9060403392a2565b506301e133808114612fe4565b5062ed4e008114612fdd565b613b05613b8d565b6001600160a01b0390602082600b541692600d54166024604051809581936370a0823160e01b835260048301525afa918215610789575f92613b59575b50808211613b505750505f90565b61280f916128dc565b9091506020813d602011613b85575b81613b75602093836127ae565b810103126104315751905f613b42565b3d9150613b68565b6013548060011b90808204600214901517156128795760145460068102908082046006149015171561287957601554600f810290808204600f14901517156128795761280f9260648080612bc794049404910461288d565b600260015414613bf6576002600155565b604051633ee5aeb560e01b8152600490fd5b60ff60025416613c1457565b60405163d93c066560e01b8152600490fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152613c6791613c626064836127ae565b6144d7565b565b335f9081527f7d7ffb7a348e1c6a02869081a26547b49160dd3df72d1d75a570eb9b698292ec60205260409020547fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217759060ff1615613cc45750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b805f525f60205260405f20335f5260205260ff60405f20541615613cc45750565b90815f525f6020526001600160a01b0360405f20911690815f5260205260ff60405f205416155f146129bf57815f525f60205260405f20815f5260205260405f20600160ff1982541617905533917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b90815f525f6020526001600160a01b0360405f20911690815f5260205260ff60405f2054165f146129bf57815f525f60205260405f20815f5260205260405f2060ff19815416905533917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b9081156129bf578160011b91820460020361287957670de0b6b3a7640000918281029281840414901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b612861565b0490565b9081156129bf576006820291808304600603612879576753444835ec5800000291808304670de0b6b3a764000014901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b9081156129bf57600f820291808304600f036128795767d02ab486cedc00000291808304670de0b6b3a764000014901517156128795780156129bf57613e3e613e439160646a1a1601fc4ea7109e0000009404612901565b6276a7008103613f08575060105490565b62ed4e008103613f19575060115490565b6301e1338014613f27575f90565b60125490565b601654600160401b81101561276157600181018060165581101561257d576001600160a01b039060165f527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b51242890191166bffffffffffffffffffffffff60a01b825416179055565b8054600160401b81101561276157613fb191600182018155612568565b6001600160a01b039291928084549260031b9316831b921b1916179055565b90613fd9612aa6565b5f925f5b335f52600660205260405f2080548210156140335781613ffc916125a7565b5060ff600482015460a01c16614016575b50600101613fdd565b949060019161402b6130cf6002890154613ef7565b96559061400d565b50509261403f82613ef7565b92335f5260209060068252604091825f20835161405b81612775565b838152828101978852848101918783526060820142815260808301935f855260a0840192600184528054600160401b811015612761576140a0916001820181556125a7565b9b909b6138fb5793518b55925160018b0155915160028a01559051600389015590516004978801805492516001600160a81b03199093166001600160a01b039283161792151560a01b60ff60a01b16929092179091556141028360095461288d565b6009556276a700861480156144485761411d8460135461288d565b6013555b335f5260178352845f20805460ff81161561442f575b5050865f5260198352845f20335f52835260ff855f205416156143fa575b81600b5416908551636eb1769f60e11b8152338a8201523060248201528481604481865afa9081156143f0579086915f916143bf575b50106143af5761419b8886612bab565b905f901561438757506002905b81811061435c575050836141c39183600c5416903390614485565b600e548451630357291360e41b815233818a019081526020810186905290918491839185169082905f90829060400103925af180156143355761433f575b5084614211575b50505050505050565b80600b5416968282600d541660248751809b81936370a0823160e01b8352868301525afa978815614335575f98614306575b5085881015614291575050825195865285015283015260608201527fbdb6a732b5b8efedf7b869b61fb57aa4414b99363435312d554e374a90582fde60803392a25b5f808080808080614208565b9250938193979650809550602485600f5416935f8a51958694859363fd9a4e6160e01b85528401525af180156142fc576142d99596506142de575b50503390600b5416613c26565b614285565b816142f492903d10610aa857610a9981836127ae565b505f806142cc565b86513d5f823e3d90fd5b9097508281813d831161432e575b61431e81836127ae565b810103126104315751965f614243565b503d614314565b85513d5f823e3d90fd5b61435590833d8511610aa857610a9981836127ae565b505f614201565b60649189918b60ff62278d008b51956319860d2960e31b875204169084015260248301526044820152fd5b62ed4e00890361439a57506006906141a8565b906301e1338089036141a857600f91506141a8565b8551630fdc9bab60e21b81528990fd5b809250868092503d83116143e9575b6143d881836127ae565b81010312610431578590515f61418b565b503d6143ce565b87513d5f823e3d90fd5b865f5260198352845f20335f528352845f20600160ff19825416179055865f526018835261442a33865f20613f94565b614155565b60ff1916600117905561444133613f2d565b5f80614137565b62ed4e0087036144665761445e8460145461288d565b601455614121565b6301e1338087036141215761447d8460155461288d565b601555614121565b9290604051926323b872dd60e01b60208501526001600160a01b03809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff84111761276157613c67926040525b905f602091828151910182855af115610789575f513d61452857506001600160a01b0381163b155b6145065750565b604051635274afe760e01b81526001600160a01b039091166004820152602490fd5b600114156144ff56fea26469706673582212201d34b6a6d51f05dd17e2cdadea7d5577af8423566f27345793edee18da8e6b6864736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009e12735d77c72c5c3670636d428f2f3815d8a4cb0000000000000000000000001275ec313fb4011542add8d4237ed64e08266a870000000000000000000000009c30979fb141f24674bff0a908f785e000b0aaa4000000000000000000000000383a6a34c623c02dcf9bb7069fae4482967fb713000000000000000000000000fa8b02596a84f3b81b4144ea2f30482f8c33d446
-----Decoded View---------------
Arg [0] : _token (address): 0x9e12735d77c72c5C3670636D428f2F3815d8A4cB
Arg [1] : _stakePool (address): 0x1275ec313FB4011542ADD8d4237Ed64E08266a87
Arg [2] : _rewardPool (address): 0x9c30979fb141f24674bfF0a908F785E000b0AAa4
Arg [3] : initialOwner (address): 0x383a6A34C623C02dcf9BB7069FAE4482967fb713
Arg [4] : initialAdmin (address): 0xFa8b02596a84F3b81B4144eA2F30482f8C33D446
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000009e12735d77c72c5c3670636d428f2f3815d8a4cb
Arg [1] : 0000000000000000000000001275ec313fb4011542add8d4237ed64e08266a87
Arg [2] : 0000000000000000000000009c30979fb141f24674bff0a908f785e000b0aaa4
Arg [3] : 000000000000000000000000383a6a34c623c02dcf9bb7069fae4482967fb713
Arg [4] : 000000000000000000000000fa8b02596a84f3b81b4144ea2f30482f8c33d446
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.