Source Code
Latest 25 from a total of 242 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Incentivize All ... | 31016739 | 5 days ago | IN | 0 FRAX | 0.00000783 | ||||
| Incentivize All ... | 30713922 | 12 days ago | IN | 0 FRAX | 0.00001175 | ||||
| Incentivize All ... | 30372756 | 20 days ago | IN | 0 FRAX | 0.00000693 | ||||
| Incentivize All ... | 30121229 | 26 days ago | IN | 0 FRAX | 0.00000764 | ||||
| Incentivize All ... | 29771235 | 34 days ago | IN | 0 FRAX | 0.00000621 | ||||
| Incentivize All ... | 29475535 | 41 days ago | IN | 0 FRAX | 0.00000745 | ||||
| Pause Pool | 29475456 | 41 days ago | IN | 0 FRAX | 0.00000367 | ||||
| Incentivize All ... | 29160642 | 48 days ago | IN | 0 FRAX | 0.00003131 | ||||
| Incentivize All ... | 28871936 | 55 days ago | IN | 0 FRAX | 0.00000952 | ||||
| Pause Pool | 28871546 | 55 days ago | IN | 0 FRAX | 0.00000359 | ||||
| Incentivize All ... | 28544993 | 63 days ago | IN | 0 FRAX | 0.00001249 | ||||
| Incentivize All ... | 28265430 | 69 days ago | IN | 0 FRAX | 0.00001153 | ||||
| Incentivize All ... | 27934446 | 77 days ago | IN | 0 FRAX | 0.00001039 | ||||
| Incentivize All ... | 27690713 | 82 days ago | IN | 0 FRAX | 0.00009851 | ||||
| Incentivize All ... | 27343193 | 90 days ago | IN | 0 FRAX | 0.0000161 | ||||
| Incentivize All ... | 27010830 | 98 days ago | IN | 0 FRAX | 0.00000957 | ||||
| Incentivize All ... | 26694757 | 105 days ago | IN | 0 FRAX | 0.0000507 | ||||
| Incentivize All ... | 26361933 | 113 days ago | IN | 0 FRAX | 0.00001692 | ||||
| Incentivize All ... | 26063663 | 120 days ago | IN | 0 FRAX | 0.00001061 | ||||
| Incentivize All ... | 25758523 | 127 days ago | IN | 0 FRAX | 0.0000144 | ||||
| Incentivize All ... | 25443883 | 134 days ago | IN | 0 FRAX | 0.00007605 | ||||
| Incentivize All ... | 25121123 | 142 days ago | IN | 0 FRAX | 0.00001709 | ||||
| Set Pool Tier | 25120906 | 142 days ago | IN | 0 FRAX | 0.00001913 | ||||
| Incentivize All ... | 24817397 | 149 days ago | IN | 0 FRAX | 0.00002869 | ||||
| Incentivize All ... | 24513732 | 156 days ago | IN | 0 FRAX | 0.00002057 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX | |||||
| 31016739 | 5 days ago | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
IncentivizerAmoV3
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
No with 2000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.19;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ====================== IncentivizerAmoV3 ===========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance
// Primary Author(s)
// Amirnader Aghayeghazvini: https://github.com/amirnader-ghazvini
// Reviewer(s) / Contributor(s)
// Dennis: https://github.com/denett
import "./interfaces/IFrax.sol";
import "./interfaces/IFxs.sol";
import "./interfaces/IIncentivizationHandler.sol";
import "./Uniswap/TransferHelper.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract IncentivizerAmoV3 is Ownable {
/* ============================================= STATE VARIABLES ==================================================== */
// Addresses Config
address public operatorAddress;
address public targetTokenAddress; // Token that AMO incentivize
address public incentiveTokenAddress; // Token that AMO uses as an incentive
// Pools related
address[] public poolArray; // List of pool addresses
struct LiquidityPool {
// Pool Addresses
address poolAddress; // Where the actual tokens are in the pool
address lpTokenAddress; // Pool LP token address
address incentivePoolAddress; // Contract that handle incentive distribution e.g. Bribe contract
address incentivizationHandlerAddress; // Incentive handler contract e.g. votemarket handler
address gaugeAddress; // Gauge address
uint256 incentivizationId; // Votemarket Bounty ID
bool isPaused;
uint lastIncentivizationTimestamp; // timestamp of last time this pool was incentivized
uint lastIncentivizationAmount; // Max amount of incentives
uint firstIncentivizationTimestamp; // timestamp of the first incentivization
uint poolCycleLength; // length of the cycle for this pool in sec (e.g. one week)
}
mapping(address => bool) public poolInitialized;
mapping(address => LiquidityPool) private poolInfo;
// Constant Incentivization can be set (e.g. DAO Deal)
mapping(address => bool) public poolHasFixedIncent;
mapping(address => uint256) public poolFixedIncentAmount; // Constant Incentivization amount
// Pool tiers
struct IncentiveTier {
uint256 tokenMaxBudgetPerUnit; // Max incentive per unit of target token per cycle for pools within this tier
uint256 kickstartPeriodLength; // Kickstart period length for pools within this tier in secs
uint256 kickstartPeriodBudget; // Kickstart period budget per cycle for pools within this tier
}
IncentiveTier[] public tierArray;
mapping(address => uint) public poolTier;
// Configurations
uint256 public minTvl; // Min TVL of pool for being considered for incentivization
uint256 public cycleStart; // timestamp of cycle start
uint256 public cycleLength; // length of the cycle in sec (e.g. one week)
string public name;
/* =============================================== CONSTRUCTOR ====================================================== */
/// @notice constructor
/// @param _operatorAddress Address of AMO Operator
/// @param _targetTokenAddress Address of Token that AMO incentivize (e.g. crvFRAX)
/// @param _incentiveTokenAddress Address of Token that AMO uses as an incentive (e.g. FXS)
/// @param _minTvl Min TVL of pool for being considered for incentivization
/// @param _cycleStart timestamp of cycle start
/// @param _cycleLength length of the cycle (e.g. one week)
constructor(
address _operatorAddress,
address _targetTokenAddress,
address _incentiveTokenAddress,
uint256 _minTvl,
uint256 _cycleStart,
uint256 _cycleLength
) Ownable() {
operatorAddress = _operatorAddress;
targetTokenAddress = _targetTokenAddress;
incentiveTokenAddress = _incentiveTokenAddress;
minTvl = _minTvl;
require(_cycleStart < block.timestamp, "Cycle start time error");
cycleStart = _cycleStart;
cycleLength = _cycleLength;
name = string.concat(ERC20(_targetTokenAddress).symbol()," Liquidity Incentivizer");
addTier(0, 0, 0);
emit StartAMO(_operatorAddress, _targetTokenAddress, _incentiveTokenAddress);
}
/* ================================================ MODIFIERS ======================================================= */
modifier onlyByOwnerOperator() {
require(msg.sender == operatorAddress || msg.sender == owner(), "Not owner or operator");
_;
}
modifier activePool(address _poolAddress) {
require(poolInitialized[_poolAddress] && !poolInfo[_poolAddress].isPaused, "Pool is not active");
require(showPoolTvl(_poolAddress) > minTvl, "Pool is small");
_;
}
/* ================================================= EVENTS ========================================================= */
/// @notice The ```StartAMO``` event fires when the AMO deploys
/// @param _operatorAddress Address of operator
/// @param _targetTokenAddress Address of Token that AMO incentivize (e.g. crvFRAX)
/// @param _incentiveTokenAddress Address of Token that AMO uses as an incentive (e.g. FXS)
event StartAMO(address _operatorAddress, address _targetTokenAddress, address _incentiveTokenAddress);
/// @notice The ```SetOperator``` event fires when the operatorAddress is set
/// @param _oldAddress The original address
/// @param _newAddress The new address
event SetOperator(address _oldAddress, address _newAddress);
/// @notice The ```AddOrSetPool``` event fires when a pool is added or modified
/// @param _poolAddress The pool address
/// @param _lpTokenAddress The pool LP token address
/// @param _gaugeAddress The gauge address
/// @param _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
/// @param _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
/// @param _indexId indexID in Votium or Votemarket
/// @param _poolCycleLength length of the cycle for this pool in sec (e.g. one week)
event AddOrSetPool(
address _poolAddress,
address _lpTokenAddress,
address _gaugeAddress,
address _incentivePoolAddress,
address _incentivizationHandlerAddress,
uint256 _indexId,
uint256 _poolCycleLength
);
/// @notice The ```AddOrSetTier``` event fires when a pool is added or modified
/// @param _tierId Index of the incentivization tier
/// @param _tokenMaxBudgetPerUnit Max incentive per unit of target token per cycle for pools within this tier
/// @param _kickstartPeriodLength Kickstart period length for pools within this tier in sec
/// @param _kickstartPeriodBudget Kickstart period budget per cycle for pools within this tier
event AddOrSetTier(uint256 _tierId,uint256 _tokenMaxBudgetPerUnit,uint256 _kickstartPeriodLength,uint256 _kickstartPeriodBudget);
/// @notice The ```ChangePauseStatusPool``` event fires when a pool is added or modified
/// @param _poolAddress The pool address
/// @param _isPaused Pool Pause Status
event ChangePauseStatusPool(address _poolAddress, bool _isPaused);
/// @notice The ```SetPoolFixedIncent``` event fires when a pool's constant incentivization is updated
/// @param _poolAddress The pool address
/// @param _hasFixedIncent Pool Deal Status
/// @param _amountPerCycle Pool Deal Amount
event SetPoolFixedIncent(address _poolAddress, bool _hasFixedIncent, uint256 _amountPerCycle);
/// @notice The ```SetPoolTier``` event fires when a pool's incentivization tier change
/// @param _poolAddress The pool address
/// @param _tierId Index of the incentivization tier
event SetPoolTier(address _poolAddress, uint256 _tierId);
/// @notice The ```IncentivizePool``` event fires when a deposit happens to a pair
/// @param _poolAddress The pool address
/// @param _amount Incentive amount
event IncentivizePool(address _poolAddress, uint256 _amount);
/* ================================================== VIEWS ========================================================= */
/// @notice Returns the total number of pools added
/// @return _length uint256 Number of pools added
function allPoolsLength() public view returns (uint256 _length) {
return poolArray.length;
}
/// @notice Returns the total number of tiers added
/// @return _length uint256 Number of tiers added
function allTiersLength() public view returns (uint256 _length) {
return tierArray.length;
}
/// @notice Show TVL of targeted token in all active pools
/// @return TVL of targeted token in all active pools
function showActivePoolsTvl() public view returns (uint256) {
uint tvl = 0;
for (uint i = 0; i < poolArray.length; i++) {
if (!poolInfo[poolArray[i]].isPaused) {
tvl += showPoolTvl(poolArray[i]);
}
}
return tvl;
}
/// @notice Show TVL of targeted token in liquidity pool
/// @param _poolAddress Address of liquidity pool
/// @return TVL of targeted token in liquidity pool
function showPoolTvl(address _poolAddress) public view returns (uint256) {
ERC20 targetToken = ERC20(targetTokenAddress);
return targetToken.balanceOf(_poolAddress);
}
/// @notice Show Pool parameters
/// @param _poolAddress Address of liquidity pool
/// @return _gaugeAddress Gauge Contract Address
/// @return _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
/// @return _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
/// @return _incentivizationId Pool General Incentivization ID (e.g. in Votemarket it is BountyID)
/// @return _poolCycleLength length of the cycle for this pool in sec (e.g. one week)
function showPoolInfo(
address _poolAddress
)
external
view
returns (
address _gaugeAddress,
address _incentivePoolAddress,
address _incentivizationHandlerAddress,
uint256 _incentivizationId,
uint256 _poolCycleLength
)
{
_incentivePoolAddress = poolInfo[_poolAddress].incentivePoolAddress;
_incentivizationHandlerAddress = poolInfo[_poolAddress].incentivizationHandlerAddress;
_gaugeAddress = poolInfo[_poolAddress].gaugeAddress;
_incentivizationId = poolInfo[_poolAddress].incentivizationId;
_poolCycleLength = poolInfo[_poolAddress].poolCycleLength;
}
/// @notice Show Pool status
/// @param _poolAddress Address of liquidity pool
/// @return _isInitialized Pool registered or not
/// @return _lastIncentivizationTimestamp timestamp of last time this pool was incentivized
/// @return _lastIncentivizationAmount last cycle incentive amount
/// @return _isPaused puased or not
function showPoolStatus(
address _poolAddress
)
external
view
returns (
bool _isInitialized,
uint _lastIncentivizationTimestamp,
uint _lastIncentivizationAmount,
bool _isPaused
)
{
_isInitialized = poolInitialized[_poolAddress];
_lastIncentivizationTimestamp = poolInfo[_poolAddress].lastIncentivizationTimestamp;
_lastIncentivizationAmount = poolInfo[_poolAddress].lastIncentivizationAmount;
_isPaused = poolInfo[_poolAddress].isPaused;
}
/// @notice Show Tier Info
/// @param _tierId Tier Index
/// @return _tokenMaxBudgetPerUnit Max incentive per unit of target token per cycle for pools within this tier
/// @return _kickstartPeriodLength Kickstart period length for pools within this tier in secs
/// @return _kickstartPeriodBudget Kickstart period budget per cycle for pools within this tier
/// @return _numberOfPools Number of pools in this tier
/// @return _poolsTvl TVL of targeted token in all active pools in a tier
function showTierInfo(
uint256 _tierId
)
external
view
returns (
uint256 _tokenMaxBudgetPerUnit,
uint256 _kickstartPeriodLength,
uint256 _kickstartPeriodBudget,
uint256 _numberOfPools,
uint256 _poolsTvl
)
{
_tokenMaxBudgetPerUnit = tierArray[_tierId].tokenMaxBudgetPerUnit;
_kickstartPeriodLength = tierArray[_tierId].kickstartPeriodLength;
_kickstartPeriodBudget = tierArray[_tierId].kickstartPeriodBudget;
uint numberOfPools = 0;
uint tvl = 0;
for (uint i = 0; i < poolArray.length; i++) {
if (!poolInfo[poolArray[i]].isPaused) {
if (poolTier[poolArray[i]] == _tierId) {
numberOfPools += 1;
tvl += showPoolTvl(poolArray[i]);
}
}
}
_numberOfPools = numberOfPools;
_poolsTvl = tvl;
}
/// @notice Show Pool Kickstart Period status
/// @param _poolAddress Address of liquidity pool
/// @return _isInKickstartPeriod Pool registered or not
function isPoolInKickstartPeriod(
address _poolAddress
)
public
view
returns (
bool _isInKickstartPeriod
)
{
if (poolInfo[_poolAddress].firstIncentivizationTimestamp == 0){
_isInKickstartPeriod = true;
} else {
uint256 tier = poolTier[_poolAddress];
uint256 firstIncentiveCycleBegin = cycleStart + (((poolInfo[_poolAddress].firstIncentivizationTimestamp - cycleStart) / cycleLength) * cycleLength);
uint256 delta = (block.timestamp - firstIncentiveCycleBegin);
if (delta > tierArray[tier].kickstartPeriodLength) {
_isInKickstartPeriod = false;
} else {
_isInKickstartPeriod = true;
}
}
}
/// @notice Show if Pool incentivized within the current cycle
/// @param _poolAddress Address of liquidity pool
/// @return _isIncentivized Pool incentivized or not
function isPoolIncentivizedAtCycle(
address _poolAddress
)
public
view
returns (
bool _isIncentivized
)
{
if (poolInfo[_poolAddress].lastIncentivizationTimestamp == 0) {
_isIncentivized = false;
} else {
uint256 currentCycle = ((block.timestamp - cycleStart) / poolInfo[_poolAddress].poolCycleLength) + 1;
uint256 lastIncentiveCycle = ((poolInfo[_poolAddress].lastIncentivizationTimestamp - cycleStart) / poolInfo[_poolAddress].poolCycleLength) + 1;
if (lastIncentiveCycle < currentCycle){
_isIncentivized = false;
} else {
_isIncentivized = true;
}
}
}
/// @notice Function to calculate max incentive budget for one pool (based on tier budgets)
/// @param _poolAddress Address of liquidity pool
/// @return _amount max incentive budget for the pool in target token
function maxBudgetForPoolByTier(address _poolAddress) public view returns (uint256 _amount) {
uint256 _poolTvl = showPoolTvl(_poolAddress);
uint256 _tierId = poolTier[_poolAddress];
uint256 _cycleRatio = (poolInfo[_poolAddress].poolCycleLength * 100_000) / cycleLength ;
uint256 _kickstartPeriodBudget = 0;
uint256 _maxUintBasedBudget = (tierArray[_tierId].tokenMaxBudgetPerUnit * _poolTvl) / (10 ** ERC20(targetTokenAddress).decimals());
if(isPoolInKickstartPeriod(_poolAddress)){
_kickstartPeriodBudget = tierArray[_tierId].kickstartPeriodBudget;
}
if(isPoolIncentivizedAtCycle(_poolAddress)) {
_amount = 0;
} else if(poolInfo[_poolAddress].isPaused) {
_amount = 0;
} else if(showPoolTvl(_poolAddress) < minTvl) {
_amount = 0;
} else if(_kickstartPeriodBudget > _maxUintBasedBudget) {
_amount = _kickstartPeriodBudget * _cycleRatio / 100_000;
} else {
_amount = _maxUintBasedBudget * _cycleRatio / 100_000;
}
}
/// @notice Function to calculate max incentive budget for all pools (based on tier budgets)
/// @return _totalMaxBudget max incentive budget for all pools in target token
function maxBudgetForAllPoolsByTier() public view returns (uint256 _totalMaxBudget) {
_totalMaxBudget = 0;
for (uint256 i = 0; i < poolArray.length; i++) {
_totalMaxBudget += maxBudgetForPoolByTier(poolArray[i]);
}
}
/// @notice Function to calculate max incentive budget for all pools in one tier
/// @param _tierId Tier Index
/// @return _totalMaxBudget max incentive budget for all pools in one tier
function maxBudgetForPoolsByTier(uint256 _tierId) public view returns (uint256 _totalMaxBudget) {
_totalMaxBudget = 0;
for (uint256 i = 0; i < poolArray.length; i++) {
if (poolTier[poolArray[i]] == _tierId) {
_totalMaxBudget += maxBudgetForPoolByTier(poolArray[i]);
}
}
}
/// @notice Function to calculate adjusted incentive budget for one pool (based on tier budgets)
/// @param _poolAddress Address of liquidity pool
/// @param _totalIncentAmount Total Incentive budget in incetive token
/// @param _totalMaxIncentiveAmount Total max Incentive budget in target token
/// @param _priceRatio (Target Token Price / Incentive Token Price) * 100_000
/// @return _amount adjusted incentive budget for one pool in incentive token
function adjustedBudgetForPoolByTier(address _poolAddress, uint256 _totalIncentAmount, uint256 _totalMaxIncentiveAmount, uint256 _priceRatio) public view returns (uint256 _amount) {
uint256 _poolMaxBudget = maxBudgetForPoolByTier(_poolAddress) * _priceRatio / 100_000;
uint256 _totalMaxIncentive = _totalMaxIncentiveAmount * _priceRatio / 100_000;
if (_totalIncentAmount > _totalMaxIncentive) {
_amount = _poolMaxBudget;
} else if (_totalMaxIncentive > 0){
_amount = (_poolMaxBudget * _totalIncentAmount) / _totalMaxIncentive;
} else {
_amount = 0;
}
}
/* ======================================== INCENTIVIZATION FUNCTIONS =============================================== */
/// @notice Function to deposit incentives to one pool
/// @param _poolAddress Address of liquidity pool
/// @param _amount Amount of incentives to be deposited
function incentivizePoolByAmount(
address _poolAddress,
uint256 _amount
) public activePool(_poolAddress) onlyByOwnerOperator {
ERC20 _incentiveToken = ERC20(incentiveTokenAddress);
_incentiveToken.approve(poolInfo[_poolAddress].incentivePoolAddress, _amount);
(bool success, ) = poolInfo[_poolAddress].incentivizationHandlerAddress.delegatecall(
abi.encodeWithSignature(
"incentivizePool(address,address,address,address,uint256,uint256)",
_poolAddress,
poolInfo[_poolAddress].gaugeAddress,
poolInfo[_poolAddress].incentivePoolAddress,
incentiveTokenAddress,
poolInfo[_poolAddress].incentivizationId,
_amount
)
);
require(success, "delegatecall failed");
if (poolInfo[_poolAddress].lastIncentivizationTimestamp == 0){
poolInfo[_poolAddress].firstIncentivizationTimestamp = block.timestamp;
}
poolInfo[_poolAddress].lastIncentivizationTimestamp = block.timestamp;
poolInfo[_poolAddress].lastIncentivizationAmount = _amount;
emit IncentivizePool(_poolAddress, _amount);
}
/// @notice Function to deposit incentives to one pool (based on ratio)
/// @param _poolAddress Address of liquidity pool
/// @param _totalIncentAmount Total budget for incentivization
/// @param _totalTvl Total active pools TVL
function incentivizePoolByTvl(
address _poolAddress,
uint256 _totalIncentAmount,
uint256 _totalTvl
) public onlyByOwnerOperator {
uint256 _poolTvl = showPoolTvl(_poolAddress);
uint256 _amount = (_totalIncentAmount * _poolTvl) / _totalTvl;
incentivizePoolByAmount(_poolAddress, _amount);
}
/// @notice Function to deposit incentives to one pool (based on budget per unit)
/// @param _poolAddress Address of liquidity pool
/// @param _unitIncentAmount Incentive per single unit of target Token
function incentivizePoolByUnitBudget(
address _poolAddress,
uint256 _unitIncentAmount
) public onlyByOwnerOperator {
uint256 _poolTvl = showPoolTvl(_poolAddress);
uint256 _amount = (_unitIncentAmount * _poolTvl) / (10 ** ERC20(targetTokenAddress).decimals());
incentivizePoolByAmount(_poolAddress, _amount);
}
/// @notice Function to deposit incentives to one pool (based on Constant Incentivization)
/// @param _poolAddress Address of liquidity pool
function incentivizePoolByFixedIncent(
address _poolAddress
) public onlyByOwnerOperator {
if (poolHasFixedIncent[_poolAddress]){
uint256 _amount = poolFixedIncentAmount[_poolAddress];
incentivizePoolByAmount(_poolAddress, _amount);
}
}
/// Functions For depositing incentives to all active pools
/// @notice Function to deposit incentives to all active pools (based on TVL ratio)
/// @param _totalIncentAmount Total Incentive budget
/// @param _FixedIncent Incentivize considering FixedIncent
function incentivizeAllPoolsByTvl(uint256 _totalIncentAmount, bool _FixedIncent) public onlyByOwnerOperator {
uint256 _totalTvl = showActivePoolsTvl();
for (uint i = 0; i < poolArray.length; i++) {
if (_FixedIncent && poolHasFixedIncent[poolArray[i]]) {
incentivizePoolByFixedIncent(poolArray[i]);
} else if (!poolInfo[poolArray[i]].isPaused && showPoolTvl(poolArray[i]) > minTvl) {
incentivizePoolByTvl(poolArray[i], _totalIncentAmount, _totalTvl);
}
}
}
/// @notice Function to deposit incentives to all active pools (based on budget per unit of target Token)
/// @param _unitIncentAmount Incentive per single unit of target Token
/// @param _FixedIncent Incentivize considering FixedIncent
function incentivizeAllPoolsByUnitBudget(uint256 _unitIncentAmount, bool _FixedIncent) public onlyByOwnerOperator {
for (uint i = 0; i < poolArray.length; i++) {
if (_FixedIncent && poolHasFixedIncent[poolArray[i]]) {
incentivizePoolByFixedIncent(poolArray[i]);
} else if (!poolInfo[poolArray[i]].isPaused && showPoolTvl(poolArray[i]) > minTvl) {
incentivizePoolByUnitBudget(poolArray[i], _unitIncentAmount);
}
}
}
/// @notice Add/Set liquidity pool
/// @param _poolAddress Address of liquidity pool
/// @param _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
/// @param _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
/// @param _gaugeAddress Address of liquidity pool gauge
/// @param _lpTokenAddress Address of liquidity pool lp token
/// @param _incentivizationId Pool General Incentivization ID (e.g. in Votemarket it is BountyID)
/// @param _poolCycleLength length of the cycle for this pool in sec (e.g. one week)
function addOrSetPool(
address _poolAddress,
address _incentivePoolAddress,
address _incentivizationHandlerAddress,
address _gaugeAddress,
address _lpTokenAddress,
uint256 _incentivizationId,
uint256 _poolCycleLength
) external onlyByOwnerOperator {
if (poolInitialized[_poolAddress]) {
poolInfo[_poolAddress].incentivePoolAddress = _incentivePoolAddress;
poolInfo[_poolAddress].incentivizationHandlerAddress = _incentivizationHandlerAddress;
poolInfo[_poolAddress].gaugeAddress = _gaugeAddress;
poolInfo[_poolAddress].incentivizationId = _incentivizationId;
poolInfo[_poolAddress].lpTokenAddress = _lpTokenAddress;
poolInfo[_poolAddress].poolCycleLength = _poolCycleLength;
} else {
poolInitialized[_poolAddress] = true;
poolArray.push(_poolAddress);
poolInfo[_poolAddress] = LiquidityPool({
poolAddress: _poolAddress,
lpTokenAddress: _lpTokenAddress,
incentivePoolAddress: _incentivePoolAddress,
incentivizationHandlerAddress: _incentivizationHandlerAddress,
gaugeAddress: _gaugeAddress,
lastIncentivizationTimestamp: 0,
lastIncentivizationAmount: 0,
firstIncentivizationTimestamp: 0,
isPaused: false,
incentivizationId: _incentivizationId,
poolCycleLength: _poolCycleLength
});
setPoolTier(_poolAddress, 0);
}
emit AddOrSetPool(
_poolAddress,
_lpTokenAddress,
_gaugeAddress,
_incentivePoolAddress,
_incentivizationHandlerAddress,
_incentivizationId,
_poolCycleLength
);
}
/// @notice Pause/Unpause liquidity pool
/// @param _poolAddress Address of liquidity pool
/// @param _isPaused bool
function pausePool(address _poolAddress, bool _isPaused) external onlyByOwnerOperator {
if (poolInitialized[_poolAddress]) {
poolInfo[_poolAddress].isPaused = _isPaused;
emit ChangePauseStatusPool(_poolAddress, _isPaused);
}
}
/// @notice Add/Change/Remove Constant Incentivization can be set (e.g. DAO Deal)
/// @param _poolAddress Address of liquidity pool
/// @param _hasFixedIncent bool
/// @param _amountPerCycle Amount of constant incentives
function setFixedIncent(address _poolAddress, bool _hasFixedIncent, uint256 _amountPerCycle) external onlyByOwnerOperator {
if (poolInitialized[_poolAddress]) {
poolHasFixedIncent[_poolAddress] = _hasFixedIncent;
poolFixedIncentAmount[_poolAddress] = _amountPerCycle;
emit SetPoolFixedIncent(_poolAddress, _hasFixedIncent, _amountPerCycle);
}
}
/* ================================== TIER BASED INCENTIVIZATION FUNCTIONS ========================================== */
/// @notice Add/Set a Incentivization Tier
/// @param _tokenMaxBudgetPerUnit Max incentive per unit of target token per cycle for pools within this tier
/// @param _kickstartPeriodLength Kickstart period length for pools within this tier in secs
/// @param _kickstartPeriodBudget Kickstart period budget per cycle for pools within this tier
function addTier(
uint256 _tokenMaxBudgetPerUnit,
uint256 _kickstartPeriodLength,
uint256 _kickstartPeriodBudget
) public onlyByOwnerOperator returns (uint256 _tierId) {
_tierId = allTiersLength();
tierArray.push(IncentiveTier({
tokenMaxBudgetPerUnit: _tokenMaxBudgetPerUnit,
kickstartPeriodLength: _kickstartPeriodLength,
kickstartPeriodBudget: _kickstartPeriodBudget
}));
emit AddOrSetTier(_tierId, _tokenMaxBudgetPerUnit, _kickstartPeriodLength, _kickstartPeriodBudget);
}
/// @notice Set liquidity pool incentivization tier
/// @param _poolAddress Address of liquidity pool
/// @param _tierId uint256
function setPoolTier(address _poolAddress, uint256 _tierId) public onlyByOwnerOperator {
if (poolInitialized[_poolAddress] && (_tierId < allTiersLength())) {
poolTier[_poolAddress] = _tierId;
emit SetPoolTier(_poolAddress, _tierId);
}
}
/// @notice Function to deposit incentives to all pools (based on tier budgets)
/// @param _totalIncentAmount Total Incentive budget in incentive token
/// @param _priceRatio (Target Token Price / Incentive Token Price) * 100_000
function incentivizeAllPoolsByTier(uint256 _totalIncentAmount, uint256 _priceRatio) public onlyByOwnerOperator {
uint256 _totalMaxIncentiveAmount = maxBudgetForAllPoolsByTier();
for (uint i = 0; i < poolArray.length; i++) {
uint256 _amount = adjustedBudgetForPoolByTier(poolArray[i], _totalIncentAmount, _totalMaxIncentiveAmount, _priceRatio);
if (_amount > 0) {
incentivizePoolByAmount(poolArray[i], _amount);
}
}
}
/// @notice Function to deposit incentives to all pools in a tier (based on tier budgets)
/// @param _tierId uint256
/// @param _totalIncentAmount Total Incentive budget in incentive token
/// @param _priceRatio (Target Token Price / Incentive Token Price) * 100_000
function incentivizePoolsByTier(uint256 _tierId, uint256 _totalIncentAmount, uint256 _priceRatio) public onlyByOwnerOperator {
uint256 _totalMaxIncentiveAmount = maxBudgetForPoolsByTier(_tierId);
for (uint i = 0; i < poolArray.length; i++) {
if (poolTier[poolArray[i]] == _tierId) {
uint256 _amount = adjustedBudgetForPoolByTier(poolArray[i], _totalIncentAmount, _totalMaxIncentiveAmount, _priceRatio);
if (_amount > 0) {
incentivizePoolByAmount(poolArray[i], _amount);
}
}
}
}
/* ====================================== RESTRICTED GOVERNANCE FUNCTIONS =========================================== */
/// @notice Change the Operator address
/// @param _newOperatorAddress Operator address
function setOperatorAddress(address _newOperatorAddress) external onlyOwner {
emit SetOperator(operatorAddress, _newOperatorAddress);
operatorAddress = _newOperatorAddress;
}
/// @notice Change the Cycle Length for incentivization
/// @param _cycleLength Cycle Length for being considered for incentivization
function setCycleLength(uint256 _cycleLength) external onlyOwner {
cycleLength = _cycleLength;
}
/// @notice Change the Min TVL for incentivization
/// @param _minTvl Min TVL of pool for being considered for incentivization
function setMinTvl(uint256 _minTvl) external onlyOwner {
minTvl = _minTvl;
}
/// @notice Recover ERC20 tokens
/// @param tokenAddress address of ERC20 token
/// @param tokenAmount amount to be withdrawn
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
// Can only be triggered by owner
TransferHelper.safeTransfer(address(tokenAddress), msg.sender, tokenAmount);
}
// Generic proxy
function execute(
address _to,
uint256 _value,
bytes calldata _data
) external onlyOwner returns (bool, bytes memory) {
(bool success, bytes memory result) = _to.call{ value: _value }(_data);
return (success, result);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
interface IFrax {
function COLLATERAL_RATIO_PAUSER() external view returns (bytes32);
function DEFAULT_ADMIN_ADDRESS() external view returns (address);
function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
function addPool(address pool_address ) external;
function allowance(address owner, address spender ) external view returns (uint256);
function approve(address spender, uint256 amount ) external returns (bool);
function balanceOf(address account ) external view returns (uint256);
function burn(uint256 amount ) external;
function burnFrom(address account, uint256 amount ) external;
function collateral_ratio_paused() external view returns (bool);
function controller_address() external view returns (address);
function creator_address() external view returns (address);
function decimals() external view returns (uint8);
function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool);
function eth_usd_consumer_address() external view returns (address);
function eth_usd_price() external view returns (uint256);
function frax_eth_oracle_address() external view returns (address);
function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256);
function frax_pools(address ) external view returns (bool);
function frax_pools_array(uint256 ) external view returns (address);
function frax_price() external view returns (uint256);
function frax_step() external view returns (uint256);
function fxs_address() external view returns (address);
function fxs_eth_oracle_address() external view returns (address);
function fxs_price() external view returns (uint256);
function genesis_supply() external view returns (uint256);
function getRoleAdmin(bytes32 role ) external view returns (bytes32);
function getRoleMember(bytes32 role, uint256 index ) external view returns (address);
function getRoleMemberCount(bytes32 role ) external view returns (uint256);
function globalCollateralValue() external view returns (uint256);
function global_collateral_ratio() external view returns (uint256);
function grantRole(bytes32 role, address account ) external;
function hasRole(bytes32 role, address account ) external view returns (bool);
function increaseAllowance(address spender, uint256 addedValue ) external returns (bool);
function last_call_time() external view returns (uint256);
function minting_fee() external view returns (uint256);
function name() external view returns (string memory);
function owner_address() external view returns (address);
function pool_burn_from(address b_address, uint256 b_amount ) external;
function pool_mint(address m_address, uint256 m_amount ) external;
function price_band() external view returns (uint256);
function price_target() external view returns (uint256);
function redemption_fee() external view returns (uint256);
function refreshCollateralRatio() external;
function refresh_cooldown() external view returns (uint256);
function removePool(address pool_address ) external;
function renounceRole(bytes32 role, address account ) external;
function revokeRole(bytes32 role, address account ) external;
function setController(address _controller_address ) external;
function setETHUSDOracle(address _eth_usd_consumer_address ) external;
function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external;
function setFXSAddress(address _fxs_address ) external;
function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external;
function setFraxStep(uint256 _new_step ) external;
function setMintingFee(uint256 min_fee ) external;
function setOwner(address _owner_address ) external;
function setPriceBand(uint256 _price_band ) external;
function setPriceTarget(uint256 _new_price_target ) external;
function setRedemptionFee(uint256 red_fee ) external;
function setRefreshCooldown(uint256 _new_cooldown ) external;
function setTimelock(address new_timelock ) external;
function symbol() external view returns (string memory);
function timelock_address() external view returns (address);
function toggleCollateralRatio() external;
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint256 amount ) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool);
function weth_address() external view returns (address);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
interface IFxs {
function DEFAULT_ADMIN_ROLE() external view returns(bytes32);
function FRAXStablecoinAdd() external view returns(address);
function FXS_DAO_min() external view returns(uint256);
function allowance(address owner, address spender) external view returns(uint256);
function approve(address spender, uint256 amount) external returns(bool);
function balanceOf(address account) external view returns(uint256);
function burn(uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes);
function decimals() external view returns(uint8);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool);
function genesis_supply() external view returns(uint256);
function getCurrentVotes(address account) external view returns(uint96);
function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96);
function getRoleAdmin(bytes32 role) external view returns(bytes32);
function getRoleMember(bytes32 role, uint256 index) external view returns(address);
function getRoleMemberCount(bytes32 role) external view returns(uint256);
function grantRole(bytes32 role, address account) external;
function hasRole(bytes32 role, address account) external view returns(bool);
function increaseAllowance(address spender, uint256 addedValue) external returns(bool);
function mint(address to, uint256 amount) external;
function name() external view returns(string memory);
function numCheckpoints(address) external view returns(uint32);
function oracle_address() external view returns(address);
function owner_address() external view returns(address);
function pool_burn_from(address b_address, uint256 b_amount) external;
function pool_mint(address m_address, uint256 m_amount) external;
function renounceRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function setFRAXAddress(address frax_contract_address) external;
function setFXSMinDAO(uint256 min_FXS) external;
function setOracle(address new_oracle) external;
function setOwner(address _owner_address) external;
function setTimelock(address new_timelock) external;
function symbol() external view returns(string memory);
function timelock_address() external view returns(address);
function toggleVotes() external;
function totalSupply() external view returns(uint256);
function trackingVotes() external view returns(bool);
function transfer(address recipient, uint256 amount) external returns(bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns(bool);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
interface IIncentivizationHandler {
function balanceOfTargetToken(
address poolAddress,
address gaugeAddress,
address targetTokenAddress) external view returns(uint256);
function balanceOfLockedTargetToken(
address poolAddress,
address lpTokenAddress,
address gaugeAddress,
address targetTokenAddress) external view returns(uint256);
function depositTargetToken(
address poolAddress,
address lpTokenAddress,
address gaugeAddress,
address targetTokenAddress,
uint256 amount) external;
function withdrawTargetToken(
address poolAddress,
address lpTokenAddress,
address gaugeAddress,
address targetTokenAddress,
uint256 amount) external;
function incentivizePool(
address poolAddress,
address gaugeAddress,
address incentivePoolAdderss,
address incentiveTokenAddress,
uint256 indexId,
uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.11;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
* 0 before setting it to a non-zero value.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
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 v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}{
"remappings": [
"ds-test/=node_modules/ds-test/src/",
"forge-std/=node_modules/forge-std/src/",
"frax-std/=node_modules/frax-standard-solidity/src/",
"@chainlink/=node_modules/@chainlink/",
"@eth-optimism/=node_modules/@eth-optimism/",
"@openzeppelin/=node_modules/@openzeppelin/",
"frax-standard-solidity/=node_modules/frax-standard-solidity/",
"solidity-bytes-utils/=node_modules/solidity-bytes-utils/"
],
"optimizer": {
"enabled": false,
"runs": 2000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"},{"internalType":"address","name":"_targetTokenAddress","type":"address"},{"internalType":"address","name":"_incentiveTokenAddress","type":"address"},{"internalType":"uint256","name":"_minTvl","type":"uint256"},{"internalType":"uint256","name":"_cycleStart","type":"uint256"},{"internalType":"uint256","name":"_cycleLength","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_poolAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_lpTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_gaugeAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_incentivePoolAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_incentivizationHandlerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"_indexId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_poolCycleLength","type":"uint256"}],"name":"AddOrSetPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tierId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenMaxBudgetPerUnit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_kickstartPeriodLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_kickstartPeriodBudget","type":"uint256"}],"name":"AddOrSetTier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_poolAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"ChangePauseStatusPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_poolAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"IncentivizePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_newAddress","type":"address"}],"name":"SetOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_poolAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"_hasFixedIncent","type":"bool"},{"indexed":false,"internalType":"uint256","name":"_amountPerCycle","type":"uint256"}],"name":"SetPoolFixedIncent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_poolAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tierId","type":"uint256"}],"name":"SetPoolTier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_operatorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_targetTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_incentiveTokenAddress","type":"address"}],"name":"StartAMO","type":"event"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"address","name":"_incentivePoolAddress","type":"address"},{"internalType":"address","name":"_incentivizationHandlerAddress","type":"address"},{"internalType":"address","name":"_gaugeAddress","type":"address"},{"internalType":"address","name":"_lpTokenAddress","type":"address"},{"internalType":"uint256","name":"_incentivizationId","type":"uint256"},{"internalType":"uint256","name":"_poolCycleLength","type":"uint256"}],"name":"addOrSetPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenMaxBudgetPerUnit","type":"uint256"},{"internalType":"uint256","name":"_kickstartPeriodLength","type":"uint256"},{"internalType":"uint256","name":"_kickstartPeriodBudget","type":"uint256"}],"name":"addTier","outputs":[{"internalType":"uint256","name":"_tierId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"uint256","name":"_totalIncentAmount","type":"uint256"},{"internalType":"uint256","name":"_totalMaxIncentiveAmount","type":"uint256"},{"internalType":"uint256","name":"_priceRatio","type":"uint256"}],"name":"adjustedBudgetForPoolByTier","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPoolsLength","outputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allTiersLength","outputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cycleLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cycleStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"incentiveTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalIncentAmount","type":"uint256"},{"internalType":"uint256","name":"_priceRatio","type":"uint256"}],"name":"incentivizeAllPoolsByTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalIncentAmount","type":"uint256"},{"internalType":"bool","name":"_FixedIncent","type":"bool"}],"name":"incentivizeAllPoolsByTvl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unitIncentAmount","type":"uint256"},{"internalType":"bool","name":"_FixedIncent","type":"bool"}],"name":"incentivizeAllPoolsByUnitBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"incentivizePoolByAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"incentivizePoolByFixedIncent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"uint256","name":"_totalIncentAmount","type":"uint256"},{"internalType":"uint256","name":"_totalTvl","type":"uint256"}],"name":"incentivizePoolByTvl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"uint256","name":"_unitIncentAmount","type":"uint256"}],"name":"incentivizePoolByUnitBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tierId","type":"uint256"},{"internalType":"uint256","name":"_totalIncentAmount","type":"uint256"},{"internalType":"uint256","name":"_priceRatio","type":"uint256"}],"name":"incentivizePoolsByTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"isPoolInKickstartPeriod","outputs":[{"internalType":"bool","name":"_isInKickstartPeriod","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"isPoolIncentivizedAtCycle","outputs":[{"internalType":"bool","name":"_isIncentivized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBudgetForAllPoolsByTier","outputs":[{"internalType":"uint256","name":"_totalMaxBudget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"maxBudgetForPoolByTier","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tierId","type":"uint256"}],"name":"maxBudgetForPoolsByTier","outputs":[{"internalType":"uint256","name":"_totalMaxBudget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTvl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"bool","name":"_isPaused","type":"bool"}],"name":"pausePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolFixedIncentAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolHasFixedIncent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolTier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cycleLength","type":"uint256"}],"name":"setCycleLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"bool","name":"_hasFixedIncent","type":"bool"},{"internalType":"uint256","name":"_amountPerCycle","type":"uint256"}],"name":"setFixedIncent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTvl","type":"uint256"}],"name":"setMinTvl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOperatorAddress","type":"address"}],"name":"setOperatorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"},{"internalType":"uint256","name":"_tierId","type":"uint256"}],"name":"setPoolTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"showActivePoolsTvl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"showPoolInfo","outputs":[{"internalType":"address","name":"_gaugeAddress","type":"address"},{"internalType":"address","name":"_incentivePoolAddress","type":"address"},{"internalType":"address","name":"_incentivizationHandlerAddress","type":"address"},{"internalType":"uint256","name":"_incentivizationId","type":"uint256"},{"internalType":"uint256","name":"_poolCycleLength","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"showPoolStatus","outputs":[{"internalType":"bool","name":"_isInitialized","type":"bool"},{"internalType":"uint256","name":"_lastIncentivizationTimestamp","type":"uint256"},{"internalType":"uint256","name":"_lastIncentivizationAmount","type":"uint256"},{"internalType":"bool","name":"_isPaused","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolAddress","type":"address"}],"name":"showPoolTvl","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tierId","type":"uint256"}],"name":"showTierInfo","outputs":[{"internalType":"uint256","name":"_tokenMaxBudgetPerUnit","type":"uint256"},{"internalType":"uint256","name":"_kickstartPeriodLength","type":"uint256"},{"internalType":"uint256","name":"_kickstartPeriodBudget","type":"uint256"},{"internalType":"uint256","name":"_numberOfPools","type":"uint256"},{"internalType":"uint256","name":"_poolsTvl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tierArray","outputs":[{"internalType":"uint256","name":"tokenMaxBudgetPerUnit","type":"uint256"},{"internalType":"uint256","name":"kickstartPeriodLength","type":"uint256"},{"internalType":"uint256","name":"kickstartPeriodBudget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162006230380380620062308339818101604052810190620000379190620005cb565b620000576200004b6200027c60201b60201c565b6200028460201b60201c565b85600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600b8190555042821062000166576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015d90620006c8565b60405180910390fd5b81600c8190555080600d819055508473ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001c0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620001eb919062000869565b604051602001620001fd91906200092d565b604051602081830303815290604052600e90816200021c919062000b8d565b506200023260008060006200034860201b60201c565b507f7fd171b754859e1fd38f494c38b79fa1028241732e981b993116333300b487e6868686604051620002689392919062000c85565b60405180910390a150505050505062000d92565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480620003e15750620003b2620004e160201b60201c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b62000423576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200041a9062000d12565b60405180910390fd5b620004336200050a60201b60201c565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb81858585604051620004d2949392919062000d45565b60405180910390a19392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600980549050905090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000558826200052b565b9050919050565b6200056a816200054b565b81146200057657600080fd5b50565b6000815190506200058a816200055f565b92915050565b6000819050919050565b620005a58162000590565b8114620005b157600080fd5b50565b600081519050620005c5816200059a565b92915050565b60008060008060008060c08789031215620005eb57620005ea62000521565b5b6000620005fb89828a0162000579565b96505060206200060e89828a0162000579565b95505060406200062189828a0162000579565b94505060606200063489828a01620005b4565b93505060806200064789828a01620005b4565b92505060a06200065a89828a01620005b4565b9150509295509295509295565b600082825260208201905092915050565b7f4379636c652073746172742074696d65206572726f7200000000000000000000600082015250565b6000620006b060168362000667565b9150620006bd8262000678565b602082019050919050565b60006020820190508181036000830152620006e381620006a1565b9050919050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200073f82620006f4565b810181811067ffffffffffffffff8211171562000761576200076062000705565b5b80604052505050565b60006200077662000517565b905062000784828262000734565b919050565b600067ffffffffffffffff821115620007a757620007a662000705565b5b620007b282620006f4565b9050602081019050919050565b60005b83811015620007df578082015181840152602081019050620007c2565b60008484015250505050565b600062000802620007fc8462000789565b6200076a565b905082815260208101848484011115620008215762000820620006ef565b5b6200082e848285620007bf565b509392505050565b600082601f8301126200084e576200084d620006ea565b5b815162000860848260208601620007eb565b91505092915050565b60006020828403121562000882576200088162000521565b5b600082015167ffffffffffffffff811115620008a357620008a262000526565b5b620008b18482850162000836565b91505092915050565b600081519050919050565b600081905092915050565b6000620008dd82620008ba565b620008e98185620008c5565b9350620008fb818560208601620007bf565b80840191505092915050565b7f204c697175696469747920496e63656e746976697a6572000000000000000000815250565b60006200093b8284620008d0565b9150620009488262000907565b60178201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200099f57607f821691505b602082108103620009b557620009b462000957565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000a1f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620009e0565b62000a2b8683620009e0565b95508019841693508086168417925050509392505050565b6000819050919050565b600062000a6e62000a6862000a628462000590565b62000a43565b62000590565b9050919050565b6000819050919050565b62000a8a8362000a4d565b62000aa262000a998262000a75565b848454620009ed565b825550505050565b600090565b62000ab962000aaa565b62000ac681848462000a7f565b505050565b5b8181101562000aee5762000ae260008262000aaf565b60018101905062000acc565b5050565b601f82111562000b3d5762000b0781620009bb565b62000b1284620009d0565b8101602085101562000b22578190505b62000b3a62000b3185620009d0565b83018262000acb565b50505b505050565b600082821c905092915050565b600062000b626000198460080262000b42565b1980831691505092915050565b600062000b7d838362000b4f565b9150826002028217905092915050565b62000b9882620008ba565b67ffffffffffffffff81111562000bb45762000bb362000705565b5b62000bc0825462000986565b62000bcd82828562000af2565b600060209050601f83116001811462000c05576000841562000bf0578287015190505b62000bfc858262000b6f565b86555062000c6c565b601f19841662000c1586620009bb565b60005b8281101562000c3f5784890151825560018201915060208501945060208101905062000c18565b8683101562000c5f578489015162000c5b601f89168262000b4f565b8355505b6001600288020188555050505b505050505050565b62000c7f816200054b565b82525050565b600060608201905062000c9c600083018662000c74565b62000cab602083018562000c74565b62000cba604083018462000c74565b949350505050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b600062000cfa60158362000667565b915062000d078262000cc2565b602082019050919050565b6000602082019050818103600083015262000d2d8162000ceb565b9050919050565b62000d3f8162000590565b82525050565b600060808201905062000d5c600083018762000d34565b62000d6b602083018662000d34565b62000d7a604083018562000d34565b62000d89606083018462000d34565b95945050505050565b61548e8062000da26000396000f3fe608060405234801561001057600080fd5b50600436106103155760003560e01c806386bfdb19116101a7578063d27761ef116100ee578063ec06a89a11610097578063efde4e6411610071578063efde4e6414610950578063f2fde38b1461096e578063f7f2e80d1461098a57610315565b8063ec06a89a146108e8578063ec16bf4714610904578063ee5b11c31461092057610315565b8063e81e5dde116100c8578063e81e5dde1461087c578063ea6efa951461089a578063eac471a0146108ca57610315565b8063d27761ef14610800578063e0a88bbc14610830578063e390ddde1461086057610315565b8063ae49945d11610150578063b75402191161012a578063b754021914610796578063cc64463a146107b4578063cdc97f77146107d057610315565b8063ae49945d14610717578063afce9fde14610735578063b61d27f61461076557610315565b80638da5cb5b116101815780638da5cb5b146106a95780639fbd2c8c146106c7578063a95dffd6146106fb57610315565b806386bfdb191461063d57806388660611146106715780638980f11f1461068d57610315565b806360976e6f1161026b57806379605ea01161021457806381d81d2a116101ee57806381d81d2a146105c157806381d8b3f8146105f157806382eac7f01461060d57610315565b806379605ea0146105425780637c43215f146105725780637ea48c10146105a557610315565b806370c8f7fe1161024557806370c8f7fe14610500578063715018a61461051c578063793171c51461052657610315565b806360976e6f146104825780636358ec571461049e5780636cef1b77146104ce57610315565b806320263e87116102cd5780633d84ceca116102a75780633d84ceca1461042c57806345c1262614610448578063581289691461046457610315565b806320263e87146103d45780632501853f146103f25780632f1d5a601461041057610315565b80630f37b6ba116102fe5780630f37b6ba14610368578063127effb2146103865780631a799e00146103a457610315565b806303ea9f1f1461031a57806306fdde031461034a575b600080fd5b610334600480360381019061032f919061431b565b6109a6565b6040516103419190614361565b60405180910390f35b6103526109be565b60405161035f919061440c565b60405180910390f35b610370610a4c565b60405161037d9190614361565b60405180910390f35b61038e610b65565b60405161039b919061443d565b60405180910390f35b6103be60048036038101906103b9919061431b565b610b8b565b6040516103cb9190614361565b60405180910390f35b6103dc610e36565b6040516103e9919061443d565b60405180910390f35b6103fa610e5c565b6040516104079190614361565b60405180910390f35b61042a6004803603810190610425919061431b565b610ed8565b005b61044660048036038101906104419190614484565b610f7f565b005b610462600480360381019061045d91906144b1565b610f91565b005b61046c6116c4565b6040516104799190614361565b60405180910390f35b61049c60048036038101906104979190614484565b6116ca565b005b6104b860048036038101906104b391906144f1565b6116dc565b6040516104c59190614361565b60405180910390f35b6104e860048036038101906104e39190614484565b61185f565b6040516104f793929190614544565b60405180910390f35b61051a600480360381019061051591906144b1565b611899565b005b610524611a3a565b005b610540600480360381019061053b919061457b565b611a4e565b005b61055c600480360381019061055791906145bb565b611bf1565b6040516105699190614361565b60405180910390f35b61058c6004803603810190610587919061431b565b611c7d565b60405161059c949392919061463d565b60405180910390f35b6105bf60048036038101906105ba91906144b1565b611db5565b005b6105db60048036038101906105d6919061431b565b611f68565b6040516105e89190614361565b60405180910390f35b61060b600480360381019061060691906146ae565b612012565b005b61062760048036038101906106229190614484565b61232b565b604051610634919061443d565b60405180910390f35b6106576004803603810190610652919061431b565b61236a565b6040516106689594939291906146ee565b60405180910390f35b61068b60048036038101906106869190614741565b612534565b005b6106a760048036038101906106a291906144b1565b6126eb565b005b6106b1612702565b6040516106be919061443d565b60405180910390f35b6106e160048036038101906106dc9190614484565b61272b565b6040516106f2959493929190614781565b60405180910390f35b610715600480360381019061071091906147d4565b61295e565b005b61071f6130e1565b60405161072c919061443d565b60405180910390f35b61074f600480360381019061074a919061431b565b613107565b60405161075c9190614361565b60405180910390f35b61077f600480360381019061077a91906148db565b61311f565b60405161078d9291906149a4565b60405180910390f35b61079e6131ae565b6040516107ab9190614361565b60405180910390f35b6107ce60048036038101906107c991906144f1565b6131b4565b005b6107ea60048036038101906107e5919061431b565b6133de565b6040516107f791906149d4565b60405180910390f35b61081a6004803603810190610815919061431b565b613568565b60405161082791906149d4565b60405180910390f35b61084a6004803603810190610845919061431b565b613588565b60405161085791906149d4565b60405180910390f35b61087a6004803603810190610875919061431b565b6136ef565b005b610884613861565b6040516108919190614361565b60405180910390f35b6108b460048036038101906108af9190614484565b61386e565b6040516108c19190614361565b60405180910390f35b6108d2613971565b6040516108df9190614361565b60405180910390f35b61090260048036038101906108fd91906146ae565b613977565b005b61091e600480360381019061091991906149ef565b613c82565b005b61093a6004803603810190610935919061431b565b613e7d565b60405161094791906149d4565b60405180910390f35b610958613e9d565b6040516109659190614361565b60405180910390f35b6109886004803603810190610983919061431b565b613eaa565b005b6109a4600480360381019061099f9190614a42565b613f2d565b005b60086020528060005260406000206000915090505481565b600e80546109cb90614ac4565b80601f01602080910402602001604051908101604052809291908181526020018280546109f790614ac4565b8015610a445780601f10610a1957610100808354040283529160200191610a44565b820191906000526020600020905b815481529060010190602001808311610a2757829003601f168201915b505050505081565b6000806000905060005b600480549050811015610b5d576006600060048381548110610a7b57610a7a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16610b4a57610b3c60048281548110610b0c57610b0b614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82610b479190614b53565b91505b8080610b5590614b87565b915050610a56565b508091505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080610b9783611f68565b90506000600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54620186a0600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154610c339190614bcf565b610c3d9190614c40565b9050600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd39190614caa565b600a610cdf9190614e0a565b8560098681548110610cf457610cf3614af5565b5b906000526020600020906003020160000154610d109190614bcf565b610d1a9190614c40565b9050610d2587613588565b15610d535760098481548110610d3e57610d3d614af5565b5b90600052602060002090600302016002015491505b610d5c876133de565b15610d6a5760009550610e2c565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1615610dc85760009550610e2b565b600b54610dd488611f68565b1015610de35760009550610e2a565b80821115610e0c57620186a08383610dfb9190614bcf565b610e059190614c40565b9550610e29565b620186a08382610e1c9190614bcf565b610e269190614c40565b95505b5b5b5b5050505050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000805b600480549050811015610ed457610eb460048281548110610e8457610e83614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82610ebf9190614b53565b91508080610ecc90614b87565b915050610e60565b5090565b610ee0614033565b7f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051610f33929190614e55565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610f87614033565b80600d8190555050565b81600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156110385750600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16155b611077576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106e90614eca565b60405180910390fd5b600b5461108382611f68565b116110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90614f36565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111515750611122612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161118790614fa2565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401611254929190614fc2565b6020604051808303816000875af1158015611273573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112979190615000565b506000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1685600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154896040516024016114569695949392919061502d565b6040516020818303038152906040527fb649fbf4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516114e091906150ca565b600060405180830381855af49150503d806000811461151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5050905080611564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155b9061512d565b60405180910390fd5b6000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036115f65742600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901819055505b42600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801819055507ff17784554852232b03320852ce4646e3da26e60c45891d2364716686a80a410485856040516116b5929190614fc2565b60405180910390a15050505050565b600c5481565b6116d2614033565b80600b8190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061176c575061173d612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290614fa2565b60405180910390fd5b6117b3613861565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb81858585604051611850949392919061514d565b60405180910390a19392505050565b6009818154811061186f57600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061192757506118f8612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90614fa2565b60405180910390fd5b600061197183611f68565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190614caa565b600a611a129190614e0a565b8284611a1e9190614bcf565b611a289190614c40565b9050611a348482610f91565b50505050565b611a42614033565b611a4c60006140b1565b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611adc5750611aad612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1290614fa2565b60405180910390fd5b6000611b25610e5c565b905060005b600480549050811015611beb576000611b8360048381548110611b5057611b4f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115611bd757611bd660048381548110611ba557611ba4614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b508080611be390614b87565b915050611b2a565b50505050565b600080620186a083611c0288610b8b565b611c0c9190614bcf565b611c169190614c40565b90506000620186a08486611c2a9190614bcf565b611c349190614c40565b905080861115611c4657819250611c73565b6000811115611c6d57808683611c5c9190614bcf565b611c669190614c40565b9250611c72565b600092505b5b5050949350505050565b600080600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701549250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801549150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1690509193509193565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e435750611e14612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990614fa2565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168015611ee15750611ede613861565b81105b15611f645780600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fc95fba30bcfd136a19e944a374d6cd9bb5655441349e1f8f755aa5242ab234148282604051611f5b929190614fc2565b60405180910390a15b5050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b8152600401611fc9919061443d565b602060405180830381865afa158015611fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200a91906151a7565b915050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a05750612071612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6120df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d690614fa2565b60405180910390fd5b60006120e9610a4c565b905060005b6004805490508110156123255782801561218f5750600760006004838154811061211b5761211a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156121e0576121db600482815481106121ab576121aa614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166136ef565b612312565b60066000600483815481106121f8576121f7614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff161580156122c25750600b546122c0600483815481106122905761228f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b1561231157612310600482815481106122de576122dd614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168584613f2d565b5b5b808061231d90614b87565b9150506120ee565b50505050565b6004818154811061233b57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169450600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549150600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154905091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806125c25750612593612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612601576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f890614fa2565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156126e75780600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160006101000a81548160ff0219169083151502179055507f86a5c093bb99c6d06a96c424a351d83258cf9b1438445e973896d74c3edf64eb82826040516126de9291906151d4565b60405180910390a15b5050565b6126f3614033565b6126fe823383614175565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060008060006009868154811061274757612746614af5565b5b90600052602060002090600302016000015494506009868154811061276f5761276e614af5565b5b90600052602060002090600302016001015493506009868154811061279757612796614af5565b5b906000526020600020906003020160020154925060008060005b60048054905081101561294c5760066000600483815481106127d6576127d5614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff166129395788600a60006004848154811061286957612868614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403612938576001836128e19190614b53565b925061292a600482815481106128fa576128f9614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b826129359190614b53565b91505b5b808061294490614b87565b9150506127b1565b50819350809250505091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806129ec57506129bd612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612a2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2290614fa2565b60405180910390fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612d145785600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555082600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0181905550613095565b6001600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506004879080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160001515815260200160008152602001600081526020016000815260200182815250600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a0155905050613094876000611db5565b5b7f43076b6254266dc6be0a352adeba4d67c257b7595d4772ede64a3d2cc343ec36878486898987876040516130d097969594939291906151fd565b60405180910390a150505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a6020528060005260406000206000915090505481565b6000606061312b614033565b6000808773ffffffffffffffffffffffffffffffffffffffff168787876040516131569291906152a0565b60006040518083038185875af1925050503d8060008114613193576040519150601f19603f3d011682016040523d82523d6000602084013e613198565b606091505b5091509150818193509350505094509492505050565b600b5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806132425750613213612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161327890614fa2565b60405180910390fd5b600061328c8461386e565b905060005b6004805490508110156133d75784600a6000600484815481106132b7576132b6614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036133c457600061336e6004838154811061333b5761333a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b905060008111156133c2576133c1600483815481106133905761338f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b505b80806133cf90614b87565b915050613291565b5050505050565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036134325760009050613563565b60006001600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c544261348791906152b9565b6134919190614c40565b61349b9190614b53565b905060006001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007015461353491906152b9565b61353e9190614c40565b6135489190614b53565b90508181101561355b5760009250613560565b600192505b50505b919050565b60076020528060005260406000206000915054906101000a900460ff1681565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060090154036135dc57600190506136ea565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54600d54600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206009015461367891906152b9565b6136829190614c40565b61368c9190614bcf565b600c546136999190614b53565b9050600081426136a991906152b9565b9050600983815481106136bf576136be614af5565b5b9060005260206000209060030201600101548111156136e157600093506136e6565b600193505b5050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061377d575061374e612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6137bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137b390614fa2565b60405180910390fd5b600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561385e576000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061385c8282610f91565b505b50565b6000600980549050905090565b6000805b60048054905081101561396b5782600a60006004848154811061389857613897614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036139585761394a6004828154811061391a57613919614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b826139559190614b53565b91505b808061396390614b87565b915050613872565b50919050565b600d5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613a0557506139d6612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613a44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a3b90614fa2565b60405180910390fd5b60005b600480549050811015613c7d57818015613ae857506007600060048381548110613a7457613a73614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15613b3957613b3460048281548110613b0457613b03614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166136ef565b613c6a565b6006600060048381548110613b5157613b50614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16158015613c1b5750600b54613c1960048381548110613be957613be8614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15613c6957613c6860048281548110613c3757613c36614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611899565b5b5b8080613c7590614b87565b915050613a47565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613d105750613ce1612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613d4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d4690614fa2565b60405180910390fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615613e785781600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f70d7e641df56680393a21230bdc277feec8e8da8af9bdcc93f2bc14f83596ddb838383604051613e6f939291906152ed565b60405180910390a15b505050565b60056020528060005260406000206000915054906101000a900460ff1681565b6000600480549050905090565b613eb2614033565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613f21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f1890615396565b60405180910390fd5b613f2a816140b1565b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613fbb5750613f8c612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613ffa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ff190614fa2565b60405180910390fd5b600061400584611f68565b905060008282856140169190614bcf565b6140209190614c40565b905061402c8582610f91565b5050505050565b61403b6142ab565b73ffffffffffffffffffffffffffffffffffffffff16614059612702565b73ffffffffffffffffffffffffffffffffffffffff16146140af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140a690615402565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016141a7929190614fc2565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516141f591906150ca565b6000604051808303816000865af19150503d8060008114614232576040519150601f19603f3d011682016040523d82523d6000602084013e614237565b606091505b509150915081801561426557506000815114806142645750808060200190518101906142639190615000565b5b5b6142a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161429b9061546e565b60405180910390fd5b5050505050565b600033905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006142e8826142bd565b9050919050565b6142f8816142dd565b811461430357600080fd5b50565b600081359050614315816142ef565b92915050565b600060208284031215614331576143306142b3565b5b600061433f84828501614306565b91505092915050565b6000819050919050565b61435b81614348565b82525050565b60006020820190506143766000830184614352565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143b657808201518184015260208101905061439b565b60008484015250505050565b6000601f19601f8301169050919050565b60006143de8261437c565b6143e88185614387565b93506143f8818560208601614398565b614401816143c2565b840191505092915050565b6000602082019050818103600083015261442681846143d3565b905092915050565b614437816142dd565b82525050565b6000602082019050614452600083018461442e565b92915050565b61446181614348565b811461446c57600080fd5b50565b60008135905061447e81614458565b92915050565b60006020828403121561449a576144996142b3565b5b60006144a88482850161446f565b91505092915050565b600080604083850312156144c8576144c76142b3565b5b60006144d685828601614306565b92505060206144e78582860161446f565b9150509250929050565b60008060006060848603121561450a576145096142b3565b5b60006145188682870161446f565b93505060206145298682870161446f565b925050604061453a8682870161446f565b9150509250925092565b60006060820190506145596000830186614352565b6145666020830185614352565b6145736040830184614352565b949350505050565b60008060408385031215614592576145916142b3565b5b60006145a08582860161446f565b92505060206145b18582860161446f565b9150509250929050565b600080600080608085870312156145d5576145d46142b3565b5b60006145e387828801614306565b94505060206145f48782880161446f565b93505060406146058782880161446f565b92505060606146168782880161446f565b91505092959194509250565b60008115159050919050565b61463781614622565b82525050565b6000608082019050614652600083018761462e565b61465f6020830186614352565b61466c6040830185614352565b614679606083018461462e565b95945050505050565b61468b81614622565b811461469657600080fd5b50565b6000813590506146a881614682565b92915050565b600080604083850312156146c5576146c46142b3565b5b60006146d38582860161446f565b92505060206146e485828601614699565b9150509250929050565b600060a082019050614703600083018861442e565b614710602083018761442e565b61471d604083018661442e565b61472a6060830185614352565b6147376080830184614352565b9695505050505050565b60008060408385031215614758576147576142b3565b5b600061476685828601614306565b925050602061477785828601614699565b9150509250929050565b600060a0820190506147966000830188614352565b6147a36020830187614352565b6147b06040830186614352565b6147bd6060830185614352565b6147ca6080830184614352565b9695505050505050565b600080600080600080600060e0888a0312156147f3576147f26142b3565b5b60006148018a828b01614306565b97505060206148128a828b01614306565b96505060406148238a828b01614306565b95505060606148348a828b01614306565b94505060806148458a828b01614306565b93505060a06148568a828b0161446f565b92505060c06148678a828b0161446f565b91505092959891949750929550565b600080fd5b600080fd5b600080fd5b60008083601f84011261489b5761489a614876565b5b8235905067ffffffffffffffff8111156148b8576148b761487b565b5b6020830191508360018202830111156148d4576148d3614880565b5b9250929050565b600080600080606085870312156148f5576148f46142b3565b5b600061490387828801614306565b94505060206149148782880161446f565b935050604085013567ffffffffffffffff811115614935576149346142b8565b5b61494187828801614885565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006149768261494f565b614980818561495a565b9350614990818560208601614398565b614999816143c2565b840191505092915050565b60006040820190506149b9600083018561462e565b81810360208301526149cb818461496b565b90509392505050565b60006020820190506149e9600083018461462e565b92915050565b600080600060608486031215614a0857614a076142b3565b5b6000614a1686828701614306565b9350506020614a2786828701614699565b9250506040614a388682870161446f565b9150509250925092565b600080600060608486031215614a5b57614a5a6142b3565b5b6000614a6986828701614306565b9350506020614a7a8682870161446f565b9250506040614a8b8682870161446f565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614adc57607f821691505b602082108103614aef57614aee614a95565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b5e82614348565b9150614b6983614348565b9250828201905080821115614b8157614b80614b24565b5b92915050565b6000614b9282614348565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614bc457614bc3614b24565b5b600182019050919050565b6000614bda82614348565b9150614be583614348565b9250828202614bf381614348565b91508282048414831517614c0a57614c09614b24565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614c4b82614348565b9150614c5683614348565b925082614c6657614c65614c11565b5b828204905092915050565b600060ff82169050919050565b614c8781614c71565b8114614c9257600080fd5b50565b600081519050614ca481614c7e565b92915050565b600060208284031215614cc057614cbf6142b3565b5b6000614cce84828501614c95565b91505092915050565b60008160011c9050919050565b6000808291508390505b6001851115614d2e57808604811115614d0a57614d09614b24565b5b6001851615614d195780820291505b8081029050614d2785614cd7565b9450614cee565b94509492505050565b600082614d475760019050614e03565b81614d555760009050614e03565b8160018114614d6b5760028114614d7557614da4565b6001915050614e03565b60ff841115614d8757614d86614b24565b5b8360020a915084821115614d9e57614d9d614b24565b5b50614e03565b5060208310610133831016604e8410600b8410161715614dd95782820a905083811115614dd457614dd3614b24565b5b614e03565b614de68484846001614ce4565b92509050818404811115614dfd57614dfc614b24565b5b81810290505b9392505050565b6000614e1582614348565b9150614e2083614c71565b9250614e4d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614d37565b905092915050565b6000604082019050614e6a600083018561442e565b614e77602083018461442e565b9392505050565b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b6000614eb4601283614387565b9150614ebf82614e7e565b602082019050919050565b60006020820190508181036000830152614ee381614ea7565b9050919050565b7f506f6f6c20697320736d616c6c00000000000000000000000000000000000000600082015250565b6000614f20600d83614387565b9150614f2b82614eea565b602082019050919050565b60006020820190508181036000830152614f4f81614f13565b9050919050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b6000614f8c601583614387565b9150614f9782614f56565b602082019050919050565b60006020820190508181036000830152614fbb81614f7f565b9050919050565b6000604082019050614fd7600083018561442e565b614fe46020830184614352565b9392505050565b600081519050614ffa81614682565b92915050565b600060208284031215615016576150156142b3565b5b600061502484828501614feb565b91505092915050565b600060c082019050615042600083018961442e565b61504f602083018861442e565b61505c604083018761442e565b615069606083018661442e565b6150766080830185614352565b61508360a0830184614352565b979650505050505050565b600081905092915050565b60006150a48261494f565b6150ae818561508e565b93506150be818560208601614398565b80840191505092915050565b60006150d68284615099565b915081905092915050565b7f64656c656761746563616c6c206661696c656400000000000000000000000000600082015250565b6000615117601383614387565b9150615122826150e1565b602082019050919050565b600060208201905081810360008301526151468161510a565b9050919050565b60006080820190506151626000830187614352565b61516f6020830186614352565b61517c6040830185614352565b6151896060830184614352565b95945050505050565b6000815190506151a181614458565b92915050565b6000602082840312156151bd576151bc6142b3565b5b60006151cb84828501615192565b91505092915050565b60006040820190506151e9600083018561442e565b6151f6602083018461462e565b9392505050565b600060e082019050615212600083018a61442e565b61521f602083018961442e565b61522c604083018861442e565b615239606083018761442e565b615246608083018661442e565b61525360a0830185614352565b61526060c0830184614352565b98975050505050505050565b82818337600083830152505050565b6000615287838561508e565b935061529483858461526c565b82840190509392505050565b60006152ad82848661527b565b91508190509392505050565b60006152c482614348565b91506152cf83614348565b92508282039050818111156152e7576152e6614b24565b5b92915050565b6000606082019050615302600083018661442e565b61530f602083018561462e565b61531c6040830184614352565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615380602683614387565b915061538b82615324565b604082019050919050565b600060208201905081810360008301526153af81615373565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006153ec602083614387565b91506153f7826153b6565b602082019050919050565b6000602082019050818103600083015261541b816153df565b9050919050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000615458601f83614387565b915061546382615422565b602082019050919050565b600060208201905081810360008301526154878161544b565b9050919050560000000000000000000000006e74053a3798e0fc9a9775f7995316b27f21c4d2000000000000000000000000fc00000000000000000000000000000000000001000000000000000000000000fc0000000000000000000000000000000000000200000000000000000000000000000000000000000000010f0cf064dd592000000000000000000000000000000000000000000000000000000000000065555b800000000000000000000000000000000000000000000000000000000000093a80
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103155760003560e01c806386bfdb19116101a7578063d27761ef116100ee578063ec06a89a11610097578063efde4e6411610071578063efde4e6414610950578063f2fde38b1461096e578063f7f2e80d1461098a57610315565b8063ec06a89a146108e8578063ec16bf4714610904578063ee5b11c31461092057610315565b8063e81e5dde116100c8578063e81e5dde1461087c578063ea6efa951461089a578063eac471a0146108ca57610315565b8063d27761ef14610800578063e0a88bbc14610830578063e390ddde1461086057610315565b8063ae49945d11610150578063b75402191161012a578063b754021914610796578063cc64463a146107b4578063cdc97f77146107d057610315565b8063ae49945d14610717578063afce9fde14610735578063b61d27f61461076557610315565b80638da5cb5b116101815780638da5cb5b146106a95780639fbd2c8c146106c7578063a95dffd6146106fb57610315565b806386bfdb191461063d57806388660611146106715780638980f11f1461068d57610315565b806360976e6f1161026b57806379605ea01161021457806381d81d2a116101ee57806381d81d2a146105c157806381d8b3f8146105f157806382eac7f01461060d57610315565b806379605ea0146105425780637c43215f146105725780637ea48c10146105a557610315565b806370c8f7fe1161024557806370c8f7fe14610500578063715018a61461051c578063793171c51461052657610315565b806360976e6f146104825780636358ec571461049e5780636cef1b77146104ce57610315565b806320263e87116102cd5780633d84ceca116102a75780633d84ceca1461042c57806345c1262614610448578063581289691461046457610315565b806320263e87146103d45780632501853f146103f25780632f1d5a601461041057610315565b80630f37b6ba116102fe5780630f37b6ba14610368578063127effb2146103865780631a799e00146103a457610315565b806303ea9f1f1461031a57806306fdde031461034a575b600080fd5b610334600480360381019061032f919061431b565b6109a6565b6040516103419190614361565b60405180910390f35b6103526109be565b60405161035f919061440c565b60405180910390f35b610370610a4c565b60405161037d9190614361565b60405180910390f35b61038e610b65565b60405161039b919061443d565b60405180910390f35b6103be60048036038101906103b9919061431b565b610b8b565b6040516103cb9190614361565b60405180910390f35b6103dc610e36565b6040516103e9919061443d565b60405180910390f35b6103fa610e5c565b6040516104079190614361565b60405180910390f35b61042a6004803603810190610425919061431b565b610ed8565b005b61044660048036038101906104419190614484565b610f7f565b005b610462600480360381019061045d91906144b1565b610f91565b005b61046c6116c4565b6040516104799190614361565b60405180910390f35b61049c60048036038101906104979190614484565b6116ca565b005b6104b860048036038101906104b391906144f1565b6116dc565b6040516104c59190614361565b60405180910390f35b6104e860048036038101906104e39190614484565b61185f565b6040516104f793929190614544565b60405180910390f35b61051a600480360381019061051591906144b1565b611899565b005b610524611a3a565b005b610540600480360381019061053b919061457b565b611a4e565b005b61055c600480360381019061055791906145bb565b611bf1565b6040516105699190614361565b60405180910390f35b61058c6004803603810190610587919061431b565b611c7d565b60405161059c949392919061463d565b60405180910390f35b6105bf60048036038101906105ba91906144b1565b611db5565b005b6105db60048036038101906105d6919061431b565b611f68565b6040516105e89190614361565b60405180910390f35b61060b600480360381019061060691906146ae565b612012565b005b61062760048036038101906106229190614484565b61232b565b604051610634919061443d565b60405180910390f35b6106576004803603810190610652919061431b565b61236a565b6040516106689594939291906146ee565b60405180910390f35b61068b60048036038101906106869190614741565b612534565b005b6106a760048036038101906106a291906144b1565b6126eb565b005b6106b1612702565b6040516106be919061443d565b60405180910390f35b6106e160048036038101906106dc9190614484565b61272b565b6040516106f2959493929190614781565b60405180910390f35b610715600480360381019061071091906147d4565b61295e565b005b61071f6130e1565b60405161072c919061443d565b60405180910390f35b61074f600480360381019061074a919061431b565b613107565b60405161075c9190614361565b60405180910390f35b61077f600480360381019061077a91906148db565b61311f565b60405161078d9291906149a4565b60405180910390f35b61079e6131ae565b6040516107ab9190614361565b60405180910390f35b6107ce60048036038101906107c991906144f1565b6131b4565b005b6107ea60048036038101906107e5919061431b565b6133de565b6040516107f791906149d4565b60405180910390f35b61081a6004803603810190610815919061431b565b613568565b60405161082791906149d4565b60405180910390f35b61084a6004803603810190610845919061431b565b613588565b60405161085791906149d4565b60405180910390f35b61087a6004803603810190610875919061431b565b6136ef565b005b610884613861565b6040516108919190614361565b60405180910390f35b6108b460048036038101906108af9190614484565b61386e565b6040516108c19190614361565b60405180910390f35b6108d2613971565b6040516108df9190614361565b60405180910390f35b61090260048036038101906108fd91906146ae565b613977565b005b61091e600480360381019061091991906149ef565b613c82565b005b61093a6004803603810190610935919061431b565b613e7d565b60405161094791906149d4565b60405180910390f35b610958613e9d565b6040516109659190614361565b60405180910390f35b6109886004803603810190610983919061431b565b613eaa565b005b6109a4600480360381019061099f9190614a42565b613f2d565b005b60086020528060005260406000206000915090505481565b600e80546109cb90614ac4565b80601f01602080910402602001604051908101604052809291908181526020018280546109f790614ac4565b8015610a445780601f10610a1957610100808354040283529160200191610a44565b820191906000526020600020905b815481529060010190602001808311610a2757829003601f168201915b505050505081565b6000806000905060005b600480549050811015610b5d576006600060048381548110610a7b57610a7a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16610b4a57610b3c60048281548110610b0c57610b0b614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82610b479190614b53565b91505b8080610b5590614b87565b915050610a56565b508091505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080610b9783611f68565b90506000600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54620186a0600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154610c339190614bcf565b610c3d9190614c40565b9050600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd39190614caa565b600a610cdf9190614e0a565b8560098681548110610cf457610cf3614af5565b5b906000526020600020906003020160000154610d109190614bcf565b610d1a9190614c40565b9050610d2587613588565b15610d535760098481548110610d3e57610d3d614af5565b5b90600052602060002090600302016002015491505b610d5c876133de565b15610d6a5760009550610e2c565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1615610dc85760009550610e2b565b600b54610dd488611f68565b1015610de35760009550610e2a565b80821115610e0c57620186a08383610dfb9190614bcf565b610e059190614c40565b9550610e29565b620186a08382610e1c9190614bcf565b610e269190614c40565b95505b5b5b5b5050505050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000805b600480549050811015610ed457610eb460048281548110610e8457610e83614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82610ebf9190614b53565b91508080610ecc90614b87565b915050610e60565b5090565b610ee0614033565b7f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051610f33929190614e55565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610f87614033565b80600d8190555050565b81600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156110385750600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16155b611077576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106e90614eca565b60405180910390fd5b600b5461108382611f68565b116110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90614f36565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111515750611122612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161118790614fa2565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401611254929190614fc2565b6020604051808303816000875af1158015611273573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112979190615000565b506000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1685600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154896040516024016114569695949392919061502d565b6040516020818303038152906040527fb649fbf4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516114e091906150ca565b600060405180830381855af49150503d806000811461151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5050905080611564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155b9061512d565b60405180910390fd5b6000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036115f65742600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901819055505b42600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801819055507ff17784554852232b03320852ce4646e3da26e60c45891d2364716686a80a410485856040516116b5929190614fc2565b60405180910390a15050505050565b600c5481565b6116d2614033565b80600b8190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061176c575061173d612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290614fa2565b60405180910390fd5b6117b3613861565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb81858585604051611850949392919061514d565b60405180910390a19392505050565b6009818154811061186f57600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061192757506118f8612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90614fa2565b60405180910390fd5b600061197183611f68565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190614caa565b600a611a129190614e0a565b8284611a1e9190614bcf565b611a289190614c40565b9050611a348482610f91565b50505050565b611a42614033565b611a4c60006140b1565b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611adc5750611aad612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1290614fa2565b60405180910390fd5b6000611b25610e5c565b905060005b600480549050811015611beb576000611b8360048381548110611b5057611b4f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115611bd757611bd660048381548110611ba557611ba4614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b508080611be390614b87565b915050611b2a565b50505050565b600080620186a083611c0288610b8b565b611c0c9190614bcf565b611c169190614c40565b90506000620186a08486611c2a9190614bcf565b611c349190614c40565b905080861115611c4657819250611c73565b6000811115611c6d57808683611c5c9190614bcf565b611c669190614c40565b9250611c72565b600092505b5b5050949350505050565b600080600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701549250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801549150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1690509193509193565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e435750611e14612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990614fa2565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168015611ee15750611ede613861565b81105b15611f645780600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fc95fba30bcfd136a19e944a374d6cd9bb5655441349e1f8f755aa5242ab234148282604051611f5b929190614fc2565b60405180910390a15b5050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b8152600401611fc9919061443d565b602060405180830381865afa158015611fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200a91906151a7565b915050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a05750612071612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6120df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d690614fa2565b60405180910390fd5b60006120e9610a4c565b905060005b6004805490508110156123255782801561218f5750600760006004838154811061211b5761211a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156121e0576121db600482815481106121ab576121aa614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166136ef565b612312565b60066000600483815481106121f8576121f7614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff161580156122c25750600b546122c0600483815481106122905761228f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b1561231157612310600482815481106122de576122dd614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168584613f2d565b5b5b808061231d90614b87565b9150506120ee565b50505050565b6004818154811061233b57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169450600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549150600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154905091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806125c25750612593612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612601576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f890614fa2565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156126e75780600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160006101000a81548160ff0219169083151502179055507f86a5c093bb99c6d06a96c424a351d83258cf9b1438445e973896d74c3edf64eb82826040516126de9291906151d4565b60405180910390a15b5050565b6126f3614033565b6126fe823383614175565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060008060006009868154811061274757612746614af5565b5b90600052602060002090600302016000015494506009868154811061276f5761276e614af5565b5b90600052602060002090600302016001015493506009868154811061279757612796614af5565b5b906000526020600020906003020160020154925060008060005b60048054905081101561294c5760066000600483815481106127d6576127d5614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff166129395788600a60006004848154811061286957612868614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403612938576001836128e19190614b53565b925061292a600482815481106128fa576128f9614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b826129359190614b53565b91505b5b808061294490614b87565b9150506127b1565b50819350809250505091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806129ec57506129bd612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612a2b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2290614fa2565b60405180910390fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612d145785600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555082600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0181905550613095565b6001600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506004879080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160001515815260200160008152602001600081526020016000815260200182815250600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a0155905050613094876000611db5565b5b7f43076b6254266dc6be0a352adeba4d67c257b7595d4772ede64a3d2cc343ec36878486898987876040516130d097969594939291906151fd565b60405180910390a150505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a6020528060005260406000206000915090505481565b6000606061312b614033565b6000808773ffffffffffffffffffffffffffffffffffffffff168787876040516131569291906152a0565b60006040518083038185875af1925050503d8060008114613193576040519150601f19603f3d011682016040523d82523d6000602084013e613198565b606091505b5091509150818193509350505094509492505050565b600b5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806132425750613213612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613281576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161327890614fa2565b60405180910390fd5b600061328c8461386e565b905060005b6004805490508110156133d75784600a6000600484815481106132b7576132b6614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036133c457600061336e6004838154811061333b5761333a614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b905060008111156133c2576133c1600483815481106133905761338f614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b505b80806133cf90614b87565b915050613291565b5050505050565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036134325760009050613563565b60006001600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c544261348791906152b9565b6134919190614c40565b61349b9190614b53565b905060006001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007015461353491906152b9565b61353e9190614c40565b6135489190614b53565b90508181101561355b5760009250613560565b600192505b50505b919050565b60076020528060005260406000206000915054906101000a900460ff1681565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060090154036135dc57600190506136ea565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54600d54600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206009015461367891906152b9565b6136829190614c40565b61368c9190614bcf565b600c546136999190614b53565b9050600081426136a991906152b9565b9050600983815481106136bf576136be614af5565b5b9060005260206000209060030201600101548111156136e157600093506136e6565b600193505b5050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061377d575061374e612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6137bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137b390614fa2565b60405180910390fd5b600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561385e576000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061385c8282610f91565b505b50565b6000600980549050905090565b6000805b60048054905081101561396b5782600a60006004848154811061389857613897614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036139585761394a6004828154811061391a57613919614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b826139559190614b53565b91505b808061396390614b87565b915050613872565b50919050565b600d5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613a0557506139d6612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613a44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613a3b90614fa2565b60405180910390fd5b60005b600480549050811015613c7d57818015613ae857506007600060048381548110613a7457613a73614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15613b3957613b3460048281548110613b0457613b03614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166136ef565b613c6a565b6006600060048381548110613b5157613b50614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16158015613c1b5750600b54613c1960048381548110613be957613be8614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15613c6957613c6860048281548110613c3757613c36614af5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611899565b5b5b8080613c7590614b87565b915050613a47565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613d105750613ce1612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613d4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d4690614fa2565b60405180910390fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615613e785781600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f70d7e641df56680393a21230bdc277feec8e8da8af9bdcc93f2bc14f83596ddb838383604051613e6f939291906152ed565b60405180910390a15b505050565b60056020528060005260406000206000915054906101000a900460ff1681565b6000600480549050905090565b613eb2614033565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613f21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f1890615396565b60405180910390fd5b613f2a816140b1565b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613fbb5750613f8c612702565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613ffa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ff190614fa2565b60405180910390fd5b600061400584611f68565b905060008282856140169190614bcf565b6140209190614c40565b905061402c8582610f91565b5050505050565b61403b6142ab565b73ffffffffffffffffffffffffffffffffffffffff16614059612702565b73ffffffffffffffffffffffffffffffffffffffff16146140af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140a690615402565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016141a7929190614fc2565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516141f591906150ca565b6000604051808303816000865af19150503d8060008114614232576040519150601f19603f3d011682016040523d82523d6000602084013e614237565b606091505b509150915081801561426557506000815114806142645750808060200190518101906142639190615000565b5b5b6142a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161429b9061546e565b60405180910390fd5b5050505050565b600033905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006142e8826142bd565b9050919050565b6142f8816142dd565b811461430357600080fd5b50565b600081359050614315816142ef565b92915050565b600060208284031215614331576143306142b3565b5b600061433f84828501614306565b91505092915050565b6000819050919050565b61435b81614348565b82525050565b60006020820190506143766000830184614352565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143b657808201518184015260208101905061439b565b60008484015250505050565b6000601f19601f8301169050919050565b60006143de8261437c565b6143e88185614387565b93506143f8818560208601614398565b614401816143c2565b840191505092915050565b6000602082019050818103600083015261442681846143d3565b905092915050565b614437816142dd565b82525050565b6000602082019050614452600083018461442e565b92915050565b61446181614348565b811461446c57600080fd5b50565b60008135905061447e81614458565b92915050565b60006020828403121561449a576144996142b3565b5b60006144a88482850161446f565b91505092915050565b600080604083850312156144c8576144c76142b3565b5b60006144d685828601614306565b92505060206144e78582860161446f565b9150509250929050565b60008060006060848603121561450a576145096142b3565b5b60006145188682870161446f565b93505060206145298682870161446f565b925050604061453a8682870161446f565b9150509250925092565b60006060820190506145596000830186614352565b6145666020830185614352565b6145736040830184614352565b949350505050565b60008060408385031215614592576145916142b3565b5b60006145a08582860161446f565b92505060206145b18582860161446f565b9150509250929050565b600080600080608085870312156145d5576145d46142b3565b5b60006145e387828801614306565b94505060206145f48782880161446f565b93505060406146058782880161446f565b92505060606146168782880161446f565b91505092959194509250565b60008115159050919050565b61463781614622565b82525050565b6000608082019050614652600083018761462e565b61465f6020830186614352565b61466c6040830185614352565b614679606083018461462e565b95945050505050565b61468b81614622565b811461469657600080fd5b50565b6000813590506146a881614682565b92915050565b600080604083850312156146c5576146c46142b3565b5b60006146d38582860161446f565b92505060206146e485828601614699565b9150509250929050565b600060a082019050614703600083018861442e565b614710602083018761442e565b61471d604083018661442e565b61472a6060830185614352565b6147376080830184614352565b9695505050505050565b60008060408385031215614758576147576142b3565b5b600061476685828601614306565b925050602061477785828601614699565b9150509250929050565b600060a0820190506147966000830188614352565b6147a36020830187614352565b6147b06040830186614352565b6147bd6060830185614352565b6147ca6080830184614352565b9695505050505050565b600080600080600080600060e0888a0312156147f3576147f26142b3565b5b60006148018a828b01614306565b97505060206148128a828b01614306565b96505060406148238a828b01614306565b95505060606148348a828b01614306565b94505060806148458a828b01614306565b93505060a06148568a828b0161446f565b92505060c06148678a828b0161446f565b91505092959891949750929550565b600080fd5b600080fd5b600080fd5b60008083601f84011261489b5761489a614876565b5b8235905067ffffffffffffffff8111156148b8576148b761487b565b5b6020830191508360018202830111156148d4576148d3614880565b5b9250929050565b600080600080606085870312156148f5576148f46142b3565b5b600061490387828801614306565b94505060206149148782880161446f565b935050604085013567ffffffffffffffff811115614935576149346142b8565b5b61494187828801614885565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60006149768261494f565b614980818561495a565b9350614990818560208601614398565b614999816143c2565b840191505092915050565b60006040820190506149b9600083018561462e565b81810360208301526149cb818461496b565b90509392505050565b60006020820190506149e9600083018461462e565b92915050565b600080600060608486031215614a0857614a076142b3565b5b6000614a1686828701614306565b9350506020614a2786828701614699565b9250506040614a388682870161446f565b9150509250925092565b600080600060608486031215614a5b57614a5a6142b3565b5b6000614a6986828701614306565b9350506020614a7a8682870161446f565b9250506040614a8b8682870161446f565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614adc57607f821691505b602082108103614aef57614aee614a95565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614b5e82614348565b9150614b6983614348565b9250828201905080821115614b8157614b80614b24565b5b92915050565b6000614b9282614348565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614bc457614bc3614b24565b5b600182019050919050565b6000614bda82614348565b9150614be583614348565b9250828202614bf381614348565b91508282048414831517614c0a57614c09614b24565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614c4b82614348565b9150614c5683614348565b925082614c6657614c65614c11565b5b828204905092915050565b600060ff82169050919050565b614c8781614c71565b8114614c9257600080fd5b50565b600081519050614ca481614c7e565b92915050565b600060208284031215614cc057614cbf6142b3565b5b6000614cce84828501614c95565b91505092915050565b60008160011c9050919050565b6000808291508390505b6001851115614d2e57808604811115614d0a57614d09614b24565b5b6001851615614d195780820291505b8081029050614d2785614cd7565b9450614cee565b94509492505050565b600082614d475760019050614e03565b81614d555760009050614e03565b8160018114614d6b5760028114614d7557614da4565b6001915050614e03565b60ff841115614d8757614d86614b24565b5b8360020a915084821115614d9e57614d9d614b24565b5b50614e03565b5060208310610133831016604e8410600b8410161715614dd95782820a905083811115614dd457614dd3614b24565b5b614e03565b614de68484846001614ce4565b92509050818404811115614dfd57614dfc614b24565b5b81810290505b9392505050565b6000614e1582614348565b9150614e2083614c71565b9250614e4d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614d37565b905092915050565b6000604082019050614e6a600083018561442e565b614e77602083018461442e565b9392505050565b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b6000614eb4601283614387565b9150614ebf82614e7e565b602082019050919050565b60006020820190508181036000830152614ee381614ea7565b9050919050565b7f506f6f6c20697320736d616c6c00000000000000000000000000000000000000600082015250565b6000614f20600d83614387565b9150614f2b82614eea565b602082019050919050565b60006020820190508181036000830152614f4f81614f13565b9050919050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b6000614f8c601583614387565b9150614f9782614f56565b602082019050919050565b60006020820190508181036000830152614fbb81614f7f565b9050919050565b6000604082019050614fd7600083018561442e565b614fe46020830184614352565b9392505050565b600081519050614ffa81614682565b92915050565b600060208284031215615016576150156142b3565b5b600061502484828501614feb565b91505092915050565b600060c082019050615042600083018961442e565b61504f602083018861442e565b61505c604083018761442e565b615069606083018661442e565b6150766080830185614352565b61508360a0830184614352565b979650505050505050565b600081905092915050565b60006150a48261494f565b6150ae818561508e565b93506150be818560208601614398565b80840191505092915050565b60006150d68284615099565b915081905092915050565b7f64656c656761746563616c6c206661696c656400000000000000000000000000600082015250565b6000615117601383614387565b9150615122826150e1565b602082019050919050565b600060208201905081810360008301526151468161510a565b9050919050565b60006080820190506151626000830187614352565b61516f6020830186614352565b61517c6040830185614352565b6151896060830184614352565b95945050505050565b6000815190506151a181614458565b92915050565b6000602082840312156151bd576151bc6142b3565b5b60006151cb84828501615192565b91505092915050565b60006040820190506151e9600083018561442e565b6151f6602083018461462e565b9392505050565b600060e082019050615212600083018a61442e565b61521f602083018961442e565b61522c604083018861442e565b615239606083018761442e565b615246608083018661442e565b61525360a0830185614352565b61526060c0830184614352565b98975050505050505050565b82818337600083830152505050565b6000615287838561508e565b935061529483858461526c565b82840190509392505050565b60006152ad82848661527b565b91508190509392505050565b60006152c482614348565b91506152cf83614348565b92508282039050818111156152e7576152e6614b24565b5b92915050565b6000606082019050615302600083018661442e565b61530f602083018561462e565b61531c6040830184614352565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615380602683614387565b915061538b82615324565b604082019050919050565b600060208201905081810360008301526153af81615373565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006153ec602083614387565b91506153f7826153b6565b602082019050919050565b6000602082019050818103600083015261541b816153df565b9050919050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000615458601f83614387565b915061546382615422565b602082019050919050565b600060208201905081810360008301526154878161544b565b905091905056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e74053a3798e0fc9a9775f7995316b27f21c4d2000000000000000000000000fc00000000000000000000000000000000000001000000000000000000000000fc0000000000000000000000000000000000000200000000000000000000000000000000000000000000010f0cf064dd592000000000000000000000000000000000000000000000000000000000000065555b800000000000000000000000000000000000000000000000000000000000093a80
-----Decoded View---------------
Arg [0] : _operatorAddress (address): 0x6e74053a3798e0fC9a9775F7995316b27f21c4D2
Arg [1] : _targetTokenAddress (address): 0xFc00000000000000000000000000000000000001
Arg [2] : _incentiveTokenAddress (address): 0xFc00000000000000000000000000000000000002
Arg [3] : _minTvl (uint256): 5000000000000000000000
Arg [4] : _cycleStart (uint256): 1700092800
Arg [5] : _cycleLength (uint256): 604800
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e74053a3798e0fc9a9775f7995316b27f21c4d2
Arg [1] : 000000000000000000000000fc00000000000000000000000000000000000001
Arg [2] : 000000000000000000000000fc00000000000000000000000000000000000002
Arg [3] : 00000000000000000000000000000000000000000000010f0cf064dd59200000
Arg [4] : 0000000000000000000000000000000000000000000000000000000065555b80
Arg [5] : 0000000000000000000000000000000000000000000000000000000000093a80
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$2,519.88
Net Worth in FRAX
2,964.513496
Token Allocations
WFRAX
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| FRAXTAL | 100.00% | $0.855192 | 2,946.5648 | $2,519.88 |
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.