Source Code
Latest 25 from a total of 828,025 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Earn Preparation | 398784783 | 1 hr ago | IN | 0 ETH | 0.00000129 | ||||
| Earn | 398784716 | 1 hr ago | IN | 0 ETH | 0.0000009 | ||||
| Earn | 398784676 | 1 hr ago | IN | 0 ETH | 0.00000868 | ||||
| Earn | 398784636 | 1 hr ago | IN | 0 ETH | 0.0000086 | ||||
| Earn | 398784591 | 1 hr ago | IN | 0 ETH | 0.00000888 | ||||
| Earn Preparation | 398784585 | 1 hr ago | IN | 0 ETH | 0.00000913 | ||||
| Collect Rewards | 398784549 | 1 hr ago | IN | 0 ETH | 0.0000026 | ||||
| Earn | 398784507 | 1 hr ago | IN | 0 ETH | 0.00000206 | ||||
| Earn | 398784467 | 1 hr ago | IN | 0 ETH | 0.0000077 | ||||
| Earn | 398784429 | 1 hr ago | IN | 0 ETH | 0.00000796 | ||||
| Earn Preparation | 398784423 | 1 hr ago | IN | 0 ETH | 0.00000824 | ||||
| Collect Rewards | 398784387 | 1 hr ago | IN | 0 ETH | 0.0000024 | ||||
| Earn | 398784345 | 1 hr ago | IN | 0 ETH | 0.00000374 | ||||
| Earn | 398784305 | 1 hr ago | IN | 0 ETH | 0.00001178 | ||||
| Earn | 398784265 | 1 hr ago | IN | 0 ETH | 0.00001178 | ||||
| Earn | 398784225 | 1 hr ago | IN | 0 ETH | 0.00001178 | ||||
| Earn | 398784185 | 1 hr ago | IN | 0 ETH | 0.00001195 | ||||
| Earn | 398784145 | 1 hr ago | IN | 0 ETH | 0.00001204 | ||||
| Earn Preparation | 398784139 | 1 hr ago | IN | 0 ETH | 0.00001229 | ||||
| Collect Rewards | 398784103 | 1 hr ago | IN | 0 ETH | 0.00000192 | ||||
| Earn | 398784061 | 1 hr ago | IN | 0 ETH | 0.00000404 | ||||
| Earn | 398784021 | 1 hr ago | IN | 0 ETH | 0.0000171 | ||||
| Earn | 398783982 | 1 hr ago | IN | 0 ETH | 0.0000169 | ||||
| Earn | 398783943 | 1 hr ago | IN | 0 ETH | 0.00001712 | ||||
| Earn | 398783903 | 1 hr ago | IN | 0 ETH | 0.00001712 |
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";
/// @dev verified, private contract
/// @dev only owner or operator/backend callable
contract Controller is AccessControl, IControllerEvent, IController {
using SafeMath for uint256;
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 _executor) {
// 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).rewardWbtcAmount()
);
}
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");
//todo: add the totalSwapOutWbtc,rewardWbtcAmount,fundManagerVaultUsedWbtc
emit EarnPreparation(
_strategyContract,
msg.sender,
IStrategyInfo(_strategyContract).liquidityNftId(),
IStrategyInfo(_strategyContract).rewardWbtcAmount(),
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 wbtcBeforeTx = IFundManagerVault(_fundManagerVaultContract).getWbtcBalance();
IFundManagerVault(_fundManagerVaultContract).allocate();
uint256 wbtcAfterTx = IFundManagerVault(_fundManagerVaultContract).getWbtcBalance();
emit Allocate(_fundManagerVaultContract, msg.sender, wbtcBeforeTx.sub(wbtcAfterTx), wbtcAfterTx);
}
/// @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()
);
}
}// 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 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 rewardWbtcAmount
);
event EarnPreparation(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
uint256 rewardWbtcAmount,
uint256 remainingEarnCountDown
);
event Earn(
address indexed strategyContract,
address indexed executorAddress,
uint256 indexed liquidityNftId,
uint256 remainingEarnCountDown
);
event Allocate(
address indexed fundManagerVaultAddress,
address indexed executorAddress,
uint256 allocatedWbtcAmount,
uint256 remainingWbtcAmount
);
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 getWbtcBalance() 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 (
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);
}// 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 rewardWbtcAmount() external view returns (uint256);
/// @dev get User-Reward-Management-related Variable
function userWbtcReward(
address userAddress
) external view returns (uint256);
function totalUserWbtcReward() 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 pure returns (address);
function getControllerAddress() external pure returns (address);
function getSwapAmountCalculatorAddress() external pure returns (address);
function getZapAddress() external pure 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;
library Constants {
/// @dev ArbiturmOne & Goerli uniswap V3
address public constant UNISWAP_V3_FACTORY_ADDRESS =
address(0x1F98431c8aD98523631AE4a59f267346ea31F984);
address public constant NONFUNGIBLE_POSITION_MANAGER_ADDRESS =
address(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
address public constant SWAP_ROUTER_ADDRESS =
address(0xE592427A0AEce92De3Edee1F18E0157C05861564);
/// @dev ArbiturmOne token address
address public constant WETH_ADDRESS =
address(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);
address public constant ARB_ADDRESS =
address(0x912CE59144191C1204E64559FE8253a0e49E6548);
address public constant WBTC_ADDRESS =
address(0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f);
address public constant USDC_ADDRESS =
address(0xaf88d065e77c8cC2239327C5EDb3A432268e5831);
address public constant USDCE_ADDRESS =
address(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8);
address public constant USDT_ADDRESS =
address(0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9);
address public constant RDNT_ADDRESS =
address(0x3082CC23568eA640225c2467653dB90e9250AaA0);
address public constant LINK_ADDRESS =
address(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4);
/// @dev black hole address
address public constant BLACK_HOLE_ADDRESS =
address(0x000000000000000000000000000000000000dEaD);
}// 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":"_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":"allocatedWbtcAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingWbtcAmount","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":"rewardWbtcAmount","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":"rewardWbtcAmount","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":"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"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162003d9938038062003d9983398101604081905262000034916200017a565b6200005060008051602062003d7983398151915260006200007f565b6200005d600033620000ca565b6200007860008051602062003d7983398151915282620000ca565b50620001ac565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b620000d68282620000da565b5050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000d6576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001363390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000602082840312156200018d57600080fd5b81516001600160a01b0381168114620001a557600080fd5b9392505050565b613bbd80620001bc6000396000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c8063751681ca1161015c578063a702332d116100ce578063e38eb66c11610087578063e38eb66c14610637578063e89d66a81461064a578063f43d71991461066d578063f824c56614610690578063fdb5fefc146106a3578063ffd7d983146105eb57600080fd5b8063a702332d146105c5578063a9ed8882146105d8578063d2dc0e22146105eb578063d547741f146105fe578063da31500714610611578063dafe6db01461062457600080fd5b806391d148541161012057806391d148541461054e57806396adee011461056157806396db06f114610574578063a0f1fb1114610587578063a217fddf146105aa578063a4b3dfc4146105b257600080fd5b8063751681ca146104ef57806377977072146105025780637898e5cd146105155780637ac041ed146105285780637eebde771461053b57600080fd5b8063385892c6116101f557806357c13aaa116101b957806357c13aaa1461044e578063581c1597146104735780635a013639146104865780635ccc5ad4146104a657806361621153146104b95780636ced8c06146104cc57600080fd5b8063385892c6146103df57806338734882146103f2578063470def1414610405578063561fc351146104185780635763dbd01461043b57600080fd5b80632130f31f116102475780632130f31f1461033d578063248a9ca31461035057806328922086146103735780632f2ff15d1461039657806336568abe146103a95780633737bb22146103bc57600080fd5b806301ffc9a71461028457806305cf450a146102ac57806307bd0265146102e25780630b548482146103055780631c6e760414610328575b600080fd5b6102976102923660046131ae565b6106b6565b60405190151581526020015b60405180910390f35b6102cf6102ba3660046131ed565b60016020526000908152604090205460020b81565b60405160029190910b81526020016102a3565b6102f7600080516020613b6883398151915281565b6040519081526020016102a3565b6102cf6103133660046131ed565b60076020526000908152604090205460020b81565b61033b610336366004613219565b6106ed565b005b61033b61034b366004613252565b610778565b6102f761035e36600461328d565b60009081526020819052604090206001015490565b6102cf6103813660046131ed565b60066020526000908152604090205460020b81565b61033b6103a43660046132a6565b61096b565b61033b6103b73660046132a6565b610995565b6102cf6103ca3660046131ed565b60086020526000908152604090205460020b81565b61033b6103ed366004613219565b610a13565b61033b6104003660046132dc565b610a95565b61033b61041336600461330a565b610b4d565b6102cf6104263660046131ed565b60056020526000908152604090205460020b81565b61033b6104493660046131ed565b610bff565b6102cf61045c3660046131ed565b600260208190526000918252604090912054900b81565b6102f76104813660046131ed565b610e4a565b6104996104943660046131ed565b610fe7565b6040516102a39190613338565b61033b6104b436600461337f565b611052565b61033b6104c73660046133ab565b611101565b6102cf6104da3660046131ed565b60046020526000908152604090205460020b81565b61033b6104fd366004613219565b6111d1565b61033b6105103660046133ab565b611253565b61033b610523366004613219565b611314565b61033b610536366004613219565b611396565b61033b610549366004613219565b611417565b61029761055c3660046132a6565b611499565b61033b61056f366004613219565b6114c2565b61033b610582366004613219565b611544565b6102cf6105953660046131ed565b600a6020526000908152604090205460020b81565b6102f7600081565b6102976105c03660046131ed565b6115c5565b61033b6105d3366004613219565b611629565b6102976105e63660046131ed565b6116ab565b61033b6105f93660046131ed565b6117b0565b61033b61060c3660046132a6565b6117d1565b61029761061f3660046131ed565b6117f6565b61033b61063236600461340c565b611877565b61033b61064536600461337f565b611a8b565b6102cf6106583660046131ed565b60036020526000908152604090205460020b81565b6102cf61067b3660046131ed565b60096020526000908152604090205460020b81565b61033b61069e36600461343a565b611b3a565b61033b6106b13660046131ed565b611e47565b60006001600160e01b03198216637965db0b60e01b14806106e757506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020613b6883398151915261070581611f57565b61070e82611f64565b6001600160a01b038316600081815260056020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f39c3e68e2a6a52a106264d6bb8eb9172b37c359aabe84a3e5a44165be1d53baa91015b60405180910390a3505050565b600080516020613b6883398151915261079081611f57565b6040516376a8e9ff60e11b81526004810185905260248101849052604481018390526001600160a01b0386169063ed51d3fe90606401600060405180830381600087803b1580156107e057600080fd5b505af11580156107f4573d6000803e3d6000fd5b50505050610801856115c5565b15156001146108495760405162461bcd60e51b815260206004820152600f60248201526e32b0b93710383932b81032b93937b960891b60448201526064015b60405180910390fd5b846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ab919061348b565b336001600160a01b0316866001600160a01b03167f305bc1ca7106255b17dbf66922802940d373f07b2c8810a76cee84700eb8c46c886001600160a01b0316636a185d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610942919061348b565b61094b8a610e4a565b604080519283526020830191909152015b60405180910390a45050505050565b60008281526020819052604090206001015461098681611f57565b6109908383611fac565b505050565b6001600160a01b0381163314610a055760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610840565b610a0f8282612030565b5050565b600080516020613b68833981519152610a2b81611f57565b610a3482612095565b6001600160a01b038316600081815260046020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fb76904a8ba51dc05f78444581f265d5e71c3783225c473e9620d4c09799df5bc910161076b565b600080516020613b68833981519152610aad81611f57565b60405163088d621d60e31b815262ffffff831660048201526001600160a01b0384169063446b10e890602401600060405180830381600087803b158015610af357600080fd5b505af1158015610b07573d6000803e3d6000fd5b505060405162ffffff851681523392506001600160a01b03861691507f8ab763dee50895615d0bb8306cdddbc0c1a6258f62aacbac6edc6be8c14ad8339060200161076b565b600080516020613b68833981519152610b6581611f57565b604051630c9590fd60e41b81526001600160a01b03838116600483015284169063c9590fd090602401600060405180830381600087803b158015610ba857600080fd5b505af1158015610bbc573d6000803e3d6000fd5b50506040516001600160a01b038581168252339350861691507f45f9e54d9f5cd84815f0bebc99eab35ed7008a0d9751ccd3c19807c4b331078a9060200161076b565b600080516020613b68833981519152610c1781611f57565b816001600160a01b03166370bb45b36040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c5257600080fd5b505af1158015610c66573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccc919061348b565b336001600160a01b0316836001600160a01b03167f5d0927b601ecc1d0a4bedb898b2beff630177e857cecab540ba9b9136b302626856001600160a01b031663314e61ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d63919061348b565b866001600160a01b0316631a536a326040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc5919061348b565b876001600160a01b0316636a185d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e27919061348b565b604080519384526020840192909252908201526060015b60405180910390a45050565b600080610e56836115c5565b9050801515600003610e6b5750600092915050565b6000836001600160a01b03166370cb00df6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610eab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed39190810190613548565b5190506000846001600160a01b031663a142492d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a919061348b565b90506000610f4883836120d5565b90506000866001600160a01b031663234c4cce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae919061348b565b9050600080610fbd84846120e8565b9150915060008111610fcf5781610fda565b610fda82600161210a565b9998505050505050505050565b610fef613174565b816001600160a01b031663cbff66e26040518163ffffffff1660e01b815260040161020060405180830381865afa15801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e791906135fa565b600080516020613b6883398151915261106a81611f57565b604051630f8a517f60e41b8152600481018390526001600160a01b0384169063f8a517f090602401600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f6c58dea38c1fef4e97173e19196cf983e5a8f566fdf04367343c63b8abaa1be99060200161076b565b600080516020613b6883398151915261111981611f57565b6040516307795f5760e41b81526001600160a01b03861690637795f570906111499087908790879060040161368b565b600060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f08e0badddf13ca7fc84b48e3f0b89b0c276e9ae5e9497643f367fd2f240fdf998686866040516111c29392919061368b565b60405180910390a35050505050565b600080516020613b688339815191526111e981611f57565b6111f282611f64565b6001600160a01b038316600081815260076020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fe796bc4f3ce03bd32fb0e15586b34a308fc7bfa8c3c5485e92cd577b1bb9390a910161076b565b600080516020613b6883398151915261126b81611f57565b604051634bd613c960e11b81526001600160a01b038616906397ac27929061129b9087908790879060040161368b565b600060405180830381600087803b1580156112b557600080fd5b505af11580156112c9573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f5b48ee2dc08a8c37693631d459c19db8be2f161266f3ae57cda789130f6ed53b8686866040516111c29392919061368b565b600080516020613b6883398151915261132c81611f57565b61133582611f64565b6001600160a01b038316600081815260066020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f4d5ea40657b0a60f4e1adf5562de4fc7b431b1087121d60e006af1b4dd80700c910161076b565b600080516020613b688339815191526113ae81611f57565b6113b782611f64565b6001600160a01b0383166000818152600a6020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917e16e8ec2d70d4a15a6124477bef7aee3fd4b10b52f714c937f219ad3d4ecae5910161076b565b600080516020613b6883398151915261142f81611f57565b61143882611f64565b6001600160a01b038316600081815260086020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fd1c1e360f9477b31cc4bd12a26e42e098d96e90f614e2fcc621dea418ae0dd5f910161076b565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020613b688339815191526114da81611f57565b6114e382611f64565b6001600160a01b038316600081815260016020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f2447a43b2c31ed21e468726ba53813b663d414569fdfda6f648a646537d19bff910161076b565b600080516020613b6883398151915261155c81611f57565b61156582611f64565b6001600160a01b038316600081815260026020818152604092839020805462ffffff191662ffffff881617905591519085900b81523392917f5d87708daffcb58a78b045d80a978ca2200af1de98d942f0fb5674e08dc14fb0910161076b565b6000816001600160a01b0316638a1966e36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611605573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e791906136af565b600080516020613b6883398151915261164181611f57565b61164a82612095565b6001600160a01b038316600081815260036020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fc1d8cd1a0ed04005edcfd0819fd55a04044b95ffbca6ad9f9c56bc0d69e06870910161076b565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611710919061348b565b9050806000036117755760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420616c6c6f772063616c6c696e67207768656e206c697175696469747960448201526904e6674496420697320360b41b6064820152608401610840565b6117a881731f98431c8ad98523631ae4a59f267346ea31f98473c36442b4a4522e871399cd717abdd847ab11fe88612116565b509392505050565b600080516020613b688339815191526117c881611f57565b610a0f82612199565b6000828152602081905260409020600101546117ec81611f57565b6109908383612030565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611837573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185b919061348b565b90508060000361186e5750600192915050565b50600092915050565b600080516020613b6883398151915261188f81611f57565b6040516338ddeee160e11b8152821515600482015260009081906001600160a01b038616906371bbddc29060240160408051808303816000875af11580156118db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ff91906136cc565b91509150846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611941573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611965919061348b565b336001600160a01b0316866001600160a01b03167f6f039c89811a62a23aa18d16914e04bb7bf86e124afcbf5f81bd141148e4ba7c8786868b6001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ff919061348b565b8c6001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a61919061348b565b6040805195151586526020860194909452928401919091526060830152608082015260a00161095c565b600080516020613b68833981519152611aa381611f57565b6040516302ef42c760e11b8152600481018390526001600160a01b038416906305de858e90602401600060405180830381600087803b158015611ae557600080fd5b505af1158015611af9573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f8d35dc65727d53b4f7a4bdebeaa6c8b7b6ee8e6d772e6c35a4bbc087aa19e7ac9060200161076b565b600080516020613b68833981519152611b5281611f57565b6001600160a01b03858116600081815260096020526040808220549051631695590760e31b8152871515600482015260029190910b60248201526044810192909252306064830152918291829188169063b4aac83890608401606060405180830381865afa158015611bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bec91906136fb565b92509250925082611c4b5760405162461bcd60e51b815260206004820152602360248201527f63757272656e7420636f6e646974696f6e206e6f7420616c6c6f772072657363604482015262616c6560e81b6064820152608401610840565b611c56888787612302565b6000611cec896001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbd919061348b565b731f98431c8ad98523631ae4a59f267346ea31f98473c36442b4a4522e871399cd717abdd847ab11fe88612487565b50506001600160a01b038a166000908152600a6020526040902054909150611d179060020b8761375e565b60020b8160020b13158015611d5757506001600160a01b0389166000908152600a6020526040902054611d4d9060020b87613783565b60020b8160020b12155b611da35760405162461bcd60e51b815260206004820152601b60248201527f6f7574206f66207469636b20746f6c6572616e63652072616e676500000000006044820152606401610840565b60405163646ea14160e11b8152600284810b600483015283900b60248201526001600160a01b038a169063c8dd428290604401600060405180830381600087803b158015611df057600080fd5b505af1158015611e04573d6000803e3d6000fd5b505050506001600160a01b0389166000908152600960205260409020805462ffffff191662ffffff8316179055611e3c8984846124bd565b505050505050505050565b600080516020613b68833981519152611e5f81611f57565b816001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e9a57600080fd5b505af1158015611eae573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f14919061348b565b336001600160a01b0384167f024aa4dfbe44229e3ca86f829e80c3a1b19d5e5d39962eae78b417b805178453611f4986610e4a565b604051908152602001610e3e565b611f6181336126f1565b50565b60008160020b1215611f615760405162461bcd60e51b81526020600482015260116024820152700696e707574206c657373207468616e203607c1b6044820152606401610840565b611fb68282611499565b610a0f576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611fec3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61203a8282611499565b15610a0f576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60018160020b13611f615760405162461bcd60e51b815260206004820152600a602482015269696e707574203c3d203160b01b6044820152606401610840565b60006120e182846137a8565b9392505050565b6000806120f5848461274a565b91506121018484612756565b90509250929050565b60006120e182846137bb565b6000806000612126868686612762565b50505091505060008060008061213c8a896127c9565b50509450945050935093508160020b8560020b1361216557600084965096505050505050612191565b8060020b8560020b12156121855760016000965096505050505050612191565b50600095509093505050505b935093915050565b6000816001600160a01b031663c221b7ec6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121fd919061348b565b9050816001600160a01b031663abaa99166040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561223a57600080fd5b505af115801561224e573d6000803e3d6000fd5b505050506000826001600160a01b031663c221b7ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b6919061348b565b9050336001600160a01b0384167f5b9d56b28a7cde78f80ab41749028c18864c008e0e3722985c63ea258111b7eb6122ee85856120d5565b60408051918252602082018690520161076b565b6000806000612348866001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b925092509250856001600160a01b03167f7a73c0af961631015e379691e5a22dadd4d0fa4c85b6c6c5b36af570aa537aa086886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc91906137ce565b6001600160a01b038a1660009081526003602090815260408083205460048352818420546005845282852054600685528386205460098652958490205484519815158952600297880b9589019590955291860b87840152850b6060870152840b608086015291830b60a0850152820b60c084015288820b60e084015287820b61010084015285820b6101208401529086900b61014083015251908190036101600190a2505050505050565b6000806000612497868686612762565b509195506124ab92508891508690506127c9565b50979b919a5098509650505050505050565b6000612500846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b50509050336001600160a01b0316846001600160a01b03167fc6d664f645086a1c833d57b521e95bb8362087047154cdaf636f6228c6940ee7866001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259b919061348b565b876001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fd919061348b565b886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561263b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265f91906137ce565b6001600160a01b038a1660009081526001602090815260408083205460028084528285205460078552838620546008865295849020548451998a529489019790975294850b878301528a850b6060880152840b608087015293830b60a086015290820b60c0850152810b60e084015288810b61010084015287900b61012083015251908190036101400190a350505050565b6126fb8282611499565b610a0f57612708816128a0565b6127138360206128b2565b60405160200161272492919061380f565b60408051601f198184030181529082905262461bcd60e51b825261084091600401613884565b60006120e182846138cd565b60006120e182846138e1565b6000806000806000806000806127788b8a6127c9565b5050505092509250925061278e8a848484612a4e565b975061279988612ad8565b909192939495509091929394509091929350809750819850829950839a5050505050505050939792965093509350565b6000806000806000806000876001600160a01b03166399fbab888a6040518263ffffffff1660e01b815260040161280291815260200190565b61018060405180830381865afa158015612820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128449190613920565b909192939495969798999a509091929394959697989950909192935090919250909150905050809750819850829950839a50849b50505050505061288784612d54565b915061289283612d54565b905092959891949750929550565b60606106e76001600160a01b03831660145b606060006128c1836002613a01565b6128cc9060026137bb565b67ffffffffffffffff8111156128e4576128e46134a4565b6040519080825280601f01601f19166020018201604052801561290e576020820181803683370190505b509050600360fc1b8160008151811061292957612929613a18565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061295857612958613a18565b60200101906001600160f81b031916908160001a905350600061297c846002613a01565b6129879060016137bb565b90505b60018111156129ff576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106129bb576129bb613a18565b1a60f81b8282815181106129d1576129d1613a18565b60200101906001600160f81b031916908160001a90535060049490941c936129f881613a2e565b905061298a565b5083156120e15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610840565b604051630b4c774160e11b81526001600160a01b038481166004830152838116602483015262ffffff8316604483015260009190861690631698ee8290606401602060405180830381865afa158015612aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acf9190613a45565b95945050505050565b6000806000806000806000876001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b459190613a74565b505060408051630dfe168160e01b8152905194995094975050506001600160a01b038b1692630dfe168192600480830193506020928290030181865afa158015612b93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb79190613a45565b9650876001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c1b9190613a45565b9550876001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7f9190613b0c565b9450866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce3919061348b565b9150856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d47919061348b565b9050919395979092949650565b60008060008360020b12612d6b578260020b612d78565b8260020b612d7890613b29565b9050612d87620d89e719613b45565b60020b811115612dbd5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610840565b600081600116600003612dd457600160801b612de6565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e25576080612e20826ffff97272373d413259a46990580e213a613a01565b901c90505b6004821615612e4f576080612e4a826ffff2e50f5f656932ef12357cf3c7fdcc613a01565b901c90505b6008821615612e79576080612e74826fffe5caca7e10e4e61c3624eaa0941cd0613a01565b901c90505b6010821615612ea3576080612e9e826fffcb9843d60f6159c9db58835c926644613a01565b901c90505b6020821615612ecd576080612ec8826fff973b41fa98c081472e6896dfb254c0613a01565b901c90505b6040821615612ef7576080612ef2826fff2ea16466c96a3843ec78b326b52861613a01565b901c90505b6080821615612f21576080612f1c826ffe5dee046a99a2a811c461f1969c3053613a01565b901c90505b610100821615612f4c576080612f47826ffcbe86c7900a88aedcffc83b479aa3a4613a01565b901c90505b610200821615612f77576080612f72826ff987a7253ac413176f2b074cf7815e54613a01565b901c90505b610400821615612fa2576080612f9d826ff3392b0822b70005940c7a398e4b70f3613a01565b901c90505b610800821615612fcd576080612fc8826fe7159475a2c29b7443b29c7fa6e889d9613a01565b901c90505b611000821615612ff8576080612ff3826fd097f3bdfd2022b8845ad8f792aa5825613a01565b901c90505b61200082161561302357608061301e826fa9f746462d870fdf8a65dc1f90e061e5613a01565b901c90505b61400082161561304e576080613049826f70d869a156d2a1b890bb3df62baf32f7613a01565b901c90505b618000821615613079576080613074826f31be135f97d08fd981231505542fcfa6613a01565b901c90505b620100008216156130a55760806130a0826f09aa508b5b7a84e1c677de54f3e99bc9613a01565b901c90505b620200008216156130d05760806130cb826e5d6af8dedb81196699c329225ee604613a01565b901c90505b620400008216156130fa5760806130f5826d2216e584f5fa1ea926041bedfe98613a01565b901c90505b6208000082161561312257608061311d826b048a170391f7dc42444e8fa2613a01565b901c90505b60008460020b131561313d5761313a816000196138cd565b90505b61314c640100000000826138e1565b1561315857600161315b565b60005b61316c9060ff16602083901c6137bb565b949350505050565b6040518061010001604052806008905b60408051808201909152600080825260208201528152602001906001900390816131845790505090565b6000602082840312156131c057600080fd5b81356001600160e01b0319811681146120e157600080fd5b6001600160a01b0381168114611f6157600080fd5b6000602082840312156131ff57600080fd5b81356120e1816131d8565b8060020b8114611f6157600080fd5b6000806040838503121561322c57600080fd5b8235613237816131d8565b915060208301356132478161320a565b809150509250929050565b6000806000806080858703121561326857600080fd5b8435613273816131d8565b966020860135965060408601359560600135945092505050565b60006020828403121561329f57600080fd5b5035919050565b600080604083850312156132b957600080fd5b823591506020830135613247816131d8565b62ffffff81168114611f6157600080fd5b600080604083850312156132ef57600080fd5b82356132fa816131d8565b91506020830135613247816132cb565b6000806040838503121561331d57600080fd5b8235613328816131d8565b91506020830135613247816131d8565b6102008101818360005b600881101561337657815180516001600160a01b031684526020908101518185015260409093019290910190600101613342565b50505092915050565b6000806040838503121561339257600080fd5b823561339d816131d8565b946020939093013593505050565b600080600080608085870312156133c157600080fd5b84356133cc816131d8565b93506020850135925060408501356133e3816131d8565b915060608501356133f3816132cb565b939692955090935050565b8015158114611f6157600080fd5b6000806040838503121561341f57600080fd5b823561342a816131d8565b91506020830135613247816133fe565b6000806000806080858703121561345057600080fd5b843561345b816131d8565b9350602085013561346b816131d8565b9250604085013561347b816133fe565b915060608501356133f38161320a565b60006020828403121561349d57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156134de576134de6134a4565b60405290565b6040805190810167ffffffffffffffff811182821017156134de576134de6134a4565b604051601f8201601f1916810167ffffffffffffffff81118282101715613530576135306134a4565b604052919050565b8051613543816131d8565b919050565b6000602080838503121561355b57600080fd5b825167ffffffffffffffff8082111561357357600080fd5b818501915085601f83011261358757600080fd5b815181811115613599576135996134a4565b8060051b91506135aa848301613507565b81815291830184019184810190888411156135c457600080fd5b938501935b838510156135ee57845192506135de836131d8565b82825293850193908501906135c9565b98975050505050505050565b600061020080838503121561360e57600080fd5b83601f84011261361d57600080fd5b6136256134ba565b90830190808583111561363757600080fd5b845b8381101561368157604081880312156136525760008081fd5b61365a6134e4565b8151613665816131d8565b8152602082810151818301529084529290920191604001613639565b5095945050505050565b9283526001600160a01b0391909116602083015262ffffff16604082015260600190565b6000602082840312156136c157600080fd5b81516120e1816133fe565b600080604083850312156136df57600080fd5b505080516020909101519092909150565b80516135438161320a565b60008060006060848603121561371057600080fd5b835161371b816133fe565b602085015190935061372c8161320a565b604085015190925061373d8161320a565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600281810b9083900b01627fffff8113627fffff19821217156106e7576106e7613748565b600282810b9082900b03627fffff198112627fffff821317156106e7576106e7613748565b818103818111156106e7576106e7613748565b808201808211156106e7576106e7613748565b6000602082840312156137e057600080fd5b81516120e18161320a565b60005b838110156138065781810151838201526020016137ee565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516138478160178501602088016137eb565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516138788160288401602088016137eb565b01602801949350505050565b60208152600082518060208401526138a38160408501602087016137eb565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601260045260246000fd5b6000826138dc576138dc6138b7565b500490565b6000826138f0576138f06138b7565b500690565b8051613543816132cb565b80516fffffffffffffffffffffffffffffffff8116811461354357600080fd5b6000806000806000806000806000806000806101808d8f03121561394357600080fd5b8c516bffffffffffffffffffffffff8116811461395f57600080fd5b9b5061396d60208e01613538565b9a5061397b60408e01613538565b995061398960608e01613538565b985061399760808e016138f5565b97506139a560a08e016136f0565b96506139b360c08e016136f0565b95506139c160e08e01613900565b94506101008d015193506101208d015192506139e06101408e01613900565b91506139ef6101608e01613900565b90509295989b509295989b509295989b565b80820281158282048414176106e7576106e7613748565b634e487b7160e01b600052603260045260246000fd5b600081613a3d57613a3d613748565b506000190190565b600060208284031215613a5757600080fd5b81516120e1816131d8565b805161ffff8116811461354357600080fd5b600080600080600080600060e0888a031215613a8f57600080fd5b8751613a9a816131d8565b6020890151909750613aab8161320a565b9550613ab960408901613a62565b9450613ac760608901613a62565b9350613ad560808901613a62565b925060a088015160ff81168114613aeb57600080fd5b60c0890151909250613afc816133fe565b8091505092959891949750929550565b600060208284031215613b1e57600080fd5b81516120e1816132cb565b6000600160ff1b8201613b3e57613b3e613748565b5060000390565b60008160020b627fffff198103613b5e57613b5e613748565b6000039291505056fed8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63a26469706673582212209c1709a30e73d7637741745e751e0f1b427fb91d397ff1a6d027113a4ff68e5364736f6c63430008120033d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061027f5760003560e01c8063751681ca1161015c578063a702332d116100ce578063e38eb66c11610087578063e38eb66c14610637578063e89d66a81461064a578063f43d71991461066d578063f824c56614610690578063fdb5fefc146106a3578063ffd7d983146105eb57600080fd5b8063a702332d146105c5578063a9ed8882146105d8578063d2dc0e22146105eb578063d547741f146105fe578063da31500714610611578063dafe6db01461062457600080fd5b806391d148541161012057806391d148541461054e57806396adee011461056157806396db06f114610574578063a0f1fb1114610587578063a217fddf146105aa578063a4b3dfc4146105b257600080fd5b8063751681ca146104ef57806377977072146105025780637898e5cd146105155780637ac041ed146105285780637eebde771461053b57600080fd5b8063385892c6116101f557806357c13aaa116101b957806357c13aaa1461044e578063581c1597146104735780635a013639146104865780635ccc5ad4146104a657806361621153146104b95780636ced8c06146104cc57600080fd5b8063385892c6146103df57806338734882146103f2578063470def1414610405578063561fc351146104185780635763dbd01461043b57600080fd5b80632130f31f116102475780632130f31f1461033d578063248a9ca31461035057806328922086146103735780632f2ff15d1461039657806336568abe146103a95780633737bb22146103bc57600080fd5b806301ffc9a71461028457806305cf450a146102ac57806307bd0265146102e25780630b548482146103055780631c6e760414610328575b600080fd5b6102976102923660046131ae565b6106b6565b60405190151581526020015b60405180910390f35b6102cf6102ba3660046131ed565b60016020526000908152604090205460020b81565b60405160029190910b81526020016102a3565b6102f7600080516020613b6883398151915281565b6040519081526020016102a3565b6102cf6103133660046131ed565b60076020526000908152604090205460020b81565b61033b610336366004613219565b6106ed565b005b61033b61034b366004613252565b610778565b6102f761035e36600461328d565b60009081526020819052604090206001015490565b6102cf6103813660046131ed565b60066020526000908152604090205460020b81565b61033b6103a43660046132a6565b61096b565b61033b6103b73660046132a6565b610995565b6102cf6103ca3660046131ed565b60086020526000908152604090205460020b81565b61033b6103ed366004613219565b610a13565b61033b6104003660046132dc565b610a95565b61033b61041336600461330a565b610b4d565b6102cf6104263660046131ed565b60056020526000908152604090205460020b81565b61033b6104493660046131ed565b610bff565b6102cf61045c3660046131ed565b600260208190526000918252604090912054900b81565b6102f76104813660046131ed565b610e4a565b6104996104943660046131ed565b610fe7565b6040516102a39190613338565b61033b6104b436600461337f565b611052565b61033b6104c73660046133ab565b611101565b6102cf6104da3660046131ed565b60046020526000908152604090205460020b81565b61033b6104fd366004613219565b6111d1565b61033b6105103660046133ab565b611253565b61033b610523366004613219565b611314565b61033b610536366004613219565b611396565b61033b610549366004613219565b611417565b61029761055c3660046132a6565b611499565b61033b61056f366004613219565b6114c2565b61033b610582366004613219565b611544565b6102cf6105953660046131ed565b600a6020526000908152604090205460020b81565b6102f7600081565b6102976105c03660046131ed565b6115c5565b61033b6105d3366004613219565b611629565b6102976105e63660046131ed565b6116ab565b61033b6105f93660046131ed565b6117b0565b61033b61060c3660046132a6565b6117d1565b61029761061f3660046131ed565b6117f6565b61033b61063236600461340c565b611877565b61033b61064536600461337f565b611a8b565b6102cf6106583660046131ed565b60036020526000908152604090205460020b81565b6102cf61067b3660046131ed565b60096020526000908152604090205460020b81565b61033b61069e36600461343a565b611b3a565b61033b6106b13660046131ed565b611e47565b60006001600160e01b03198216637965db0b60e01b14806106e757506301ffc9a760e01b6001600160e01b03198316145b92915050565b600080516020613b6883398151915261070581611f57565b61070e82611f64565b6001600160a01b038316600081815260056020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f39c3e68e2a6a52a106264d6bb8eb9172b37c359aabe84a3e5a44165be1d53baa91015b60405180910390a3505050565b600080516020613b6883398151915261079081611f57565b6040516376a8e9ff60e11b81526004810185905260248101849052604481018390526001600160a01b0386169063ed51d3fe90606401600060405180830381600087803b1580156107e057600080fd5b505af11580156107f4573d6000803e3d6000fd5b50505050610801856115c5565b15156001146108495760405162461bcd60e51b815260206004820152600f60248201526e32b0b93710383932b81032b93937b960891b60448201526064015b60405180910390fd5b846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ab919061348b565b336001600160a01b0316866001600160a01b03167f305bc1ca7106255b17dbf66922802940d373f07b2c8810a76cee84700eb8c46c886001600160a01b0316636a185d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610942919061348b565b61094b8a610e4a565b604080519283526020830191909152015b60405180910390a45050505050565b60008281526020819052604090206001015461098681611f57565b6109908383611fac565b505050565b6001600160a01b0381163314610a055760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610840565b610a0f8282612030565b5050565b600080516020613b68833981519152610a2b81611f57565b610a3482612095565b6001600160a01b038316600081815260046020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fb76904a8ba51dc05f78444581f265d5e71c3783225c473e9620d4c09799df5bc910161076b565b600080516020613b68833981519152610aad81611f57565b60405163088d621d60e31b815262ffffff831660048201526001600160a01b0384169063446b10e890602401600060405180830381600087803b158015610af357600080fd5b505af1158015610b07573d6000803e3d6000fd5b505060405162ffffff851681523392506001600160a01b03861691507f8ab763dee50895615d0bb8306cdddbc0c1a6258f62aacbac6edc6be8c14ad8339060200161076b565b600080516020613b68833981519152610b6581611f57565b604051630c9590fd60e41b81526001600160a01b03838116600483015284169063c9590fd090602401600060405180830381600087803b158015610ba857600080fd5b505af1158015610bbc573d6000803e3d6000fd5b50506040516001600160a01b038581168252339350861691507f45f9e54d9f5cd84815f0bebc99eab35ed7008a0d9751ccd3c19807c4b331078a9060200161076b565b600080516020613b68833981519152610c1781611f57565b816001600160a01b03166370bb45b36040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610c5257600080fd5b505af1158015610c66573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccc919061348b565b336001600160a01b0316836001600160a01b03167f5d0927b601ecc1d0a4bedb898b2beff630177e857cecab540ba9b9136b302626856001600160a01b031663314e61ca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d63919061348b565b866001600160a01b0316631a536a326040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc5919061348b565b876001600160a01b0316636a185d5f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e27919061348b565b604080519384526020840192909252908201526060015b60405180910390a45050565b600080610e56836115c5565b9050801515600003610e6b5750600092915050565b6000836001600160a01b03166370cb00df6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610eab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed39190810190613548565b5190506000846001600160a01b031663a142492d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a919061348b565b90506000610f4883836120d5565b90506000866001600160a01b031663234c4cce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae919061348b565b9050600080610fbd84846120e8565b9150915060008111610fcf5781610fda565b610fda82600161210a565b9998505050505050505050565b610fef613174565b816001600160a01b031663cbff66e26040518163ffffffff1660e01b815260040161020060405180830381865afa15801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e791906135fa565b600080516020613b6883398151915261106a81611f57565b604051630f8a517f60e41b8152600481018390526001600160a01b0384169063f8a517f090602401600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f6c58dea38c1fef4e97173e19196cf983e5a8f566fdf04367343c63b8abaa1be99060200161076b565b600080516020613b6883398151915261111981611f57565b6040516307795f5760e41b81526001600160a01b03861690637795f570906111499087908790879060040161368b565b600060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f08e0badddf13ca7fc84b48e3f0b89b0c276e9ae5e9497643f367fd2f240fdf998686866040516111c29392919061368b565b60405180910390a35050505050565b600080516020613b688339815191526111e981611f57565b6111f282611f64565b6001600160a01b038316600081815260076020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fe796bc4f3ce03bd32fb0e15586b34a308fc7bfa8c3c5485e92cd577b1bb9390a910161076b565b600080516020613b6883398151915261126b81611f57565b604051634bd613c960e11b81526001600160a01b038616906397ac27929061129b9087908790879060040161368b565b600060405180830381600087803b1580156112b557600080fd5b505af11580156112c9573d6000803e3d6000fd5b50505050336001600160a01b0316856001600160a01b03167f5b48ee2dc08a8c37693631d459c19db8be2f161266f3ae57cda789130f6ed53b8686866040516111c29392919061368b565b600080516020613b6883398151915261132c81611f57565b61133582611f64565b6001600160a01b038316600081815260066020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f4d5ea40657b0a60f4e1adf5562de4fc7b431b1087121d60e006af1b4dd80700c910161076b565b600080516020613b688339815191526113ae81611f57565b6113b782611f64565b6001600160a01b0383166000818152600a6020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917e16e8ec2d70d4a15a6124477bef7aee3fd4b10b52f714c937f219ad3d4ecae5910161076b565b600080516020613b6883398151915261142f81611f57565b61143882611f64565b6001600160a01b038316600081815260086020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fd1c1e360f9477b31cc4bd12a26e42e098d96e90f614e2fcc621dea418ae0dd5f910161076b565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b600080516020613b688339815191526114da81611f57565b6114e382611f64565b6001600160a01b038316600081815260016020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917f2447a43b2c31ed21e468726ba53813b663d414569fdfda6f648a646537d19bff910161076b565b600080516020613b6883398151915261155c81611f57565b61156582611f64565b6001600160a01b038316600081815260026020818152604092839020805462ffffff191662ffffff881617905591519085900b81523392917f5d87708daffcb58a78b045d80a978ca2200af1de98d942f0fb5674e08dc14fb0910161076b565b6000816001600160a01b0316638a1966e36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611605573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e791906136af565b600080516020613b6883398151915261164181611f57565b61164a82612095565b6001600160a01b038316600081815260036020908152604091829020805462ffffff191662ffffff87161790559051600285900b81523392917fc1d8cd1a0ed04005edcfd0819fd55a04044b95ffbca6ad9f9c56bc0d69e06870910161076b565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611710919061348b565b9050806000036117755760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420616c6c6f772063616c6c696e67207768656e206c697175696469747960448201526904e6674496420697320360b41b6064820152608401610840565b6117a881731f98431c8ad98523631ae4a59f267346ea31f98473c36442b4a4522e871399cd717abdd847ab11fe88612116565b509392505050565b600080516020613b688339815191526117c881611f57565b610a0f82612199565b6000828152602081905260409020600101546117ec81611f57565b6109908383612030565b600080826001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611837573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185b919061348b565b90508060000361186e5750600192915050565b50600092915050565b600080516020613b6883398151915261188f81611f57565b6040516338ddeee160e11b8152821515600482015260009081906001600160a01b038616906371bbddc29060240160408051808303816000875af11580156118db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ff91906136cc565b91509150846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611941573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611965919061348b565b336001600160a01b0316866001600160a01b03167f6f039c89811a62a23aa18d16914e04bb7bf86e124afcbf5f81bd141148e4ba7c8786868b6001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ff919061348b565b8c6001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a61919061348b565b6040805195151586526020860194909452928401919091526060830152608082015260a00161095c565b600080516020613b68833981519152611aa381611f57565b6040516302ef42c760e11b8152600481018390526001600160a01b038416906305de858e90602401600060405180830381600087803b158015611ae557600080fd5b505af1158015611af9573d6000803e3d6000fd5b50506040518481523392506001600160a01b03861691507f8d35dc65727d53b4f7a4bdebeaa6c8b7b6ee8e6d772e6c35a4bbc087aa19e7ac9060200161076b565b600080516020613b68833981519152611b5281611f57565b6001600160a01b03858116600081815260096020526040808220549051631695590760e31b8152871515600482015260029190910b60248201526044810192909252306064830152918291829188169063b4aac83890608401606060405180830381865afa158015611bc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bec91906136fb565b92509250925082611c4b5760405162461bcd60e51b815260206004820152602360248201527f63757272656e7420636f6e646974696f6e206e6f7420616c6c6f772072657363604482015262616c6560e81b6064820152608401610840565b611c56888787612302565b6000611cec896001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbd919061348b565b731f98431c8ad98523631ae4a59f267346ea31f98473c36442b4a4522e871399cd717abdd847ab11fe88612487565b50506001600160a01b038a166000908152600a6020526040902054909150611d179060020b8761375e565b60020b8160020b13158015611d5757506001600160a01b0389166000908152600a6020526040902054611d4d9060020b87613783565b60020b8160020b12155b611da35760405162461bcd60e51b815260206004820152601b60248201527f6f7574206f66207469636b20746f6c6572616e63652072616e676500000000006044820152606401610840565b60405163646ea14160e11b8152600284810b600483015283900b60248201526001600160a01b038a169063c8dd428290604401600060405180830381600087803b158015611df057600080fd5b505af1158015611e04573d6000803e3d6000fd5b505050506001600160a01b0389166000908152600960205260409020805462ffffff191662ffffff8316179055611e3c8984846124bd565b505050505050505050565b600080516020613b68833981519152611e5f81611f57565b816001600160a01b031663d389800f6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e9a57600080fd5b505af1158015611eae573d6000803e3d6000fd5b50505050816001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f14919061348b565b336001600160a01b0384167f024aa4dfbe44229e3ca86f829e80c3a1b19d5e5d39962eae78b417b805178453611f4986610e4a565b604051908152602001610e3e565b611f6181336126f1565b50565b60008160020b1215611f615760405162461bcd60e51b81526020600482015260116024820152700696e707574206c657373207468616e203607c1b6044820152606401610840565b611fb68282611499565b610a0f576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611fec3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b61203a8282611499565b15610a0f576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60018160020b13611f615760405162461bcd60e51b815260206004820152600a602482015269696e707574203c3d203160b01b6044820152606401610840565b60006120e182846137a8565b9392505050565b6000806120f5848461274a565b91506121018484612756565b90509250929050565b60006120e182846137bb565b6000806000612126868686612762565b50505091505060008060008061213c8a896127c9565b50509450945050935093508160020b8560020b1361216557600084965096505050505050612191565b8060020b8560020b12156121855760016000965096505050505050612191565b50600095509093505050505b935093915050565b6000816001600160a01b031663c221b7ec6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121fd919061348b565b9050816001600160a01b031663abaa99166040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561223a57600080fd5b505af115801561224e573d6000803e3d6000fd5b505050506000826001600160a01b031663c221b7ec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b6919061348b565b9050336001600160a01b0384167f5b9d56b28a7cde78f80ab41749028c18864c008e0e3722985c63ea258111b7eb6122ee85856120d5565b60408051918252602082018690520161076b565b6000806000612348866001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b925092509250856001600160a01b03167f7a73c0af961631015e379691e5a22dadd4d0fa4c85b6c6c5b36af570aa537aa086886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dc91906137ce565b6001600160a01b038a1660009081526003602090815260408083205460048352818420546005845282852054600685528386205460098652958490205484519815158952600297880b9589019590955291860b87840152850b6060870152840b608086015291830b60a0850152820b60c084015288820b60e084015287820b61010084015285820b6101208401529086900b61014083015251908190036101600190a2505050505050565b6000806000612497868686612762565b509195506124ab92508891508690506127c9565b50979b919a5098509650505050505050565b6000612500846001600160a01b031663ead892be6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c99573d6000803e3d6000fd5b50509050336001600160a01b0316846001600160a01b03167fc6d664f645086a1c833d57b521e95bb8362087047154cdaf636f6228c6940ee7866001600160a01b0316634f89b24d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061259b919061348b565b876001600160a01b031663bf8895ea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125fd919061348b565b886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561263b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265f91906137ce565b6001600160a01b038a1660009081526001602090815260408083205460028084528285205460078552838620546008865295849020548451998a529489019790975294850b878301528a850b6060880152840b608087015293830b60a086015290820b60c0850152810b60e084015288810b61010084015287900b61012083015251908190036101400190a350505050565b6126fb8282611499565b610a0f57612708816128a0565b6127138360206128b2565b60405160200161272492919061380f565b60408051601f198184030181529082905262461bcd60e51b825261084091600401613884565b60006120e182846138cd565b60006120e182846138e1565b6000806000806000806000806127788b8a6127c9565b5050505092509250925061278e8a848484612a4e565b975061279988612ad8565b909192939495509091929394509091929350809750819850829950839a5050505050505050939792965093509350565b6000806000806000806000876001600160a01b03166399fbab888a6040518263ffffffff1660e01b815260040161280291815260200190565b61018060405180830381865afa158015612820573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128449190613920565b909192939495969798999a509091929394959697989950909192935090919250909150905050809750819850829950839a50849b50505050505061288784612d54565b915061289283612d54565b905092959891949750929550565b60606106e76001600160a01b03831660145b606060006128c1836002613a01565b6128cc9060026137bb565b67ffffffffffffffff8111156128e4576128e46134a4565b6040519080825280601f01601f19166020018201604052801561290e576020820181803683370190505b509050600360fc1b8160008151811061292957612929613a18565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061295857612958613a18565b60200101906001600160f81b031916908160001a905350600061297c846002613a01565b6129879060016137bb565b90505b60018111156129ff576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106129bb576129bb613a18565b1a60f81b8282815181106129d1576129d1613a18565b60200101906001600160f81b031916908160001a90535060049490941c936129f881613a2e565b905061298a565b5083156120e15760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610840565b604051630b4c774160e11b81526001600160a01b038481166004830152838116602483015262ffffff8316604483015260009190861690631698ee8290606401602060405180830381865afa158015612aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acf9190613a45565b95945050505050565b6000806000806000806000876001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015612b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b459190613a74565b505060408051630dfe168160e01b8152905194995094975050506001600160a01b038b1692630dfe168192600480830193506020928290030181865afa158015612b93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb79190613a45565b9650876001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c1b9190613a45565b9550876001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7f9190613b0c565b9450866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce3919061348b565b9150856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d47919061348b565b9050919395979092949650565b60008060008360020b12612d6b578260020b612d78565b8260020b612d7890613b29565b9050612d87620d89e719613b45565b60020b811115612dbd5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610840565b600081600116600003612dd457600160801b612de6565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e25576080612e20826ffff97272373d413259a46990580e213a613a01565b901c90505b6004821615612e4f576080612e4a826ffff2e50f5f656932ef12357cf3c7fdcc613a01565b901c90505b6008821615612e79576080612e74826fffe5caca7e10e4e61c3624eaa0941cd0613a01565b901c90505b6010821615612ea3576080612e9e826fffcb9843d60f6159c9db58835c926644613a01565b901c90505b6020821615612ecd576080612ec8826fff973b41fa98c081472e6896dfb254c0613a01565b901c90505b6040821615612ef7576080612ef2826fff2ea16466c96a3843ec78b326b52861613a01565b901c90505b6080821615612f21576080612f1c826ffe5dee046a99a2a811c461f1969c3053613a01565b901c90505b610100821615612f4c576080612f47826ffcbe86c7900a88aedcffc83b479aa3a4613a01565b901c90505b610200821615612f77576080612f72826ff987a7253ac413176f2b074cf7815e54613a01565b901c90505b610400821615612fa2576080612f9d826ff3392b0822b70005940c7a398e4b70f3613a01565b901c90505b610800821615612fcd576080612fc8826fe7159475a2c29b7443b29c7fa6e889d9613a01565b901c90505b611000821615612ff8576080612ff3826fd097f3bdfd2022b8845ad8f792aa5825613a01565b901c90505b61200082161561302357608061301e826fa9f746462d870fdf8a65dc1f90e061e5613a01565b901c90505b61400082161561304e576080613049826f70d869a156d2a1b890bb3df62baf32f7613a01565b901c90505b618000821615613079576080613074826f31be135f97d08fd981231505542fcfa6613a01565b901c90505b620100008216156130a55760806130a0826f09aa508b5b7a84e1c677de54f3e99bc9613a01565b901c90505b620200008216156130d05760806130cb826e5d6af8dedb81196699c329225ee604613a01565b901c90505b620400008216156130fa5760806130f5826d2216e584f5fa1ea926041bedfe98613a01565b901c90505b6208000082161561312257608061311d826b048a170391f7dc42444e8fa2613a01565b901c90505b60008460020b131561313d5761313a816000196138cd565b90505b61314c640100000000826138e1565b1561315857600161315b565b60005b61316c9060ff16602083901c6137bb565b949350505050565b6040518061010001604052806008905b60408051808201909152600080825260208201528152602001906001900390816131845790505090565b6000602082840312156131c057600080fd5b81356001600160e01b0319811681146120e157600080fd5b6001600160a01b0381168114611f6157600080fd5b6000602082840312156131ff57600080fd5b81356120e1816131d8565b8060020b8114611f6157600080fd5b6000806040838503121561322c57600080fd5b8235613237816131d8565b915060208301356132478161320a565b809150509250929050565b6000806000806080858703121561326857600080fd5b8435613273816131d8565b966020860135965060408601359560600135945092505050565b60006020828403121561329f57600080fd5b5035919050565b600080604083850312156132b957600080fd5b823591506020830135613247816131d8565b62ffffff81168114611f6157600080fd5b600080604083850312156132ef57600080fd5b82356132fa816131d8565b91506020830135613247816132cb565b6000806040838503121561331d57600080fd5b8235613328816131d8565b91506020830135613247816131d8565b6102008101818360005b600881101561337657815180516001600160a01b031684526020908101518185015260409093019290910190600101613342565b50505092915050565b6000806040838503121561339257600080fd5b823561339d816131d8565b946020939093013593505050565b600080600080608085870312156133c157600080fd5b84356133cc816131d8565b93506020850135925060408501356133e3816131d8565b915060608501356133f3816132cb565b939692955090935050565b8015158114611f6157600080fd5b6000806040838503121561341f57600080fd5b823561342a816131d8565b91506020830135613247816133fe565b6000806000806080858703121561345057600080fd5b843561345b816131d8565b9350602085013561346b816131d8565b9250604085013561347b816133fe565b915060608501356133f38161320a565b60006020828403121561349d57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156134de576134de6134a4565b60405290565b6040805190810167ffffffffffffffff811182821017156134de576134de6134a4565b604051601f8201601f1916810167ffffffffffffffff81118282101715613530576135306134a4565b604052919050565b8051613543816131d8565b919050565b6000602080838503121561355b57600080fd5b825167ffffffffffffffff8082111561357357600080fd5b818501915085601f83011261358757600080fd5b815181811115613599576135996134a4565b8060051b91506135aa848301613507565b81815291830184019184810190888411156135c457600080fd5b938501935b838510156135ee57845192506135de836131d8565b82825293850193908501906135c9565b98975050505050505050565b600061020080838503121561360e57600080fd5b83601f84011261361d57600080fd5b6136256134ba565b90830190808583111561363757600080fd5b845b8381101561368157604081880312156136525760008081fd5b61365a6134e4565b8151613665816131d8565b8152602082810151818301529084529290920191604001613639565b5095945050505050565b9283526001600160a01b0391909116602083015262ffffff16604082015260600190565b6000602082840312156136c157600080fd5b81516120e1816133fe565b600080604083850312156136df57600080fd5b505080516020909101519092909150565b80516135438161320a565b60008060006060848603121561371057600080fd5b835161371b816133fe565b602085015190935061372c8161320a565b604085015190925061373d8161320a565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600281810b9083900b01627fffff8113627fffff19821217156106e7576106e7613748565b600282810b9082900b03627fffff198112627fffff821317156106e7576106e7613748565b818103818111156106e7576106e7613748565b808201808211156106e7576106e7613748565b6000602082840312156137e057600080fd5b81516120e18161320a565b60005b838110156138065781810151838201526020016137ee565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516138478160178501602088016137eb565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516138788160288401602088016137eb565b01602801949350505050565b60208152600082518060208401526138a38160408501602087016137eb565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601260045260246000fd5b6000826138dc576138dc6138b7565b500490565b6000826138f0576138f06138b7565b500690565b8051613543816132cb565b80516fffffffffffffffffffffffffffffffff8116811461354357600080fd5b6000806000806000806000806000806000806101808d8f03121561394357600080fd5b8c516bffffffffffffffffffffffff8116811461395f57600080fd5b9b5061396d60208e01613538565b9a5061397b60408e01613538565b995061398960608e01613538565b985061399760808e016138f5565b97506139a560a08e016136f0565b96506139b360c08e016136f0565b95506139c160e08e01613900565b94506101008d015193506101208d015192506139e06101408e01613900565b91506139ef6101608e01613900565b90509295989b509295989b509295989b565b80820281158282048414176106e7576106e7613748565b634e487b7160e01b600052603260045260246000fd5b600081613a3d57613a3d613748565b506000190190565b600060208284031215613a5757600080fd5b81516120e1816131d8565b805161ffff8116811461354357600080fd5b600080600080600080600060e0888a031215613a8f57600080fd5b8751613a9a816131d8565b6020890151909750613aab8161320a565b9550613ab960408901613a62565b9450613ac760608901613a62565b9350613ad560808901613a62565b925060a088015160ff81168114613aeb57600080fd5b60c0890151909250613afc816133fe565b8091505092959891949750929550565b600060208284031215613b1e57600080fd5b81516120e1816132cb565b6000600160ff1b8201613b3e57613b3e613748565b5060000390565b60008160020b627fffff198103613b5e57613b5e613748565b6000039291505056fed8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63a26469706673582212209c1709a30e73d7637741745e751e0f1b427fb91d397ff1a6d027113a4ff68e5364736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
-----Decoded View---------------
Arg [0] : _executor (address): 0xB60adcf4aFDA59132407C3b3e8b85B3C33bcfe7c
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000b60adcf4afda59132407c3b3e8b85b3c33bcfe7c
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.