Source Code
Latest 25 from a total of 82 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Incentivize All ... | 30121278 | 28 days ago | IN | 0 FRAX | 0.00000363 | ||||
| Incentivize All ... | 29771290 | 36 days ago | IN | 0 FRAX | 0.00000276 | ||||
| Incentivize All ... | 29475632 | 43 days ago | IN | 0 FRAX | 0.00000357 | ||||
| Incentivize All ... | 29160707 | 50 days ago | IN | 0 FRAX | 0.00003402 | ||||
| Incentivize All ... | 28872046 | 57 days ago | IN | 0 FRAX | 0.000005 | ||||
| Incentivize All ... | 28545165 | 64 days ago | IN | 0 FRAX | 0.00000744 | ||||
| Incentivize All ... | 28265488 | 71 days ago | IN | 0 FRAX | 0.00000763 | ||||
| Incentivize All ... | 27934518 | 78 days ago | IN | 0 FRAX | 0.00000637 | ||||
| Incentivize All ... | 27690791 | 84 days ago | IN | 0 FRAX | 0.00010228 | ||||
| Incentivize All ... | 27343410 | 92 days ago | IN | 0 FRAX | 0.00000941 | ||||
| Incentivize All ... | 27010955 | 100 days ago | IN | 0 FRAX | 0.00000895 | ||||
| Incentivize All ... | 26694839 | 107 days ago | IN | 0 FRAX | 0.00004213 | ||||
| Incentivize All ... | 26362006 | 115 days ago | IN | 0 FRAX | 0.00001287 | ||||
| Incentivize All ... | 26063719 | 122 days ago | IN | 0 FRAX | 0.00001067 | ||||
| Incentivize All ... | 25758609 | 129 days ago | IN | 0 FRAX | 0.00001576 | ||||
| Incentivize All ... | 25443939 | 136 days ago | IN | 0 FRAX | 0.00008025 | ||||
| Incentivize All ... | 25121193 | 144 days ago | IN | 0 FRAX | 0.0000153 | ||||
| Incentivize All ... | 24817501 | 151 days ago | IN | 0 FRAX | 0.00001887 | ||||
| Incentivize All ... | 24513806 | 158 days ago | IN | 0 FRAX | 0.00001942 | ||||
| Incentivize All ... | 24203153 | 165 days ago | IN | 0 FRAX | 0.00003086 | ||||
| Incentivize All ... | 23900408 | 172 days ago | IN | 0 FRAX | 0.00002749 | ||||
| Incentivize All ... | 23606700 | 179 days ago | IN | 0 FRAX | 0.00001762 | ||||
| Incentivize All ... | 23297341 | 186 days ago | IN | 0 FRAX | 0.00002373 | ||||
| Incentivize All ... | 22996669 | 193 days ago | IN | 0 FRAX | 0.00060423 | ||||
| Incentivize All ... | 22733217 | 199 days ago | IN | 0 FRAX | 0.00010968 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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:
IncentivizerAmoV32
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;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ======================= IncentivizerAmoV32 =========================
// ====================================================================
// 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 "./interfaces/IStrategyHandler.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 IncentivizerAmoV32 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);
IIncentivizationHandler handler = IIncentivizationHandler(poolInfo[_poolAddress].incentivizationHandlerAddress);
try handler.balanceOfTargetToken(_poolAddress, poolInfo[_poolAddress].gaugeAddress, targetTokenAddress) returns (uint256 balance) {
return balance;
} catch {
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: UNLICENSED
pragma solidity ^0.8.19;
interface IStrategyHandler {
function tokens(
address poolAddress,
address gaugeAddress) external view returns(address[] memory tokens);
function tokenCount(
address poolAddress,
address gaugeAddress) external view returns(uint256);
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 targetTokenToLPTokenRatio(
address poolAddress,
address lpTokenAddress,
address gaugeAddress,
address targetTokenAddress,
uint256 amount) external view returns(uint256);
function lpTokenToTargetTokenRatio(
address poolAddress,
address lpTokenAddress,
address gaugeAddress,
address targetTokenAddress,
uint256 amount) external view returns(uint256);
function balanceOfLPIncentives(
address poolAddress,
address lpTokenAddress,
address gaugeAddress) external view returns(address[] memory rewardTokens, uint256[] memory rewardAmounts);
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 claimLPIncentives(
address poolAddress,
address lpTokenAddress,
address gaugeAddress) 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
60806040523480156200001157600080fd5b50604051620063da380380620063da8339818101604052810190620000379190620005cb565b620000576200004b6200027c60201b60201c565b6200028460201b60201c565b85600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600b8190555042821062000166576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015d90620006c8565b60405180910390fd5b81600c8190555080600d819055508473ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001c0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620001eb919062000869565b604051602001620001fd91906200092d565b604051602081830303815290604052600e90816200021c919062000b8d565b506200023260008060006200034860201b60201c565b507f7fd171b754859e1fd38f494c38b79fa1028241732e981b993116333300b487e6868686604051620002689392919062000c85565b60405180910390a150505050505062000d92565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480620003e15750620003b2620004e160201b60201c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b62000423576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200041a9062000d12565b60405180910390fd5b620004336200050a60201b60201c565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb81858585604051620004d2949392919062000d45565b60405180910390a19392505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600980549050905090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000558826200052b565b9050919050565b6200056a816200054b565b81146200057657600080fd5b50565b6000815190506200058a816200055f565b92915050565b6000819050919050565b620005a58162000590565b8114620005b157600080fd5b50565b600081519050620005c5816200059a565b92915050565b60008060008060008060c08789031215620005eb57620005ea62000521565b5b6000620005fb89828a0162000579565b96505060206200060e89828a0162000579565b95505060406200062189828a0162000579565b94505060606200063489828a01620005b4565b93505060806200064789828a01620005b4565b92505060a06200065a89828a01620005b4565b9150509295509295509295565b600082825260208201905092915050565b7f4379636c652073746172742074696d65206572726f7200000000000000000000600082015250565b6000620006b060168362000667565b9150620006bd8262000678565b602082019050919050565b60006020820190508181036000830152620006e381620006a1565b9050919050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200073f82620006f4565b810181811067ffffffffffffffff8211171562000761576200076062000705565b5b80604052505050565b60006200077662000517565b905062000784828262000734565b919050565b600067ffffffffffffffff821115620007a757620007a662000705565b5b620007b282620006f4565b9050602081019050919050565b60005b83811015620007df578082015181840152602081019050620007c2565b60008484015250505050565b600062000802620007fc8462000789565b6200076a565b905082815260208101848484011115620008215762000820620006ef565b5b6200082e848285620007bf565b509392505050565b600082601f8301126200084e576200084d620006ea565b5b815162000860848260208601620007eb565b91505092915050565b60006020828403121562000882576200088162000521565b5b600082015167ffffffffffffffff811115620008a357620008a262000526565b5b620008b18482850162000836565b91505092915050565b600081519050919050565b600081905092915050565b6000620008dd82620008ba565b620008e98185620008c5565b9350620008fb818560208601620007bf565b80840191505092915050565b7f204c697175696469747920496e63656e746976697a6572000000000000000000815250565b60006200093b8284620008d0565b9150620009488262000907565b60178201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200099f57607f821691505b602082108103620009b557620009b462000957565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000a1f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620009e0565b62000a2b8683620009e0565b95508019841693508086168417925050509392505050565b6000819050919050565b600062000a6e62000a6862000a628462000590565b62000a43565b62000590565b9050919050565b6000819050919050565b62000a8a8362000a4d565b62000aa262000a998262000a75565b848454620009ed565b825550505050565b600090565b62000ab962000aaa565b62000ac681848462000a7f565b505050565b5b8181101562000aee5762000ae260008262000aaf565b60018101905062000acc565b5050565b601f82111562000b3d5762000b0781620009bb565b62000b1284620009d0565b8101602085101562000b22578190505b62000b3a62000b3185620009d0565b83018262000acb565b50505b505050565b600082821c905092915050565b600062000b626000198460080262000b42565b1980831691505092915050565b600062000b7d838362000b4f565b9150826002028217905092915050565b62000b9882620008ba565b67ffffffffffffffff81111562000bb45762000bb362000705565b5b62000bc0825462000986565b62000bcd82828562000af2565b600060209050601f83116001811462000c05576000841562000bf0578287015190505b62000bfc858262000b6f565b86555062000c6c565b601f19841662000c1586620009bb565b60005b8281101562000c3f5784890151825560018201915060208501945060208101905062000c18565b8683101562000c5f578489015162000c5b601f89168262000b4f565b8355505b6001600288020188555050505b505050505050565b62000c7f816200054b565b82525050565b600060608201905062000c9c600083018662000c74565b62000cab602083018562000c74565b62000cba604083018462000c74565b949350505050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b600062000cfa60158362000667565b915062000d078262000cc2565b602082019050919050565b6000602082019050818103600083015262000d2d8162000ceb565b9050919050565b62000d3f8162000590565b82525050565b600060808201905062000d5c600083018762000d34565b62000d6b602083018662000d34565b62000d7a604083018562000d34565b62000d89606083018462000d34565b95945050505050565b6156388062000da26000396000f3fe608060405234801561001057600080fd5b50600436106103155760003560e01c806386bfdb19116101a7578063d27761ef116100ee578063ec06a89a11610097578063efde4e6411610071578063efde4e6414610950578063f2fde38b1461096e578063f7f2e80d1461098a57610315565b8063ec06a89a146108e8578063ec16bf4714610904578063ee5b11c31461092057610315565b8063e81e5dde116100c8578063e81e5dde1461087c578063ea6efa951461089a578063eac471a0146108ca57610315565b8063d27761ef14610800578063e0a88bbc14610830578063e390ddde1461086057610315565b8063ae49945d11610150578063b75402191161012a578063b754021914610796578063cc64463a146107b4578063cdc97f77146107d057610315565b8063ae49945d14610717578063afce9fde14610735578063b61d27f61461076557610315565b80638da5cb5b116101815780638da5cb5b146106a95780639fbd2c8c146106c7578063a95dffd6146106fb57610315565b806386bfdb191461063d57806388660611146106715780638980f11f1461068d57610315565b806360976e6f1161026b57806379605ea01161021457806381d81d2a116101ee57806381d81d2a146105c157806381d8b3f8146105f157806382eac7f01461060d57610315565b806379605ea0146105425780637c43215f146105725780637ea48c10146105a557610315565b806370c8f7fe1161024557806370c8f7fe14610500578063715018a61461051c578063793171c51461052657610315565b806360976e6f146104825780636358ec571461049e5780636cef1b77146104ce57610315565b806320263e87116102cd5780633d84ceca116102a75780633d84ceca1461042c57806345c1262614610448578063581289691461046457610315565b806320263e87146103d45780632501853f146103f25780632f1d5a601461041057610315565b80630f37b6ba116102fe5780630f37b6ba14610368578063127effb2146103865780631a799e00146103a457610315565b806303ea9f1f1461031a57806306fdde031461034a575b600080fd5b610334600480360381019061032f919061448e565b6109a6565b60405161034191906144d4565b60405180910390f35b6103526109be565b60405161035f919061457f565b60405180910390f35b610370610a4c565b60405161037d91906144d4565b60405180910390f35b61038e610b65565b60405161039b91906145b0565b60405180910390f35b6103be60048036038101906103b9919061448e565b610b8b565b6040516103cb91906144d4565b60405180910390f35b6103dc610e36565b6040516103e991906145b0565b60405180910390f35b6103fa610e5c565b60405161040791906144d4565b60405180910390f35b61042a6004803603810190610425919061448e565b610ed8565b005b610446600480360381019061044191906145f7565b610f7f565b005b610462600480360381019061045d9190614624565b610f91565b005b61046c6116c4565b60405161047991906144d4565b60405180910390f35b61049c600480360381019061049791906145f7565b6116ca565b005b6104b860048036038101906104b39190614664565b6116dc565b6040516104c591906144d4565b60405180910390f35b6104e860048036038101906104e391906145f7565b61185f565b6040516104f7939291906146b7565b60405180910390f35b61051a60048036038101906105159190614624565b611899565b005b610524611a3a565b005b610540600480360381019061053b91906146ee565b611a4e565b005b61055c6004803603810190610557919061472e565b611bf1565b60405161056991906144d4565b60405180910390f35b61058c6004803603810190610587919061448e565b611c7d565b60405161059c94939291906147b0565b60405180910390f35b6105bf60048036038101906105ba9190614624565b611db5565b005b6105db60048036038101906105d6919061448e565b611f68565b6040516105e891906144d4565b60405180910390f35b61060b60048036038101906106069190614821565b612185565b005b610627600480360381019061062291906145f7565b61249e565b60405161063491906145b0565b60405180910390f35b6106576004803603810190610652919061448e565b6124dd565b604051610668959493929190614861565b60405180910390f35b61068b600480360381019061068691906148b4565b6126a7565b005b6106a760048036038101906106a29190614624565b61285e565b005b6106b1612875565b6040516106be91906145b0565b60405180910390f35b6106e160048036038101906106dc91906145f7565b61289e565b6040516106f29594939291906148f4565b60405180910390f35b61071560048036038101906107109190614947565b612ad1565b005b61071f613254565b60405161072c91906145b0565b60405180910390f35b61074f600480360381019061074a919061448e565b61327a565b60405161075c91906144d4565b60405180910390f35b61077f600480360381019061077a9190614a4e565b613292565b60405161078d929190614b17565b60405180910390f35b61079e613321565b6040516107ab91906144d4565b60405180910390f35b6107ce60048036038101906107c99190614664565b613327565b005b6107ea60048036038101906107e5919061448e565b613551565b6040516107f79190614b47565b60405180910390f35b61081a6004803603810190610815919061448e565b6136db565b6040516108279190614b47565b60405180910390f35b61084a6004803603810190610845919061448e565b6136fb565b6040516108579190614b47565b60405180910390f35b61087a6004803603810190610875919061448e565b613862565b005b6108846139d4565b60405161089191906144d4565b60405180910390f35b6108b460048036038101906108af91906145f7565b6139e1565b6040516108c191906144d4565b60405180910390f35b6108d2613ae4565b6040516108df91906144d4565b60405180910390f35b61090260048036038101906108fd9190614821565b613aea565b005b61091e60048036038101906109199190614b62565b613df5565b005b61093a6004803603810190610935919061448e565b613ff0565b6040516109479190614b47565b60405180910390f35b610958614010565b60405161096591906144d4565b60405180910390f35b6109886004803603810190610983919061448e565b61401d565b005b6109a4600480360381019061099f9190614bb5565b6140a0565b005b60086020528060005260406000206000915090505481565b600e80546109cb90614c37565b80601f01602080910402602001604051908101604052809291908181526020018280546109f790614c37565b8015610a445780601f10610a1957610100808354040283529160200191610a44565b820191906000526020600020905b815481529060010190602001808311610a2757829003601f168201915b505050505081565b6000806000905060005b600480549050811015610b5d576006600060048381548110610a7b57610a7a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16610b4a57610b3c60048281548110610b0c57610b0b614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82610b479190614cc6565b91505b8080610b5590614cfa565b915050610a56565b508091505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080610b9783611f68565b90506000600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54620186a0600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154610c339190614d42565b610c3d9190614db3565b9050600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd39190614e1d565b600a610cdf9190614f7d565b8560098681548110610cf457610cf3614c68565b5b906000526020600020906003020160000154610d109190614d42565b610d1a9190614db3565b9050610d25876136fb565b15610d535760098481548110610d3e57610d3d614c68565b5b90600052602060002090600302016002015491505b610d5c87613551565b15610d6a5760009550610e2c565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1615610dc85760009550610e2b565b600b54610dd488611f68565b1015610de35760009550610e2a565b80821115610e0c57620186a08383610dfb9190614d42565b610e059190614db3565b9550610e29565b620186a08382610e1c9190614d42565b610e269190614db3565b95505b5b5b5b5050505050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000805b600480549050811015610ed457610eb460048281548110610e8457610e83614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82610ebf9190614cc6565b91508080610ecc90614cfa565b915050610e60565b5090565b610ee06141a6565b7f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051610f33929190614fc8565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610f876141a6565b80600d8190555050565b81600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156110385750600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16155b611077576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106e9061503d565b60405180910390fd5b600b5461108382611f68565b116110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba906150a9565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111515750611122612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161118790615115565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401611254929190615135565b6020604051808303816000875af1158015611273573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112979190615173565b506000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1685600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005015489604051602401611456969594939291906151a0565b6040516020818303038152906040527fb649fbf4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516114e0919061523d565b600060405180830381855af49150503d806000811461151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5050905080611564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155b906152a0565b60405180910390fd5b6000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036115f65742600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901819055505b42600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801819055507ff17784554852232b03320852ce4646e3da26e60c45891d2364716686a80a410485856040516116b5929190615135565b60405180910390a15050505050565b600c5481565b6116d26141a6565b80600b8190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061176c575061173d612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290615115565b60405180910390fd5b6117b36139d4565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb8185858560405161185094939291906152c0565b60405180910390a19392505050565b6009818154811061186f57600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061192757506118f8612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90615115565b60405180910390fd5b600061197183611f68565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190614e1d565b600a611a129190614f7d565b8284611a1e9190614d42565b611a289190614db3565b9050611a348482610f91565b50505050565b611a426141a6565b611a4c6000614224565b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611adc5750611aad612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1290615115565b60405180910390fd5b6000611b25610e5c565b905060005b600480549050811015611beb576000611b8360048381548110611b5057611b4f614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115611bd757611bd660048381548110611ba557611ba4614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b508080611be390614cfa565b915050611b2a565b50505050565b600080620186a083611c0288610b8b565b611c0c9190614d42565b611c169190614db3565b90506000620186a08486611c2a9190614d42565b611c349190614db3565b905080861115611c4657819250611c73565b6000811115611c6d57808683611c5c9190614d42565b611c669190614db3565b9250611c72565b600092505b5b5050949350505050565b600080600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701549250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801549150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1690509193509193565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e435750611e14612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990615115565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168015611ee15750611ede6139d4565b81105b15611f645780600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fc95fba30bcfd136a19e944a374d6cd9bb5655441349e1f8f755aa5242ab234148282604051611f5b929190615135565b60405180910390a15b5050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663b481ca2c85600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff1660e01b81526004016120b893929190615305565b602060405180830381865afa9250505080156120f257506040513d601f19601f820116820180604052508101906120ef9190615351565b60015b612179578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b815260040161212f91906145b0565b602060405180830381865afa15801561214c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121709190615351565b92505050612180565b8093505050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061221357506121e4612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612252576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224990615115565b60405180910390fd5b600061225c610a4c565b905060005b600480549050811015612498578280156123025750600760006004838154811061228e5761228d614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156123535761234e6004828154811061231e5761231d614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613862565b612485565b600660006004838154811061236b5761236a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff161580156124355750600b546124336004838154811061240357612402614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15612484576124836004828154811061245157612450614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685846140a0565b5b5b808061249090614cfa565b915050612261565b50505050565b600481815481106124ae57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169450600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549150600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154905091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806127355750612706612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90615115565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561285a5780600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160006101000a81548160ff0219169083151502179055507f86a5c093bb99c6d06a96c424a351d83258cf9b1438445e973896d74c3edf64eb828260405161285192919061537e565b60405180910390a15b5050565b6128666141a6565b6128718233836142e8565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806000806000600986815481106128ba576128b9614c68565b5b9060005260206000209060030201600001549450600986815481106128e2576128e1614c68565b5b90600052602060002090600302016001015493506009868154811061290a57612909614c68565b5b906000526020600020906003020160020154925060008060005b600480549050811015612abf57600660006004838154811061294957612948614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16612aac5788600a6000600484815481106129dc576129db614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403612aab57600183612a549190614cc6565b9250612a9d60048281548110612a6d57612a6c614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82612aa89190614cc6565b91505b5b8080612ab790614cfa565b915050612924565b50819350809250505091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480612b5f5750612b30612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612b9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9590615115565b60405180910390fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612e875785600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555082600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0181905550613208565b6001600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506004879080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160001515815260200160008152602001600081526020016000815260200182815250600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a0155905050613207876000611db5565b5b7f43076b6254266dc6be0a352adeba4d67c257b7595d4772ede64a3d2cc343ec368784868989878760405161324397969594939291906153a7565b60405180910390a150505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a6020528060005260406000206000915090505481565b6000606061329e6141a6565b6000808773ffffffffffffffffffffffffffffffffffffffff168787876040516132c992919061544a565b60006040518083038185875af1925050503d8060008114613306576040519150601f19603f3d011682016040523d82523d6000602084013e61330b565b606091505b5091509150818193509350505094509492505050565b600b5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806133b55750613386612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6133f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133eb90615115565b60405180910390fd5b60006133ff846139e1565b905060005b60048054905081101561354a5784600a60006004848154811061342a57613429614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036135375760006134e1600483815481106134ae576134ad614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115613535576135346004838154811061350357613502614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b505b808061354290614cfa565b915050613404565b5050505050565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036135a557600090506136d6565b60006001600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54426135fa9190615463565b6136049190614db3565b61360e9190614cc6565b905060006001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701546136a79190615463565b6136b19190614db3565b6136bb9190614cc6565b9050818110156136ce57600092506136d3565b600192505b50505b919050565b60076020528060005260406000206000915054906101000a900460ff1681565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901540361374f576001905061385d565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54600d54600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901546137eb9190615463565b6137f59190614db3565b6137ff9190614d42565b600c5461380c9190614cc6565b90506000814261381c9190615463565b90506009838154811061383257613831614c68565b5b9060005260206000209060030201600101548111156138545760009350613859565b600193505b5050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806138f057506138c1612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61392f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161392690615115565b60405180910390fd5b600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156139d1576000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506139cf8282610f91565b505b50565b6000600980549050905090565b6000805b600480549050811015613ade5782600a600060048481548110613a0b57613a0a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403613acb57613abd60048281548110613a8d57613a8c614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82613ac89190614cc6565b91505b8080613ad690614cfa565b9150506139e5565b50919050565b600d5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613b785750613b49612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613bae90615115565b60405180910390fd5b60005b600480549050811015613df057818015613c5b57506007600060048381548110613be757613be6614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15613cac57613ca760048281548110613c7757613c76614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613862565b613ddd565b6006600060048381548110613cc457613cc3614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16158015613d8e5750600b54613d8c60048381548110613d5c57613d5b614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15613ddc57613ddb60048281548110613daa57613da9614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611899565b5b5b8080613de890614cfa565b915050613bba565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613e835750613e54612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613ec2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613eb990615115565b60405180910390fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615613feb5781600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f70d7e641df56680393a21230bdc277feec8e8da8af9bdcc93f2bc14f83596ddb838383604051613fe293929190615497565b60405180910390a15b505050565b60056020528060005260406000206000915054906101000a900460ff1681565b6000600480549050905090565b6140256141a6565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603614094576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408b90615540565b60405180910390fd5b61409d81614224565b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061412e57506140ff612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61416d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161416490615115565b60405180910390fd5b600061417884611f68565b905060008282856141899190614d42565b6141939190614db3565b905061419f8582610f91565b5050505050565b6141ae61441e565b73ffffffffffffffffffffffffffffffffffffffff166141cc612875565b73ffffffffffffffffffffffffffffffffffffffff1614614222576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614219906155ac565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb858560405160240161431a929190615135565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051614368919061523d565b6000604051808303816000865af19150503d80600081146143a5576040519150601f19603f3d011682016040523d82523d6000602084013e6143aa565b606091505b50915091508180156143d857506000815114806143d75750808060200190518101906143d69190615173565b5b5b614417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161440e90615618565b60405180910390fd5b5050505050565b600033905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061445b82614430565b9050919050565b61446b81614450565b811461447657600080fd5b50565b60008135905061448881614462565b92915050565b6000602082840312156144a4576144a3614426565b5b60006144b284828501614479565b91505092915050565b6000819050919050565b6144ce816144bb565b82525050565b60006020820190506144e960008301846144c5565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561452957808201518184015260208101905061450e565b60008484015250505050565b6000601f19601f8301169050919050565b6000614551826144ef565b61455b81856144fa565b935061456b81856020860161450b565b61457481614535565b840191505092915050565b600060208201905081810360008301526145998184614546565b905092915050565b6145aa81614450565b82525050565b60006020820190506145c560008301846145a1565b92915050565b6145d4816144bb565b81146145df57600080fd5b50565b6000813590506145f1816145cb565b92915050565b60006020828403121561460d5761460c614426565b5b600061461b848285016145e2565b91505092915050565b6000806040838503121561463b5761463a614426565b5b600061464985828601614479565b925050602061465a858286016145e2565b9150509250929050565b60008060006060848603121561467d5761467c614426565b5b600061468b868287016145e2565b935050602061469c868287016145e2565b92505060406146ad868287016145e2565b9150509250925092565b60006060820190506146cc60008301866144c5565b6146d960208301856144c5565b6146e660408301846144c5565b949350505050565b6000806040838503121561470557614704614426565b5b6000614713858286016145e2565b9250506020614724858286016145e2565b9150509250929050565b6000806000806080858703121561474857614747614426565b5b600061475687828801614479565b9450506020614767878288016145e2565b9350506040614778878288016145e2565b9250506060614789878288016145e2565b91505092959194509250565b60008115159050919050565b6147aa81614795565b82525050565b60006080820190506147c560008301876147a1565b6147d260208301866144c5565b6147df60408301856144c5565b6147ec60608301846147a1565b95945050505050565b6147fe81614795565b811461480957600080fd5b50565b60008135905061481b816147f5565b92915050565b6000806040838503121561483857614837614426565b5b6000614846858286016145e2565b92505060206148578582860161480c565b9150509250929050565b600060a08201905061487660008301886145a1565b61488360208301876145a1565b61489060408301866145a1565b61489d60608301856144c5565b6148aa60808301846144c5565b9695505050505050565b600080604083850312156148cb576148ca614426565b5b60006148d985828601614479565b92505060206148ea8582860161480c565b9150509250929050565b600060a08201905061490960008301886144c5565b61491660208301876144c5565b61492360408301866144c5565b61493060608301856144c5565b61493d60808301846144c5565b9695505050505050565b600080600080600080600060e0888a03121561496657614965614426565b5b60006149748a828b01614479565b97505060206149858a828b01614479565b96505060406149968a828b01614479565b95505060606149a78a828b01614479565b94505060806149b88a828b01614479565b93505060a06149c98a828b016145e2565b92505060c06149da8a828b016145e2565b91505092959891949750929550565b600080fd5b600080fd5b600080fd5b60008083601f840112614a0e57614a0d6149e9565b5b8235905067ffffffffffffffff811115614a2b57614a2a6149ee565b5b602083019150836001820283011115614a4757614a466149f3565b5b9250929050565b60008060008060608587031215614a6857614a67614426565b5b6000614a7687828801614479565b9450506020614a87878288016145e2565b935050604085013567ffffffffffffffff811115614aa857614aa761442b565b5b614ab4878288016149f8565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000614ae982614ac2565b614af38185614acd565b9350614b0381856020860161450b565b614b0c81614535565b840191505092915050565b6000604082019050614b2c60008301856147a1565b8181036020830152614b3e8184614ade565b90509392505050565b6000602082019050614b5c60008301846147a1565b92915050565b600080600060608486031215614b7b57614b7a614426565b5b6000614b8986828701614479565b9350506020614b9a8682870161480c565b9250506040614bab868287016145e2565b9150509250925092565b600080600060608486031215614bce57614bcd614426565b5b6000614bdc86828701614479565b9350506020614bed868287016145e2565b9250506040614bfe868287016145e2565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614c4f57607f821691505b602082108103614c6257614c61614c08565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614cd1826144bb565b9150614cdc836144bb565b9250828201905080821115614cf457614cf3614c97565b5b92915050565b6000614d05826144bb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d3757614d36614c97565b5b600182019050919050565b6000614d4d826144bb565b9150614d58836144bb565b9250828202614d66816144bb565b91508282048414831517614d7d57614d7c614c97565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614dbe826144bb565b9150614dc9836144bb565b925082614dd957614dd8614d84565b5b828204905092915050565b600060ff82169050919050565b614dfa81614de4565b8114614e0557600080fd5b50565b600081519050614e1781614df1565b92915050565b600060208284031215614e3357614e32614426565b5b6000614e4184828501614e08565b91505092915050565b60008160011c9050919050565b6000808291508390505b6001851115614ea157808604811115614e7d57614e7c614c97565b5b6001851615614e8c5780820291505b8081029050614e9a85614e4a565b9450614e61565b94509492505050565b600082614eba5760019050614f76565b81614ec85760009050614f76565b8160018114614ede5760028114614ee857614f17565b6001915050614f76565b60ff841115614efa57614ef9614c97565b5b8360020a915084821115614f1157614f10614c97565b5b50614f76565b5060208310610133831016604e8410600b8410161715614f4c5782820a905083811115614f4757614f46614c97565b5b614f76565b614f598484846001614e57565b92509050818404811115614f7057614f6f614c97565b5b81810290505b9392505050565b6000614f88826144bb565b9150614f9383614de4565b9250614fc07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614eaa565b905092915050565b6000604082019050614fdd60008301856145a1565b614fea60208301846145a1565b9392505050565b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b60006150276012836144fa565b915061503282614ff1565b602082019050919050565b600060208201905081810360008301526150568161501a565b9050919050565b7f506f6f6c20697320736d616c6c00000000000000000000000000000000000000600082015250565b6000615093600d836144fa565b915061509e8261505d565b602082019050919050565b600060208201905081810360008301526150c281615086565b9050919050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b60006150ff6015836144fa565b915061510a826150c9565b602082019050919050565b6000602082019050818103600083015261512e816150f2565b9050919050565b600060408201905061514a60008301856145a1565b61515760208301846144c5565b9392505050565b60008151905061516d816147f5565b92915050565b60006020828403121561518957615188614426565b5b60006151978482850161515e565b91505092915050565b600060c0820190506151b560008301896145a1565b6151c260208301886145a1565b6151cf60408301876145a1565b6151dc60608301866145a1565b6151e960808301856144c5565b6151f660a08301846144c5565b979650505050505050565b600081905092915050565b600061521782614ac2565b6152218185615201565b935061523181856020860161450b565b80840191505092915050565b6000615249828461520c565b915081905092915050565b7f64656c656761746563616c6c206661696c656400000000000000000000000000600082015250565b600061528a6013836144fa565b915061529582615254565b602082019050919050565b600060208201905081810360008301526152b98161527d565b9050919050565b60006080820190506152d560008301876144c5565b6152e260208301866144c5565b6152ef60408301856144c5565b6152fc60608301846144c5565b95945050505050565b600060608201905061531a60008301866145a1565b61532760208301856145a1565b61533460408301846145a1565b949350505050565b60008151905061534b816145cb565b92915050565b60006020828403121561536757615366614426565b5b60006153758482850161533c565b91505092915050565b600060408201905061539360008301856145a1565b6153a060208301846147a1565b9392505050565b600060e0820190506153bc600083018a6145a1565b6153c960208301896145a1565b6153d660408301886145a1565b6153e360608301876145a1565b6153f060808301866145a1565b6153fd60a08301856144c5565b61540a60c08301846144c5565b98975050505050505050565b82818337600083830152505050565b60006154318385615201565b935061543e838584615416565b82840190509392505050565b6000615457828486615425565b91508190509392505050565b600061546e826144bb565b9150615479836144bb565b925082820390508181111561549157615490614c97565b5b92915050565b60006060820190506154ac60008301866145a1565b6154b960208301856147a1565b6154c660408301846144c5565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061552a6026836144fa565b9150615535826154ce565b604082019050919050565b600060208201905081810360008301526155598161551d565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006155966020836144fa565b91506155a182615560565b602082019050919050565b600060208201905081810360008301526155c581615589565b9050919050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000615602601f836144fa565b915061560d826155cc565b602082019050919050565b60006020820190508181036000830152615631816155f5565b9050919050560000000000000000000000006e74053a3798e0fc9a9775f7995316b27f21c4d2000000000000000000000000fc00000000000000000000000000000000000008000000000000000000000000fc0000000000000000000000000000000000000200000000000000000000000000000000000000000000010f0cf064dd592000000000000000000000000000000000000000000000000000000000000065555b800000000000000000000000000000000000000000000000000000000000093a80
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103155760003560e01c806386bfdb19116101a7578063d27761ef116100ee578063ec06a89a11610097578063efde4e6411610071578063efde4e6414610950578063f2fde38b1461096e578063f7f2e80d1461098a57610315565b8063ec06a89a146108e8578063ec16bf4714610904578063ee5b11c31461092057610315565b8063e81e5dde116100c8578063e81e5dde1461087c578063ea6efa951461089a578063eac471a0146108ca57610315565b8063d27761ef14610800578063e0a88bbc14610830578063e390ddde1461086057610315565b8063ae49945d11610150578063b75402191161012a578063b754021914610796578063cc64463a146107b4578063cdc97f77146107d057610315565b8063ae49945d14610717578063afce9fde14610735578063b61d27f61461076557610315565b80638da5cb5b116101815780638da5cb5b146106a95780639fbd2c8c146106c7578063a95dffd6146106fb57610315565b806386bfdb191461063d57806388660611146106715780638980f11f1461068d57610315565b806360976e6f1161026b57806379605ea01161021457806381d81d2a116101ee57806381d81d2a146105c157806381d8b3f8146105f157806382eac7f01461060d57610315565b806379605ea0146105425780637c43215f146105725780637ea48c10146105a557610315565b806370c8f7fe1161024557806370c8f7fe14610500578063715018a61461051c578063793171c51461052657610315565b806360976e6f146104825780636358ec571461049e5780636cef1b77146104ce57610315565b806320263e87116102cd5780633d84ceca116102a75780633d84ceca1461042c57806345c1262614610448578063581289691461046457610315565b806320263e87146103d45780632501853f146103f25780632f1d5a601461041057610315565b80630f37b6ba116102fe5780630f37b6ba14610368578063127effb2146103865780631a799e00146103a457610315565b806303ea9f1f1461031a57806306fdde031461034a575b600080fd5b610334600480360381019061032f919061448e565b6109a6565b60405161034191906144d4565b60405180910390f35b6103526109be565b60405161035f919061457f565b60405180910390f35b610370610a4c565b60405161037d91906144d4565b60405180910390f35b61038e610b65565b60405161039b91906145b0565b60405180910390f35b6103be60048036038101906103b9919061448e565b610b8b565b6040516103cb91906144d4565b60405180910390f35b6103dc610e36565b6040516103e991906145b0565b60405180910390f35b6103fa610e5c565b60405161040791906144d4565b60405180910390f35b61042a6004803603810190610425919061448e565b610ed8565b005b610446600480360381019061044191906145f7565b610f7f565b005b610462600480360381019061045d9190614624565b610f91565b005b61046c6116c4565b60405161047991906144d4565b60405180910390f35b61049c600480360381019061049791906145f7565b6116ca565b005b6104b860048036038101906104b39190614664565b6116dc565b6040516104c591906144d4565b60405180910390f35b6104e860048036038101906104e391906145f7565b61185f565b6040516104f7939291906146b7565b60405180910390f35b61051a60048036038101906105159190614624565b611899565b005b610524611a3a565b005b610540600480360381019061053b91906146ee565b611a4e565b005b61055c6004803603810190610557919061472e565b611bf1565b60405161056991906144d4565b60405180910390f35b61058c6004803603810190610587919061448e565b611c7d565b60405161059c94939291906147b0565b60405180910390f35b6105bf60048036038101906105ba9190614624565b611db5565b005b6105db60048036038101906105d6919061448e565b611f68565b6040516105e891906144d4565b60405180910390f35b61060b60048036038101906106069190614821565b612185565b005b610627600480360381019061062291906145f7565b61249e565b60405161063491906145b0565b60405180910390f35b6106576004803603810190610652919061448e565b6124dd565b604051610668959493929190614861565b60405180910390f35b61068b600480360381019061068691906148b4565b6126a7565b005b6106a760048036038101906106a29190614624565b61285e565b005b6106b1612875565b6040516106be91906145b0565b60405180910390f35b6106e160048036038101906106dc91906145f7565b61289e565b6040516106f29594939291906148f4565b60405180910390f35b61071560048036038101906107109190614947565b612ad1565b005b61071f613254565b60405161072c91906145b0565b60405180910390f35b61074f600480360381019061074a919061448e565b61327a565b60405161075c91906144d4565b60405180910390f35b61077f600480360381019061077a9190614a4e565b613292565b60405161078d929190614b17565b60405180910390f35b61079e613321565b6040516107ab91906144d4565b60405180910390f35b6107ce60048036038101906107c99190614664565b613327565b005b6107ea60048036038101906107e5919061448e565b613551565b6040516107f79190614b47565b60405180910390f35b61081a6004803603810190610815919061448e565b6136db565b6040516108279190614b47565b60405180910390f35b61084a6004803603810190610845919061448e565b6136fb565b6040516108579190614b47565b60405180910390f35b61087a6004803603810190610875919061448e565b613862565b005b6108846139d4565b60405161089191906144d4565b60405180910390f35b6108b460048036038101906108af91906145f7565b6139e1565b6040516108c191906144d4565b60405180910390f35b6108d2613ae4565b6040516108df91906144d4565b60405180910390f35b61090260048036038101906108fd9190614821565b613aea565b005b61091e60048036038101906109199190614b62565b613df5565b005b61093a6004803603810190610935919061448e565b613ff0565b6040516109479190614b47565b60405180910390f35b610958614010565b60405161096591906144d4565b60405180910390f35b6109886004803603810190610983919061448e565b61401d565b005b6109a4600480360381019061099f9190614bb5565b6140a0565b005b60086020528060005260406000206000915090505481565b600e80546109cb90614c37565b80601f01602080910402602001604051908101604052809291908181526020018280546109f790614c37565b8015610a445780601f10610a1957610100808354040283529160200191610a44565b820191906000526020600020905b815481529060010190602001808311610a2757829003601f168201915b505050505081565b6000806000905060005b600480549050811015610b5d576006600060048381548110610a7b57610a7a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16610b4a57610b3c60048281548110610b0c57610b0b614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82610b479190614cc6565b91505b8080610b5590614cfa565b915050610a56565b508091505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080610b9783611f68565b90506000600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54620186a0600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154610c339190614d42565b610c3d9190614db3565b9050600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd39190614e1d565b600a610cdf9190614f7d565b8560098681548110610cf457610cf3614c68565b5b906000526020600020906003020160000154610d109190614d42565b610d1a9190614db3565b9050610d25876136fb565b15610d535760098481548110610d3e57610d3d614c68565b5b90600052602060002090600302016002015491505b610d5c87613551565b15610d6a5760009550610e2c565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1615610dc85760009550610e2b565b600b54610dd488611f68565b1015610de35760009550610e2a565b80821115610e0c57620186a08383610dfb9190614d42565b610e059190614db3565b9550610e29565b620186a08382610e1c9190614d42565b610e269190614db3565b95505b5b5b5b5050505050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000805b600480549050811015610ed457610eb460048281548110610e8457610e83614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82610ebf9190614cc6565b91508080610ecc90614cfa565b915050610e60565b5090565b610ee06141a6565b7f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051610f33929190614fc8565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610f876141a6565b80600d8190555050565b81600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156110385750600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16155b611077576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106e9061503d565b60405180910390fd5b600b5461108382611f68565b116110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba906150a9565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806111515750611122612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611190576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161118790615115565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401611254929190615135565b6020604051808303816000875af1158015611273573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112979190615173565b506000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1685600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005015489604051602401611456969594939291906151a0565b6040516020818303038152906040527fb649fbf4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516114e0919061523d565b600060405180830381855af49150503d806000811461151b576040519150601f19603f3d011682016040523d82523d6000602084013e611520565b606091505b5050905080611564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155b906152a0565b60405180910390fd5b6000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036115f65742600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901819055505b42600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018190555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801819055507ff17784554852232b03320852ce4646e3da26e60c45891d2364716686a80a410485856040516116b5929190615135565b60405180910390a15050505050565b600c5481565b6116d26141a6565b80600b8190555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061176c575061173d612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290615115565b60405180910390fd5b6117b36139d4565b90506009604051806060016040528086815260200185815260200184815250908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000155602082015181600101556040820151816002015550507fbb11b8f6480c54266351bc3225ee33bb24859e8948cdd029716195a477bd7ddb8185858560405161185094939291906152c0565b60405180910390a19392505050565b6009818154811061186f57600080fd5b90600052602060002090600302016000915090508060000154908060010154908060020154905083565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061192757506118f8612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195d90615115565b60405180910390fd5b600061197183611f68565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a069190614e1d565b600a611a129190614f7d565b8284611a1e9190614d42565b611a289190614db3565b9050611a348482610f91565b50505050565b611a426141a6565b611a4c6000614224565b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611adc5750611aad612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611b1b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b1290615115565b60405180910390fd5b6000611b25610e5c565b905060005b600480549050811015611beb576000611b8360048381548110611b5057611b4f614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115611bd757611bd660048381548110611ba557611ba4614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b508080611be390614cfa565b915050611b2a565b50505050565b600080620186a083611c0288610b8b565b611c0c9190614d42565b611c169190614db3565b90506000620186a08486611c2a9190614d42565b611c349190614db3565b905080861115611c4657819250611c73565b6000811115611c6d57808683611c5c9190614d42565b611c669190614db3565b9250611c72565b600092505b5b5050949350505050565b600080600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701549250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600801549150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff1690509193509193565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611e435750611e14612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611e82576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7990615115565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168015611ee15750611ede6139d4565b81105b15611f645780600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fc95fba30bcfd136a19e944a374d6cd9bb5655441349e1f8f755aa5242ab234148282604051611f5b929190615135565b60405180910390a15b5050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663b481ca2c85600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518463ffffffff1660e01b81526004016120b893929190615305565b602060405180830381865afa9250505080156120f257506040513d601f19601f820116820180604052508101906120ef9190615351565b60015b612179578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b815260040161212f91906145b0565b602060405180830381865afa15801561214c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121709190615351565b92505050612180565b8093505050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061221357506121e4612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612252576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224990615115565b60405180910390fd5b600061225c610a4c565b905060005b600480549050811015612498578280156123025750600760006004838154811061228e5761228d614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156123535761234e6004828154811061231e5761231d614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613862565b612485565b600660006004838154811061236b5761236a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff161580156124355750600b546124336004838154811061240357612402614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15612484576124836004828154811061245157612450614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685846140a0565b5b5b808061249090614cfa565b915050612261565b50505050565b600481815481106124ae57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169450600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549150600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154905091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806127355750612706612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90615115565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561285a5780600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160006101000a81548160ff0219169083151502179055507f86a5c093bb99c6d06a96c424a351d83258cf9b1438445e973896d74c3edf64eb828260405161285192919061537e565b60405180910390a15b5050565b6128666141a6565b6128718233836142e8565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806000806000600986815481106128ba576128b9614c68565b5b9060005260206000209060030201600001549450600986815481106128e2576128e1614c68565b5b90600052602060002090600302016001015493506009868154811061290a57612909614c68565b5b906000526020600020906003020160020154925060008060005b600480549050811015612abf57600660006004838154811061294957612948614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16612aac5788600a6000600484815481106129dc576129db614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403612aab57600183612a549190614cc6565b9250612a9d60048281548110612a6d57612a6c614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b82612aa89190614cc6565b91505b5b8080612ab790614cfa565b915050612924565b50819350809250505091939590929450565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480612b5f5750612b30612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612b9e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9590615115565b60405180910390fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612e875785600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018190555082600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0181905550613208565b6001600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506004879080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518061016001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff16815260200183815260200160001515815260200160008152602001600081526020016000815260200182815250600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a0820151816005015560c08201518160060160006101000a81548160ff02191690831515021790555060e082015181600701556101008201518160080155610120820151816009015561014082015181600a0155905050613207876000611db5565b5b7f43076b6254266dc6be0a352adeba4d67c257b7595d4772ede64a3d2cc343ec368784868989878760405161324397969594939291906153a7565b60405180910390a150505050505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a6020528060005260406000206000915090505481565b6000606061329e6141a6565b6000808773ffffffffffffffffffffffffffffffffffffffff168787876040516132c992919061544a565b60006040518083038185875af1925050503d8060008114613306576040519150601f19603f3d011682016040523d82523d6000602084013e61330b565b606091505b5091509150818193509350505094509492505050565b600b5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806133b55750613386612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6133f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133eb90615115565b60405180910390fd5b60006133ff846139e1565b905060005b60048054905081101561354a5784600a60006004848154811061342a57613429614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054036135375760006134e1600483815481106134ae576134ad614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16868587611bf1565b90506000811115613535576135346004838154811061350357613502614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682610f91565b5b505b808061354290614cfa565b915050613404565b5050505050565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070154036135a557600090506136d6565b60006001600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54426135fa9190615463565b6136049190614db3565b61360e9190614cc6565b905060006001600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600a0154600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701546136a79190615463565b6136b19190614db3565b6136bb9190614cc6565b9050818110156136ce57600092506136d3565b600192505b50505b919050565b60076020528060005260406000206000915054906101000a900460ff1681565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901540361374f576001905061385d565b6000600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600d54600d54600c54600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600901546137eb9190615463565b6137f59190614db3565b6137ff9190614d42565b600c5461380c9190614cc6565b90506000814261381c9190615463565b90506009838154811061383257613831614c68565b5b9060005260206000209060030201600101548111156138545760009350613859565b600193505b5050505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806138f057506138c1612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61392f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161392690615115565b60405180910390fd5b600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156139d1576000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506139cf8282610f91565b505b50565b6000600980549050905090565b6000805b600480549050811015613ade5782600a600060048481548110613a0b57613a0a614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205403613acb57613abd60048281548110613a8d57613a8c614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16610b8b565b82613ac89190614cc6565b91505b8080613ad690614cfa565b9150506139e5565b50919050565b600d5481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613b785750613b49612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613bb7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613bae90615115565b60405180910390fd5b60005b600480549050811015613df057818015613c5b57506007600060048381548110613be757613be6614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b15613cac57613ca760048281548110613c7757613c76614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613862565b613ddd565b6006600060048381548110613cc457613cc3614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060060160009054906101000a900460ff16158015613d8e5750600b54613d8c60048381548110613d5c57613d5b614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611f68565b115b15613ddc57613ddb60048281548110613daa57613da9614c68565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611899565b5b5b8080613de890614cfa565b915050613bba565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480613e835750613e54612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b613ec2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613eb990615115565b60405180910390fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615613feb5781600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f70d7e641df56680393a21230bdc277feec8e8da8af9bdcc93f2bc14f83596ddb838383604051613fe293929190615497565b60405180910390a15b505050565b60056020528060005260406000206000915054906101000a900460ff1681565b6000600480549050905090565b6140256141a6565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603614094576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408b90615540565b60405180910390fd5b61409d81614224565b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061412e57506140ff612875565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61416d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161416490615115565b60405180910390fd5b600061417884611f68565b905060008282856141899190614d42565b6141939190614db3565b905061419f8582610f91565b5050505050565b6141ae61441e565b73ffffffffffffffffffffffffffffffffffffffff166141cc612875565b73ffffffffffffffffffffffffffffffffffffffff1614614222576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614219906155ac565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb858560405160240161431a929190615135565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051614368919061523d565b6000604051808303816000865af19150503d80600081146143a5576040519150601f19603f3d011682016040523d82523d6000602084013e6143aa565b606091505b50915091508180156143d857506000815114806143d75750808060200190518101906143d69190615173565b5b5b614417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161440e90615618565b60405180910390fd5b5050505050565b600033905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061445b82614430565b9050919050565b61446b81614450565b811461447657600080fd5b50565b60008135905061448881614462565b92915050565b6000602082840312156144a4576144a3614426565b5b60006144b284828501614479565b91505092915050565b6000819050919050565b6144ce816144bb565b82525050565b60006020820190506144e960008301846144c5565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561452957808201518184015260208101905061450e565b60008484015250505050565b6000601f19601f8301169050919050565b6000614551826144ef565b61455b81856144fa565b935061456b81856020860161450b565b61457481614535565b840191505092915050565b600060208201905081810360008301526145998184614546565b905092915050565b6145aa81614450565b82525050565b60006020820190506145c560008301846145a1565b92915050565b6145d4816144bb565b81146145df57600080fd5b50565b6000813590506145f1816145cb565b92915050565b60006020828403121561460d5761460c614426565b5b600061461b848285016145e2565b91505092915050565b6000806040838503121561463b5761463a614426565b5b600061464985828601614479565b925050602061465a858286016145e2565b9150509250929050565b60008060006060848603121561467d5761467c614426565b5b600061468b868287016145e2565b935050602061469c868287016145e2565b92505060406146ad868287016145e2565b9150509250925092565b60006060820190506146cc60008301866144c5565b6146d960208301856144c5565b6146e660408301846144c5565b949350505050565b6000806040838503121561470557614704614426565b5b6000614713858286016145e2565b9250506020614724858286016145e2565b9150509250929050565b6000806000806080858703121561474857614747614426565b5b600061475687828801614479565b9450506020614767878288016145e2565b9350506040614778878288016145e2565b9250506060614789878288016145e2565b91505092959194509250565b60008115159050919050565b6147aa81614795565b82525050565b60006080820190506147c560008301876147a1565b6147d260208301866144c5565b6147df60408301856144c5565b6147ec60608301846147a1565b95945050505050565b6147fe81614795565b811461480957600080fd5b50565b60008135905061481b816147f5565b92915050565b6000806040838503121561483857614837614426565b5b6000614846858286016145e2565b92505060206148578582860161480c565b9150509250929050565b600060a08201905061487660008301886145a1565b61488360208301876145a1565b61489060408301866145a1565b61489d60608301856144c5565b6148aa60808301846144c5565b9695505050505050565b600080604083850312156148cb576148ca614426565b5b60006148d985828601614479565b92505060206148ea8582860161480c565b9150509250929050565b600060a08201905061490960008301886144c5565b61491660208301876144c5565b61492360408301866144c5565b61493060608301856144c5565b61493d60808301846144c5565b9695505050505050565b600080600080600080600060e0888a03121561496657614965614426565b5b60006149748a828b01614479565b97505060206149858a828b01614479565b96505060406149968a828b01614479565b95505060606149a78a828b01614479565b94505060806149b88a828b01614479565b93505060a06149c98a828b016145e2565b92505060c06149da8a828b016145e2565b91505092959891949750929550565b600080fd5b600080fd5b600080fd5b60008083601f840112614a0e57614a0d6149e9565b5b8235905067ffffffffffffffff811115614a2b57614a2a6149ee565b5b602083019150836001820283011115614a4757614a466149f3565b5b9250929050565b60008060008060608587031215614a6857614a67614426565b5b6000614a7687828801614479565b9450506020614a87878288016145e2565b935050604085013567ffffffffffffffff811115614aa857614aa761442b565b5b614ab4878288016149f8565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000614ae982614ac2565b614af38185614acd565b9350614b0381856020860161450b565b614b0c81614535565b840191505092915050565b6000604082019050614b2c60008301856147a1565b8181036020830152614b3e8184614ade565b90509392505050565b6000602082019050614b5c60008301846147a1565b92915050565b600080600060608486031215614b7b57614b7a614426565b5b6000614b8986828701614479565b9350506020614b9a8682870161480c565b9250506040614bab868287016145e2565b9150509250925092565b600080600060608486031215614bce57614bcd614426565b5b6000614bdc86828701614479565b9350506020614bed868287016145e2565b9250506040614bfe868287016145e2565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614c4f57607f821691505b602082108103614c6257614c61614c08565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614cd1826144bb565b9150614cdc836144bb565b9250828201905080821115614cf457614cf3614c97565b5b92915050565b6000614d05826144bb565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614d3757614d36614c97565b5b600182019050919050565b6000614d4d826144bb565b9150614d58836144bb565b9250828202614d66816144bb565b91508282048414831517614d7d57614d7c614c97565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614dbe826144bb565b9150614dc9836144bb565b925082614dd957614dd8614d84565b5b828204905092915050565b600060ff82169050919050565b614dfa81614de4565b8114614e0557600080fd5b50565b600081519050614e1781614df1565b92915050565b600060208284031215614e3357614e32614426565b5b6000614e4184828501614e08565b91505092915050565b60008160011c9050919050565b6000808291508390505b6001851115614ea157808604811115614e7d57614e7c614c97565b5b6001851615614e8c5780820291505b8081029050614e9a85614e4a565b9450614e61565b94509492505050565b600082614eba5760019050614f76565b81614ec85760009050614f76565b8160018114614ede5760028114614ee857614f17565b6001915050614f76565b60ff841115614efa57614ef9614c97565b5b8360020a915084821115614f1157614f10614c97565b5b50614f76565b5060208310610133831016604e8410600b8410161715614f4c5782820a905083811115614f4757614f46614c97565b5b614f76565b614f598484846001614e57565b92509050818404811115614f7057614f6f614c97565b5b81810290505b9392505050565b6000614f88826144bb565b9150614f9383614de4565b9250614fc07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614eaa565b905092915050565b6000604082019050614fdd60008301856145a1565b614fea60208301846145a1565b9392505050565b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b60006150276012836144fa565b915061503282614ff1565b602082019050919050565b600060208201905081810360008301526150568161501a565b9050919050565b7f506f6f6c20697320736d616c6c00000000000000000000000000000000000000600082015250565b6000615093600d836144fa565b915061509e8261505d565b602082019050919050565b600060208201905081810360008301526150c281615086565b9050919050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b60006150ff6015836144fa565b915061510a826150c9565b602082019050919050565b6000602082019050818103600083015261512e816150f2565b9050919050565b600060408201905061514a60008301856145a1565b61515760208301846144c5565b9392505050565b60008151905061516d816147f5565b92915050565b60006020828403121561518957615188614426565b5b60006151978482850161515e565b91505092915050565b600060c0820190506151b560008301896145a1565b6151c260208301886145a1565b6151cf60408301876145a1565b6151dc60608301866145a1565b6151e960808301856144c5565b6151f660a08301846144c5565b979650505050505050565b600081905092915050565b600061521782614ac2565b6152218185615201565b935061523181856020860161450b565b80840191505092915050565b6000615249828461520c565b915081905092915050565b7f64656c656761746563616c6c206661696c656400000000000000000000000000600082015250565b600061528a6013836144fa565b915061529582615254565b602082019050919050565b600060208201905081810360008301526152b98161527d565b9050919050565b60006080820190506152d560008301876144c5565b6152e260208301866144c5565b6152ef60408301856144c5565b6152fc60608301846144c5565b95945050505050565b600060608201905061531a60008301866145a1565b61532760208301856145a1565b61533460408301846145a1565b949350505050565b60008151905061534b816145cb565b92915050565b60006020828403121561536757615366614426565b5b60006153758482850161533c565b91505092915050565b600060408201905061539360008301856145a1565b6153a060208301846147a1565b9392505050565b600060e0820190506153bc600083018a6145a1565b6153c960208301896145a1565b6153d660408301886145a1565b6153e360608301876145a1565b6153f060808301866145a1565b6153fd60a08301856144c5565b61540a60c08301846144c5565b98975050505050505050565b82818337600083830152505050565b60006154318385615201565b935061543e838584615416565b82840190509392505050565b6000615457828486615425565b91508190509392505050565b600061546e826144bb565b9150615479836144bb565b925082820390508181111561549157615490614c97565b5b92915050565b60006060820190506154ac60008301866145a1565b6154b960208301856147a1565b6154c660408301846144c5565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061552a6026836144fa565b9150615535826154ce565b604082019050919050565b600060208201905081810360008301526155598161551d565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006155966020836144fa565b91506155a182615560565b602082019050919050565b600060208201905081810360008301526155c581615589565b9050919050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000615602601f836144fa565b915061560d826155cc565b602082019050919050565b60006020820190508181036000830152615631816155f5565b905091905056
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e74053a3798e0fc9a9775f7995316b27f21c4d2000000000000000000000000fc00000000000000000000000000000000000008000000000000000000000000fc0000000000000000000000000000000000000200000000000000000000000000000000000000000000010f0cf064dd592000000000000000000000000000000000000000000000000000000000000065555b800000000000000000000000000000000000000000000000000000000000093a80
-----Decoded View---------------
Arg [0] : _operatorAddress (address): 0x6e74053a3798e0fC9a9775F7995316b27f21c4D2
Arg [1] : _targetTokenAddress (address): 0xfc00000000000000000000000000000000000008
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] : 000000000000000000000000fc00000000000000000000000000000000000008
Arg [2] : 000000000000000000000000fc00000000000000000000000000000000000002
Arg [3] : 00000000000000000000000000000000000000000000010f0cf064dd59200000
Arg [4] : 0000000000000000000000000000000000000000000000000000000065555b80
Arg [5] : 0000000000000000000000000000000000000000000000000000000000093a80
Loading...
Loading
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.