Source Code
Latest 25 from a total of 96,246 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Rescale | 427258343 | 37 mins ago | IN | 0 ETH | 0.00002003 | ||||
| Earn Preparation | 427251729 | 1 hr ago | IN | 0 ETH | 0.00000248 | ||||
| Rescale | 427243824 | 1 hr ago | IN | 0 ETH | 0.00002831 | ||||
| Rescale | 427229329 | 2 hrs ago | IN | 0 ETH | 0.00001673 | ||||
| Rescale | 427229312 | 2 hrs ago | IN | 0 ETH | 0.00001665 | ||||
| Rescale | 427214742 | 3 hrs ago | IN | 0 ETH | 0.00001671 | ||||
| Rescale | 427214725 | 3 hrs ago | IN | 0 ETH | 0.00001597 | ||||
| Earn Preparation | 427194637 | 5 hrs ago | IN | 0 ETH | 0.00000206 | ||||
| Earn Preparation | 427194612 | 5 hrs ago | IN | 0 ETH | 0.00000261 | ||||
| Earn | 427193680 | 5 hrs ago | IN | 0 ETH | 0.00000207 | ||||
| Earn Preparation | 427193654 | 5 hrs ago | IN | 0 ETH | 0.00000747 | ||||
| Collect Rewards | 427193630 | 5 hrs ago | IN | 0 ETH | 0.00000445 | ||||
| Earn | 427191768 | 5 hrs ago | IN | 0 ETH | 0.00000204 | ||||
| Earn Preparation | 427191744 | 5 hrs ago | IN | 0 ETH | 0.0000025 | ||||
| Collect Rewards | 427191721 | 5 hrs ago | IN | 0 ETH | 0.00000261 | ||||
| Earn | 427189918 | 5 hrs ago | IN | 0 ETH | 0.0000032 | ||||
| Earn Preparation | 427189900 | 5 hrs ago | IN | 0 ETH | 0.00001336 | ||||
| Collect Rewards | 427189877 | 5 hrs ago | IN | 0 ETH | 0.00000528 | ||||
| Earn | 427188156 | 5 hrs ago | IN | 0 ETH | 0.00000434 | ||||
| Earn Preparation | 427188132 | 5 hrs ago | IN | 0 ETH | 0.00000345 | ||||
| Collect Rewards | 427188101 | 5 hrs ago | IN | 0 ETH | 0.00000272 | ||||
| Rescale | 427185902 | 5 hrs ago | IN | 0 ETH | 0.00001784 | ||||
| Rescale | 427185887 | 5 hrs ago | IN | 0 ETH | 0.00001741 | ||||
| Rescale | 427185869 | 5 hrs ago | IN | 0 ETH | 0.00001732 | ||||
| Set Tick Spread ... | 427173719 | 6 hrs ago | IN | 0 ETH | 0.00000063 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Controller
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/IFundManagerVault.sol";
import "./interfaces/IRescaleTickBoundaryCalculator.sol";
import "./interfaces/IController.sol";
import "./interfaces/IControllerEvent.sol";
import "./interfaces/IStrategyInfo.sol";
import "./interfaces/IStrategy.sol";
import "./interfaces/IStrategySetter.sol";
// import "./libraries/constants/Constants.sol";
import "./libraries/LiquidityNftHelper.sol";
import "./libraries/ParameterVerificationHelper.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./interfaces/IConstants.sol";
/// @dev verified,private contract
/// @dev only owner or operator/backend callable
contract Controller is AccessControl, IControllerEvent, IController {
using SafeMath for uint256;
IConstants public Constants;
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
mapping(address => int24) public tickSpreadUpper; // strategy => tickSpreadUpper
mapping(address => int24) public tickSpreadLower; // strategy => tickSpreadLower
mapping(address => int24) public tickGapUpper; // strategy => tickGapUpper
mapping(address => int24) public tickGapLower; // strategy => tickGapLower
mapping(address => int24) public tickUpperBoundaryOffset; // strategy => tickUpperBoundaryOffset
mapping(address => int24) public tickLowerBoundaryOffset; // strategy => tickLowerBoundaryOffset
mapping(address => int24) public rescaleTickUpperBoundaryOffset; // strategy => rescaleTickUpperBoundaryOffset
mapping(address => int24) public rescaleTickLowerBoundaryOffset; // strategy => rescaleTickLowerBoundaryOffset
mapping(address => int24) public lastRescaleTick; // strategy => lastRescaleTick
mapping(address => int24) public rescaleTickTolerance; // strategy => rescaleTickTolerance
constructor(address _constants, address _executor) {
require(_constants != address(0), "Constants address cannot be zero");
Constants = IConstants(_constants);
// set deployer as EXECUTOR_ROLE roleAdmin
_setRoleAdmin(EXECUTOR_ROLE, DEFAULT_ADMIN_ROLE);
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
// set EXECUTOR_ROLE memebers
_setupRole(EXECUTOR_ROLE, _executor);
}
/// @dev backend get function support
function isNftWithinRange(address _strategyContract) public view returns (bool isWithinRange) {
uint256 liquidityNftId = IStrategyInfo(_strategyContract).liquidityNftId();
require(liquidityNftId != 0, "not allow calling when liquidityNftId is 0");
(isWithinRange,) = LiquidityNftHelper.verifyCurrentPriceInLiquidityNftRange(
liquidityNftId, Constants.UNISWAP_V3_FACTORY_ADDRESS(), Constants.NONFUNGIBLE_POSITION_MANAGER_ADDRESS()
);
}
function getEarningFlag(address _strategyContract) public view returns (bool isEarningFlag) {
return IStrategyInfo(_strategyContract).isEarning();
}
function getRescalingFlag(address _strategyContract) public view returns (bool isRescalingFlag) {
uint256 liquidityNftId = IStrategyInfo(_strategyContract).liquidityNftId();
if (liquidityNftId == 0) {
return true;
} else {
return false;
}
}
function getRemainingEarnCountDown(address _strategyContract) public view returns (uint256 remainingEarn) {
bool isEarningFlag = getEarningFlag(_strategyContract);
if (isEarningFlag == false) {
return 0;
}
uint256 userListLength = IStrategyInfo(_strategyContract).getAllUsersInUserList().length;
uint256 earnLoopStartIndex = IStrategyInfo(_strategyContract).earnLoopStartIndex();
uint256 remainingUserNumber = userListLength.sub(earnLoopStartIndex);
uint256 earnLoopSegmentSize = IStrategyInfo(_strategyContract).earnLoopSegmentSize();
(uint256 quotient, uint256 remainder) = calculateQuotientAndRemainder(remainingUserNumber, earnLoopSegmentSize);
return remainder > 0 ? (quotient.add(1)) : quotient;
}
function calculateQuotientAndRemainder(uint256 dividend, uint256 divisor)
internal
pure
returns (uint256 quotient, uint256 remainder)
{
quotient = dividend.div(divisor);
remainder = dividend.mod(divisor);
}
function getAllFundManagers(address _fundManagerVaultContract)
public
view
returns (IFundManagerVault.FundManager[8] memory)
{
return IFundManagerVault(_fundManagerVaultContract).getAllFundManagers();
}
/// @dev transactionDeadlineDuration setter
function setTransactionDeadlineDuration(address _strategyContract, uint256 _transactionDeadlineDuration)
public
onlyRole(EXECUTOR_ROLE)
{
IStrategySetter(_strategyContract).setTransactionDeadlineDuration(_transactionDeadlineDuration);
emit SetTransactionDeadlineDuration(_strategyContract, msg.sender, _transactionDeadlineDuration);
}
/// @dev tickSpreadUpper setter
function setTickSpreadUpper(address _strategyContract, int24 _tickSpreadUpper) public onlyRole(EXECUTOR_ROLE) {
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_tickSpreadUpper);
// update tickSpreadUpper
tickSpreadUpper[_strategyContract] = _tickSpreadUpper;
// emit SetTickSpreadUpper event
emit SetTickSpreadUpper(_strategyContract, msg.sender, _tickSpreadUpper);
}
/// @dev tickSpreadLower setter
function setTickSpreadLower(address _strategyContract, int24 _tickSpreadLower) public onlyRole(EXECUTOR_ROLE) {
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_tickSpreadLower);
// update tickSpreadLower
tickSpreadLower[_strategyContract] = _tickSpreadLower;
// emit SetTickSpreadLower event
emit SetTickSpreadLower(_strategyContract, msg.sender, _tickSpreadLower);
}
/// @dev tickGapUpper setter
function setTickGapUpper(address _strategyContract, int24 _tickGapUpper) public onlyRole(EXECUTOR_ROLE) {
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOne(_tickGapUpper);
// update tickGapUpper
tickGapUpper[_strategyContract] = _tickGapUpper;
// emit SetTickGapUpper event
emit SetTickGapUpper(_strategyContract, msg.sender, _tickGapUpper);
}
/// @dev tickGapLower setter
function setTickGapLower(address _strategyContract, int24 _tickGapLower) public onlyRole(EXECUTOR_ROLE) {
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOne(_tickGapLower);
// update tickGapLower
tickGapLower[_strategyContract] = _tickGapLower;
// emit SetTickGapLower event
emit SetTickGapLower(_strategyContract, msg.sender, _tickGapLower);
}
/// @dev buyBackToken setter
function setBuyBackToken(address _strategyContract, address _buyBackToken) public onlyRole(EXECUTOR_ROLE) {
IStrategySetter(_strategyContract).setBuyBackToken(_buyBackToken);
emit SetBuyBackToken(_strategyContract, msg.sender, _buyBackToken);
}
/// @dev buyBackNumerator setter
function setBuyBackNumerator(address _strategyContract, uint24 _buyBackNumerator) public onlyRole(EXECUTOR_ROLE) {
IStrategySetter(_strategyContract).setBuyBackNumerator(_buyBackNumerator);
emit SetBuyBackNumerator(_strategyContract, msg.sender, _buyBackNumerator);
}
/// @dev fundManagerVault setter
function setFundManagerVaultByIndex(
address _strategyContract,
uint256 _index,
address _fundManagerVaultAddress,
uint24 _fundManagerProfitVaultNumerator
) public onlyRole(EXECUTOR_ROLE) {
IStrategySetter(_strategyContract).setFundManagerVaultByIndex(
_index, _fundManagerVaultAddress, _fundManagerProfitVaultNumerator
);
emit SetFundManagerVaultByIndex(
_strategyContract, msg.sender, _index, _fundManagerVaultAddress, _fundManagerProfitVaultNumerator
);
}
/// @dev fundManager setter
function setFundManagerByIndex(
address _fundManagerVaultContract,
uint256 _index,
address _fundManagerAddress,
uint24 _fundManagerProfitNumerator
) public onlyRole(EXECUTOR_ROLE) {
IFundManagerVault(_fundManagerVaultContract).setFundManagerByIndex(
_index, _fundManagerAddress, _fundManagerProfitNumerator
);
emit SetFundManagerByIndex(
_fundManagerVaultContract, msg.sender, _index, _fundManagerAddress, _fundManagerProfitNumerator
);
}
/// @dev earnLoopSegmentSize setter
function setEarnLoopSegmentSize(address _strategyContract, uint256 _earnLoopSegmentSize)
public
onlyRole(EXECUTOR_ROLE)
{
IStrategySetter(_strategyContract).setEarnLoopSegmentSize(_earnLoopSegmentSize);
emit SetEarnLoopSegmentSize(_strategyContract, msg.sender, _earnLoopSegmentSize);
}
/// @dev tickBoundaryOffset setter
function setTickUpperBoundaryOffset(address _strategyContract, int24 _tickUpperBoundaryOffset)
public
onlyRole(EXECUTOR_ROLE)
{
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_tickUpperBoundaryOffset);
// update tickBoundaryOffset
tickUpperBoundaryOffset[_strategyContract] = _tickUpperBoundaryOffset;
// emit SetTickUpperBoundaryOffset event
emit SetTickUpperBoundaryOffset(_strategyContract, msg.sender, _tickUpperBoundaryOffset);
}
function setTickLowerBoundaryOffset(address _strategyContract, int24 _tickLowerBoundaryOffset)
public
onlyRole(EXECUTOR_ROLE)
{
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_tickLowerBoundaryOffset);
// update tickBoundaryOffset
tickLowerBoundaryOffset[_strategyContract] = _tickLowerBoundaryOffset;
// emit SetTickLowerBoundaryOffset event
emit SetTickLowerBoundaryOffset(_strategyContract, msg.sender, _tickLowerBoundaryOffset);
}
/// @dev rescaleTickBoundaryOffset setter
function setRescaleTickUpperBoundaryOffset(address _strategyContract, int24 _rescaleTickUpperBoundaryOffset)
public
onlyRole(EXECUTOR_ROLE)
{
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_rescaleTickUpperBoundaryOffset);
// update rescaleTickBoundaryOffset
rescaleTickUpperBoundaryOffset[_strategyContract] = _rescaleTickUpperBoundaryOffset;
// emit SetRescaleTickUpperBoundaryOffset event
emit SetRescaleTickUpperBoundaryOffset(_strategyContract, msg.sender, _rescaleTickUpperBoundaryOffset);
}
function setRescaleTickLowerBoundaryOffset(address _strategyContract, int24 _rescaleTickLowerBoundaryOffset)
public
onlyRole(EXECUTOR_ROLE)
{
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_rescaleTickLowerBoundaryOffset);
// update rescaleTickBoundaryOffset
rescaleTickLowerBoundaryOffset[_strategyContract] = _rescaleTickLowerBoundaryOffset;
// emit SetRescaleTickLowerBoundaryOffset event
emit SetRescaleTickLowerBoundaryOffset(_strategyContract, msg.sender, _rescaleTickLowerBoundaryOffset);
}
/// @dev rescaleTickTolerance setter
function setRescaleTickTolerance(address _strategyContract, int24 _rescaleTickTolerance)
public
onlyRole(EXECUTOR_ROLE)
{
// parameter verification
ParameterVerificationHelper.verifyGreaterThanOrEqualToZero(_rescaleTickTolerance);
// update rescaleTickTolerance
rescaleTickTolerance[_strategyContract] = _rescaleTickTolerance;
// emit SetRescaleTickTolerance event
emit SetRescaleTickTolerance(_strategyContract, msg.sender, _rescaleTickTolerance);
}
/// @dev earn related
function collectRewards(address _strategyContract) public onlyRole(EXECUTOR_ROLE) {
IStrategy(_strategyContract).collectRewards();
emit CollectRewards(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).liquidityNftId(),
IStrategyInfo(_strategyContract).rewardToken0Amount(),
IStrategyInfo(_strategyContract).rewardToken1Amount(),
IStrategyInfo(_strategyContract).distributeRewardAmount()
);
}
function earnPreparation(
address _strategyContract,
uint256 _minimumToken0SwapOutAmount,
uint256 _minimumToken1SwapOutAmount,
uint256 _minimumBuybackSwapOutAmount
) public onlyRole(EXECUTOR_ROLE) {
IStrategy(_strategyContract).earnPreparation(
_minimumToken0SwapOutAmount, _minimumToken1SwapOutAmount, _minimumBuybackSwapOutAmount
);
require(getEarningFlag(_strategyContract) == true, "earn prep error");
emit EarnPreparation(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).liquidityNftId(),
IStrategyInfo(_strategyContract).distributeRewardAmount(),
getRemainingEarnCountDown(_strategyContract)
);
}
function earn(address _strategyContract) public onlyRole(EXECUTOR_ROLE) {
IStrategy(_strategyContract).earn();
emit Earn(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).liquidityNftId(),
getRemainingEarnCountDown(_strategyContract)
);
}
function earnPreparation(address _fundManagerVaultContract) public onlyRole(EXECUTOR_ROLE) {
distribute(_fundManagerVaultContract);
}
function allocate(address _fundManagerVaultContract) public onlyRole(EXECUTOR_ROLE) {
distribute(_fundManagerVaultContract);
}
function distribute(address _fundManagerVaultContract) private {
uint256 distributeRewardBeforeTx = IFundManagerVault(_fundManagerVaultContract).getDistributeRewardBalance();
IFundManagerVault(_fundManagerVaultContract).allocate();
uint256 distributeRewardAfterTx = IFundManagerVault(_fundManagerVaultContract).getDistributeRewardBalance();
emit Allocate(
_fundManagerVaultContract,
msg.sender,
distributeRewardBeforeTx.sub(distributeRewardAfterTx),
distributeRewardAfterTx
);
}
/// @dev rescale related
/// @param _strategyContract strategy contract address
/// @param _wasInRange true if lastRescaleTick was in the currentTickUpper and currentTickLower before
function rescale(
address _strategyContract,
address _rescaleTickBoundaryCalculatorContract,
bool _wasInRange,
int24 _tickBeforeRescale
) public onlyRole(EXECUTOR_ROLE) {
(bool allowRescale, int24 newTickUpper, int24 newTickLower) = IRescaleTickBoundaryCalculator(
_rescaleTickBoundaryCalculatorContract
).verifyAndGetNewRescaleTickBoundary(
_wasInRange, lastRescaleTick[_strategyContract], _strategyContract, address(this)
);
require(allowRescale, "current condition not allow rescale");
triggerRescaleStartEvent(_strategyContract, _wasInRange, _tickBeforeRescale);
(int24 currentTick,,) = LiquidityNftHelper.getTickInfo(
IStrategyInfo(_strategyContract).liquidityNftId(),
Constants.UNISWAP_V3_FACTORY_ADDRESS(),
Constants.NONFUNGIBLE_POSITION_MANAGER_ADDRESS()
);
require(
currentTick <= (_tickBeforeRescale + rescaleTickTolerance[_strategyContract])
&& currentTick >= (_tickBeforeRescale - rescaleTickTolerance[_strategyContract]),
"out of tick tolerance range"
);
IStrategy(_strategyContract).rescale(newTickUpper, newTickLower);
lastRescaleTick[_strategyContract] = currentTick;
triggerRescaleEndEvent(_strategyContract, newTickUpper, newTickLower);
}
//! the RescaleStart event need deduct one field, or it will occur stack too deep error
function triggerRescaleStartEvent(address _strategyContract, bool _wasInRange, int24 _tickBeforeRescale) internal {
(int24 currentTick, int24 originalTickLower, int24 originalTickUpper) = LiquidityNftHelper.getTickInfo(
IStrategyInfo(_strategyContract).liquidityNftId(),
Constants.UNISWAP_V3_FACTORY_ADDRESS(),
Constants.NONFUNGIBLE_POSITION_MANAGER_ADDRESS()
);
emit RescaleStart(
_strategyContract,
_wasInRange,
IStrategyInfo(_strategyContract).tickSpacing(),
tickGapUpper[_strategyContract],
tickGapLower[_strategyContract],
tickUpperBoundaryOffset[_strategyContract],
tickLowerBoundaryOffset[_strategyContract],
lastRescaleTick[_strategyContract],
_tickBeforeRescale,
currentTick,
originalTickUpper,
originalTickLower
);
}
function triggerRescaleEndEvent(address _strategyContract, int24 newTickUpper, int24 newTickLower) internal {
(int24 currentTick,,) = LiquidityNftHelper.getTickInfo(
IStrategyInfo(_strategyContract).liquidityNftId(),
Constants.UNISWAP_V3_FACTORY_ADDRESS(),
Constants.NONFUNGIBLE_POSITION_MANAGER_ADDRESS()
);
emit RescaleEnd(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).dustToken0Amount(),
IStrategyInfo(_strategyContract).dustToken1Amount(),
IStrategyInfo(_strategyContract).tickSpacing(),
currentTick,
tickSpreadUpper[_strategyContract],
tickSpreadLower[_strategyContract],
rescaleTickUpperBoundaryOffset[_strategyContract],
rescaleTickLowerBoundaryOffset[_strategyContract],
newTickUpper,
newTickLower
);
}
/// @dev deposit dust token related
function depositDustToken(address _strategyContract, bool _depositDustToken0) public onlyRole(EXECUTOR_ROLE) {
(uint256 increasedToken0Amount, uint256 increasedToken1Amount) =
IStrategy(_strategyContract).depositDustToken(_depositDustToken0);
emit DepositDustToken(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).liquidityNftId(),
_depositDustToken0,
increasedToken0Amount,
increasedToken1Amount,
IStrategyInfo(_strategyContract).dustToken0Amount(),
IStrategyInfo(_strategyContract).dustToken1Amount()
);
}
function updateZapContract(address _strategyContract, address _zapContract) public onlyRole(EXECUTOR_ROLE) {
IStrategy(_strategyContract).updateZapContract(_zapContract);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// 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 (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 v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IERC20Querier is IERC20 {
function decimals() external view returns (uint256);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IConstants {
/// @dev Uniswap v3 Related
function UNISWAP_V3_FACTORY_ADDRESS() external view returns (address);
function NONFUNGIBLE_POSITION_MANAGER_ADDRESS() external view returns (address);
function SWAP_ROUTER_ADDRESS() external view returns (address);
/// @dev Distribute reward token address
function DISTRIBUTE_REWARD_ADDRESS() external view returns (address);
/// @dev Token address (combine each chain)
function WETH_ADDRESS() external view returns (address);
function WBTC_ADDRESS() external view returns (address);
function ARB_ADDRESS() external view returns (address);
function USDC_ADDRESS() external view returns (address);
function USDCE_ADDRESS() external view returns (address);
function USDT_ADDRESS() external view returns (address);
function RDNT_ADDRESS() external view returns (address);
function LINK_ADDRESS() external view returns (address);
function DEGEN_ADDRESS() external view returns (address);
function BRETT_ADDRESS() external view returns (address);
function TOSHI_ADDRESS() external view returns (address);
function CIRCLE_ADDRESS() external view returns (address);
function ROOST_ADDRESS() external view returns (address);
function AERO_ADDRESS() external view returns (address);
function INT_ADDRESS() external view returns (address);
function HIGHER_ADDRESS() external view returns (address);
function KEYCAT_ADDRESS() external view returns (address);
/// @dev Black hole address
function BLACK_HOLE_ADDRESS() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IController {
function tickSpreadUpper(address strategyAddress) external view returns (int24);
function tickSpreadLower(address strategyAddress) external view returns (int24);
function tickGapUpper(address strategyAddress) external view returns (int24);
function tickGapLower(address strategyAddress) external view returns (int24);
function tickUpperBoundaryOffset(address strategyAddress) external view returns (int24);
function tickLowerBoundaryOffset(address strategyAddress) external view returns (int24);
function rescaleTickUpperBoundaryOffset(address strategyAddress) external view returns (int24);
function rescaleTickLowerBoundaryOffset(address strategyAddress) external view returns (int24);
function lastRescaleTick(address strategyAddress) external view returns (int24);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IControllerEvent {
event SetTransactionDeadlineDuration(
address indexed strategyContract, address indexed executorAddress, uint256 transactionDeadlineDuration
);
event SetTickSpreadUpper(address indexed strategyContract, address indexed executorAddress, int24 tickSpreadUpper);
event SetTickSpreadLower(address indexed strategyContract, address indexed executorAddress, int24 tickSpreadLower);
event SetTickGapUpper(address indexed strategyContract, address indexed executorAddress, int24 tickGapUpper);
event SetTickGapLower(address indexed strategyContract, address indexed executorAddress, int24 tickGapLower);
event SetBuyBackToken(address indexed strategyContract, address indexed executorAddress, address buyBackToken);
event SetBuyBackNumerator(
address indexed strategyContract, address indexed executorAddress, uint24 buyBackNumerator
);
event SetFundManagerVaultByIndex(
address indexed strategyContract,
address indexed executorAddress,
uint256 index,
address fundManagerVaultAddress,
uint24 fundManagerProfitVaultNumerator
);
event SetFundManagerByIndex(
address indexed fundManagerVaultAddress,
address indexed executorAddress,
uint256 index,
address fundManagerAddress,
uint24 fundManagerProfitNumerator
);
event SetEarnLoopSegmentSize(
address indexed strategyContract, address indexed executorAddress, uint256 earnLoopSegmentSize
);
event SetTickUpperBoundaryOffset(
address indexed strategyContract, address indexed executorAddress, int24 tickUpperBoundaryOffset
);
event SetTickLowerBoundaryOffset(
address indexed strategyContract, address indexed executorAddress, int24 tickLowerBoundaryOffset
);
event SetRescaleTickUpperBoundaryOffset(
address indexed strategyContract, address indexed executorAddress, int24 rescaleTickUpperBoundaryOffset
);
event SetRescaleTickLowerBoundaryOffset(
address indexed strategyContract, address indexed executorAddress, int24 rescaleTickLowerBoundaryOffset
);
event SetRescaleTickTolerance(
address indexed strategyContract, address indexed executorAddress, int24 rescaleTickTolerance
);
event CollectRewards(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
uint256 rewardToken0Amount,
uint256 rewardToken1Amount,
uint256 distributeRewardAmount
);
event EarnPreparation(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
uint256 distributeRewardAmount,
uint256 remainingEarnCountDown
);
event Earn(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
uint256 remainingEarnCountDown
);
event Allocate(
address indexed fundManagerVaultAddress,
address indexed executorAddress,
uint256 allocatedDistributeRewardAmount,
uint256 remainingDistributeRewardAmount
);
event RescaleStart(
address indexed strategyContract,
bool wasInRange,
int24 tickSpacing,
int24 tickGapUpper,
int24 tickGapLower,
int24 tickUpperBoundaryOffset,
int24 tickLowerBoundaryOffset,
int24 lastRescaleTick,
int24 tickBeforeRescale,
int24 thisRescaleTick,
int24 originalTickUpper,
int24 originalTickLower
);
event RescaleEnd(
address indexed strategyContract,
address indexed executorAddress,
uint256 dustToken0Amount,
uint256 dustToken1Amount,
int24 tickSpacing,
int24 thisRescaleTick,
int24 tickSpreadUpper,
int24 tickSpreadLower,
int24 rescaleTickUpperBoundaryOffset,
int24 rescaleTickLowerBoundaryOffset,
int24 newTickUpper,
int24 newTickLower
);
event DepositDustToken(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
bool depositDustToken0,
uint256 increasedToken0Amount,
uint256 increasedToken1Amount,
uint256 dustToken0Amount,
uint256 dustToken1Amount
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IFundManagerVault {
struct FundManager {
address fundManagerAddress;
uint256 fundManagerProfitNumerator;
}
function getDistributeRewardBalance() external view returns (uint256);
function getAllFundManagers() external view returns (FundManager[8] memory);
function setFundManagerByIndex(uint256 index, address fundManagerAddress, uint24 fundManagerProfitNumerator)
external;
function allocate() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IRescaleTickBoundaryCalculator {
function verifyAndGetNewRescaleTickBoundary(
bool wasInRange,
int24 lastRescaleTick,
address strategyAddress,
address controllerAddress
)
external
view
returns (bool allowRescale, int24 newTickUpper, int24 newTickLower);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStrategy {
function depositLiquidity(
bool isETH,
address userAddress,
address inputToken,
uint256 inputAmount,
uint256 swapInAmount,
uint256 minimumSwapOutAmount
)
external
payable
returns (
uint128 increasedLiquidity,
uint256 increasedShare,
uint256 increasedToken0Amount,
uint256 increasedToken1Amount,
uint256 sendBackToken0Amount,
uint256 sendBackToken1Amount
);
function withdrawLiquidity(address userAddress, uint256 withdrawShares)
external
returns (uint256 userReceivedToken0Amount, uint256 userReceivedToken1Amount);
function collectRewards() external;
function earnPreparation(
uint256 minimumToken0SwapOutAmount,
uint256 minimumToken1SwapOutAmount,
uint256 minimumBuybackSwapOutAmount
) external;
function earn() external;
function claimReward(address userAddress) external;
function rescale(int24 newTickUpper, int24 newTickLower) external;
function depositDustToken(bool depositDustToken0)
external
returns (uint256 increasedToken0Amount, uint256 increasedToken1Amount);
function updateZapContract(address newZapContract) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStrategyInfo {
/// @dev Uniswap-Transaction-related Variable
function transactionDeadlineDuration() external view returns (uint256);
/// @dev get Liquidity-NFT-related Variable
function liquidityNftId() external view returns (uint256);
function tickSpacing() external view returns (int24);
/// @dev get Pool-related Variable
function poolAddress() external view returns (address);
function poolFee() external view returns (uint24);
function token0Address() external view returns (address);
function token1Address() external view returns (address);
/// @dev get Tracker-Token-related Variable
function trackerTokenAddress() external view returns (address);
/// @dev get User-Management-related Variable
function isInUserList(address userAddress) external view returns (bool);
function userIndex(address userAddress) external view returns (uint256);
function getAllUsersInUserList() external view returns (address[] memory);
/// @dev get User-Share-Management-related Variable
function userShare(address userAddress) external view returns (uint256);
function totalUserShare() external view returns (uint256);
/// @dev get Reward-Management-related Variable
function rewardToken0Amount() external view returns (uint256);
function rewardToken1Amount() external view returns (uint256);
function distributeRewardAmount() external view returns (uint256);
/// @dev get User-Reward-Management-related Variable
function userDistributeReward(address userAddress) external view returns (uint256);
function totalUserDistributeReward() external view returns (uint256);
/// @dev get Buyback-related Variable
function buyBackToken() external view returns (address);
function buyBackNumerator() external view returns (uint24);
/// @dev get Fund-Manager-related Variable
struct FundManagerVault {
address fundManagerVaultAddress;
uint256 fundManagerProfitVaultNumerator;
}
function getAllFundManagerVaults() external view returns (FundManagerVault[3] memory);
/// @dev get Earn-Loop-Control-related Variable
function earnLoopSegmentSize() external view returns (uint256);
function earnLoopDistributedAmount() external view returns (uint256);
function earnLoopStartIndex() external view returns (uint256);
function isEarning() external view returns (bool);
/// @dev get Rescale-related Variable
function dustToken0Amount() external view returns (uint256);
function dustToken1Amount() external view returns (uint256);
/// @dev get Constant Variable
function getBuyBackDenominator() external pure returns (uint24);
function getFundManagerProfitVaultDenominator() external pure returns (uint24);
function getFarmAddress() external view returns (address);
function getControllerAddress() external view returns (address);
function getSwapAmountCalculatorAddress() external view returns (address);
function getZapAddress() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IStrategySetter {
function setTransactionDeadlineDuration(
uint256 _transactionDeadlineDuration
) external;
function setBuyBackToken(address _buyBackToken) external;
function setBuyBackNumerator(uint24 _buyBackNumerator) external;
function setFundManagerVaultByIndex(
uint256 index,
address _fundManagerVaultAddress,
uint24 _fundManagerProfitVaultNumerator
) external;
function setEarnLoopSegmentSize(uint256 _earnLoopSegmentSize) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
interface INonfungiblePositionManager {
/// @notice Returns the position information associated with a given token ID.
/// @dev Throws if the token ID is not valid.
/// @param tokenId The ID of the token that represents the position
/// @return nonce The nonce for permits
/// @return operator The address that is approved for spending
/// @return token0 The address of the token0 for a specific pool
/// @return token1 The address of the token1 for a specific pool
/// @return fee The fee associated with the pool
/// @return tickLower The lower end of the tick range for the position
/// @return tickUpper The higher end of the tick range for the position
/// @return liquidity The liquidity of the position
/// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position
/// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position
/// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation
/// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation
function positions(
uint256 tokenId
)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
/// @notice Refunds any ETH balance held by this contract to the `msg.sender`
/// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps
/// that use ether for the input amount
function refundETH() external payable;
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
/// @notice Creates a new position wrapped in a NFT
/// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized
/// a method does not exist, i.e. the pool is assumed to be initialized.
/// @param params The params necessary to mint a position, encoded as `MintParams` in calldata
/// @return tokenId The ID of the token that represents the minted position
/// @return liquidity The amount of liquidity for this position
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function mint(
MintParams calldata params
)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`
/// @param params tokenId The ID of the token for which liquidity is being increased,
/// amount0Desired The desired amount of token0 to be spent,
/// amount1Desired The desired amount of token1 to be spent,
/// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,
/// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,
/// deadline The time by which the transaction must be included to effect the change
/// @return liquidity The new liquidity amount as a result of the increase
/// @return amount0 The amount of token0 to acheive resulting liquidity
/// @return amount1 The amount of token1 to acheive resulting liquidity
function increaseLiquidity(
IncreaseLiquidityParams calldata params
)
external
payable
returns (uint128 liquidity, uint256 amount0, uint256 amount1);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Decreases the amount of liquidity in a position and accounts it to the position
/// @param params tokenId The ID of the token for which liquidity is being decreased,
/// amount The amount by which liquidity will be decreased,
/// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,
/// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,
/// deadline The time by which the transaction must be included to effect the change
/// @return amount0 The amount of token0 accounted to the position's tokens owed
/// @return amount1 The amount of token1 accounted to the position's tokens owed
function decreaseLiquidity(
DecreaseLiquidityParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
/// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient
/// @param params tokenId The ID of the NFT for which tokens are being collected,
/// recipient The account that should receive the tokens,
/// amount0Max The maximum amount of token0 to collect,
/// amount1Max The maximum amount of token1 to collect
/// @return amount0 The amount of fees collected in token0
/// @return amount1 The amount of fees collected in token1
function collect(
CollectParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
/// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens
/// must be collected first.
/// @param tokenId The ID of the token that is being burned
function burn(uint256 tokenId) external payable;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
interface IUniswapV3Factory {
/// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
/// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
/// @param tokenA The contract address of either token0 or token1
/// @param tokenB The contract address of the other token
/// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
/// @return pool The pool address
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
interface IUniswapV3Pool {
/// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
/// tick The current tick of the pool, i.e. according to the last tick transition that was run.
/// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// observationIndex The index of the last oracle observation that was written,
/// observationCardinality The current maximum number of observations stored in the pool,
/// observationCardinalityNext The next maximum number of observations, to be updated when the observation.
/// feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice The pool tick spacing
/// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive
/// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...
/// This value is an int24 to avoid casting even though it is always positive.
/// @return The tick spacing
function tickSpacing() external view returns (int24);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/uniswapV3/INonfungiblePositionManager.sol";
import "./uniswapV3/TickMath.sol";
import "./PoolHelper.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
library LiquidityNftHelper {
using SafeMath for uint256;
function getLiquidityAmountByNftId(
uint256 liquidityNftId,
address nonfungiblePositionManagerAddress
) internal view returns (uint128 liquidity) {
(, , , , , , , liquidity, , , , ) = INonfungiblePositionManager(
nonfungiblePositionManagerAddress
).positions(liquidityNftId);
}
function getPoolInfoByLiquidityNft(
uint256 liquidityNftId,
address uniswapV3FactoryAddress,
address nonfungiblePositionManagerAddress
)
internal
view
returns (
address poolAddress,
int24 tick,
uint160 sqrtPriceX96,
uint256 decimal0,
uint256 decimal1
)
{
(
address token0,
address token1,
uint24 poolFee,
,
,
,
) = getLiquidityNftPositionsInfo(
liquidityNftId,
nonfungiblePositionManagerAddress
);
poolAddress = PoolHelper.getPoolAddress(
uniswapV3FactoryAddress,
token0,
token1,
poolFee
);
(, , , tick, sqrtPriceX96, decimal0, decimal1) = PoolHelper.getPoolInfo(
poolAddress
);
}
function getLiquidityNftPositionsInfo(
uint256 liquidityNftId,
address nonfungiblePositionManagerAddress
)
internal
view
returns (
address token0,
address token1,
uint24 poolFee,
int24 tickLower,
int24 tickUpper,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96
)
{
(
,
,
token0,
token1,
poolFee,
tickLower,
tickUpper,
,
,
,
,
) = INonfungiblePositionManager(nonfungiblePositionManagerAddress)
.positions(liquidityNftId);
sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
}
/// @dev formula explanation
/*
[Original formula (without decimal precision)]
tickUpper -> sqrtRatioBX96
tickLower -> sqrtRatioAX96
tick -> sqrtPriceX96
(token1 * (10^decimal1)) / (token0 * (10^decimal0)) =
(sqrtPriceX96 * sqrtRatioBX96 * (sqrtPriceX96 - sqrtRatioAX96))
/ ((2^192) * (sqrtRatioBX96 - sqrtPriceX96))
[Formula with decimal precision & decimal adjustment]
liquidityRatioWithDecimalAdj = liquidityRatio * (10^decimalPrecision)
= (sqrtPriceX96 * (10^decimalPrecision) / (2^96))
* (sqrtPriceBX96 * (10^decimalPrecision) / (2^96))
* (sqrtPriceX96 - sqrtRatioAX96)
/ ((sqrtRatioBX96 - sqrtPriceX96) * (10^(decimalPrecision + decimal1 - decimal0)))
*/
function getInRangeLiquidityRatioWithDecimals(
uint256 liquidityNftId,
uint256 decimalPrecision,
address uniswapV3FactoryAddress,
address nonfungiblePositionManagerAddress
) internal view returns (uint256 liquidityRatioWithDecimals) {
// get sqrtPrice of tickUpper, tick, tickLower
(
,
,
,
,
,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96
) = getLiquidityNftPositionsInfo(
liquidityNftId,
nonfungiblePositionManagerAddress
);
(
,
,
uint160 sqrtPriceX96,
uint256 decimal0,
uint256 decimal1
) = getPoolInfoByLiquidityNft(
liquidityNftId,
uniswapV3FactoryAddress,
nonfungiblePositionManagerAddress
);
// when decimalPrecision is 18,
// calculation restriction: 79228162514264337594 <= sqrtPriceX96 <= type(uint160).max
uint256 scaledPriceX96 = uint256(sqrtPriceX96)
.mul(10 ** decimalPrecision)
.div(2 ** 96);
uint256 scaledPriceBX96 = uint256(sqrtRatioBX96)
.mul(10 ** decimalPrecision)
.div(2 ** 96);
uint256 decimalAdj = decimalPrecision.add(decimal1).sub(decimal0);
uint256 preLiquidityRatioWithDecimals = scaledPriceX96
.mul(scaledPriceBX96)
.div(10 ** decimalAdj);
liquidityRatioWithDecimals = preLiquidityRatioWithDecimals
.mul(uint256(sqrtPriceX96).sub(sqrtRatioAX96))
.div(uint256(sqrtRatioBX96).sub(sqrtPriceX96));
}
function verifyInputTokenIsLiquidityNftTokenPair(
uint256 liquidityNftId,
address inputToken,
address nonfungiblePositionManagerAddress
) internal view {
(
address token0,
address token1,
,
,
,
,
) = getLiquidityNftPositionsInfo(
liquidityNftId,
nonfungiblePositionManagerAddress
);
require(
inputToken == token0 || inputToken == token1,
"inputToken not in token pair"
);
}
function verifyCurrentPriceInLiquidityNftRange(
uint256 liquidityNftId,
address uniswapV3FactoryAddress,
address nonfungiblePositionManagerAddress
) internal view returns (bool isInRange, address liquidity0Token) {
(, int24 tick, , , ) = getPoolInfoByLiquidityNft(
liquidityNftId,
uniswapV3FactoryAddress,
nonfungiblePositionManagerAddress
);
(
address token0,
address token1,
,
int24 tickLower,
int24 tickUpper,
,
) = getLiquidityNftPositionsInfo(
liquidityNftId,
nonfungiblePositionManagerAddress
);
// tick out of range, tick <= tickLower left token0
if (tick <= tickLower) {
return (false, token0);
// tick in range, tickLower < tick < tickUpper
} else if (tick < tickUpper) {
return (true, address(0));
// tick out of range, tick >= tickUpper left token1
} else {
return (false, token1);
}
}
function getTickInfo(
uint256 liquidityNftId,
address uniswapV3FactoryAddress,
address nonfungiblePositionManagerAddress
) internal view returns (int24 tick, int24 tickLower, int24 tickUpper) {
(, tick, , , ) = getPoolInfoByLiquidityNft(
liquidityNftId,
uniswapV3FactoryAddress,
nonfungiblePositionManagerAddress
);
(, , , tickLower, tickUpper, , ) = getLiquidityNftPositionsInfo(
liquidityNftId,
nonfungiblePositionManagerAddress
);
}
function verifyNoDuplicateTickAndTickLower(
uint256 liquidityNftId,
address uniswapV3FactoryAddress,
address nonfungiblePositionManagerAddress
) internal view {
(int24 tick, int24 tickLower, ) = getTickInfo(
liquidityNftId,
uniswapV3FactoryAddress,
nonfungiblePositionManagerAddress
);
require(tickLower != tick, "tickLower == tick");
}
// for general condition (except tickSpacing 1 condition)
function calculateInitTickBoundary(
address poolAddress,
int24 tickSpread,
int24 tickSpacing
) internal view returns (int24 tickLower, int24 tickUpper) {
require(tickSpacing != 1, "tickSpacing == 1");
// Get current tick
(, , , int24 currentTick, , , ) = PoolHelper.getPoolInfo(poolAddress);
// Calculate the floor tick value
int24 tickFloor = floorTick(currentTick, tickSpacing);
// Calculate the tickLower & tickToTickLower value
tickLower = tickFloor - tickSpacing * tickSpread;
int24 tickToTickLower = currentTick - tickLower;
// Calculate the tickUpper & tickUpperToTick value
tickUpper = floorTick((currentTick + tickToTickLower), tickSpacing);
int24 tickUpperToTick = tickUpper - currentTick;
// Check
// if the tickSpacing is greater than 1
// and
// if the (tickToTickLower - tickUpperToTick) is greater than or equal to (tickSpacing / 2)
if (
tickSpacing > 1 &&
(tickToTickLower - tickUpperToTick) >= (tickSpacing / 2)
) {
// Increment the tickUpper by the tickSpacing
tickUpper += tickSpacing;
}
}
function floorTick(
int24 tick,
int24 tickSpacing
) internal pure returns (int24) {
int24 baseFloor = tick / tickSpacing;
if (tick < 0 && tick % tickSpacing != 0) {
return (baseFloor - 1) * tickSpacing;
}
return baseFloor * tickSpacing;
}
function ceilingTick(
int24 tick,
int24 tickSpacing
) internal pure returns (int24) {
int24 baseFloor = tick / tickSpacing;
if (tick > 0 && tick % tickSpacing != 0) {
return (baseFloor + 1) * tickSpacing;
}
return baseFloor * tickSpacing;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library ParameterVerificationHelper {
function verifyNotZeroAddress(address inputAddress) internal pure {
require(inputAddress != address(0), "input zero address");
}
function verifyGreaterThanZero(uint256 inputNumber) internal pure {
require(inputNumber > 0, "input 0");
}
function verifyGreaterThanZero(int24 inputNumber) internal pure {
require(inputNumber > 0, "input 0");
}
function verifyGreaterThanOne(int24 inputNumber) internal pure {
require(inputNumber > 1, "input <= 1");
}
function verifyGreaterThanOrEqualToZero(int24 inputNumber) internal pure {
require(inputNumber >= 0, "input less than 0");
}
function verifyPairTokensHaveWeth(
address token0Address,
address token1Address,
address wethAddress
) internal pure {
require(
token0Address == wethAddress || token1Address == wethAddress,
"pair token not have WETH"
);
}
function verifyMsgValueEqualsInputAmount(
uint256 inputAmount
) internal view {
require(msg.value == inputAmount, "msg.value != inputAmount");
}
function verifyPairTokensHaveInputToken(
address token0Address,
address token1Address,
address inputToken
) internal pure {
require(
token0Address == inputToken || token1Address == inputToken,
"pair token not have inputToken"
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/external/IERC20Querier.sol";
import "../interfaces/uniswapV3/IUniswapV3Factory.sol";
import "../interfaces/uniswapV3/IUniswapV3Pool.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
library PoolHelper {
using SafeMath for uint256;
function getPoolAddress(address uniswapV3FactoryAddress, address tokenA, address tokenB, uint24 poolFee)
internal
view
returns (address poolAddress)
{
return IUniswapV3Factory(uniswapV3FactoryAddress).getPool(tokenA, tokenB, poolFee);
}
function getPoolInfo(address poolAddress)
internal
view
returns (
address token0,
address token1,
uint24 poolFee,
int24 tick,
uint160 sqrtPriceX96,
uint256 decimal0,
uint256 decimal1
)
{
(sqrtPriceX96, tick,,,,,) = IUniswapV3Pool(poolAddress).slot0();
token0 = IUniswapV3Pool(poolAddress).token0();
token1 = IUniswapV3Pool(poolAddress).token1();
poolFee = IUniswapV3Pool(poolAddress).fee();
decimal0 = IERC20Querier(token0).decimals();
decimal1 = IERC20Querier(token1).decimals();
}
/// @dev formula explanation
/*
[Original formula (without decimal precision)]
(token1 * (10^decimal1)) / (token0 * (10^decimal0)) = (sqrtPriceX96 / (2^96))^2
tokenPrice = token1/token0 = (sqrtPriceX96 / (2^96))^2 * (10^decimal0) / (10^decimal1)
[Formula with decimal precision & decimal adjustment]
tokenPriceWithDecimalAdj = tokenPrice * (10^decimalPrecision)
= (sqrtPriceX96 * (10^decimalPrecision) / (2^96))^2
/ 10^(decimalPrecision + decimal1 - decimal0)
*/
function getTokenPriceWithDecimalsByPool(address poolAddress, uint256 decimalPrecision)
internal
view
returns (uint256 tokenPriceWithDecimals)
{
(,,,, uint160 sqrtPriceX96, uint256 decimal0, uint256 decimal1) = getPoolInfo(poolAddress);
// when decimalPrecision is 18,
// calculation restriction: 79228162514264337594 <= sqrtPriceX96 <= type(uint160).max
uint256 scaledPriceX96 = uint256(sqrtPriceX96).mul(10 ** decimalPrecision).div(2 ** 96);
uint256 tokenPriceWithoutDecimalAdj = scaledPriceX96.mul(scaledPriceX96);
uint256 decimalAdj = decimalPrecision.add(decimal1).sub(decimal0);
uint256 result = tokenPriceWithoutDecimalAdj.div(10 ** decimalAdj);
require(result > 0, "token price too small");
tokenPriceWithDecimals = result;
}
function getTokenDecimalAdjustment(address token) internal view returns (uint256 decimalAdjustment) {
uint256 tokenDecimalStandard = 18;
uint256 decimal = IERC20Querier(token).decimals();
return tokenDecimalStandard.sub(decimal);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
/// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
int24 internal constant MIN_TICK = -887272;
/// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
int24 internal constant MAX_TICK = -MIN_TICK;
/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
uint160 internal constant MAX_SQRT_RATIO =
1461446703485210103287273052203988822378723970342;
/// @notice Calculates sqrt(1.0001^tick) * 2^96
/// @dev Throws if |tick| > max tick
/// @param tick The input tick for the above formula
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
/// at the given tick
function getSqrtRatioAtTick(
int24 tick
) internal pure returns (uint160 sqrtPriceX96) {
uint256 absTick = tick < 0
? uint256(-int256(tick))
: uint256(int256(tick));
require(absTick <= uint256(int256(MAX_TICK)), "T");
uint256 ratio = absTick & 0x1 != 0
? 0xfffcb933bd6fad37aa2d162d1a594001
: 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0)
ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0)
ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0)
ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0)
ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0)
ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0)
ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0)
ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0)
ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0)
ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0)
ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0)
ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0)
ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0)
ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0)
ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0)
ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0)
ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0)
ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0)
ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0)
ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
// we then downcast because we know the result always fits within 160 bits due to our tick input constraint
// we round up in the division so getTickAtSqrtRatio of the output price is always consistent
sqrtPriceX96 = uint160(
(ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)
);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_constants","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fundManagerVaultAddress","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"allocatedDistributeRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingDistributeRewardAmount","type":"uint256"}],"name":"Allocate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidityNftId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardToken0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardToken1Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"distributeRewardAmount","type":"uint256"}],"name":"CollectRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidityNftId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"depositDustToken0","type":"bool"},{"indexed":false,"internalType":"uint256","name":"increasedToken0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"increasedToken1Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dustToken0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dustToken1Amount","type":"uint256"}],"name":"DepositDustToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidityNftId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingEarnCountDown","type":"uint256"}],"name":"Earn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"liquidityNftId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"distributeRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingEarnCountDown","type":"uint256"}],"name":"EarnPreparation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"dustToken0Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dustToken1Amount","type":"uint256"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"int24","name":"thisRescaleTick","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickSpreadUpper","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickSpreadLower","type":"int24"},{"indexed":false,"internalType":"int24","name":"rescaleTickUpperBoundaryOffset","type":"int24"},{"indexed":false,"internalType":"int24","name":"rescaleTickLowerBoundaryOffset","type":"int24"},{"indexed":false,"internalType":"int24","name":"newTickUpper","type":"int24"},{"indexed":false,"internalType":"int24","name":"newTickLower","type":"int24"}],"name":"RescaleEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":false,"internalType":"bool","name":"wasInRange","type":"bool"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickGapUpper","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickGapLower","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickUpperBoundaryOffset","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickLowerBoundaryOffset","type":"int24"},{"indexed":false,"internalType":"int24","name":"lastRescaleTick","type":"int24"},{"indexed":false,"internalType":"int24","name":"tickBeforeRescale","type":"int24"},{"indexed":false,"internalType":"int24","name":"thisRescaleTick","type":"int24"},{"indexed":false,"internalType":"int24","name":"originalTickUpper","type":"int24"},{"indexed":false,"internalType":"int24","name":"originalTickLower","type":"int24"}],"name":"RescaleStart","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint24","name":"buyBackNumerator","type":"uint24"}],"name":"SetBuyBackNumerator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"buyBackToken","type":"address"}],"name":"SetBuyBackToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"earnLoopSegmentSize","type":"uint256"}],"name":"SetEarnLoopSegmentSize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fundManagerVaultAddress","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"fundManagerAddress","type":"address"},{"indexed":false,"internalType":"uint24","name":"fundManagerProfitNumerator","type":"uint24"}],"name":"SetFundManagerByIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"fundManagerVaultAddress","type":"address"},{"indexed":false,"internalType":"uint24","name":"fundManagerProfitVaultNumerator","type":"uint24"}],"name":"SetFundManagerVaultByIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"rescaleTickLowerBoundaryOffset","type":"int24"}],"name":"SetRescaleTickLowerBoundaryOffset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"rescaleTickTolerance","type":"int24"}],"name":"SetRescaleTickTolerance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"rescaleTickUpperBoundaryOffset","type":"int24"}],"name":"SetRescaleTickUpperBoundaryOffset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickGapLower","type":"int24"}],"name":"SetTickGapLower","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickGapUpper","type":"int24"}],"name":"SetTickGapUpper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickLowerBoundaryOffset","type":"int24"}],"name":"SetTickLowerBoundaryOffset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickSpreadLower","type":"int24"}],"name":"SetTickSpreadLower","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickSpreadUpper","type":"int24"}],"name":"SetTickSpreadUpper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"int24","name":"tickUpperBoundaryOffset","type":"int24"}],"name":"SetTickUpperBoundaryOffset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategyContract","type":"address"},{"indexed":true,"internalType":"address","name":"executorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"transactionDeadlineDuration","type":"uint256"}],"name":"SetTransactionDeadlineDuration","type":"event"},{"inputs":[],"name":"Constants","outputs":[{"internalType":"contract IConstants","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXECUTOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_fundManagerVaultContract","type":"address"}],"name":"allocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"collectRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"bool","name":"_depositDustToken0","type":"bool"}],"name":"depositDustToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"earn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"uint256","name":"_minimumToken0SwapOutAmount","type":"uint256"},{"internalType":"uint256","name":"_minimumToken1SwapOutAmount","type":"uint256"},{"internalType":"uint256","name":"_minimumBuybackSwapOutAmount","type":"uint256"}],"name":"earnPreparation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fundManagerVaultContract","type":"address"}],"name":"earnPreparation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fundManagerVaultContract","type":"address"}],"name":"getAllFundManagers","outputs":[{"components":[{"internalType":"address","name":"fundManagerAddress","type":"address"},{"internalType":"uint256","name":"fundManagerProfitNumerator","type":"uint256"}],"internalType":"struct IFundManagerVault.FundManager[8]","name":"","type":"tuple[8]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"getEarningFlag","outputs":[{"internalType":"bool","name":"isEarningFlag","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"getRemainingEarnCountDown","outputs":[{"internalType":"uint256","name":"remainingEarn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"getRescalingFlag","outputs":[{"internalType":"bool","name":"isRescalingFlag","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"}],"name":"isNftWithinRange","outputs":[{"internalType":"bool","name":"isWithinRange","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRescaleTick","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"address","name":"_rescaleTickBoundaryCalculatorContract","type":"address"},{"internalType":"bool","name":"_wasInRange","type":"bool"},{"internalType":"int24","name":"_tickBeforeRescale","type":"int24"}],"name":"rescale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rescaleTickLowerBoundaryOffset","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rescaleTickTolerance","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rescaleTickUpperBoundaryOffset","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"uint24","name":"_buyBackNumerator","type":"uint24"}],"name":"setBuyBackNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"address","name":"_buyBackToken","type":"address"}],"name":"setBuyBackToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"uint256","name":"_earnLoopSegmentSize","type":"uint256"}],"name":"setEarnLoopSegmentSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fundManagerVaultContract","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_fundManagerAddress","type":"address"},{"internalType":"uint24","name":"_fundManagerProfitNumerator","type":"uint24"}],"name":"setFundManagerByIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_fundManagerVaultAddress","type":"address"},{"internalType":"uint24","name":"_fundManagerProfitVaultNumerator","type":"uint24"}],"name":"setFundManagerVaultByIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_rescaleTickLowerBoundaryOffset","type":"int24"}],"name":"setRescaleTickLowerBoundaryOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_rescaleTickTolerance","type":"int24"}],"name":"setRescaleTickTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_rescaleTickUpperBoundaryOffset","type":"int24"}],"name":"setRescaleTickUpperBoundaryOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickGapLower","type":"int24"}],"name":"setTickGapLower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickGapUpper","type":"int24"}],"name":"setTickGapUpper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickLowerBoundaryOffset","type":"int24"}],"name":"setTickLowerBoundaryOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickSpreadLower","type":"int24"}],"name":"setTickSpreadLower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickSpreadUpper","type":"int24"}],"name":"setTickSpreadUpper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"int24","name":"_tickUpperBoundaryOffset","type":"int24"}],"name":"setTickUpperBoundaryOffset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"uint256","name":"_transactionDeadlineDuration","type":"uint256"}],"name":"setTransactionDeadlineDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickGapLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickGapUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickLowerBoundaryOffset","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickSpreadLower","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickSpreadUpper","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickUpperBoundaryOffset","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyContract","type":"address"},{"internalType":"address","name":"_zapContract","type":"address"}],"name":"updateZapContract","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50604051620040873803806200408783398101604081905262000034916200020e565b6001600160a01b0382166200008f5760405162461bcd60e51b815260206004820181905260248201527f436f6e7374616e747320616464726573732063616e6e6f74206265207a65726f604482015260640160405180910390fd5b600180546001600160a01b0319166001600160a01b038416179055620000c6600080516020620040678339815191526000620000f6565b620000d360003362000141565b620000ee600080516020620040678339815191528262000141565b505062000246565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6200014d828262000151565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff166200014d576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001ad3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b80516001600160a01b03811681146200020957600080fd5b919050565b600080604083850312156200022257600080fd5b6200022d83620001f1565b91506200023d60208401620001f1565b90509250929050565b613e1180620002566000396000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c8063751681ca11610167578063a9ed8882116100ce578063e38eb66c11610087578063e38eb66c1461068b578063e89d66a81461069e578063f43d7199146106c1578063f824c566146106e4578063fdb5fefc146106f7578063ffd7d9831461063f57600080fd5b8063a9ed888214610619578063cfa83b0f1461062c578063d2dc0e221461063f578063d547741f14610652578063da31500714610665578063dafe6db01461067857600080fd5b806396adee011161012057806396adee01146105a257806396db06f1146105b5578063a0f1fb11146105c8578063a217fddf146105eb578063a4b3dfc4146105f3578063a702332d1461060657600080fd5b8063751681ca1461053057806377977072146105435780637898e5cd146105565780637ac041ed146105695780637eebde771461057c57806391d148541461058f57600080fd5b8063385892c61161020b578063581c1597116101c4578063581c1597146104895780635a0136391461049c5780635cb7d1f4146104bc5780635ccc5ad4146104e757806361621153146104fa5780636ced8c061461050d57600080fd5b8063385892c6146103f7578063387348821461040a578063470def141461041d578063561fc351146104305780635763dbd01461045357806357c13aaa1461046657600080fd5b80632130f31f1161025d5780632130f31f14610355578063248a9ca314610368578063289220861461038b5780632f2ff15d146103ae57806336568abe146103c15780633737bb22146103d457600080fd5b806301ffc9a71461029a57806305cf450a146102c257806307bd0265146102fa5780630b5484821461031d5780631c6e760414610340575b600080fd5b6102ad6102a8366004613402565b61070a565b60405190151581526020015b60405180910390f35b6102e76102d0366004613441565b600260208190526000918252604090912054900b81565b60405160029190910b81526020016102b9565b61030f600080516020613dbc83398151915281565b6040519081526020016102b9565b6102e761032b366004613441565b60086020526000908152604090205460020b81565b61035361034e36600461346d565b610741565b005b6103536103633660046134a6565b6107cc565b61030f6103763660046134e1565b60009081526020819052604090206001015490565b6102e7610399366004613441565b60076020526000908152604090205460020b81565b6103536103bc3660046134fa565b6109bf565b6103536103cf3660046134fa565b6109e9565b6102e76103e2366004613441565b60096020526000908152604090205460020b81565b61035361040536600461346d565b610a67565b610353610418366004613530565b610ae9565b61035361042b36600461355e565b610ba1565b6102e761043e366004613441565b60066020526000908152604090205460020b81565b610353610461366004613441565b610c53565b6102e7610474366004613441565b60036020526000908152604090205460020b81565b61030f610497366004613441565b610e9e565b6104af6104aa366004613441565b61103b565b6040516102b9919061358c565b6001546104cf906001600160a01b031681565b6040516001600160a01b0390911681526020016102b9565b6103536104f53660046135d3565b6110a6565b6103536105083660046135ff565b611155565b6102e761051b366004613441565b60056020526000908152604090205460020b81565b61035361053e36600461346d565b611225565b6103536105513660046135ff565b6112a7565b61035361056436600461346d565b611368565b61035361057736600461346d565b6113ea565b61035361058a36600461346d565b61146b565b6102ad61059d3660046134fa565b6114ed565b6103536105b036600461346d565b611516565b6103536105c336600461346d565b611597565b6102e76105d6366004613441565b600b6020526000908152604090205460020b81565b61030f600081565b6102ad610601366004613441565b611619565b61035361061436600461346d565b61167d565b6102ad610627366004613441565b6116ff565b61035361063a36600461355e565b6118c8565b61035361064d366004613441565b611940565b6103536106603660046134fa565b611961565b6102ad610673366004613441565b611986565b610353610686366004613660565b611a07565b6103536106993660046135d3565b611c1b565b6102e76106ac366004613441565b60046020526000908152604090205460020b81565b6102e76106cf366004613441565b600a6020526000908152604090205460020b81565b6103536106f236600461368e565b611cca565b610353610705366004613441565b61209b565b60006001600160e01b03198216637965db0b60e01b148061073b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020613dbc833981519152610759816121ab565b610762826121b8565b6001600160a01b038316600081815260066020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f39c3e68e2a6a52a106264d6bb8eb9172b37c359aabe84a3e5a44165be1d53baa91015b60405180910390a3505050565b600080516020613dbc8339815191526107e4816121ab565b6040516376a8e9ff60e11b81526004810185905260248101849052604481018390526001600160a01b0386169063ed51d3fe90606401600060405180830381600087803b15801561083457600080fd5b505af1158015610848573d6000803e3d6000fd5b5050505061085585611619565b151560011461089d5760405162461bcd60e51b815260206004820152600f60248201526e32b0b93710383932b81032b93937b960891b60448201526064015b60405180910390fd5b846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ff91906136df565b336001600160a01b0316866001600160a01b03167f305bc1ca7106255b17dbf66922802940d373f07b2c8810a76cee84700eb8c46c886001600160a01b03166379aeda7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610972573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099691906136df565b61099f8a610e9e565b604080519283526020830191909152015b60405180910390a45050505050565b6000828152602081905260409020600101546109da816121ab565b6109e48383612200565b505050565b6001600160a01b0381163314610a595760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610894565b610a638282612284565b5050565b600080516020613dbc833981519152610a7f816121ab565b610a88826122e9565b6001600160a01b038316600081815260056020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fb76904a8ba51dc05f78444581f265d5e71c3783225c473e9620d4c09799df5bc91016107bf565b600080516020613dbc833981519152610b01816121ab565b60405163088d621d60e31b815262ffffff831660048201526001600160a01b0384169063446b10e890602401600060405180830381600087803b158015610b4757600080fd5b505af1158015610b5b573d6000803e3d6000fd5b505060405162ffffff851681523392506001600160a01b03861691507f8ab763dee50895615d0bb8306cdddbc0c1a6258f62aacbac6edc6be8c14ad833906020016107bf565b600080516020613dbc833981519152610bb9816121ab565b604051630c9590fd60e41b81526001600160a01b03838116600483015284169063c9590fd090602401600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b50506040516001600160a01b038581168252339350861691507f45f9e54d9f5cd84815f0bebc99eab35ed7008a0d9751ccd3c19807c4b331078a906020016107bf565b600080516020613dbc833981519152610c6b816121ab565b816001600160a01b03166370bb45b36040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca657600080fd5b505af1158015610cba573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2091906136df565b336001600160a01b0316836001600160a01b03167f5d0927b601ecc1d0a4bedb898b2beff630177e857cecab540ba9b9136b302626856001600160a01b031663314e61ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db791906136df565b866001600160a01b0316631a536a326040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1991906136df565b876001600160a01b03166379aeda7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7b91906136df565b604080519384526020840192909252908201526060015b60405180910390a45050565b600080610eaa83611619565b9050801515600003610ebf5750600092915050565b6000836001600160a01b03166370cb00df6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610eff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f27919081019061379c565b5190506000846001600160a01b031663a142492d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8e91906136df565b90506000610f9c8383612329565b90506000866001600160a01b031663234c4cce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100291906136df565b9050600080611011848461233c565b9150915060008111611023578161102e565b61102e82600161235e565b9998505050505050505050565b6110436133c8565b816001600160a01b031663cbff66e26040518163ffffffff1660e01b815260040161020060405180830381865afa158015611082573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b919061384e565b600080516020613dbc8339815191526110be816121ab565b604051630f8a517f60e41b8152600481018390526001600160a01b0384169063f8a517f090602401600060405180830381600087803b15801561110057600080fd5b505af1158015611114573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f6c58dea38c1fef4e97173e19196cf983e5a8f566fdf04367343c63b8abaa1be9906020016107bf565b600080516020613dbc83398151915261116d816121ab565b6040516307795f5760e41b81526001600160a01b03861690637795f5709061119d908790879087906004016138df565b600060405180830381600087803b1580156111b757600080fd5b505af11580156111cb573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f08e0badddf13ca7fc84b48e3f0b89b0c276e9ae5e9497643f367fd2f240fdf99868686604051611216939291906138df565b60405180910390a35050505050565b600080516020613dbc83398151915261123d816121ab565b611246826121b8565b6001600160a01b038316600081815260086020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fe796bc4f3ce03bd32fb0e15586b34a308fc7bfa8c3c5485e92cd577b1bb9390a91016107bf565b600080516020613dbc8339815191526112bf816121ab565b604051634bd613c960e11b81526001600160a01b038616906397ac2792906112ef908790879087906004016138df565b600060405180830381600087803b15801561130957600080fd5b505af115801561131d573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f5b48ee2dc08a8c37693631d459c19db8be2f161266f3ae57cda789130f6ed53b868686604051611216939291906138df565b600080516020613dbc833981519152611380816121ab565b611389826121b8565b6001600160a01b038316600081815260076020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f4d5ea40657b0a60f4e1adf5562de4fc7b431b1087121d60e006af1b4dd80700c91016107bf565b600080516020613dbc833981519152611402816121ab565b61140b826121b8565b6001600160a01b0383166000818152600b6020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917e16e8ec2d70d4a15a6124477bef7aee3fd4b10b52f714c937f219ad3d4ecae591016107bf565b600080516020613dbc833981519152611483816121ab565b61148c826121b8565b6001600160a01b038316600081815260096020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fd1c1e360f9477b31cc4bd12a26e42e098d96e90f614e2fcc621dea418ae0dd5f91016107bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020613dbc83398151915261152e816121ab565b611537826121b8565b6001600160a01b038316600081815260026020818152604092839020805462ffffff191662ffffff881617905591519085900b81523392917f2447a43b2c31ed21e468726ba53813b663d414569fdfda6f648a646537d19bff91016107bf565b600080516020613dbc8339815191526115af816121ab565b6115b8826121b8565b6001600160a01b038316600081815260036020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f5d87708daffcb58a78b045d80a978ca2200af1de98d942f0fb5674e08dc14fb091016107bf565b6000816001600160a01b0316638a1966e36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b9190613903565b600080516020613dbc833981519152611695816121ab565b61169e826122e9565b6001600160a01b038316600081815260046020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fc1d8cd1a0ed04005edcfd0819fd55a04044b95ffbca6ad9f9c56bc0d69e0687091016107bf565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611740573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176491906136df565b9050806000036117c95760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420616c6c6f772063616c6c696e67207768656e206c697175696469747960448201526904e6674496420697320360b41b6064820152608401610894565b6118c081600160009054906101000a90046001600160a01b03166001600160a01b031663e3d11ba06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190613920565b600160009054906101000a90046001600160a01b03166001600160a01b031663b16e29806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb9190613920565b61236a565b509392505050565b600080516020613dbc8339815191526118e0816121ab565b6040516324cdbe8360e01b81526001600160a01b0383811660048301528416906324cdbe8390602401600060405180830381600087803b15801561192357600080fd5b505af1158015611937573d6000803e3d6000fd5b50505050505050565b600080516020613dbc833981519152611958816121ab565b610a63826123ed565b60008281526020819052604090206001015461197c816121ab565b6109e48383612284565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119eb91906136df565b9050806000036119fe5750600192915050565b50600092915050565b600080516020613dbc833981519152611a1f816121ab565b6040516338ddeee160e11b8152821515600482015260009081906001600160a01b038616906371bbddc29060240160408051808303816000875af1158015611a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8f919061393d565b91509150846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af591906136df565b336001600160a01b0316866001600160a01b03167f6f039c89811a62a23aa18d16914e04bb7bf86e124afcbf5f81bd141148e4ba7c8786868b6001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f91906136df565b8c6001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf191906136df565b6040805195151586526020860194909452928401919091526060830152608082015260a0016109b0565b600080516020613dbc833981519152611c33816121ab565b6040516302ef42c760e11b8152600481018390526001600160a01b038416906305de858e90602401600060405180830381600087803b158015611c7557600080fd5b505af1158015611c89573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f8d35dc65727d53b4f7a4bdebeaa6c8b7b6ee8e6d772e6c35a4bbc087aa19e7ac906020016107bf565b600080516020613dbc833981519152611ce2816121ab565b6001600160a01b038581166000818152600a6020526040808220549051631695590760e31b8152871515600482015260029190910b60248201526044810192909252306064830152918291829188169063b4aac83890608401606060405180830381865afa158015611d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7c919061396c565b92509250925082611ddb5760405162461bcd60e51b815260206004820152602360248201527f63757272656e7420636f6e646974696f6e206e6f7420616c6c6f772072657363604482015262616c6560e81b6064820152608401610894565b611de6888787612556565b6000611f40896001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4d91906136df565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3d11ba06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec49190613920565b600160009054906101000a90046001600160a01b03166001600160a01b031663b16e29806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b9190613920565b6126db565b50506001600160a01b038a166000908152600b6020526040902054909150611f6b9060020b876139cf565b60020b8160020b13158015611fab57506001600160a01b0389166000908152600b6020526040902054611fa19060020b876139f4565b60020b8160020b12155b611ff75760405162461bcd60e51b815260206004820152601b60248201527f6f7574206f66207469636b20746f6c6572616e63652072616e676500000000006044820152606401610894565b60405163646ea14160e11b8152600284810b600483015283900b60248201526001600160a01b038a169063c8dd428290604401600060405180830381600087803b15801561204457600080fd5b505af1158015612058573d6000803e3d6000fd5b505050506001600160a01b0389166000908152600a60205260409020805462ffffff191662ffffff8316179055612090898484612711565b505050505050505050565b600080516020613dbc8339815191526120b3816121ab565b816001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120ee57600080fd5b505af1158015612102573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612144573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216891906136df565b336001600160a01b0384167f024aa4dfbe44229e3ca86f829e80c3a1b19d5e5d39962eae78b417b80517845361219d86610e9e565b604051908152602001610e92565b6121b58133612945565b50565b60008160020b12156121b55760405162461bcd60e51b81526020600482015260116024820152700696e707574206c657373207468616e203607c1b6044820152606401610894565b61220a82826114ed565b610a63576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556122403390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61228e82826114ed565b15610a63576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60018160020b136121b55760405162461bcd60e51b815260206004820152600a602482015269696e707574203c3d203160b01b6044820152606401610894565b60006123358284613a19565b9392505050565b600080612349848461299e565b915061235584846129aa565b90509250929050565b60006123358284613a2c565b600080600061237a8686866129b6565b5050509150506000806000806123908a89612a1d565b50509450945050935093508160020b8560020b136123b9576000849650965050505050506123e5565b8060020b8560020b12156123d957600160009650965050505050506123e5565b50600095509093505050505b935093915050565b6000816001600160a01b031663eca8d0016040518163ffffffff1660e01b8152600401602060405180830381865afa15801561242d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245191906136df565b9050816001600160a01b031663abaa99166040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561248e57600080fd5b505af11580156124a2573d6000803e3d6000fd5b505050506000826001600160a01b031663eca8d0016040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250a91906136df565b9050336001600160a01b0384167f5b9d56b28a7cde78f80ab41749028c18864c008e0e3722985c63ea258111b7eb6125428585612329565b6040805191825260208201869052016107bf565b600080600061259c866001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b925092509250856001600160a01b03167f7a73c0af961631015e379691e5a22dadd4d0fa4c85b6c6c5b36af570aa537aa086886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561260c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126309190613a3f565b6001600160a01b038a16600090815260046020908152604080832054600583528184205460068452828520546007855283862054600a8652958490205484519815158952600297880b9589019590955291860b87840152850b6060870152840b608086015291830b60a0850152820b60c084015288820b60e084015287820b61010084015285820b6101208401529086900b61014083015251908190036101600190a2505050505050565b60008060006126eb8686866129b6565b509195506126ff9250889150869050612a1d565b50979b919a5098509650505050505050565b6000612754846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b50509050336001600160a01b0316846001600160a01b03167fc6d664f645086a1c833d57b521e95bb8362087047154cdaf636f6228c6940ee7866001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ef91906136df565b876001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285191906136df565b886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561288f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b39190613a3f565b6001600160a01b038a16600090815260026020818152604080842054600383528185205460088452828620546009855295839020548351998a529389019790975294830b9087015289820b606087015292810b608086015292830b60a0850152820b60c0840152810b60e083015287810b61010083015286900b6101208201526101400160405180910390a350505050565b61294f82826114ed565b610a635761295c81612af4565b612967836020612b06565b604051602001612978929190613a80565b60408051601f198184030181529082905262461bcd60e51b825261089491600401613af5565b60006123358284613b3e565b60006123358284613b52565b6000806000806000806000806129cc8b8a612a1d565b505050509250925092506129e28a848484612ca2565b97506129ed88612d2c565b909192939495509091929394509091929350809750819850829950839a5050505050505050939792965093509350565b6000806000806000806000876001600160a01b03166399fbab888a6040518263ffffffff1660e01b8152600401612a5691815260200190565b61018060405180830381865afa158015612a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a989190613b91565b909192939495969798999a509091929394959697989950909192935090919250909150905050809750819850829950839a50849b505050505050612adb84612fa8565b9150612ae683612fa8565b905092959891949750929550565b606061073b6001600160a01b03831660145b60606000612b15836002613c72565b612b20906002613a2c565b67ffffffffffffffff811115612b3857612b386136f8565b6040519080825280601f01601f191660200182016040528015612b62576020820181803683370190505b509050600360fc1b81600081518110612b7d57612b7d613c89565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612bac57612bac613c89565b60200101906001600160f81b031916908160001a9053506000612bd0846002613c72565b612bdb906001613a2c565b90505b6001811115612c53576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612c0f57612c0f613c89565b1a60f81b828281518110612c2557612c25613c89565b60200101906001600160f81b031916908160001a90535060049490941c93612c4c81613c9f565b9050612bde565b5083156123355760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610894565b604051630b4c774160e11b81526001600160a01b038481166004830152838116602483015262ffffff8316604483015260009190861690631698ee8290606401602060405180830381865afa158015612cff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d239190613920565b95945050505050565b6000806000806000806000876001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d999190613cc8565b505060408051630dfe168160e01b8152905194995094975050506001600160a01b038b1692630dfe168192600480830193506020928290030181865afa158015612de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0b9190613920565b9650876001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6f9190613920565b9550876001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed39190613d60565b9450866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3791906136df565b9150856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906136df565b9050919395979092949650565b60008060008360020b12612fbf578260020b612fcc565b8260020b612fcc90613d7d565b9050612fdb620d89e719613d99565b60020b8111156130115760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610894565b60008160011660000361302857600160801b61303a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615613079576080613074826ffff97272373d413259a46990580e213a613c72565b901c90505b60048216156130a357608061309e826ffff2e50f5f656932ef12357cf3c7fdcc613c72565b901c90505b60088216156130cd5760806130c8826fffe5caca7e10e4e61c3624eaa0941cd0613c72565b901c90505b60108216156130f75760806130f2826fffcb9843d60f6159c9db58835c926644613c72565b901c90505b602082161561312157608061311c826fff973b41fa98c081472e6896dfb254c0613c72565b901c90505b604082161561314b576080613146826fff2ea16466c96a3843ec78b326b52861613c72565b901c90505b6080821615613175576080613170826ffe5dee046a99a2a811c461f1969c3053613c72565b901c90505b6101008216156131a057608061319b826ffcbe86c7900a88aedcffc83b479aa3a4613c72565b901c90505b6102008216156131cb5760806131c6826ff987a7253ac413176f2b074cf7815e54613c72565b901c90505b6104008216156131f65760806131f1826ff3392b0822b70005940c7a398e4b70f3613c72565b901c90505b61080082161561322157608061321c826fe7159475a2c29b7443b29c7fa6e889d9613c72565b901c90505b61100082161561324c576080613247826fd097f3bdfd2022b8845ad8f792aa5825613c72565b901c90505b612000821615613277576080613272826fa9f746462d870fdf8a65dc1f90e061e5613c72565b901c90505b6140008216156132a257608061329d826f70d869a156d2a1b890bb3df62baf32f7613c72565b901c90505b6180008216156132cd5760806132c8826f31be135f97d08fd981231505542fcfa6613c72565b901c90505b620100008216156132f95760806132f4826f09aa508b5b7a84e1c677de54f3e99bc9613c72565b901c90505b6202000082161561332457608061331f826e5d6af8dedb81196699c329225ee604613c72565b901c90505b6204000082161561334e576080613349826d2216e584f5fa1ea926041bedfe98613c72565b901c90505b62080000821615613376576080613371826b048a170391f7dc42444e8fa2613c72565b901c90505b60008460020b13156133915761338e81600019613b3e565b90505b6133a064010000000082613b52565b156133ac5760016133af565b60005b6133c09060ff16602083901c613a2c565b949350505050565b6040518061010001604052806008905b60408051808201909152600080825260208201528152602001906001900390816133d85790505090565b60006020828403121561341457600080fd5b81356001600160e01b03198116811461233557600080fd5b6001600160a01b03811681146121b557600080fd5b60006020828403121561345357600080fd5b81356123358161342c565b8060020b81146121b557600080fd5b6000806040838503121561348057600080fd5b823561348b8161342c565b9150602083013561349b8161345e565b809150509250929050565b600080600080608085870312156134bc57600080fd5b84356134c78161342c565b966020860135965060408601359560600135945092505050565b6000602082840312156134f357600080fd5b5035919050565b6000806040838503121561350d57600080fd5b82359150602083013561349b8161342c565b62ffffff811681146121b557600080fd5b6000806040838503121561354357600080fd5b823561354e8161342c565b9150602083013561349b8161351f565b6000806040838503121561357157600080fd5b823561357c8161342c565b9150602083013561349b8161342c565b6102008101818360005b60088110156135ca57815180516001600160a01b031684526020908101518185015260409093019290910190600101613596565b50505092915050565b600080604083850312156135e657600080fd5b82356135f18161342c565b946020939093013593505050565b6000806000806080858703121561361557600080fd5b84356136208161342c565b93506020850135925060408501356136378161342c565b915060608501356136478161351f565b939692955090935050565b80151581146121b557600080fd5b6000806040838503121561367357600080fd5b823561367e8161342c565b9150602083013561349b81613652565b600080600080608085870312156136a457600080fd5b84356136af8161342c565b935060208501356136bf8161342c565b925060408501356136cf81613652565b915060608501356136478161345e565b6000602082840312156136f157600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613732576137326136f8565b60405290565b6040805190810167ffffffffffffffff81118282101715613732576137326136f8565b604051601f8201601f1916810167ffffffffffffffff81118282101715613784576137846136f8565b604052919050565b80516137978161342c565b919050565b600060208083850312156137af57600080fd5b825167ffffffffffffffff808211156137c757600080fd5b818501915085601f8301126137db57600080fd5b8151818111156137ed576137ed6136f8565b8060051b91506137fe84830161375b565b818152918301840191848101908884111561381857600080fd5b938501935b8385101561384257845192506138328361342c565b828252938501939085019061381d565b98975050505050505050565b600061020080838503121561386257600080fd5b83601f84011261387157600080fd5b61387961370e565b90830190808583111561388b57600080fd5b845b838110156138d557604081880312156138a65760008081fd5b6138ae613738565b81516138b98161342c565b815260208281015181830152908452929092019160400161388d565b5095945050505050565b9283526001600160a01b0391909116602083015262ffffff16604082015260600190565b60006020828403121561391557600080fd5b815161233581613652565b60006020828403121561393257600080fd5b81516123358161342c565b6000806040838503121561395057600080fd5b505080516020909101519092909150565b80516137978161345e565b60008060006060848603121561398157600080fd5b835161398c81613652565b602085015190935061399d8161345e565b60408501519092506139ae8161345e565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600281810b9083900b01627fffff8113627fffff198212171561073b5761073b6139b9565b600282810b9082900b03627fffff198112627fffff8213171561073b5761073b6139b9565b8181038181111561073b5761073b6139b9565b8082018082111561073b5761073b6139b9565b600060208284031215613a5157600080fd5b81516123358161345e565b60005b83811015613a77578181015183820152602001613a5f565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613ab8816017850160208801613a5c565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613ae9816028840160208801613a5c565b01602801949350505050565b6020815260008251806020840152613b14816040850160208701613a5c565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601260045260246000fd5b600082613b4d57613b4d613b28565b500490565b600082613b6157613b61613b28565b500690565b80516137978161351f565b80516fffffffffffffffffffffffffffffffff8116811461379757600080fd5b6000806000806000806000806000806000806101808d8f031215613bb457600080fd5b8c516bffffffffffffffffffffffff81168114613bd057600080fd5b9b50613bde60208e0161378c565b9a50613bec60408e0161378c565b9950613bfa60608e0161378c565b9850613c0860808e01613b66565b9750613c1660a08e01613961565b9650613c2460c08e01613961565b9550613c3260e08e01613b71565b94506101008d015193506101208d01519250613c516101408e01613b71565b9150613c606101608e01613b71565b90509295989b509295989b509295989b565b808202811582820484141761073b5761073b6139b9565b634e487b7160e01b600052603260045260246000fd5b600081613cae57613cae6139b9565b506000190190565b805161ffff8116811461379757600080fd5b600080600080600080600060e0888a031215613ce357600080fd5b8751613cee8161342c565b6020890151909750613cff8161345e565b9550613d0d60408901613cb6565b9450613d1b60608901613cb6565b9350613d2960808901613cb6565b925060a088015160ff81168114613d3f57600080fd5b60c0890151909250613d5081613652565b8091505092959891949750929550565b600060208284031215613d7257600080fd5b81516123358161351f565b6000600160ff1b8201613d9257613d926139b9565b5060000390565b60008160020b627fffff198103613db257613db26139b9565b6000039291505056fed8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63a264697066735822122002aab7d88388544ece71408ef7d0f4e7641136246f568cdb84717516967d175264736f6c63430008120033d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63000000000000000000000000d6868650ed58e20d09ccd2fecee8e5e04feb9a10000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102955760003560e01c8063751681ca11610167578063a9ed8882116100ce578063e38eb66c11610087578063e38eb66c1461068b578063e89d66a81461069e578063f43d7199146106c1578063f824c566146106e4578063fdb5fefc146106f7578063ffd7d9831461063f57600080fd5b8063a9ed888214610619578063cfa83b0f1461062c578063d2dc0e221461063f578063d547741f14610652578063da31500714610665578063dafe6db01461067857600080fd5b806396adee011161012057806396adee01146105a257806396db06f1146105b5578063a0f1fb11146105c8578063a217fddf146105eb578063a4b3dfc4146105f3578063a702332d1461060657600080fd5b8063751681ca1461053057806377977072146105435780637898e5cd146105565780637ac041ed146105695780637eebde771461057c57806391d148541461058f57600080fd5b8063385892c61161020b578063581c1597116101c4578063581c1597146104895780635a0136391461049c5780635cb7d1f4146104bc5780635ccc5ad4146104e757806361621153146104fa5780636ced8c061461050d57600080fd5b8063385892c6146103f7578063387348821461040a578063470def141461041d578063561fc351146104305780635763dbd01461045357806357c13aaa1461046657600080fd5b80632130f31f1161025d5780632130f31f14610355578063248a9ca314610368578063289220861461038b5780632f2ff15d146103ae57806336568abe146103c15780633737bb22146103d457600080fd5b806301ffc9a71461029a57806305cf450a146102c257806307bd0265146102fa5780630b5484821461031d5780631c6e760414610340575b600080fd5b6102ad6102a8366004613402565b61070a565b60405190151581526020015b60405180910390f35b6102e76102d0366004613441565b600260208190526000918252604090912054900b81565b60405160029190910b81526020016102b9565b61030f600080516020613dbc83398151915281565b6040519081526020016102b9565b6102e761032b366004613441565b60086020526000908152604090205460020b81565b61035361034e36600461346d565b610741565b005b6103536103633660046134a6565b6107cc565b61030f6103763660046134e1565b60009081526020819052604090206001015490565b6102e7610399366004613441565b60076020526000908152604090205460020b81565b6103536103bc3660046134fa565b6109bf565b6103536103cf3660046134fa565b6109e9565b6102e76103e2366004613441565b60096020526000908152604090205460020b81565b61035361040536600461346d565b610a67565b610353610418366004613530565b610ae9565b61035361042b36600461355e565b610ba1565b6102e761043e366004613441565b60066020526000908152604090205460020b81565b610353610461366004613441565b610c53565b6102e7610474366004613441565b60036020526000908152604090205460020b81565b61030f610497366004613441565b610e9e565b6104af6104aa366004613441565b61103b565b6040516102b9919061358c565b6001546104cf906001600160a01b031681565b6040516001600160a01b0390911681526020016102b9565b6103536104f53660046135d3565b6110a6565b6103536105083660046135ff565b611155565b6102e761051b366004613441565b60056020526000908152604090205460020b81565b61035361053e36600461346d565b611225565b6103536105513660046135ff565b6112a7565b61035361056436600461346d565b611368565b61035361057736600461346d565b6113ea565b61035361058a36600461346d565b61146b565b6102ad61059d3660046134fa565b6114ed565b6103536105b036600461346d565b611516565b6103536105c336600461346d565b611597565b6102e76105d6366004613441565b600b6020526000908152604090205460020b81565b61030f600081565b6102ad610601366004613441565b611619565b61035361061436600461346d565b61167d565b6102ad610627366004613441565b6116ff565b61035361063a36600461355e565b6118c8565b61035361064d366004613441565b611940565b6103536106603660046134fa565b611961565b6102ad610673366004613441565b611986565b610353610686366004613660565b611a07565b6103536106993660046135d3565b611c1b565b6102e76106ac366004613441565b60046020526000908152604090205460020b81565b6102e76106cf366004613441565b600a6020526000908152604090205460020b81565b6103536106f236600461368e565b611cca565b610353610705366004613441565b61209b565b60006001600160e01b03198216637965db0b60e01b148061073b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020613dbc833981519152610759816121ab565b610762826121b8565b6001600160a01b038316600081815260066020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f39c3e68e2a6a52a106264d6bb8eb9172b37c359aabe84a3e5a44165be1d53baa91015b60405180910390a3505050565b600080516020613dbc8339815191526107e4816121ab565b6040516376a8e9ff60e11b81526004810185905260248101849052604481018390526001600160a01b0386169063ed51d3fe90606401600060405180830381600087803b15801561083457600080fd5b505af1158015610848573d6000803e3d6000fd5b5050505061085585611619565b151560011461089d5760405162461bcd60e51b815260206004820152600f60248201526e32b0b93710383932b81032b93937b960891b60448201526064015b60405180910390fd5b846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ff91906136df565b336001600160a01b0316866001600160a01b03167f305bc1ca7106255b17dbf66922802940d373f07b2c8810a76cee84700eb8c46c886001600160a01b03166379aeda7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610972573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099691906136df565b61099f8a610e9e565b604080519283526020830191909152015b60405180910390a45050505050565b6000828152602081905260409020600101546109da816121ab565b6109e48383612200565b505050565b6001600160a01b0381163314610a595760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610894565b610a638282612284565b5050565b600080516020613dbc833981519152610a7f816121ab565b610a88826122e9565b6001600160a01b038316600081815260056020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fb76904a8ba51dc05f78444581f265d5e71c3783225c473e9620d4c09799df5bc91016107bf565b600080516020613dbc833981519152610b01816121ab565b60405163088d621d60e31b815262ffffff831660048201526001600160a01b0384169063446b10e890602401600060405180830381600087803b158015610b4757600080fd5b505af1158015610b5b573d6000803e3d6000fd5b505060405162ffffff851681523392506001600160a01b03861691507f8ab763dee50895615d0bb8306cdddbc0c1a6258f62aacbac6edc6be8c14ad833906020016107bf565b600080516020613dbc833981519152610bb9816121ab565b604051630c9590fd60e41b81526001600160a01b03838116600483015284169063c9590fd090602401600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b50506040516001600160a01b038581168252339350861691507f45f9e54d9f5cd84815f0bebc99eab35ed7008a0d9751ccd3c19807c4b331078a906020016107bf565b600080516020613dbc833981519152610c6b816121ab565b816001600160a01b03166370bb45b36040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca657600080fd5b505af1158015610cba573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2091906136df565b336001600160a01b0316836001600160a01b03167f5d0927b601ecc1d0a4bedb898b2beff630177e857cecab540ba9b9136b302626856001600160a01b031663314e61ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db791906136df565b866001600160a01b0316631a536a326040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1991906136df565b876001600160a01b03166379aeda7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7b91906136df565b604080519384526020840192909252908201526060015b60405180910390a45050565b600080610eaa83611619565b9050801515600003610ebf5750600092915050565b6000836001600160a01b03166370cb00df6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610eff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f27919081019061379c565b5190506000846001600160a01b031663a142492d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8e91906136df565b90506000610f9c8383612329565b90506000866001600160a01b031663234c4cce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100291906136df565b9050600080611011848461233c565b9150915060008111611023578161102e565b61102e82600161235e565b9998505050505050505050565b6110436133c8565b816001600160a01b031663cbff66e26040518163ffffffff1660e01b815260040161020060405180830381865afa158015611082573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b919061384e565b600080516020613dbc8339815191526110be816121ab565b604051630f8a517f60e41b8152600481018390526001600160a01b0384169063f8a517f090602401600060405180830381600087803b15801561110057600080fd5b505af1158015611114573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f6c58dea38c1fef4e97173e19196cf983e5a8f566fdf04367343c63b8abaa1be9906020016107bf565b600080516020613dbc83398151915261116d816121ab565b6040516307795f5760e41b81526001600160a01b03861690637795f5709061119d908790879087906004016138df565b600060405180830381600087803b1580156111b757600080fd5b505af11580156111cb573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f08e0badddf13ca7fc84b48e3f0b89b0c276e9ae5e9497643f367fd2f240fdf99868686604051611216939291906138df565b60405180910390a35050505050565b600080516020613dbc83398151915261123d816121ab565b611246826121b8565b6001600160a01b038316600081815260086020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fe796bc4f3ce03bd32fb0e15586b34a308fc7bfa8c3c5485e92cd577b1bb9390a91016107bf565b600080516020613dbc8339815191526112bf816121ab565b604051634bd613c960e11b81526001600160a01b038616906397ac2792906112ef908790879087906004016138df565b600060405180830381600087803b15801561130957600080fd5b505af115801561131d573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f5b48ee2dc08a8c37693631d459c19db8be2f161266f3ae57cda789130f6ed53b868686604051611216939291906138df565b600080516020613dbc833981519152611380816121ab565b611389826121b8565b6001600160a01b038316600081815260076020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f4d5ea40657b0a60f4e1adf5562de4fc7b431b1087121d60e006af1b4dd80700c91016107bf565b600080516020613dbc833981519152611402816121ab565b61140b826121b8565b6001600160a01b0383166000818152600b6020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917e16e8ec2d70d4a15a6124477bef7aee3fd4b10b52f714c937f219ad3d4ecae591016107bf565b600080516020613dbc833981519152611483816121ab565b61148c826121b8565b6001600160a01b038316600081815260096020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fd1c1e360f9477b31cc4bd12a26e42e098d96e90f614e2fcc621dea418ae0dd5f91016107bf565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020613dbc83398151915261152e816121ab565b611537826121b8565b6001600160a01b038316600081815260026020818152604092839020805462ffffff191662ffffff881617905591519085900b81523392917f2447a43b2c31ed21e468726ba53813b663d414569fdfda6f648a646537d19bff91016107bf565b600080516020613dbc8339815191526115af816121ab565b6115b8826121b8565b6001600160a01b038316600081815260036020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f5d87708daffcb58a78b045d80a978ca2200af1de98d942f0fb5674e08dc14fb091016107bf565b6000816001600160a01b0316638a1966e36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b9190613903565b600080516020613dbc833981519152611695816121ab565b61169e826122e9565b6001600160a01b038316600081815260046020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fc1d8cd1a0ed04005edcfd0819fd55a04044b95ffbca6ad9f9c56bc0d69e0687091016107bf565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611740573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176491906136df565b9050806000036117c95760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420616c6c6f772063616c6c696e67207768656e206c697175696469747960448201526904e6674496420697320360b41b6064820152608401610894565b6118c081600160009054906101000a90046001600160a01b03166001600160a01b031663e3d11ba06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118449190613920565b600160009054906101000a90046001600160a01b03166001600160a01b031663b16e29806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb9190613920565b61236a565b509392505050565b600080516020613dbc8339815191526118e0816121ab565b6040516324cdbe8360e01b81526001600160a01b0383811660048301528416906324cdbe8390602401600060405180830381600087803b15801561192357600080fd5b505af1158015611937573d6000803e3d6000fd5b50505050505050565b600080516020613dbc833981519152611958816121ab565b610a63826123ed565b60008281526020819052604090206001015461197c816121ab565b6109e48383612284565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119eb91906136df565b9050806000036119fe5750600192915050565b50600092915050565b600080516020613dbc833981519152611a1f816121ab565b6040516338ddeee160e11b8152821515600482015260009081906001600160a01b038616906371bbddc29060240160408051808303816000875af1158015611a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8f919061393d565b91509150846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af591906136df565b336001600160a01b0316866001600160a01b03167f6f039c89811a62a23aa18d16914e04bb7bf86e124afcbf5f81bd141148e4ba7c8786868b6001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f91906136df565b8c6001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf191906136df565b6040805195151586526020860194909452928401919091526060830152608082015260a0016109b0565b600080516020613dbc833981519152611c33816121ab565b6040516302ef42c760e11b8152600481018390526001600160a01b038416906305de858e90602401600060405180830381600087803b158015611c7557600080fd5b505af1158015611c89573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f8d35dc65727d53b4f7a4bdebeaa6c8b7b6ee8e6d772e6c35a4bbc087aa19e7ac906020016107bf565b600080516020613dbc833981519152611ce2816121ab565b6001600160a01b038581166000818152600a6020526040808220549051631695590760e31b8152871515600482015260029190910b60248201526044810192909252306064830152918291829188169063b4aac83890608401606060405180830381865afa158015611d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7c919061396c565b92509250925082611ddb5760405162461bcd60e51b815260206004820152602360248201527f63757272656e7420636f6e646974696f6e206e6f7420616c6c6f772072657363604482015262616c6560e81b6064820152608401610894565b611de6888787612556565b6000611f40896001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4d91906136df565b600160009054906101000a90046001600160a01b03166001600160a01b031663e3d11ba06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec49190613920565b600160009054906101000a90046001600160a01b03166001600160a01b031663b16e29806040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b9190613920565b6126db565b50506001600160a01b038a166000908152600b6020526040902054909150611f6b9060020b876139cf565b60020b8160020b13158015611fab57506001600160a01b0389166000908152600b6020526040902054611fa19060020b876139f4565b60020b8160020b12155b611ff75760405162461bcd60e51b815260206004820152601b60248201527f6f7574206f66207469636b20746f6c6572616e63652072616e676500000000006044820152606401610894565b60405163646ea14160e11b8152600284810b600483015283900b60248201526001600160a01b038a169063c8dd428290604401600060405180830381600087803b15801561204457600080fd5b505af1158015612058573d6000803e3d6000fd5b505050506001600160a01b0389166000908152600a60205260409020805462ffffff191662ffffff8316179055612090898484612711565b505050505050505050565b600080516020613dbc8339815191526120b3816121ab565b816001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120ee57600080fd5b505af1158015612102573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612144573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216891906136df565b336001600160a01b0384167f024aa4dfbe44229e3ca86f829e80c3a1b19d5e5d39962eae78b417b80517845361219d86610e9e565b604051908152602001610e92565b6121b58133612945565b50565b60008160020b12156121b55760405162461bcd60e51b81526020600482015260116024820152700696e707574206c657373207468616e203607c1b6044820152606401610894565b61220a82826114ed565b610a63576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556122403390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61228e82826114ed565b15610a63576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60018160020b136121b55760405162461bcd60e51b815260206004820152600a602482015269696e707574203c3d203160b01b6044820152606401610894565b60006123358284613a19565b9392505050565b600080612349848461299e565b915061235584846129aa565b90509250929050565b60006123358284613a2c565b600080600061237a8686866129b6565b5050509150506000806000806123908a89612a1d565b50509450945050935093508160020b8560020b136123b9576000849650965050505050506123e5565b8060020b8560020b12156123d957600160009650965050505050506123e5565b50600095509093505050505b935093915050565b6000816001600160a01b031663eca8d0016040518163ffffffff1660e01b8152600401602060405180830381865afa15801561242d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245191906136df565b9050816001600160a01b031663abaa99166040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561248e57600080fd5b505af11580156124a2573d6000803e3d6000fd5b505050506000826001600160a01b031663eca8d0016040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250a91906136df565b9050336001600160a01b0384167f5b9d56b28a7cde78f80ab41749028c18864c008e0e3722985c63ea258111b7eb6125428585612329565b6040805191825260208201869052016107bf565b600080600061259c866001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b925092509250856001600160a01b03167f7a73c0af961631015e379691e5a22dadd4d0fa4c85b6c6c5b36af570aa537aa086886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561260c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126309190613a3f565b6001600160a01b038a16600090815260046020908152604080832054600583528184205460068452828520546007855283862054600a8652958490205484519815158952600297880b9589019590955291860b87840152850b6060870152840b608086015291830b60a0850152820b60c084015288820b60e084015287820b61010084015285820b6101208401529086900b61014083015251908190036101600190a2505050505050565b60008060006126eb8686866129b6565b509195506126ff9250889150869050612a1d565b50979b919a5098509650505050505050565b6000612754846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e29573d6000803e3d6000fd5b50509050336001600160a01b0316846001600160a01b03167fc6d664f645086a1c833d57b521e95bb8362087047154cdaf636f6228c6940ee7866001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ef91906136df565b876001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285191906136df565b886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561288f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b39190613a3f565b6001600160a01b038a16600090815260026020818152604080842054600383528185205460088452828620546009855295839020548351998a529389019790975294830b9087015289820b606087015292810b608086015292830b60a0850152820b60c0840152810b60e083015287810b61010083015286900b6101208201526101400160405180910390a350505050565b61294f82826114ed565b610a635761295c81612af4565b612967836020612b06565b604051602001612978929190613a80565b60408051601f198184030181529082905262461bcd60e51b825261089491600401613af5565b60006123358284613b3e565b60006123358284613b52565b6000806000806000806000806129cc8b8a612a1d565b505050509250925092506129e28a848484612ca2565b97506129ed88612d2c565b909192939495509091929394509091929350809750819850829950839a5050505050505050939792965093509350565b6000806000806000806000876001600160a01b03166399fbab888a6040518263ffffffff1660e01b8152600401612a5691815260200190565b61018060405180830381865afa158015612a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a989190613b91565b909192939495969798999a509091929394959697989950909192935090919250909150905050809750819850829950839a50849b505050505050612adb84612fa8565b9150612ae683612fa8565b905092959891949750929550565b606061073b6001600160a01b03831660145b60606000612b15836002613c72565b612b20906002613a2c565b67ffffffffffffffff811115612b3857612b386136f8565b6040519080825280601f01601f191660200182016040528015612b62576020820181803683370190505b509050600360fc1b81600081518110612b7d57612b7d613c89565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612bac57612bac613c89565b60200101906001600160f81b031916908160001a9053506000612bd0846002613c72565b612bdb906001613a2c565b90505b6001811115612c53576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612c0f57612c0f613c89565b1a60f81b828281518110612c2557612c25613c89565b60200101906001600160f81b031916908160001a90535060049490941c93612c4c81613c9f565b9050612bde565b5083156123355760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610894565b604051630b4c774160e11b81526001600160a01b038481166004830152838116602483015262ffffff8316604483015260009190861690631698ee8290606401602060405180830381865afa158015612cff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d239190613920565b95945050505050565b6000806000806000806000876001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612d75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d999190613cc8565b505060408051630dfe168160e01b8152905194995094975050506001600160a01b038b1692630dfe168192600480830193506020928290030181865afa158015612de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0b9190613920565b9650876001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6f9190613920565b9550876001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed39190613d60565b9450866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3791906136df565b9150856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b91906136df565b9050919395979092949650565b60008060008360020b12612fbf578260020b612fcc565b8260020b612fcc90613d7d565b9050612fdb620d89e719613d99565b60020b8111156130115760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610894565b60008160011660000361302857600160801b61303a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615613079576080613074826ffff97272373d413259a46990580e213a613c72565b901c90505b60048216156130a357608061309e826ffff2e50f5f656932ef12357cf3c7fdcc613c72565b901c90505b60088216156130cd5760806130c8826fffe5caca7e10e4e61c3624eaa0941cd0613c72565b901c90505b60108216156130f75760806130f2826fffcb9843d60f6159c9db58835c926644613c72565b901c90505b602082161561312157608061311c826fff973b41fa98c081472e6896dfb254c0613c72565b901c90505b604082161561314b576080613146826fff2ea16466c96a3843ec78b326b52861613c72565b901c90505b6080821615613175576080613170826ffe5dee046a99a2a811c461f1969c3053613c72565b901c90505b6101008216156131a057608061319b826ffcbe86c7900a88aedcffc83b479aa3a4613c72565b901c90505b6102008216156131cb5760806131c6826ff987a7253ac413176f2b074cf7815e54613c72565b901c90505b6104008216156131f65760806131f1826ff3392b0822b70005940c7a398e4b70f3613c72565b901c90505b61080082161561322157608061321c826fe7159475a2c29b7443b29c7fa6e889d9613c72565b901c90505b61100082161561324c576080613247826fd097f3bdfd2022b8845ad8f792aa5825613c72565b901c90505b612000821615613277576080613272826fa9f746462d870fdf8a65dc1f90e061e5613c72565b901c90505b6140008216156132a257608061329d826f70d869a156d2a1b890bb3df62baf32f7613c72565b901c90505b6180008216156132cd5760806132c8826f31be135f97d08fd981231505542fcfa6613c72565b901c90505b620100008216156132f95760806132f4826f09aa508b5b7a84e1c677de54f3e99bc9613c72565b901c90505b6202000082161561332457608061331f826e5d6af8dedb81196699c329225ee604613c72565b901c90505b6204000082161561334e576080613349826d2216e584f5fa1ea926041bedfe98613c72565b901c90505b62080000821615613376576080613371826b048a170391f7dc42444e8fa2613c72565b901c90505b60008460020b13156133915761338e81600019613b3e565b90505b6133a064010000000082613b52565b156133ac5760016133af565b60005b6133c09060ff16602083901c613a2c565b949350505050565b6040518061010001604052806008905b60408051808201909152600080825260208201528152602001906001900390816133d85790505090565b60006020828403121561341457600080fd5b81356001600160e01b03198116811461233557600080fd5b6001600160a01b03811681146121b557600080fd5b60006020828403121561345357600080fd5b81356123358161342c565b8060020b81146121b557600080fd5b6000806040838503121561348057600080fd5b823561348b8161342c565b9150602083013561349b8161345e565b809150509250929050565b600080600080608085870312156134bc57600080fd5b84356134c78161342c565b966020860135965060408601359560600135945092505050565b6000602082840312156134f357600080fd5b5035919050565b6000806040838503121561350d57600080fd5b82359150602083013561349b8161342c565b62ffffff811681146121b557600080fd5b6000806040838503121561354357600080fd5b823561354e8161342c565b9150602083013561349b8161351f565b6000806040838503121561357157600080fd5b823561357c8161342c565b9150602083013561349b8161342c565b6102008101818360005b60088110156135ca57815180516001600160a01b031684526020908101518185015260409093019290910190600101613596565b50505092915050565b600080604083850312156135e657600080fd5b82356135f18161342c565b946020939093013593505050565b6000806000806080858703121561361557600080fd5b84356136208161342c565b93506020850135925060408501356136378161342c565b915060608501356136478161351f565b939692955090935050565b80151581146121b557600080fd5b6000806040838503121561367357600080fd5b823561367e8161342c565b9150602083013561349b81613652565b600080600080608085870312156136a457600080fd5b84356136af8161342c565b935060208501356136bf8161342c565b925060408501356136cf81613652565b915060608501356136478161345e565b6000602082840312156136f157600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613732576137326136f8565b60405290565b6040805190810167ffffffffffffffff81118282101715613732576137326136f8565b604051601f8201601f1916810167ffffffffffffffff81118282101715613784576137846136f8565b604052919050565b80516137978161342c565b919050565b600060208083850312156137af57600080fd5b825167ffffffffffffffff808211156137c757600080fd5b818501915085601f8301126137db57600080fd5b8151818111156137ed576137ed6136f8565b8060051b91506137fe84830161375b565b818152918301840191848101908884111561381857600080fd5b938501935b8385101561384257845192506138328361342c565b828252938501939085019061381d565b98975050505050505050565b600061020080838503121561386257600080fd5b83601f84011261387157600080fd5b61387961370e565b90830190808583111561388b57600080fd5b845b838110156138d557604081880312156138a65760008081fd5b6138ae613738565b81516138b98161342c565b815260208281015181830152908452929092019160400161388d565b5095945050505050565b9283526001600160a01b0391909116602083015262ffffff16604082015260600190565b60006020828403121561391557600080fd5b815161233581613652565b60006020828403121561393257600080fd5b81516123358161342c565b6000806040838503121561395057600080fd5b505080516020909101519092909150565b80516137978161345e565b60008060006060848603121561398157600080fd5b835161398c81613652565b602085015190935061399d8161345e565b60408501519092506139ae8161345e565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600281810b9083900b01627fffff8113627fffff198212171561073b5761073b6139b9565b600282810b9082900b03627fffff198112627fffff8213171561073b5761073b6139b9565b8181038181111561073b5761073b6139b9565b8082018082111561073b5761073b6139b9565b600060208284031215613a5157600080fd5b81516123358161345e565b60005b83811015613a77578181015183820152602001613a5f565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613ab8816017850160208801613a5c565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613ae9816028840160208801613a5c565b01602801949350505050565b6020815260008251806020840152613b14816040850160208701613a5c565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601260045260246000fd5b600082613b4d57613b4d613b28565b500490565b600082613b6157613b61613b28565b500690565b80516137978161351f565b80516fffffffffffffffffffffffffffffffff8116811461379757600080fd5b6000806000806000806000806000806000806101808d8f031215613bb457600080fd5b8c516bffffffffffffffffffffffff81168114613bd057600080fd5b9b50613bde60208e0161378c565b9a50613bec60408e0161378c565b9950613bfa60608e0161378c565b9850613c0860808e01613b66565b9750613c1660a08e01613961565b9650613c2460c08e01613961565b9550613c3260e08e01613b71565b94506101008d015193506101208d01519250613c516101408e01613b71565b9150613c606101608e01613b71565b90509295989b509295989b509295989b565b808202811582820484141761073b5761073b6139b9565b634e487b7160e01b600052603260045260246000fd5b600081613cae57613cae6139b9565b506000190190565b805161ffff8116811461379757600080fd5b600080600080600080600060e0888a031215613ce357600080fd5b8751613cee8161342c565b6020890151909750613cff8161345e565b9550613d0d60408901613cb6565b9450613d1b60608901613cb6565b9350613d2960808901613cb6565b925060a088015160ff81168114613d3f57600080fd5b60c0890151909250613d5081613652565b8091505092959891949750929550565b600060208284031215613d7257600080fd5b81516123358161351f565b6000600160ff1b8201613d9257613d926139b9565b5060000390565b60008160020b627fffff198103613db257613db26139b9565b6000039291505056fed8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63a264697066735822122002aab7d88388544ece71408ef7d0f4e7641136246f568cdb84717516967d175264736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d6868650ed58e20d09ccd2fecee8e5e04feb9a10000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
-----Decoded View---------------
Arg [0] : _constants (address): 0xd6868650Ed58E20D09Ccd2FECEe8E5E04fEB9A10
Arg [1] : _executor (address): 0xB60adcf4aFDA59132407C3b3e8b85B3C33bcfe7c
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000d6868650ed58e20d09ccd2fecee8e5e04feb9a10
Arg [1] : 000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.