Source Code
Latest 25 from a total of 536 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Execute Availabl... | 23456122 | 117 days ago | IN | 0 ETH | 0.00001602 | ||||
| Execute Unlocks | 23343221 | 132 days ago | IN | 0 ETH | 0.00012391 | ||||
| Execute Availabl... | 22452584 | 257 days ago | IN | 0 ETH | 0.00037403 | ||||
| Claim Fees | 22452554 | 257 days ago | IN | 0 ETH | 0.00040512 | ||||
| Execute Unlocks | 22243177 | 286 days ago | IN | 0 ETH | 0.00013811 | ||||
| Execute Availabl... | 22033073 | 315 days ago | IN | 0 ETH | 0.00013897 | ||||
| Execute Availabl... | 22032838 | 316 days ago | IN | 0 ETH | 0.00006015 | ||||
| Execute Unlocks | 22028269 | 316 days ago | IN | 0 ETH | 0.00014629 | ||||
| Execute Availabl... | 22023158 | 317 days ago | IN | 0 ETH | 0.00009061 | ||||
| Execute Unlocks | 22017542 | 318 days ago | IN | 0 ETH | 0.00029147 | ||||
| Execute Availabl... | 22015609 | 318 days ago | IN | 0 ETH | 0.00030196 | ||||
| Execute Availabl... | 22014066 | 318 days ago | IN | 0 ETH | 0.00009025 | ||||
| Execute Unlocks | 22009353 | 319 days ago | IN | 0 ETH | 0.00015371 | ||||
| Execute Availabl... | 22000009 | 320 days ago | IN | 0 ETH | 0.00007842 | ||||
| Execute Availabl... | 21999508 | 320 days ago | IN | 0 ETH | 0.00025834 | ||||
| Execute Availabl... | 21997587 | 320 days ago | IN | 0 ETH | 0.00018153 | ||||
| Execute Unlocks | 21997221 | 320 days ago | IN | 0 ETH | 0.00011928 | ||||
| Execute Availabl... | 21997030 | 321 days ago | IN | 0 ETH | 0.00011386 | ||||
| Execute Availabl... | 21997026 | 321 days ago | IN | 0 ETH | 0.00016898 | ||||
| Execute Availabl... | 21996947 | 321 days ago | IN | 0 ETH | 0.00028593 | ||||
| Execute Availabl... | 21996935 | 321 days ago | IN | 0 ETH | 0.00021611 | ||||
| Execute Availabl... | 21996905 | 321 days ago | IN | 0 ETH | 0.00009515 | ||||
| Lock For | 21996547 | 321 days ago | IN | 0 ETH | 0.00031571 | ||||
| Execute Unlocks | 21985227 | 322 days ago | IN | 0 ETH | 0.00016519 | ||||
| Lock For | 21979459 | 323 days ago | IN | 0 ETH | 0.0002097 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CNCLockerV3
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "SafeERC20.sol";
import "IERC20.sol";
import "Ownable.sol";
import "ScaledMath.sol";
import "ICNCLockerV3.sol";
import "ICNCToken.sol";
import "ICNCVoteLocker.sol";
import "IController.sol";
contract CNCLockerV3 is ICNCLockerV3, Ownable {
using SafeERC20 for ICNCToken;
using SafeERC20 for IERC20;
using ScaledMath for uint256;
using ScaledMath for uint128;
using MerkleProof for MerkleProof.Proof;
uint128 internal constant _MIN_LOCK_AMOUNT = 10e18;
uint128 internal constant _MAX_LOCKS = 10;
uint128 internal constant _MIN_LOCK_TIME = 120 days;
uint128 internal constant _MAX_LOCK_TIME = 240 days;
uint128 internal constant _GRACE_PERIOD = 28 days;
uint128 internal constant _MIN_BOOST = 1e18;
uint128 internal constant _MAX_BOOST = 1.5e18;
uint128 internal constant _KICK_PENALTY = 1e17;
uint256 internal constant _MAX_KICK_PENALTY_AMOUNT = 1000e18;
uint128 constant _AIRDROP_DURATION = 182 days;
uint256 internal constant _MIN_AIRDROP_BOOST = 1e18;
uint256 internal constant _MAX_AIRDROP_BOOST = 3.5e18;
ICNCToken public immutable cncToken;
// Boost data
mapping(address => uint256) public lockedBalance;
mapping(address => uint256) public lockedBoosted;
mapping(address => VoteLock[]) public voteLocks;
mapping(address => uint256) internal _airdroppedBoost;
mapping(address => bool) public override claimedAirdrop;
uint64 internal _nextId;
uint256 public immutable airdropEndTime;
bytes32 public immutable merkleRoot;
uint256 public totalLocked;
uint256 public totalBoosted;
bool public isShutdown;
// Fee data
IERC20 public immutable crv;
IERC20 public immutable cvx;
uint256 public accruedFeesIntegralCrv;
uint256 public accruedFeesIntegralCvx;
mapping(address => uint256) public perAccountAccruedCrv;
mapping(address => uint256) public perAccountFeesCrv;
mapping(address => uint256) public perAccountAccruedCvx;
mapping(address => uint256) public perAccountFeesCvx;
address public immutable treasury;
IController public immutable controller;
constructor(
address _controller,
address _cncToken,
address _treasury,
address _crv,
address _cvx,
bytes32 _merkleRoot
) Ownable() {
controller = IController(_controller);
cncToken = ICNCToken(_cncToken);
treasury = _treasury;
crv = IERC20(_crv);
cvx = IERC20(_cvx);
airdropEndTime = block.timestamp + _AIRDROP_DURATION;
merkleRoot = _merkleRoot;
}
function lock(uint256 amount, uint64 lockTime) external override {
lock(amount, lockTime, false);
}
/// @notice Lock an amount of CNC for vlCNC.
/// @param amount Amount of CNC to lock.
/// @param lockTime Duration of the lock.
/// @param relock_ `True` if this is a relock of an existing lock.
function lock(uint256 amount, uint64 lockTime, bool relock_) public override {
lockFor(amount, lockTime, relock_, msg.sender);
}
/// @notice Lock an amount of CNC for vlCNC.
/// @param amount Amount of CNC to lock.
/// @param lockTime Duration of the lock.
/// @param relock_ `True` if this is a relock of all existing locks.
/// @param account The account to receive the vlCNC.
function lockFor(
uint256 amount,
uint64 lockTime,
bool relock_,
address account
) public override {
require(!isShutdown, "locker suspended");
require(amount >= _MIN_LOCK_AMOUNT, "amount too small");
require((_MIN_LOCK_TIME <= lockTime) && (lockTime <= _MAX_LOCK_TIME), "lock time invalid");
require(!relock_ || msg.sender == account, "relock only for self");
require(voteLocks[account].length < _MAX_LOCKS, "too many locks");
_feeCheckpoint(account);
cncToken.safeTransferFrom(msg.sender, address(this), amount);
uint128 boost = computeBoost(lockTime);
uint256 airdropBoost_ = airdropBoost(msg.sender);
if (airdropBoost_ > 1e18) {
claimedAirdrop[msg.sender] = true;
boost = boost.mulDownUint128(uint128(airdropBoost_));
delete _airdroppedBoost[msg.sender];
}
uint64 unlockTime = uint64(block.timestamp) + lockTime;
uint256 boostedAmount;
if (relock_) {
uint256 length = voteLocks[account].length;
for (uint256 i; i < length; i++) {
require(
voteLocks[account][i].unlockTime < unlockTime,
"cannot move the unlock time up"
);
}
delete voteLocks[account];
totalBoosted -= lockedBoosted[account];
lockedBoosted[account] = 0;
_addVoteLock(account, lockedBalance[account] + amount, unlockTime, boost);
boostedAmount = (lockedBalance[account] + amount).mulDown(uint256(boost));
} else {
_addVoteLock(account, amount, unlockTime, boost);
boostedAmount = amount.mulDown(boost);
}
totalLocked += amount;
totalBoosted += boostedAmount;
lockedBalance[account] += amount;
lockedBoosted[account] += boostedAmount;
emit Locked(account, amount, unlockTime, relock_);
}
/// @notice Process all expired locks of msg.sender and withdraw unlocked CNC.
function executeAvailableUnlocks() external override returns (uint256) {
return executeAvailableUnlocksFor(msg.sender);
}
/// @notice Process all expired locks of msg.sender and withdraw unlocked CNC to `dst`.
function executeAvailableUnlocksFor(address dst) public override returns (uint256) {
require(dst != address(0), "invalid destination");
_feeCheckpoint(msg.sender);
uint256 sumUnlockable;
uint256 sumBoosted;
VoteLock[] storage _pending = voteLocks[msg.sender];
uint256 i = _pending.length;
while (i > 0) {
i = i - 1;
if (isShutdown || _pending[i].unlockTime <= block.timestamp) {
sumUnlockable += _pending[i].amount;
sumBoosted += _pending[i].amount.mulDown(_pending[i].boost);
_pending[i] = _pending[_pending.length - 1];
_pending.pop();
}
}
totalLocked -= sumUnlockable;
totalBoosted -= sumBoosted;
lockedBalance[msg.sender] -= sumUnlockable;
lockedBoosted[msg.sender] -= sumBoosted;
cncToken.safeTransfer(dst, sumUnlockable);
emit UnlockExecuted(msg.sender, sumUnlockable);
return sumUnlockable;
}
/// @notice Process specified locks of msg.sender and withdraw unlocked CNC to `dst`.
/// @param dst Destination address to receive unlocked CNC.
/// @param lockIds Array of lock IDs to process.
/// @return unlocked Amount of CNC unlocked.
function executeUnlocks(
address dst,
uint64[] calldata lockIds
) public override returns (uint256) {
_feeCheckpoint(msg.sender);
uint256 sumUnlockable;
uint256 sumBoosted;
VoteLock[] storage _pending = voteLocks[msg.sender];
for (uint256 idIndex; idIndex < lockIds.length; idIndex++) {
uint256 index = _getLockIndexById(msg.sender, lockIds[idIndex]);
require(
isShutdown || _pending[index].unlockTime <= block.timestamp,
"lock not expired"
);
sumUnlockable += _pending[index].amount;
sumBoosted += _pending[index].amount.mulDown(_pending[index].boost);
_pending[index] = _pending[_pending.length - 1];
_pending.pop();
}
totalLocked -= sumUnlockable;
totalBoosted -= sumBoosted;
lockedBalance[msg.sender] -= sumUnlockable;
lockedBoosted[msg.sender] -= sumBoosted;
cncToken.safeTransfer(dst, sumUnlockable);
emit UnlockExecuted(msg.sender, sumUnlockable);
return sumUnlockable;
}
/// @notice Get unlocked CNC balance for an address
/// @param user Address to get unlocked CNC balance for
/// @return Unlocked CNC balance
function unlockableBalance(address user) public view override returns (uint256) {
uint256 sumUnlockable = 0;
VoteLock[] storage _pending = voteLocks[user];
uint256 length = _pending.length;
for (uint256 i; i < length; i++) {
if (_pending[i].unlockTime <= uint128(block.timestamp)) {
sumUnlockable += _pending[i].amount;
}
}
return sumUnlockable;
}
/// @notice Get unlocked boosted CNC balance for an address
/// @param user Address to get unlocked boosted CNC balance for
/// @return Unlocked boosted CNC balance
function unlockableBalanceBoosted(address user) public view override returns (uint256) {
uint256 sumUnlockable = 0;
VoteLock[] storage _pending = voteLocks[user];
uint256 length = _pending.length;
for (uint256 i; i < length; i++) {
if (_pending[i].unlockTime <= uint128(block.timestamp)) {
sumUnlockable += _pending[i].amount.mulDown(_pending[i].boost);
}
}
return sumUnlockable;
}
function shutDown() external override onlyOwner {
require(!isShutdown, "locker already suspended");
isShutdown = true;
emit Shutdown();
}
function recoverToken(address token) external override {
require(
token != address(cncToken) && token != address(crv) && token != address(cvx),
"cannot withdraw token"
);
IERC20 _token = IERC20(token);
_token.safeTransfer(treasury, _token.balanceOf(address(this)));
emit TokenRecovered(token);
}
/// @notice Relock a specific lock
/// @dev Users locking CNC can create multiple locks therefore individual locks can be relocked separately.
/// @param lockId Id of the lock to relock.
/// @param lockTime Duration for which the locks's CNC amount should be relocked for.
function relock(uint64 lockId, uint64 lockTime) external override {
require(!isShutdown, "locker suspended");
require((_MIN_LOCK_TIME <= lockTime) && (lockTime <= _MAX_LOCK_TIME), "lock time invalid");
_feeCheckpoint(msg.sender);
_relock(lockId, lockTime);
}
/// @notice Relock specified locks
/// @param lockIds Ids of the locks to relock.
/// @param lockTime Duration for which the locks's CNC amount should be relocked for.
function relockMultiple(uint64[] calldata lockIds, uint64 lockTime) external override {
require(!isShutdown, "locker suspended");
require((_MIN_LOCK_TIME <= lockTime) && (lockTime <= _MAX_LOCK_TIME), "lock time invalid");
_feeCheckpoint(msg.sender);
for (uint256 i; i < lockIds.length; i++) {
_relock(lockIds[i], lockTime);
}
}
function _relock(uint64 lockId, uint64 lockTime) internal {
uint256 lockIndex = _getLockIndexById(msg.sender, lockId);
uint128 boost = computeBoost(lockTime);
uint64 unlockTime = uint64(block.timestamp) + lockTime;
VoteLock[] storage locks = voteLocks[msg.sender];
require(locks[lockIndex].unlockTime < unlockTime, "cannot move the unlock time up");
uint256 amount = locks[lockIndex].amount;
uint256 previousBoostedAmount = locks[lockIndex].amount.mulDown(locks[lockIndex].boost);
locks[lockIndex] = locks[locks.length - 1];
locks.pop();
_addVoteLock(msg.sender, amount, unlockTime, boost);
uint256 boostedAmount = amount.mulDown(boost);
totalBoosted = totalBoosted + boostedAmount - previousBoostedAmount;
lockedBoosted[msg.sender] =
lockedBoosted[msg.sender] +
boostedAmount -
previousBoostedAmount;
emit Relocked(msg.sender, amount);
}
function relock(uint64 lockTime) external override {
require(!isShutdown, "locker suspended");
require((_MIN_LOCK_TIME <= lockTime) && (lockTime <= _MAX_LOCK_TIME), "lock time invalid");
_feeCheckpoint(msg.sender);
uint128 boost = computeBoost(lockTime);
uint64 unlockTime = uint64(block.timestamp) + lockTime;
uint256 length = voteLocks[msg.sender].length;
for (uint256 i; i < length; i++) {
require(
voteLocks[msg.sender][i].unlockTime < unlockTime,
"cannot move the unlock time up"
);
}
delete voteLocks[msg.sender];
totalBoosted -= lockedBoosted[msg.sender];
lockedBoosted[msg.sender] = 0;
_addVoteLock(msg.sender, lockedBalance[msg.sender], unlockTime, boost);
uint256 boostedAmount = lockedBalance[msg.sender].mulDown(uint256(boost));
totalBoosted += boostedAmount;
lockedBoosted[msg.sender] += boostedAmount;
emit Relocked(msg.sender, lockedBalance[msg.sender]);
}
function batchKick(LockId[] memory locks) external override {
for (uint256 i; i < locks.length; i++) {
kick(locks[i].user, locks[i].id);
}
}
/// @notice Kick an expired lock
function kick(address user, uint64 lockId) public override {
uint256 lockIndex = _getLockIndexById(user, lockId);
VoteLock[] storage _pending = voteLocks[user];
require(
_pending[lockIndex].unlockTime + _GRACE_PERIOD <= uint128(block.timestamp),
"cannot kick this lock"
);
_feeCheckpoint(user);
uint256 amount = _pending[lockIndex].amount;
totalLocked -= amount;
totalBoosted -= amount.mulDown(_pending[lockIndex].boost);
lockedBalance[user] -= amount;
lockedBoosted[user] -= amount.mulDown(_pending[lockIndex].boost);
uint256 kickPenalty = amount.mulDown(_KICK_PENALTY);
if (kickPenalty > _MAX_KICK_PENALTY_AMOUNT) {
kickPenalty = _MAX_KICK_PENALTY_AMOUNT;
}
cncToken.safeTransfer(user, amount - kickPenalty);
cncToken.safeTransfer(msg.sender, kickPenalty);
emit KickExecuted(user, msg.sender, amount);
_pending[lockIndex] = _pending[_pending.length - 1];
_pending.pop();
}
function receiveFees(uint256 amountCrv, uint256 amountCvx) external override {
crv.safeTransferFrom(msg.sender, address(this), amountCrv);
cvx.safeTransferFrom(msg.sender, address(this), amountCvx);
accruedFeesIntegralCrv += amountCrv.divDown(totalBoosted);
accruedFeesIntegralCvx += amountCvx.divDown(totalBoosted);
emit FeesReceived(msg.sender, amountCrv, amountCvx);
}
function claimFees() external override returns (uint256 crvAmount, uint256 cvxAmount) {
_feeCheckpoint(msg.sender);
crvAmount = perAccountFeesCrv[msg.sender];
cvxAmount = perAccountFeesCvx[msg.sender];
crv.safeTransfer(msg.sender, crvAmount);
cvx.safeTransfer(msg.sender, cvxAmount);
perAccountFeesCrv[msg.sender] = 0;
perAccountFeesCvx[msg.sender] = 0;
emit FeesClaimed(msg.sender, crvAmount, cvxAmount);
}
function claimAirdropBoost(uint256 amount, MerkleProof.Proof calldata proof) external override {
require(block.timestamp < airdropEndTime, "airdrop ended");
require(!claimedAirdrop[msg.sender], "already claimed");
require(amount >= _MIN_AIRDROP_BOOST, "amount cannot be below 1");
require(amount <= _MAX_AIRDROP_BOOST, "amount exceeds max airdrop boost");
bytes32 node = keccak256(abi.encodePacked(msg.sender, amount));
require(proof.isValid(node, merkleRoot), "invalid proof");
_airdroppedBoost[msg.sender] = amount;
emit AirdropBoostClaimed(msg.sender, amount);
}
function claimableFees(
address account
) external view override returns (uint256 claimableCrv, uint256 claimableCvx) {
uint256 boost_ = lockedBoosted[account];
claimableCrv =
perAccountFeesCrv[account] +
boost_.mulDown(accruedFeesIntegralCrv - perAccountAccruedCrv[account]);
claimableCvx =
perAccountFeesCvx[account] +
boost_.mulDown(accruedFeesIntegralCvx - perAccountAccruedCvx[account]);
}
function balanceOf(address user) external view override returns (uint256) {
return totalVoteBoost(user);
}
function _feeCheckpoint(address account) internal {
uint256 boost_ = lockedBoosted[account];
uint256 accruedFeesIntegralCrv_ = accruedFeesIntegralCrv;
uint256 accruedFeesIntegralCvx_ = accruedFeesIntegralCvx;
perAccountFeesCrv[account] += boost_.mulDown(
accruedFeesIntegralCrv_ - perAccountAccruedCrv[account]
);
perAccountAccruedCrv[account] = accruedFeesIntegralCrv_;
perAccountFeesCvx[account] += boost_.mulDown(
accruedFeesIntegralCvx_ - perAccountAccruedCvx[account]
);
perAccountAccruedCvx[account] = accruedFeesIntegralCvx_;
// bonding stream
IBonding bonding = controller.bonding();
bonding.accountCheckpoint(account);
}
function computeBoost(uint128 lockTime) public pure override returns (uint128) {
return ((_MAX_BOOST - _MIN_BOOST).mulDownUint128(
(lockTime - _MIN_LOCK_TIME).divDownUint128(_MAX_LOCK_TIME - _MIN_LOCK_TIME)
) + _MIN_BOOST);
}
function airdropBoost(address account) public view override returns (uint256) {
if (_airdroppedBoost[account] == 0) return 1e18;
return _airdroppedBoost[account];
}
function totalVoteBoost(address account) public view override returns (uint256) {
return totalRewardsBoost(account).mulDown(controller.lpTokenStaker().getBoost(account));
}
function totalStreamBoost(address account) external view override returns (uint256) {
return lockedBoosted[account];
}
function totalRewardsBoost(address account) public view override returns (uint256) {
return lockedBoosted[account] - unlockableBalanceBoosted(account);
}
function userLocks(address account) external view override returns (VoteLock[] memory) {
return voteLocks[account];
}
function _getLockIndexById(address user, uint64 id) internal view returns (uint256) {
uint256 length_ = voteLocks[user].length;
for (uint256 i; i < length_; i++) {
if (voteLocks[user][i].id == id) {
return i;
}
}
revert("lock doesn't exist");
}
function _addVoteLock(address user, uint256 amount, uint64 unlockTime, uint128 boost) internal {
uint64 id = _nextId;
voteLocks[user].push(VoteLock(amount, unlockTime, boost, id));
_nextId = id + 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "IERC20.sol";
import "IERC20Permit.sol";
import "Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (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 (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts 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: GPL-3.0-or-later
pragma solidity 0.8.17;
library ScaledMath {
uint256 internal constant DECIMALS = 18;
uint256 internal constant ONE = 10 ** DECIMALS;
function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * b) / ONE;
}
function mulDown(uint256 a, uint256 b, uint256 decimals) internal pure returns (uint256) {
return (a * b) / (10 ** decimals);
}
function divDown(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * ONE) / b;
}
function divDown(uint256 a, uint256 b, uint256 decimals) internal pure returns (uint256) {
return (a * 10 ** decimals) / b;
}
function divUp(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
return ((a * ONE) - 1) / b + 1;
}
function mulDown(int256 a, int256 b) internal pure returns (int256) {
return (a * b) / int256(ONE);
}
function mulDownUint128(uint128 a, uint128 b) internal pure returns (uint128) {
return (a * b) / uint128(ONE);
}
function mulDown(int256 a, int256 b, uint256 decimals) internal pure returns (int256) {
return (a * b) / int256(10 ** decimals);
}
function divDown(int256 a, int256 b) internal pure returns (int256) {
return (a * int256(ONE)) / b;
}
function divDownUint128(uint128 a, uint128 b) internal pure returns (uint128) {
return (a * uint128(ONE)) / b;
}
function divDown(int256 a, int256 b, uint256 decimals) internal pure returns (int256) {
return (a * int256(10 ** decimals)) / b;
}
function convertScale(
uint256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (uint256) {
if (fromDecimals == toDecimals) return a;
if (fromDecimals > toDecimals) return downscale(a, fromDecimals, toDecimals);
return upscale(a, fromDecimals, toDecimals);
}
function convertScale(
int256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (int256) {
if (fromDecimals == toDecimals) return a;
if (fromDecimals > toDecimals) return downscale(a, fromDecimals, toDecimals);
return upscale(a, fromDecimals, toDecimals);
}
function upscale(
uint256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (uint256) {
return a * (10 ** (toDecimals - fromDecimals));
}
function downscale(
uint256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (uint256) {
return a / (10 ** (fromDecimals - toDecimals));
}
function upscale(
int256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (int256) {
return a * int256(10 ** (toDecimals - fromDecimals));
}
function downscale(
int256 a,
uint8 fromDecimals,
uint8 toDecimals
) internal pure returns (int256) {
return a / int256(10 ** (fromDecimals - toDecimals));
}
function intPow(uint256 a, uint256 n) internal pure returns (uint256) {
uint256 result = ONE;
for (uint256 i; i < n; ) {
result = mulDown(result, a);
unchecked {
++i;
}
}
return result;
}
function absSub(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
return a >= b ? a - b : b - a;
}
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a <= b ? a : b;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "MerkleProof.sol";
import "IFeeRecipient.sol";
interface ICNCLockerV3 is IFeeRecipient {
event Locked(address indexed account, uint256 amount, uint256 unlockTime, bool relocked);
event UnlockExecuted(address indexed account, uint256 amount);
event Relocked(address indexed account, uint256 amount);
event KickExecuted(address indexed account, address indexed kicker, uint256 amount);
event FeesClaimed(address indexed claimer, uint256 crvAmount, uint256 cvxAmount);
event AirdropBoostClaimed(address indexed claimer, uint256 amount);
event Shutdown();
event TokenRecovered(address indexed token);
struct VoteLock {
uint256 amount;
uint64 unlockTime;
uint128 boost;
uint64 id;
}
struct LockId {
address user;
uint64 id;
}
function lock(uint256 amount, uint64 lockTime) external;
function lock(uint256 amount, uint64 lockTime, bool relock) external;
function lockFor(uint256 amount, uint64 lockTime, bool relock, address account) external;
function relock(uint64 lockId, uint64 lockTime) external;
function relock(uint64 lockTime) external;
function relockMultiple(uint64[] calldata lockIds, uint64 lockTime) external;
function totalBoosted() external view returns (uint256);
function shutDown() external;
function recoverToken(address token) external;
function executeAvailableUnlocks() external returns (uint256);
function executeAvailableUnlocksFor(address dst) external returns (uint256);
function executeUnlocks(address dst, uint64[] calldata lockIds) external returns (uint256);
function claimAirdropBoost(uint256 amount, MerkleProof.Proof calldata proof) external;
// This will need to include the boosts etc.
function balanceOf(address user) external view returns (uint256);
function unlockableBalance(address user) external view returns (uint256);
function unlockableBalanceBoosted(address user) external view returns (uint256);
function kick(address user, uint64 lockId) external;
function batchKick(LockId[] memory locks) external;
function claimableFees(
address account
) external view returns (uint256 claimableCrv, uint256 claimableCvx);
function claimFees() external returns (uint256 crvAmount, uint256 cvxAmount);
function computeBoost(uint128 lockTime) external view returns (uint128);
function airdropBoost(address account) external view returns (uint256);
function claimedAirdrop(address account) external view returns (bool);
function totalVoteBoost(address account) external view returns (uint256);
function totalStreamBoost(address account) external view returns (uint256);
function totalRewardsBoost(address account) external view returns (uint256);
function userLocks(address account) external view returns (VoteLock[] memory);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
library MerkleProof {
struct Proof {
uint16 nodeIndex;
bytes32[] hashes;
}
function isValid(
Proof memory proof,
bytes32 node,
bytes32 merkleRoot
) internal pure returns (bool) {
uint256 length = proof.hashes.length;
uint16 nodeIndex = proof.nodeIndex;
for (uint256 i = 0; i < length; i++) {
if (nodeIndex % 2 == 0) {
node = keccak256(abi.encodePacked(node, proof.hashes[i]));
} else {
node = keccak256(abi.encodePacked(proof.hashes[i], node));
}
nodeIndex /= 2;
}
return node == merkleRoot;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IFeeRecipient {
event FeesReceived(address indexed sender, uint256 crvAmount, uint256 cvxAmount);
function receiveFees(uint256 amountCrv, uint256 amountCvx) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "IERC20.sol";
interface ICNCToken is IERC20 {
event MinterAdded(address minter);
event MinterRemoved(address minter);
event InitialDistributionMinted(uint256 amount);
event AirdropMinted(uint256 amount);
event AMMRewardsMinted(uint256 amount);
event TreasuryRewardsMinted(uint256 amount);
event SeedShareMinted(uint256 amount);
/// @notice adds a new minter
function addMinter(address newMinter) external;
/// @notice renounces the minter rights of the sender
function renounceMinterRights() external;
/// @notice mints the initial distribution amount to the distribution contract
function mintInitialDistribution(address distribution) external;
/// @notice mints the airdrop amount to the airdrop contract
function mintAirdrop(address airdropHandler) external;
/// @notice mints the amm rewards
function mintAMMRewards(address ammGauge) external;
/// @notice mints `amount` to `account`
function mint(address account, uint256 amount) external returns (uint256);
/// @notice returns a list of all authorized minters
function listMinters() external view returns (address[] memory);
/// @notice returns the ratio of inflation already minted
function inflationMintedRatio() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface ICNCVoteLocker {
event Locked(address indexed account, uint256 amount, uint256 unlockTime, bool relocked);
event UnlockExecuted(address indexed account, uint256 amount);
function lock(uint256 amount) external;
function lock(uint256 amount, bool relock) external;
function shutDown() external;
function recoverToken(address token) external;
function executeAvailableUnlocks() external returns (uint256);
function balanceOf(address user) external view returns (uint256);
function unlockableBalance(address user) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "IConicPoolWeightManagement.sol";
import "IConicPool.sol";
import "IGenericOracle.sol";
import "IInflationManager.sol";
import "ILpTokenStaker.sol";
import "IBonding.sol";
import "IPoolAdapter.sol";
import "IFeeRecipient.sol";
import "ICurveRegistryCache.sol";
interface IController {
event PoolAdded(address indexed pool);
event PoolRemoved(address indexed pool);
event PoolShutdown(address indexed pool);
event ConvexBoosterSet(address convexBooster);
event CurveHandlerSet(address curveHandler);
event ConvexHandlerSet(address convexHandler);
event CurveRegistryCacheSet(address curveRegistryCache);
event InflationManagerSet(address inflationManager);
event BondingSet(address bonding);
event FeeRecipientSet(address feeRecipient);
event PriceOracleSet(address priceOracle);
event WeightUpdateMinDelaySet(uint256 weightUpdateMinDelay);
event PauseManagerSet(address indexed manager, bool isManager);
event MultiDepositsWithdrawsWhitelistSet(address pool, bool allowed);
event MinimumTaintedTransferAmountSet(address indexed token, uint256 amount);
event DefaultPoolAdapterSet(address poolAdapter);
event CustomPoolAdapterSet(address indexed pool, address poolAdapter);
struct WeightUpdate {
address conicPoolAddress;
IConicPoolWeightManagement.PoolWeight[] weights;
}
function initialize(address _lpTokenStaker) external;
// inflation manager
function inflationManager() external view returns (IInflationManager);
function setInflationManager(address manager) external;
// views
function curveRegistryCache() external view returns (ICurveRegistryCache);
// pool adapter
function poolAdapterFor(address pool) external view returns (IPoolAdapter);
function defaultPoolAdapter() external view returns (IPoolAdapter);
function setDefaultPoolAdapter(address poolAdapter) external;
function setCustomPoolAdapter(address pool, address poolAdapter) external;
/// lp token staker
function switchLpTokenStaker(address _lpTokenStaker) external;
function lpTokenStaker() external view returns (ILpTokenStaker);
// bonding
function bonding() external view returns (IBonding);
function setBonding(address _bonding) external;
// fees
function feeRecipient() external view returns (IFeeRecipient);
function setFeeRecipient(address _feeRecipient) external;
// oracle
function priceOracle() external view returns (IGenericOracle);
function setPriceOracle(address oracle) external;
// pool functions
function listPools() external view returns (address[] memory);
function listActivePools() external view returns (address[] memory);
function isPool(address poolAddress) external view returns (bool);
function isActivePool(address poolAddress) external view returns (bool);
function addPool(address poolAddress) external;
function shutdownPool(address poolAddress) external;
function removePool(address poolAddress) external;
function cncToken() external view returns (address);
function lastWeightUpdate(address poolAddress) external view returns (uint256);
function updateWeights(WeightUpdate memory update) external;
function updateAllWeights(WeightUpdate[] memory weights) external;
// handler functions
function convexBooster() external view returns (address);
function curveHandler() external view returns (address);
function convexHandler() external view returns (address);
function setConvexBooster(address _convexBooster) external;
function setCurveHandler(address _curveHandler) external;
function setConvexHandler(address _convexHandler) external;
function setCurveRegistryCache(address curveRegistryCache_) external;
function setWeightUpdateMinDelay(uint256 delay) external;
function isPauseManager(address account) external view returns (bool);
function listPauseManagers() external view returns (address[] memory);
function setPauseManager(address account, bool isManager) external;
// deposit/withdrawal whitelist
function isAllowedMultipleDepositsWithdraws(address poolAddress) external view returns (bool);
function setAllowedMultipleDepositsWithdraws(address account, bool allowed) external;
function getMultipleDepositsWithdrawsWhitelist() external view returns (address[] memory);
// tainted transfer amount
function setMinimumTaintedTransferAmount(address token, uint256 amount) external;
function getMinimumTaintedTransferAmount(address token) external view returns (uint256);
// constants
function MAX_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);
function MIN_WEIGHT_UPDATE_MIN_DELAY() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IConicPoolWeightManagement {
struct PoolWeight {
address poolAddress;
uint256 weight;
}
function addPool(address pool) external;
function removePool(address pool) external;
function updateWeights(PoolWeight[] memory poolWeights) external;
function handleDepeggedCurvePool(address curvePool_) external;
function handleInvalidConvexPid(address pool) external returns (uint256);
function allPools() external view returns (address[] memory);
function poolsCount() external view returns (uint256);
function getPoolAtIndex(uint256 _index) external view returns (address);
function getWeight(address curvePool) external view returns (uint256);
function getWeights() external view returns (PoolWeight[] memory);
function isRegisteredPool(address _pool) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "ILpToken.sol";
import "IRewardManager.sol";
import "IOracle.sol";
import "IController.sol";
import "IPausable.sol";
import "IConicPoolWeightManagement.sol";
interface IConicPool is IConicPoolWeightManagement, IPausable {
event Deposit(
address indexed sender,
address indexed receiver,
uint256 depositedAmount,
uint256 lpReceived
);
event Withdraw(address indexed account, uint256 amount);
event NewWeight(address indexed curvePool, uint256 newWeight);
event NewMaxIdleCurveLpRatio(uint256 newRatio);
event ClaimedRewards(uint256 claimedCrv, uint256 claimedCvx);
event HandledDepeggedCurvePool(address curvePool_);
event HandledInvalidConvexPid(address curvePool_, uint256 pid_);
event CurvePoolAdded(address curvePool_);
event CurvePoolRemoved(address curvePool_);
event Shutdown();
event DepegThresholdUpdated(uint256 newThreshold);
event MaxDeviationUpdated(uint256 newMaxDeviation);
event RebalancingRewardsEnabledSet(bool enabled);
event EmergencyRebalancingRewardFactorUpdated(uint256 factor);
struct PoolWithAmount {
address poolAddress;
uint256 amount;
}
function underlying() external view returns (IERC20Metadata);
function lpToken() external view returns (ILpToken);
function rewardManager() external view returns (IRewardManager);
function depegThreshold() external view returns (uint256);
function maxIdleCurveLpRatio() external view returns (uint256);
function setMaxIdleCurveLpRatio(uint256 value) external;
function setMaxDeviation(uint256 maxDeviation_) external;
function updateDepegThreshold(uint256 value) external;
function depositFor(
address _account,
uint256 _amount,
uint256 _minLpReceived,
bool stake
) external returns (uint256);
function deposit(uint256 _amount, uint256 _minLpReceived) external returns (uint256);
function deposit(
uint256 _amount,
uint256 _minLpReceived,
bool stake
) external returns (uint256);
function exchangeRate() external view returns (uint256);
function usdExchangeRate() external view returns (uint256);
function unstakeAndWithdraw(uint256 _amount, uint256 _minAmount) external returns (uint256);
function unstakeAndWithdraw(
uint256 _amount,
uint256 _minAmount,
address _to
) external returns (uint256);
function withdraw(uint256 _amount, uint256 _minAmount) external returns (uint256);
function withdraw(uint256 _amount, uint256 _minAmount, address _to) external returns (uint256);
function getAllocatedUnderlying() external view returns (PoolWithAmount[] memory);
function rebalancingRewardActive() external view returns (bool);
function totalDeviationAfterWeightUpdate() external view returns (uint256);
function computeTotalDeviation() external view returns (uint256);
/// @notice returns the total amount of funds held by this pool in terms of underlying
function totalUnderlying() external view returns (uint256);
function getTotalAndPerPoolUnderlying()
external
view
returns (
uint256 totalUnderlying_,
uint256 totalAllocated_,
uint256[] memory perPoolUnderlying_
);
/// @notice same as `totalUnderlying` but returns a cached version
/// that might be slightly outdated if oracle prices have changed
/// @dev this is useful in cases where we want to reduce gas usage and do
/// not need a precise value
function cachedTotalUnderlying() external view returns (uint256);
function updateRewardSpendingApproval(address token, bool approved) external;
function shutdownPool() external;
function isShutdown() external view returns (bool);
function isBalanced() external view returns (bool);
function rebalancingRewardsEnabled() external view returns (bool);
function setRebalancingRewardsEnabled(bool enabled) external;
function getAllUnderlyingCoins() external view returns (address[] memory result);
function rebalancingRewardsFactor() external view returns (uint256);
function rebalancingRewardsActivatedAt() external view returns (uint64);
function getWeights() external view returns (PoolWeight[] memory);
function runSanityChecks() external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "IERC20Metadata.sol";
interface ILpToken is IERC20Metadata {
function minter() external view returns (address);
function mint(address account, uint256 amount, address ubo) external returns (uint256);
function burn(address _owner, uint256 _amount, address ubo) external returns (uint256);
function taint(address from, address to, uint256 amount) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IRewardManager {
event ClaimedRewards(uint256 claimedCrv, uint256 claimedCvx);
event SoldRewardTokens(uint256 targetTokenReceived);
event ExtraRewardAdded(address reward);
event ExtraRewardRemoved(address reward);
event ExtraRewardsCurvePoolSet(address extraReward, address curvePool);
event FeesSet(uint256 feePercentage);
event FeesEnabled(uint256 feePercentage);
event EarningsClaimed(
address indexed claimedBy,
uint256 cncEarned,
uint256 crvEarned,
uint256 cvxEarned
);
function accountCheckpoint(address account) external;
function poolCheckpoint() external returns (bool);
function addExtraReward(address reward) external returns (bool);
function addBatchExtraRewards(address[] memory rewards) external;
function conicPool() external view returns (address);
function setFeePercentage(uint256 _feePercentage) external;
function claimableRewards(
address account
) external view returns (uint256 cncRewards, uint256 crvRewards, uint256 cvxRewards);
function claimEarnings() external returns (uint256, uint256, uint256);
function claimPoolEarningsAndSellRewardTokens() external;
function feePercentage() external view returns (uint256);
function feesEnabled() external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IOracle {
event TokenUpdated(address indexed token, address feed, uint256 maxDelay, bool isEthPrice);
/// @notice returns the price in USD of symbol.
function getUSDPrice(address token) external view returns (uint256);
/// @notice returns if the given token is supported for pricing.
function isTokenSupported(address token) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "Ownable.sol";
import "IController.sol";
interface IPausable {
event Paused(uint256 pausedUntil);
event PauseDurationSet(uint256 pauseDuration);
function controller() external view returns (IController);
function pausedUntil() external view returns (uint256);
function pauseDuration() external view returns (uint256);
function isPaused() external view returns (bool);
function setPauseDuration(uint256 _pauseDuration) external;
function pause() external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "IOracle.sol";
interface IGenericOracle is IOracle {
/// @notice returns the oracle to be used to price `token`
function getOracle(address token) external view returns (IOracle);
/// @notice converts the price of an LP token to the given underlying
function curveLpToUnderlying(
address curveLpToken,
address underlying,
uint256 curveLpAmount
) external view returns (uint256);
/// @notice same as above but avoids fetching the underlying price again
function curveLpToUnderlying(
address curveLpToken,
address underlying,
uint256 curveLpAmount,
uint256 underlyingPrice
) external view returns (uint256);
/// @notice converts the price an underlying asset to a given Curve LP token
function underlyingToCurveLp(
address underlying,
address curveLpToken,
uint256 underlyingAmount
) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IInflationManager {
event TokensClaimed(address indexed pool, uint256 cncAmount);
event RebalancingRewardHandlerAdded(address indexed pool, address indexed handler);
event RebalancingRewardHandlerRemoved(address indexed pool, address indexed handler);
event PoolWeightsUpdated();
function executeInflationRateUpdate() external;
function updatePoolWeights() external;
/// @notice returns the weights of the Conic pools to know how much inflation
/// each of them will receive, as well as the total amount of USD value in all the pools
function computePoolWeights()
external
view
returns (address[] memory _pools, uint256[] memory poolWeights, uint256 totalUSDValue);
function computePoolWeight(
address pool
) external view returns (uint256 poolWeight, uint256 totalUSDValue);
function currentInflationRate() external view returns (uint256);
function getCurrentPoolInflationRate(address pool) external view returns (uint256);
function handleRebalancingRewards(
address account,
uint256 deviationBefore,
uint256 deviationAfter
) external;
function addPoolRebalancingRewardHandler(
address poolAddress,
address rebalancingRewardHandler
) external;
function removePoolRebalancingRewardHandler(
address poolAddress,
address rebalancingRewardHandler
) external;
function rebalancingRewardHandlers(
address poolAddress
) external view returns (address[] memory);
function hasPoolRebalancingRewardHandler(
address poolAddress,
address handler
) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface ILpTokenStaker {
event LpTokenStaked(address indexed account, uint256 amount);
event LpTokenUnstaked(address indexed account, uint256 amount);
event TokensClaimed(address indexed pool, uint256 cncAmount);
event Shutdown();
function stake(uint256 amount, address conicPool) external;
function unstake(uint256 amount, address conicPool) external;
function stakeFor(uint256 amount, address conicPool, address account) external;
function unstakeFor(uint256 amount, address conicPool, address account) external;
function unstakeFrom(uint256 amount, address account) external;
function getUserBalanceForPool(
address conicPool,
address account
) external view returns (uint256);
function getBalanceForPool(address conicPool) external view returns (uint256);
function updateBoost(address user) external;
function claimCNCRewardsForPool(address pool) external;
function claimableCnc(address pool) external view returns (uint256);
function checkpoint(address pool) external returns (uint256);
function shutdown() external;
function getBoost(address user) external view returns (uint256);
function isShutdown() external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IBonding {
event CncStartPriceSet(uint256 startPrice);
event PriceIncreaseFactorSet(uint256 factor);
event MinBondingAmountSet(uint256 amount);
event Bonded(
address indexed account,
address indexed recipient,
uint256 lpTokenAmount,
uint256 cncReceived,
uint256 lockTime
);
event DebtPoolSet(address indexed pool);
event DebtPoolFeesClaimed(uint256 crvAmount, uint256 cvxAmount, uint256 cncAmount);
event StreamClaimed(address indexed account, uint256 amount);
event BondingStarted(uint256 amount, uint256 epochs);
event RemainingCNCRecovered(uint256 amount);
function startBonding() external;
function setCncStartPrice(uint256 _cncStartPrice) external;
function setCncPriceIncreaseFactor(uint256 _priceIncreaseFactor) external;
function setMinBondingAmount(uint256 _minBondingAmount) external;
function setDebtPool(address _debtPool) external;
function bondCncCrvUsd(
uint256 lpTokenAmount,
uint256 minCncReceived,
uint64 cncLockTime
) external returns (uint256);
function recoverRemainingCNC() external;
function claimStream() external;
function claimFeesForDebtPool() external;
function streamCheckpoint() external;
function accountCheckpoint(address account) external;
function computeCurrentCncBondPrice() external view returns (uint256);
function cncAvailable() external view returns (uint256);
function cncBondPrice() external view returns (uint256);
function bondCncCrvUsdFor(
uint256 lpTokenAmount,
uint256 minCncReceived,
uint64 cncLockTime,
address recipient
) external returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
interface IPoolAdapter {
/// @notice This is to set which LP token price the value computation should use
/// `Latest` uses a freshly computed price
/// `Cached` uses the price in cache
/// `Minimum` uses the minimum of these two
enum PriceMode {
Latest,
Cached,
Minimum
}
/// @notice Deposit `underlyingAmount` of `underlying` into `pool`
/// @dev This function should be written with the assumption that it will be delegate-called into
function deposit(address pool, address underlying, uint256 underlyingAmount) external;
/// @notice Withdraw `underlyingAmount` of `underlying` from `pool`
/// @dev This function should be written with the assumption that it will be delegate-called into
function withdraw(address pool, address underlying, uint256 underlyingAmount) external;
/// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of USD
function computePoolValueInUSD(
address conicPool,
address pool
) external view returns (uint256 usdAmount);
/// @notice Updates the price caches of the given pools
function updatePriceCache(address pool) external;
/// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of USD
/// using the given price mode
function computePoolValueInUSD(
address conicPool,
address pool,
PriceMode priceMode
) external view returns (uint256 usdAmount);
/// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of underlying
function computePoolValueInUnderlying(
address conicPool,
address pool,
address underlying,
uint256 underlyingPrice
) external view returns (uint256 underlyingAmount);
/// @notice Returns the amount of of assets that `conicPool` holds in `pool`, in terms of underlying
/// using the given price mode
function computePoolValueInUnderlying(
address conicPool,
address pool,
address underlying,
uint256 underlyingPrice,
PriceMode priceMode
) external view returns (uint256 underlyingAmount);
/// @notice Claim earnings of `conicPool` from `pool`
function claimEarnings(address conicPool, address pool) external;
/// @notice Returns the LP token of a given `pool`
function lpToken(address pool) external view returns (address);
/// @notice Returns true if `pool` supports `asset`
function supportsAsset(address pool, address asset) external view returns (bool);
/// @notice Returns the amount of CRV earned by `pool` on Convex
function getCRVEarnedOnConvex(
address account,
address curvePool
) external view returns (uint256);
/// @notice Executes a sanity check, e.g. checking for reentrancy
function executeSanityCheck(address pool) external;
/// @notice returns all the underlying coins of the pool
function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "IBooster.sol";
import "CurvePoolUtils.sol";
interface ICurveRegistryCache {
event PoolInitialized(address indexed pool, uint256 indexed pid);
function BOOSTER() external view returns (IBooster);
function initPool(address pool_) external;
function initPool(address pool_, uint256 pid_) external;
function lpToken(address pool_) external view returns (address);
function assetType(address pool_) external view returns (CurvePoolUtils.AssetType);
function isRegistered(address pool_) external view returns (bool);
function hasCoinDirectly(address pool_, address coin_) external view returns (bool);
function hasCoinAnywhere(address pool_, address coin_) external view returns (bool);
function basePool(address pool_) external view returns (address);
function coinIndex(address pool_, address coin_) external view returns (int128);
function nCoins(address pool_) external view returns (uint256);
function coinIndices(
address pool_,
address from_,
address to_
) external view returns (int128, int128, bool);
function decimals(address pool_) external view returns (uint256[] memory);
function interfaceVersion(address pool_) external view returns (uint256);
function poolFromLpToken(address lpToken_) external view returns (address);
function coins(address pool_) external view returns (address[] memory);
function getPid(address _pool) external view returns (uint256);
function getRewardPool(address _pool) external view returns (address);
function isShutdownPid(uint256 pid_) external view returns (bool);
/// @notice this returns the underlying coins of a pool, including the underlying of the base pool
/// if the given pool is a meta pool
/// This does not return the LP token of the base pool as an underlying
/// e.g. if the pool is 3CrvFrax, this will return FRAX, DAI, USDC, USDT
function getAllUnderlyingCoins(address pool) external view returns (address[] memory);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
interface IBooster {
function poolInfo(
uint256 pid
)
external
view
returns (
address lpToken,
address token,
address gauge,
address crvRewards,
address stash,
bool shutdown
);
function poolLength() external view returns (uint256);
function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns (bool);
function withdraw(uint256 _pid, uint256 _amount) external returns (bool);
function withdrawAll(uint256 _pid) external returns (bool);
function depositAll(uint256 _pid, bool _stake) external returns (bool);
function earmarkRewards(uint256 _pid) external returns (bool);
function isShutdown() external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "ICurvePoolV2.sol";
import "ICurvePoolV1.sol";
import "ScaledMath.sol";
library CurvePoolUtils {
using ScaledMath for uint256;
error NotWithinThreshold(address pool, uint256 assetA, uint256 assetB);
/// @dev by default, allow for 30 bps deviation regardless of pool fees
uint256 internal constant _DEFAULT_IMBALANCE_BUFFER = 30e14;
/// @dev Curve scales the `fee` by 1e10
uint8 internal constant _CURVE_POOL_FEE_DECIMALS = 10;
/// @dev allow imbalance to be buffer + 3x the fee, e.g. if fee is 3.6 bps and buffer is 30 bps, allow 40.8 bps
uint256 internal constant _FEE_IMBALANCE_MULTIPLIER = 3;
enum AssetType {
USD,
ETH,
BTC,
OTHER,
CRYPTO
}
struct PoolMeta {
address pool;
uint256 numberOfCoins;
AssetType assetType;
uint256[] decimals;
uint256[] prices;
uint256[] imbalanceBuffers;
}
function ensurePoolBalanced(PoolMeta memory poolMeta) internal view {
uint256 poolFee = ICurvePoolV1(poolMeta.pool).fee().convertScale(
_CURVE_POOL_FEE_DECIMALS,
18
);
for (uint256 i = 0; i < poolMeta.numberOfCoins - 1; i++) {
uint256 fromDecimals = poolMeta.decimals[i];
uint256 fromBalance = 10 ** fromDecimals;
uint256 fromPrice = poolMeta.prices[i];
for (uint256 j = i + 1; j < poolMeta.numberOfCoins; j++) {
uint256 toDecimals = poolMeta.decimals[j];
uint256 toPrice = poolMeta.prices[j];
uint256 toExpectedUnscaled = (fromBalance * fromPrice) / toPrice;
uint256 toExpected = toExpectedUnscaled.convertScale(
uint8(fromDecimals),
uint8(toDecimals)
);
uint256 toActual;
if (poolMeta.assetType == AssetType.CRYPTO) {
// Handling crypto pools
toActual = ICurvePoolV2(poolMeta.pool).get_dy(i, j, fromBalance);
} else {
// Handling other pools
toActual = ICurvePoolV1(poolMeta.pool).get_dy(
int128(uint128(i)),
int128(uint128(j)),
fromBalance
);
}
uint256 _maxImbalanceBuffer = poolMeta.imbalanceBuffers[i].max(
poolMeta.imbalanceBuffers[j]
);
if (!_isWithinThreshold(toExpected, toActual, poolFee, _maxImbalanceBuffer))
revert NotWithinThreshold(poolMeta.pool, i, j);
}
}
}
function _isWithinThreshold(
uint256 a,
uint256 b,
uint256 poolFee,
uint256 imbalanceBuffer
) internal pure returns (bool) {
if (imbalanceBuffer == 0) imbalanceBuffer = _DEFAULT_IMBALANCE_BUFFER;
uint256 imbalanceTreshold = imbalanceBuffer + poolFee * _FEE_IMBALANCE_MULTIPLIER;
if (a > b) return (a - b).divDown(a) <= imbalanceTreshold;
return (b - a).divDown(b) <= imbalanceTreshold;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
interface ICurvePoolV2 {
function token() external view returns (address);
function coins(uint256 i) external view returns (address);
function factory() external view returns (address);
function exchange(
uint256 i,
uint256 j,
uint256 dx,
uint256 min_dy,
bool use_eth,
address receiver
) external returns (uint256);
function exchange_underlying(
uint256 i,
uint256 j,
uint256 dx,
uint256 min_dy,
address receiver
) external returns (uint256);
function add_liquidity(
uint256[2] memory amounts,
uint256 min_mint_amount,
bool use_eth,
address receiver
) external returns (uint256);
function add_liquidity(
uint256[2] memory amounts,
uint256 min_mint_amount
) external returns (uint256);
function add_liquidity(
uint256[3] memory amounts,
uint256 min_mint_amount,
bool use_eth,
address receiver
) external returns (uint256);
function add_liquidity(
uint256[3] memory amounts,
uint256 min_mint_amount
) external returns (uint256);
function remove_liquidity(
uint256 _amount,
uint256[2] memory min_amounts,
bool use_eth,
address receiver
) external;
function remove_liquidity(uint256 _amount, uint256[2] memory min_amounts) external;
function remove_liquidity(
uint256 _amount,
uint256[3] memory min_amounts,
bool use_eth,
address receiver
) external;
function remove_liquidity(uint256 _amount, uint256[3] memory min_amounts) external;
function remove_liquidity_one_coin(
uint256 token_amount,
uint256 i,
uint256 min_amount,
bool use_eth,
address receiver
) external returns (uint256);
function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256);
function calc_token_amount(uint256[] memory amounts) external view returns (uint256);
function calc_withdraw_one_coin(
uint256 token_amount,
uint256 i
) external view returns (uint256);
function get_virtual_price() external view returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
interface ICurvePoolV1 {
function get_virtual_price() external view returns (uint256);
function add_liquidity(uint256[8] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[7] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[6] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[5] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external;
function add_liquidity(uint256[2] calldata amounts, uint256 min_mint_amount) external;
function remove_liquidity_imbalance(
uint256[4] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity_imbalance(
uint256[3] calldata amounts,
uint256 max_burn_amount
) external;
function remove_liquidity_imbalance(
uint256[2] calldata amounts,
uint256 max_burn_amount
) external;
function lp_token() external view returns (address);
function A_PRECISION() external view returns (uint256);
function A_precise() external view returns (uint256);
function remove_liquidity(uint256 _amount, uint256[3] calldata min_amounts) external;
function exchange(
int128 from,
int128 to,
uint256 _from_amount,
uint256 _min_to_amount
) external;
function coins(uint256 i) external view returns (address);
function balances(uint256 i) external view returns (uint256);
function get_dy(int128 i, int128 j, uint256 _dx) external view returns (uint256);
function calc_token_amount(
uint256[4] calldata amounts,
bool deposit
) external view returns (uint256);
function calc_token_amount(
uint256[3] calldata amounts,
bool deposit
) external view returns (uint256);
function calc_token_amount(
uint256[2] calldata amounts,
bool deposit
) external view returns (uint256);
function calc_withdraw_one_coin(
uint256 _token_amount,
int128 i
) external view returns (uint256);
function remove_liquidity_one_coin(
uint256 _token_amount,
int128 i,
uint256 min_amount
) external;
function fee() external view returns (uint256);
}{
"evmVersion": "london",
"optimizer": {
"enabled": true,
"runs": 200
},
"libraries": {
"CNCLockerV3.sol": {}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_controller","type":"address"},{"internalType":"address","name":"_cncToken","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_crv","type":"address"},{"internalType":"address","name":"_cvx","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AirdropBoostClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"crvAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cvxAmount","type":"uint256"}],"name":"FeesClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"crvAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cvxAmount","type":"uint256"}],"name":"FeesReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"kicker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KickExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"},{"indexed":false,"internalType":"bool","name":"relocked","type":"bool"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Relocked","type":"event"},{"anonymous":false,"inputs":[],"name":"Shutdown","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnlockExecuted","type":"event"},{"inputs":[],"name":"accruedFeesIntegralCrv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedFeesIntegralCvx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"airdropBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"airdropEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"}],"internalType":"struct ICNCLockerV3.LockId[]","name":"locks","type":"tuple[]"}],"name":"batchKick","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint16","name":"nodeIndex","type":"uint16"},{"internalType":"bytes32[]","name":"hashes","type":"bytes32[]"}],"internalType":"struct MerkleProof.Proof","name":"proof","type":"tuple"}],"name":"claimAirdropBoost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"crvAmount","type":"uint256"},{"internalType":"uint256","name":"cvxAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimableFees","outputs":[{"internalType":"uint256","name":"claimableCrv","type":"uint256"},{"internalType":"uint256","name":"claimableCvx","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimedAirdrop","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cncToken","outputs":[{"internalType":"contract ICNCToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"lockTime","type":"uint128"}],"name":"computeBoost","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crv","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cvx","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executeAvailableUnlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"}],"name":"executeAvailableUnlocksFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint64[]","name":"lockIds","type":"uint64[]"}],"name":"executeUnlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"lockId","type":"uint64"}],"name":"kick","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"lockTime","type":"uint64"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"lockTime","type":"uint64"},{"internalType":"bool","name":"relock_","type":"bool"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"lockTime","type":"uint64"},{"internalType":"bool","name":"relock_","type":"bool"},{"internalType":"address","name":"account","type":"address"}],"name":"lockFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedBoosted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountAccruedCrv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountAccruedCvx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountFeesCrv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perAccountFeesCvx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountCrv","type":"uint256"},{"internalType":"uint256","name":"amountCvx","type":"uint256"}],"name":"receiveFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"recoverToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"lockId","type":"uint64"},{"internalType":"uint64","name":"lockTime","type":"uint64"}],"name":"relock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"lockTime","type":"uint64"}],"name":"relock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"lockIds","type":"uint64[]"},{"internalType":"uint64","name":"lockTime","type":"uint64"}],"name":"relockMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutDown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalBoosted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"totalRewardsBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"totalStreamBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"totalVoteBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"unlockableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"unlockableBalanceBoosted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"userLocks","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"unlockTime","type":"uint64"},{"internalType":"uint128","name":"boost","type":"uint128"},{"internalType":"uint64","name":"id","type":"uint64"}],"internalType":"struct ICNCLockerV3.VoteLock[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"voteLocks","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"unlockTime","type":"uint64"},{"internalType":"uint128","name":"boost","type":"uint128"},{"internalType":"uint64","name":"id","type":"uint64"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101606040523480156200001257600080fd5b5060405162003f2d38038062003f2d8339810160408190526200003591620000f6565b620000403362000089565b6001600160a01b03808716610140528581166080528481166101205283811660e0528216610100526200007762eff100426200016e565b60a05260c05250620001969350505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620000f157600080fd5b919050565b60008060008060008060c087890312156200011057600080fd5b6200011b87620000d9565b95506200012b60208801620000d9565b94506200013b60408801620000d9565b93506200014b60608801620000d9565b92506200015b60808801620000d9565b915060a087015190509295509295509295565b808201808211156200019057634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c05160e051610100516101205161014051613cc5620002686000396000818161078e01528181610f3b015261297c0152600081816104b301526117d801526000818161060a01528181610dac0152818161174401526121b901526000818161052201528181610d7701528181611706015261217d0152600081816103fb0152610a180152600081816105d2015261086e0152600081816104fb01528181611423015281816116c901528181611ab501528181611ae901528181611e1e015261256f0152613cc56000f3fe608060405234801561001057600080fd5b50600436106102bb5760003560e01c8063715018a611610182578063a6aed923116100e9578063ddecf662116100a2578063edaf69bd1161007c578063edaf69bd14610763578063f2fde38b14610776578063f77c479114610789578063f816144e146107b057600080fd5b8063ddecf662146106db578063dfb142ae14610725578063ea312d761461073857600080fd5b8063a6aed92314610685578063bb3cac5414610698578063bf4b3e65146106ab578063bf86d690146106b3578063c5890d2d146106c0578063d294f093146106d357600080fd5b80638da5cb5b1161013b5780638da5cb5b146105f4578063923c1d611461060557806393ed9d011461062c578063984acb491461063f5780639ae697bf146106525780639be65a601461067257600080fd5b8063715018a61461055757806378f89c201461055f5780637907706f146105725780637bf500c8146105855780637e0b2492146105a5578063806019c1146105cd57600080fd5b806346e919d0116102265780635f07112f116101df5780635f07112f1461049b57806361d027b3146104ae578063631516c2146104ed578063645d28a8146104f65780636a4874a11461051d57806370a082311461054457600080fd5b806346e919d0146104305780634f348758146104435780635219c5121461045657806356891412146104695780635cad88eb146104725780635ee26ad01461047b57600080fd5b80631c91607f116102785780631c91607f1461038757806326a4c842146103a757806328a81039146103ba5780632a324607146103e35780632eb4a7ab146103f65780633efa99791461041d57600080fd5b80630259ef58146102c05780630499abd4146102e95780630b70608f1461031757806310b9e5831461032c57806311e1dc1e146103345780631b93f66d14610354575b600080fd5b6102d36102ce366004613301565b6107b9565b6040516102e0919061331e565b60405180910390f35b6103096102f7366004613301565b600c6020526000908152604090205481565b6040519081526020016102e0565b61032a610325366004613397565b61086c565b005b61032a610ad5565b610309610342366004613301565b600e6020526000908152604090205481565b610377610362366004613301565b60056020526000908152604090205460ff1681565b60405190151581526020016102e0565b610309610395366004613301565b600f6020526000908152604090205481565b61032a6103b536600461344b565b610b68565b6103096103c8366004613301565b6001600160a01b031660009081526002602052604090205490565b6103096103f1366004613301565b610c2c565b6103097f000000000000000000000000000000000000000000000000000000000000000081565b61032a61042b36600461349e565b610d26565b61030961043e366004613301565b610d36565b61032a6104513660046134ca565b610d6a565b610309610464366004613301565b610e5b565b61030960075481565b610309600a5481565b610309610489366004613301565b60026020526000908152604090205481565b61032a6104a93660046134fa565b610f04565b6104d57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102e0565b61030960085481565b6104d57f000000000000000000000000000000000000000000000000000000000000000081565b6104d57f000000000000000000000000000000000000000000000000000000000000000081565b610309610552366004613301565b610f15565b61032a610f20565b61030961056d366004613301565b610f34565b61032a61058036600461353a565b611036565b610309610593366004613301565b600d6020526000908152604090205481565b6105b86105b3366004613301565b6110b1565b604080519283526020830191909152016102e0565b6103097f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b03166104d5565b6104d57f000000000000000000000000000000000000000000000000000000000000000081565b61030961063a366004613564565b61116b565b61032a61064d3660046135b8565b61148a565b610309610660366004613301565b60016020526000908152604090205481565b61032a610680366004613301565b6116c7565b61032a6106933660046135d3565b611896565b6103096106a6366004613301565b611c4a565b610309611c94565b6009546103779060ff1681565b61032a6106ce3660046135f1565b611ca4565b6105b861214b565b6106ee6106e9366004613642565b61223a565b604080519485526001600160401b0393841660208601526001600160801b03909216918401919091521660608201526080016102e0565b610309610733366004613301565b61229a565b61074b61074636600461366e565b6125d5565b6040516001600160801b0390911681526020016102e0565b61032a610771366004613728565b612646565b61032a610784366004613301565b6126a8565b6104d57f000000000000000000000000000000000000000000000000000000000000000081565b610309600b5481565b6001600160a01b0381166000908152600360209081526040808320805482518185028101850190935280835260609492939192909184015b828210156108615760008481526020908190206040805160808101825260028602909201805483526001908101546001600160401b03808216858701526001600160801b03600160401b83041693850193909352600160c01b9004909116606083015290835290920191016107f1565b505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000042106108d05760405162461bcd60e51b815260206004820152600d60248201526c185a5c991c9bdc08195b991959609a1b60448201526064015b60405180910390fd5b3360009081526005602052604090205460ff16156109225760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b60448201526064016108c7565b670de0b6b3a764000082101561097a5760405162461bcd60e51b815260206004820152601860248201527f616d6f756e742063616e6e6f742062652062656c6f772031000000000000000060448201526064016108c7565b6730927f74c9de00008211156109d25760405162461bcd60e51b815260206004820181905260248201527f616d6f756e742065786365656473206d61782061697264726f7020626f6f737460448201526064016108c7565b6040516bffffffffffffffffffffffff193360601b16602082015260348101839052600090605401604051602081830303815290604052805190602001209050610a48817f000000000000000000000000000000000000000000000000000000000000000084610a41906137e8565b9190612721565b610a845760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b60448201526064016108c7565b3360008181526004602052604090819020859055517ffb7c165a21b698d172209fd3fbb4a907042c12438cd506666064cd98e0a142aa90610ac89086815260200190565b60405180910390a2505050565b610add61281f565b60095460ff1615610b305760405162461bcd60e51b815260206004820152601860248201527f6c6f636b657220616c72656164792073757370656e646564000000000000000060448201526064016108c7565b6009805460ff191660011790556040517f4426aa1fb73e391071491fcfe21a88b5c38a0a0333a1f6e77161470439704cf890600090a1565b60095460ff1615610b8b5760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e340011801590610bb4575063013c68006001600160401b03821611155b610bd05760405162461bcd60e51b81526004016108c7906138c7565b610bd933612879565b60005b82811015610c2657610c14848483818110610bf957610bf96138f2565b9050602002016020810190610c0e91906135b8565b83612a4f565b80610c1e8161391e565b915050610bdc565b50505050565b6001600160a01b03811660009081526003602052604081208054829190825b81811015610d1c57426001600160801b0316838281548110610c6f57610c6f6138f2565b60009182526020909120600160029092020101546001600160401b031611610d0a57610cfd838281548110610ca657610ca66138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316848381548110610ce657610ce66138f2565b600091825260209091206002909102015490612d1e565b610d079085613937565b93505b80610d148161391e565b915050610c4b565b5091949350505050565b610d3282826000610f04565b5050565b6000610d4182610c2c565b6001600160a01b038316600090815260026020526040902054610d64919061394a565b92915050565b610d9f6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085612d47565b610dd46001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612d47565b600854610de2908390612db2565b600a6000828254610df39190613937565b9091555050600854610e06908290612db2565b600b6000828254610e179190613937565b9091555050604080518381526020810183905233917f213e72af0d3613bd643cff3059f872c1015e6541624e37872bf95eefbaf220a8910160405180910390a25050565b6001600160a01b03811660009081526003602052604081208054829190825b81811015610d1c57426001600160801b0316838281548110610e9e57610e9e6138f2565b60009182526020909120600160029092020101546001600160401b031611610ef257828181548110610ed257610ed26138f2565b90600052602060002090600202016000015484610eef9190613937565b93505b80610efc8161391e565b915050610e7a565b610f1083838333611ca4565b505050565b6000610d6482610f34565b610f2861281f565b610f326000612dcb565b565b6000610d647f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166348439e7e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb919061395d565b60405163067ba3d960e41b81526001600160a01b03858116600483015291909116906367ba3d9090602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611027919061397a565b61103084610d36565b90612d1e565b60095460ff16156110595760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e340011801590611082575063013c68006001600160401b03821611155b61109e5760405162461bcd60e51b81526004016108c7906138c7565b6110a733612879565b610d328282612a4f565b6001600160a01b038116600090815260026020908152604080832054600c909252822054600a548392916110f0916110e9919061394a565b8290612d1e565b6001600160a01b0385166000908152600d60205260409020546111139190613937565b6001600160a01b0385166000908152600e6020526040902054600b54919450611140916110e9919061394a565b6001600160a01b0385166000908152600f60205260409020546111639190613937565b915050915091565b600061117633612879565b3360009081526003602052604081208190815b8581101561139c5760006111c3338989858181106111a9576111a96138f2565b90506020020160208101906111be91906135b8565b612e1b565b60095490915060ff16806112055750428382815481106111e5576111e56138f2565b60009182526020909120600160029092020101546001600160401b031611155b6112445760405162461bcd60e51b815260206004820152601060248201526f1b1bd8dac81b9bdd08195e1c1a5c995960821b60448201526064016108c7565b828181548110611256576112566138f2565b906000526020600020906002020160000154856112739190613937565b945061128a838281548110610ca657610ca66138f2565b6112949085613937565b835490945083906112a79060019061394a565b815481106112b7576112b76138f2565b90600052602060002090600202018382815481106112d7576112d76138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b03909116179055825483908061136b5761136b613993565b60008281526020812060026000199093019283020181815560010155905550806113948161391e565b915050611189565b5082600760008282546113af919061394a565b9250508190555081600860008282546113c8919061394a565b909155505033600090815260016020526040812080548592906113ec90849061394a565b9091555050336000908152600260205260408120805484929061141090849061394a565b9091555061144a90506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168885612ef6565b60405183815233907fb291e2a2847a5ad6d47409943306c6d6e8c63a9855b849701b868191e94789709060200160405180910390a2509095945050505050565b60095460ff16156114ad5760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e3400118015906114d6575063013c68006001600160401b03821611155b6114f25760405162461bcd60e51b81526004016108c7906138c7565b6114fb33612879565b600061150f826001600160401b03166125d5565b9050600061151d83426139a9565b336000908152600360205260408120549192505b818110156115b25733600090815260036020526040902080546001600160401b038516919083908110611566576115666138f2565b60009182526020909120600160029092020101546001600160401b0316106115a05760405162461bcd60e51b81526004016108c7906139d0565b806115aa8161391e565b915050611531565b503360009081526003602052604081206115cb916132b1565b3360009081526002602052604081205460088054919290916115ee90849061394a565b9091555050336000818152600260209081526040808320839055600190915290205461161c91908486612f26565b3360009081526001602052604081205461163f906001600160801b038616612d1e565b905080600860008282546116539190613937565b90915550503360009081526002602052604081208054839290611677908490613937565b9091555050336000818152600160209081526040918290205491519182527fe2d155d9d74decc198a9a9b4f5bddb24ee0842ee745c9ce57e3573b971e50d9d910160405180910390a25050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161415801561173b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614155b801561177957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614155b6117bd5760405162461bcd60e51b815260206004820152601560248201527431b0b73737ba103bb4ba34323930bb903a37b5b2b760591b60448201526064016108c7565b6040516370a0823160e01b8152306004820152819061185e907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184d919061397a565b6001600160a01b0384169190612ef6565b6040516001600160a01b038316907f17a79be10b6da9324a110f0ea6d3043db38f1eee6e2ee1dbfa7272338e39da4590600090a25050565b60006118a28383612e1b565b6001600160a01b03841660009081526003602052604090208054919250906001600160801b034216906224ea00908390859081106118e2576118e26138f2565b600091825260209091206001600290920201015461190991906001600160401b0316613a07565b6001600160801b031611156119585760405162461bcd60e51b815260206004820152601560248201527463616e6e6f74206b69636b2074686973206c6f636b60581b60448201526064016108c7565b61196184612879565b6000818381548110611975576119756138f2565b9060005260206000209060020201600001549050806007600082825461199b919061394a565b925050819055506119e28284815481106119b7576119b76138f2565b60009182526020909120600290910201600101548290600160401b90046001600160801b0316612d1e565b600860008282546119f3919061394a565b90915550506001600160a01b03851660009081526001602052604081208054839290611a2090849061394a565b92505081905550611a3c8284815481106119b7576119b76138f2565b6001600160a01b03861660009081526002602052604081208054909190611a6490849061394a565b9091555060009050611a7e8267016345785d8a0000612d1e565b9050683635c9adc5dea00000811115611a9d5750683635c9adc5dea000005b611adc86611aab838561394a565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190612ef6565b611b106001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612ef6565b60405182815233906001600160a01b038816907f9716d4c8630c7c1a47a462f169d1764a38687f7532baf2bd74a791afc20030e69060200160405180910390a382548390611b609060019061394a565b81548110611b7057611b706138f2565b9060005260206000209060020201838581548110611b9057611b906138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b039091161790558254839080611c2457611c24613993565b600082815260208120600260001990930192830201818155600101559055505050505050565b6001600160a01b0381166000908152600460205260408120548103611c785750670de0b6b3a7640000919050565b506001600160a01b031660009081526004602052604090205490565b6000611c9f3361229a565b905090565b60095460ff1615611cc75760405162461bcd60e51b81526004016108c79061389d565b678ac7230489e80000841015611d125760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b60448201526064016108c7565b6001600160401b038316629e340011801590611d3b575063013c68006001600160401b03841611155b611d575760405162461bcd60e51b81526004016108c7906138c7565b811580611d6c5750336001600160a01b038216145b611daf5760405162461bcd60e51b81526020600482015260146024820152733932b637b1b59037b7363c903337b91039b2b63360611b60448201526064016108c7565b6001600160a01b038116600090815260036020526040902054600a11611e085760405162461bcd60e51b815260206004820152600e60248201526d746f6f206d616e79206c6f636b7360901b60448201526064016108c7565b611e1181612879565b611e466001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333087612d47565b6000611e5a846001600160401b03166125d5565b90506000611e6733611c4a565b9050670de0b6b3a7640000811115611eb957336000908152600560205260409020805460ff19166001179055611ea66001600160801b03831682613011565b3360009081526004602052604081205591505b6000611ec586426139a9565b905060008515612040576001600160a01b038516600090815260036020526040812054905b81811015611f74576001600160a01b038716600090815260036020526040902080546001600160401b038616919083908110611f2857611f286138f2565b60009182526020909120600160029092020101546001600160401b031610611f625760405162461bcd60e51b81526004016108c7906139d0565b80611f6c8161391e565b915050611eea565b506001600160a01b0386166000908152600360205260408120611f96916132b1565b6001600160a01b0386166000908152600260205260408120546008805491929091611fc290849061394a565b90915550506001600160a01b03861660009081526002602090815260408083208390556001909152902054612005908790611ffe908c90613937565b8588612f26565b6001600160a01b038616600090815260016020526040902054612038906001600160801b03871690611030908c90613937565b915050612062565b61204c85898487612f26565b61205f886001600160801b038616612d1e565b90505b87600760008282546120749190613937565b92505081905550806008600082825461208d9190613937565b90915550506001600160a01b038516600090815260016020526040812080548a92906120ba908490613937565b90915550506001600160a01b038516600090815260026020526040812080548392906120e7908490613937565b9091555050604080518981526001600160401b03841660208201528715158183015290516001600160a01b038716917fca8d506eda84f8ed07c2908ae102299d34888ef5e19b97f56e4d6fcd1104c31e919081900360600190a25050505050505050565b60008061215733612879565b5050336000818152600d6020908152604080832054600f9092529091205490916121ac907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169084612ef6565b6121e06001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612ef6565b336000818152600d60209081526040808320839055600f82528083209290925581518581529081018490527f1ac537f0ad67b64ac68a04587ff3a4cb6977de22eb2c37ee560897a92c6d07c7910160405180910390a29091565b6003602052816000526040600020818154811061225657600080fd5b6000918252602090912060029091020180546001909101549092506001600160401b0380821692506001600160801b03600160401b83041691600160c01b90041684565b60006001600160a01b0382166122e85760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b2103232b9ba34b730ba34b7b760691b60448201526064016108c7565b6122f133612879565b33600090815260036020526040812080548291905b80156124e95761231760018261394a565b60095490915060ff1680612359575042828281548110612339576123396138f2565b60009182526020909120600160029092020101546001600160401b031611155b156124e457818181548110612370576123706138f2565b9060005260206000209060020201600001548461238d9190613937565b93506123e48282815481106123a4576123a46138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316838381548110610ce657610ce66138f2565b6123ee9084613937565b825490935082906124019060019061394a565b81548110612411576124116138f2565b9060005260206000209060020201828281548110612431576124316138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b0390911617905581548290806124c5576124c5613993565b6000828152602081206002600019909301928302018181556001015590555b612306565b83600760008282546124fb919061394a565b925050819055508260086000828254612514919061394a565b9091555050336000908152600160205260408120805486929061253890849061394a565b9091555050336000908152600260205260408120805485929061255c90849061394a565b9091555061259690506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168786612ef6565b60405184815233907fb291e2a2847a5ad6d47409943306c6d6e8c63a9855b849701b868191e94789709060200160405180910390a25091949350505050565b6000670de0b6b3a764000061263c6126136125f7629e340063013c6800613a27565b612604629e340087613a27565b6001600160801b031690613033565b61262d670de0b6b3a76400006714d1120d7b160000613a27565b6001600160801b031690613011565b610d649190613a07565b60005b8151811015610d3257612696828281518110612667576126676138f2565b602002602001015160000151838381518110612685576126856138f2565b602002602001015160200151611896565b806126a08161391e565b915050612649565b6126b061281f565b6001600160a01b0381166127155760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108c7565b61271e81612dcb565b50565b602083015151835160009190825b8281101561281457612742600283613a5d565b61ffff166000036127a3578587602001518281518110612764576127646138f2565b6020026020010151604051602001612786929190918252602082015260400190565b6040516020818303038152906040528051906020012095506127f5565b866020015181815181106127b9576127b96138f2565b6020026020010151866040516020016127dc929190918252602082015260400190565b6040516020818303038152906040528051906020012095505b612800600283613a7e565b91508061280c8161391e565b91505061272f565b505050911492915050565b6000546001600160a01b03163314610f325760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b6001600160a01b038116600090815260026020908152604080832054600a54600b54600c90945291909320549091906128bd906128b6908461394a565b8490612d1e565b6001600160a01b0385166000908152600d6020526040812080549091906128e5908490613937565b90915550506001600160a01b0384166000908152600c60209081526040808320859055600e90915290205461291e906128b6908361394a565b6001600160a01b0385166000908152600f602052604081208054909190612946908490613937565b90915550506001600160a01b038085166000908152600e602090815260408083208590558051639845755960e01b8152905192937f000000000000000000000000000000000000000000000000000000000000000016926398457559926004808401939192918290030181865afa1580156129c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e9919061395d565b60405163bf928f8b60e01b81526001600160a01b0387811660048301529192509082169063bf928f8b90602401600060405180830381600087803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b505050505050505050565b6000612a5b3384612e1b565b90506000612a71836001600160401b03166125d5565b90506000612a7f84426139a9565b3360009081526003602052604090208054919250906001600160401b03831690829086908110612ab157612ab16138f2565b60009182526020909120600160029092020101546001600160401b031610612aeb5760405162461bcd60e51b81526004016108c7906139d0565b6000818581548110612aff57612aff6138f2565b90600052602060002090600202016000015490506000612b6a838781548110612b2a57612b2a6138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316848881548110610ce657610ce66138f2565b83549091508390612b7d9060019061394a565b81548110612b8d57612b8d6138f2565b9060005260206000209060020201838781548110612bad57612bad6138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b039091161790558254839080612c4157612c41613993565b600082815260208120600260001990930192830201818155600101559055612c6b33838688612f26565b6000612c80836001600160801b038816612d1e565b90508181600854612c919190613937565b612c9b919061394a565b600855336000908152600260205260409020548290612cbb908390613937565b612cc5919061394a565b33600081815260026020526040908190209290925590517fe2d155d9d74decc198a9a9b4f5bddb24ee0842ee745c9ce57e3573b971e50d9d90612d0b9086815260200190565b60405180910390a2505050505050505050565b6000612d2c6012600a613b83565b612d368385613b8f565b612d409190613ba6565b9392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610c269085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261304c565b600081612dc16012600a613b83565b612d369085613b8f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600090815260036020526040812054815b81811015612eb8576001600160a01b038516600090815260036020526040902080546001600160401b038616919083908110612e7457612e746138f2565b6000918252602090912060029091020160010154600160c01b90046001600160401b031603612ea6579150610d649050565b80612eb08161391e565b915050612e36565b5060405162461bcd60e51b81526020600482015260126024820152711b1bd8dac8191bd95cdb89dd08195e1a5cdd60721b60448201526064016108c7565b6040516001600160a01b038316602482015260448101829052610f1090849063a9059cbb60e01b90606401612d7b565b6006546001600160a01b038516600090815260036020908152604080832081516080810183528881526001600160401b038881168286019081526001600160801b03808a1695840195865297821660608401818152855460018181018855968a529790982093516002909702909301958655519483018054945196518216600160c01b026001600160c01b0397909816600160401b026001600160c01b031990951695909116949094179290921793909316939093179055612fe99082906139a9565b6006805467ffffffffffffffff19166001600160401b03929092169190911790555050505050565b600061301f6012600a613b83565b6130298385613bba565b612d409190613be5565b6000816130426012600a613b83565b6130299085613bba565b60006130a1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131219092919063ffffffff16565b90508051600014806130c25750808060200190518101906130c29190613bff565b610f105760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108c7565b60606131308484600085613138565b949350505050565b6060824710156131995760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108c7565b600080866001600160a01b031685876040516131b59190613c40565b60006040518083038185875af1925050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b509150915061320887838387613213565b979650505050505050565b6060831561328257825160000361327b576001600160a01b0385163b61327b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108c7565b5081613130565b61313083838151156132975781518083602001fd5b8060405162461bcd60e51b81526004016108c79190613c5c565b508054600082556002029060005260206000209081019061271e91905b808211156132e857600080825560018201556002016132ce565b5090565b6001600160a01b038116811461271e57600080fd5b60006020828403121561331357600080fd5b8135612d40816132ec565b602080825282518282018190526000919060409081850190868401855b8281101561338a57815180518552868101516001600160401b0390811688870152868201516001600160801b03168787015260609182015116908501526080909301929085019060010161333b565b5091979650505050505050565b600080604083850312156133aa57600080fd5b8235915060208301356001600160401b038111156133c757600080fd5b8301604081860312156133d957600080fd5b809150509250929050565b60008083601f8401126133f657600080fd5b5081356001600160401b0381111561340d57600080fd5b6020830191508360208260051b850101111561342857600080fd5b9250929050565b80356001600160401b038116811461344657600080fd5b919050565b60008060006040848603121561346057600080fd5b83356001600160401b0381111561347657600080fd5b613482868287016133e4565b909450925061349590506020850161342f565b90509250925092565b600080604083850312156134b157600080fd5b823591506134c16020840161342f565b90509250929050565b600080604083850312156134dd57600080fd5b50508035926020909101359150565b801515811461271e57600080fd5b60008060006060848603121561350f57600080fd5b8335925061351f6020850161342f565b9150604084013561352f816134ec565b809150509250925092565b6000806040838503121561354d57600080fd5b6135568361342f565b91506134c16020840161342f565b60008060006040848603121561357957600080fd5b8335613584816132ec565b925060208401356001600160401b0381111561359f57600080fd5b6135ab868287016133e4565b9497909650939450505050565b6000602082840312156135ca57600080fd5b612d408261342f565b600080604083850312156135e657600080fd5b8235613556816132ec565b6000806000806080858703121561360757600080fd5b843593506136176020860161342f565b92506040850135613627816134ec565b91506060850135613637816132ec565b939692955090935050565b6000806040838503121561365557600080fd5b8235613660816132ec565b946020939093013593505050565b60006020828403121561368057600080fd5b81356001600160801b0381168114612d4057600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156136cf576136cf613697565b60405290565b604051601f8201601f191681016001600160401b03811182821017156136fd576136fd613697565b604052919050565b60006001600160401b0382111561371e5761371e613697565b5060051b60200190565b6000602080838503121561373b57600080fd5b82356001600160401b0381111561375157600080fd5b8301601f8101851361376257600080fd5b803561377561377082613705565b6136d5565b81815260069190911b8201830190838101908783111561379457600080fd5b928401925b8284101561320857604084890312156137b25760008081fd5b6137ba6136ad565b84356137c5816132ec565b81526137d285870161342f565b8187015282526040939093019290840190613799565b6000604082360312156137fa57600080fd5b6138026136ad565b823561ffff8116811461381457600080fd5b81526020838101356001600160401b0381111561383057600080fd5b840136601f82011261384157600080fd5b803561384f61377082613705565b81815260059190911b8201830190838101903683111561386e57600080fd5b928401925b8284101561388c57833582529284019290840190613873565b938501939093525091949350505050565b60208082526010908201526f1b1bd8dad95c881cdd5cdc195b99195960821b604082015260600190565b6020808252601190820152701b1bd8dac81d1a5b59481a5b9d985b1a59607a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161393057613930613908565b5060010190565b80820180821115610d6457610d64613908565b81810381811115610d6457610d64613908565b60006020828403121561396f57600080fd5b8151612d40816132ec565b60006020828403121561398c57600080fd5b5051919050565b634e487b7160e01b600052603160045260246000fd5b6001600160401b038181168382160190808211156139c9576139c9613908565b5092915050565b6020808252601e908201527f63616e6e6f74206d6f76652074686520756e6c6f636b2074696d652075700000604082015260600190565b6001600160801b038181168382160190808211156139c9576139c9613908565b6001600160801b038281168282160390808211156139c9576139c9613908565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680613a7257613a72613a47565b92169190910692915050565b600061ffff80841680613a9357613a93613a47565b92169190910492915050565b600181815b80851115613ada578160001904821115613ac057613ac0613908565b80851615613acd57918102915b93841c9390800290613aa4565b509250929050565b600082613af157506001610d64565b81613afe57506000610d64565b8160018114613b145760028114613b1e57613b3a565b6001915050610d64565b60ff841115613b2f57613b2f613908565b50506001821b610d64565b5060208310610133831016604e8410600b8410161715613b5d575081810a610d64565b613b678383613a9f565b8060001904821115613b7b57613b7b613908565b029392505050565b6000612d408383613ae2565b8082028115828204841417610d6457610d64613908565b600082613bb557613bb5613a47565b500490565b6001600160801b03818116838216028082169190828114613bdd57613bdd613908565b505092915050565b60006001600160801b0380841680613a9357613a93613a47565b600060208284031215613c1157600080fd5b8151612d40816134ec565b60005b83811015613c37578181015183820152602001613c1f565b50506000910152565b60008251613c52818460208701613c1c565b9190910192915050565b6020815260008251806020840152613c7b816040850160208701613c1c565b601f01601f1916919091016040019291505056fea2646970667358221220110a4a0bdcb2a334a38a1327bc995e846ea2733286b8c500341b4b85048b6e7164736f6c634300081100330000000000000000000000002790ec478f150a98f5d96755601a26403df57eae0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc000000000000000000000000b27dc5f8286f063f11491c8f349053cb37718bea000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2bdb5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c5
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102bb5760003560e01c8063715018a611610182578063a6aed923116100e9578063ddecf662116100a2578063edaf69bd1161007c578063edaf69bd14610763578063f2fde38b14610776578063f77c479114610789578063f816144e146107b057600080fd5b8063ddecf662146106db578063dfb142ae14610725578063ea312d761461073857600080fd5b8063a6aed92314610685578063bb3cac5414610698578063bf4b3e65146106ab578063bf86d690146106b3578063c5890d2d146106c0578063d294f093146106d357600080fd5b80638da5cb5b1161013b5780638da5cb5b146105f4578063923c1d611461060557806393ed9d011461062c578063984acb491461063f5780639ae697bf146106525780639be65a601461067257600080fd5b8063715018a61461055757806378f89c201461055f5780637907706f146105725780637bf500c8146105855780637e0b2492146105a5578063806019c1146105cd57600080fd5b806346e919d0116102265780635f07112f116101df5780635f07112f1461049b57806361d027b3146104ae578063631516c2146104ed578063645d28a8146104f65780636a4874a11461051d57806370a082311461054457600080fd5b806346e919d0146104305780634f348758146104435780635219c5121461045657806356891412146104695780635cad88eb146104725780635ee26ad01461047b57600080fd5b80631c91607f116102785780631c91607f1461038757806326a4c842146103a757806328a81039146103ba5780632a324607146103e35780632eb4a7ab146103f65780633efa99791461041d57600080fd5b80630259ef58146102c05780630499abd4146102e95780630b70608f1461031757806310b9e5831461032c57806311e1dc1e146103345780631b93f66d14610354575b600080fd5b6102d36102ce366004613301565b6107b9565b6040516102e0919061331e565b60405180910390f35b6103096102f7366004613301565b600c6020526000908152604090205481565b6040519081526020016102e0565b61032a610325366004613397565b61086c565b005b61032a610ad5565b610309610342366004613301565b600e6020526000908152604090205481565b610377610362366004613301565b60056020526000908152604090205460ff1681565b60405190151581526020016102e0565b610309610395366004613301565b600f6020526000908152604090205481565b61032a6103b536600461344b565b610b68565b6103096103c8366004613301565b6001600160a01b031660009081526002602052604090205490565b6103096103f1366004613301565b610c2c565b6103097fdb5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c581565b61032a61042b36600461349e565b610d26565b61030961043e366004613301565b610d36565b61032a6104513660046134ca565b610d6a565b610309610464366004613301565b610e5b565b61030960075481565b610309600a5481565b610309610489366004613301565b60026020526000908152604090205481565b61032a6104a93660046134fa565b610f04565b6104d57f000000000000000000000000b27dc5f8286f063f11491c8f349053cb37718bea81565b6040516001600160a01b0390911681526020016102e0565b61030960085481565b6104d57f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc81565b6104d57f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd5281565b610309610552366004613301565b610f15565b61032a610f20565b61030961056d366004613301565b610f34565b61032a61058036600461353a565b611036565b610309610593366004613301565b600d6020526000908152604090205481565b6105b86105b3366004613301565b6110b1565b604080519283526020830191909152016102e0565b6103097f00000000000000000000000000000000000000000000000000000000669f916781565b6000546001600160a01b03166104d5565b6104d57f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b81565b61030961063a366004613564565b61116b565b61032a61064d3660046135b8565b61148a565b610309610660366004613301565b60016020526000908152604090205481565b61032a610680366004613301565b6116c7565b61032a6106933660046135d3565b611896565b6103096106a6366004613301565b611c4a565b610309611c94565b6009546103779060ff1681565b61032a6106ce3660046135f1565b611ca4565b6105b861214b565b6106ee6106e9366004613642565b61223a565b604080519485526001600160401b0393841660208601526001600160801b03909216918401919091521660608201526080016102e0565b610309610733366004613301565b61229a565b61074b61074636600461366e565b6125d5565b6040516001600160801b0390911681526020016102e0565b61032a610771366004613728565b612646565b61032a610784366004613301565b6126a8565b6104d57f0000000000000000000000002790ec478f150a98f5d96755601a26403df57eae81565b610309600b5481565b6001600160a01b0381166000908152600360209081526040808320805482518185028101850190935280835260609492939192909184015b828210156108615760008481526020908190206040805160808101825260028602909201805483526001908101546001600160401b03808216858701526001600160801b03600160401b83041693850193909352600160c01b9004909116606083015290835290920191016107f1565b505050509050919050565b7f00000000000000000000000000000000000000000000000000000000669f916742106108d05760405162461bcd60e51b815260206004820152600d60248201526c185a5c991c9bdc08195b991959609a1b60448201526064015b60405180910390fd5b3360009081526005602052604090205460ff16156109225760405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b60448201526064016108c7565b670de0b6b3a764000082101561097a5760405162461bcd60e51b815260206004820152601860248201527f616d6f756e742063616e6e6f742062652062656c6f772031000000000000000060448201526064016108c7565b6730927f74c9de00008211156109d25760405162461bcd60e51b815260206004820181905260248201527f616d6f756e742065786365656473206d61782061697264726f7020626f6f737460448201526064016108c7565b6040516bffffffffffffffffffffffff193360601b16602082015260348101839052600090605401604051602081830303815290604052805190602001209050610a48817fdb5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c584610a41906137e8565b9190612721565b610a845760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b60448201526064016108c7565b3360008181526004602052604090819020859055517ffb7c165a21b698d172209fd3fbb4a907042c12438cd506666064cd98e0a142aa90610ac89086815260200190565b60405180910390a2505050565b610add61281f565b60095460ff1615610b305760405162461bcd60e51b815260206004820152601860248201527f6c6f636b657220616c72656164792073757370656e646564000000000000000060448201526064016108c7565b6009805460ff191660011790556040517f4426aa1fb73e391071491fcfe21a88b5c38a0a0333a1f6e77161470439704cf890600090a1565b60095460ff1615610b8b5760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e340011801590610bb4575063013c68006001600160401b03821611155b610bd05760405162461bcd60e51b81526004016108c7906138c7565b610bd933612879565b60005b82811015610c2657610c14848483818110610bf957610bf96138f2565b9050602002016020810190610c0e91906135b8565b83612a4f565b80610c1e8161391e565b915050610bdc565b50505050565b6001600160a01b03811660009081526003602052604081208054829190825b81811015610d1c57426001600160801b0316838281548110610c6f57610c6f6138f2565b60009182526020909120600160029092020101546001600160401b031611610d0a57610cfd838281548110610ca657610ca66138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316848381548110610ce657610ce66138f2565b600091825260209091206002909102015490612d1e565b610d079085613937565b93505b80610d148161391e565b915050610c4b565b5091949350505050565b610d3282826000610f04565b5050565b6000610d4182610c2c565b6001600160a01b038316600090815260026020526040902054610d64919061394a565b92915050565b610d9f6001600160a01b037f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd5216333085612d47565b610dd46001600160a01b037f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b16333084612d47565b600854610de2908390612db2565b600a6000828254610df39190613937565b9091555050600854610e06908290612db2565b600b6000828254610e179190613937565b9091555050604080518381526020810183905233917f213e72af0d3613bd643cff3059f872c1015e6541624e37872bf95eefbaf220a8910160405180910390a25050565b6001600160a01b03811660009081526003602052604081208054829190825b81811015610d1c57426001600160801b0316838281548110610e9e57610e9e6138f2565b60009182526020909120600160029092020101546001600160401b031611610ef257828181548110610ed257610ed26138f2565b90600052602060002090600202016000015484610eef9190613937565b93505b80610efc8161391e565b915050610e7a565b610f1083838333611ca4565b505050565b6000610d6482610f34565b610f2861281f565b610f326000612dcb565b565b6000610d647f0000000000000000000000002790ec478f150a98f5d96755601a26403df57eae6001600160a01b03166348439e7e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbb919061395d565b60405163067ba3d960e41b81526001600160a01b03858116600483015291909116906367ba3d9090602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611027919061397a565b61103084610d36565b90612d1e565b60095460ff16156110595760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e340011801590611082575063013c68006001600160401b03821611155b61109e5760405162461bcd60e51b81526004016108c7906138c7565b6110a733612879565b610d328282612a4f565b6001600160a01b038116600090815260026020908152604080832054600c909252822054600a548392916110f0916110e9919061394a565b8290612d1e565b6001600160a01b0385166000908152600d60205260409020546111139190613937565b6001600160a01b0385166000908152600e6020526040902054600b54919450611140916110e9919061394a565b6001600160a01b0385166000908152600f60205260409020546111639190613937565b915050915091565b600061117633612879565b3360009081526003602052604081208190815b8581101561139c5760006111c3338989858181106111a9576111a96138f2565b90506020020160208101906111be91906135b8565b612e1b565b60095490915060ff16806112055750428382815481106111e5576111e56138f2565b60009182526020909120600160029092020101546001600160401b031611155b6112445760405162461bcd60e51b815260206004820152601060248201526f1b1bd8dac81b9bdd08195e1c1a5c995960821b60448201526064016108c7565b828181548110611256576112566138f2565b906000526020600020906002020160000154856112739190613937565b945061128a838281548110610ca657610ca66138f2565b6112949085613937565b835490945083906112a79060019061394a565b815481106112b7576112b76138f2565b90600052602060002090600202018382815481106112d7576112d76138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b03909116179055825483908061136b5761136b613993565b60008281526020812060026000199093019283020181815560010155905550806113948161391e565b915050611189565b5082600760008282546113af919061394a565b9250508190555081600860008282546113c8919061394a565b909155505033600090815260016020526040812080548592906113ec90849061394a565b9091555050336000908152600260205260408120805484929061141090849061394a565b9091555061144a90506001600160a01b037f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc168885612ef6565b60405183815233907fb291e2a2847a5ad6d47409943306c6d6e8c63a9855b849701b868191e94789709060200160405180910390a2509095945050505050565b60095460ff16156114ad5760405162461bcd60e51b81526004016108c79061389d565b6001600160401b038116629e3400118015906114d6575063013c68006001600160401b03821611155b6114f25760405162461bcd60e51b81526004016108c7906138c7565b6114fb33612879565b600061150f826001600160401b03166125d5565b9050600061151d83426139a9565b336000908152600360205260408120549192505b818110156115b25733600090815260036020526040902080546001600160401b038516919083908110611566576115666138f2565b60009182526020909120600160029092020101546001600160401b0316106115a05760405162461bcd60e51b81526004016108c7906139d0565b806115aa8161391e565b915050611531565b503360009081526003602052604081206115cb916132b1565b3360009081526002602052604081205460088054919290916115ee90849061394a565b9091555050336000818152600260209081526040808320839055600190915290205461161c91908486612f26565b3360009081526001602052604081205461163f906001600160801b038616612d1e565b905080600860008282546116539190613937565b90915550503360009081526002602052604081208054839290611677908490613937565b9091555050336000818152600160209081526040918290205491519182527fe2d155d9d74decc198a9a9b4f5bddb24ee0842ee745c9ce57e3573b971e50d9d910160405180910390a25050505050565b7f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc6001600160a01b0316816001600160a01b03161415801561173b57507f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd526001600160a01b0316816001600160a01b031614155b801561177957507f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b0316816001600160a01b031614155b6117bd5760405162461bcd60e51b815260206004820152601560248201527431b0b73737ba103bb4ba34323930bb903a37b5b2b760591b60448201526064016108c7565b6040516370a0823160e01b8152306004820152819061185e907f000000000000000000000000b27dc5f8286f063f11491c8f349053cb37718bea906001600160a01b038416906370a0823190602401602060405180830381865afa158015611829573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184d919061397a565b6001600160a01b0384169190612ef6565b6040516001600160a01b038316907f17a79be10b6da9324a110f0ea6d3043db38f1eee6e2ee1dbfa7272338e39da4590600090a25050565b60006118a28383612e1b565b6001600160a01b03841660009081526003602052604090208054919250906001600160801b034216906224ea00908390859081106118e2576118e26138f2565b600091825260209091206001600290920201015461190991906001600160401b0316613a07565b6001600160801b031611156119585760405162461bcd60e51b815260206004820152601560248201527463616e6e6f74206b69636b2074686973206c6f636b60581b60448201526064016108c7565b61196184612879565b6000818381548110611975576119756138f2565b9060005260206000209060020201600001549050806007600082825461199b919061394a565b925050819055506119e28284815481106119b7576119b76138f2565b60009182526020909120600290910201600101548290600160401b90046001600160801b0316612d1e565b600860008282546119f3919061394a565b90915550506001600160a01b03851660009081526001602052604081208054839290611a2090849061394a565b92505081905550611a3c8284815481106119b7576119b76138f2565b6001600160a01b03861660009081526002602052604081208054909190611a6490849061394a565b9091555060009050611a7e8267016345785d8a0000612d1e565b9050683635c9adc5dea00000811115611a9d5750683635c9adc5dea000005b611adc86611aab838561394a565b6001600160a01b037f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc169190612ef6565b611b106001600160a01b037f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc163383612ef6565b60405182815233906001600160a01b038816907f9716d4c8630c7c1a47a462f169d1764a38687f7532baf2bd74a791afc20030e69060200160405180910390a382548390611b609060019061394a565b81548110611b7057611b706138f2565b9060005260206000209060020201838581548110611b9057611b906138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b039091161790558254839080611c2457611c24613993565b600082815260208120600260001990930192830201818155600101559055505050505050565b6001600160a01b0381166000908152600460205260408120548103611c785750670de0b6b3a7640000919050565b506001600160a01b031660009081526004602052604090205490565b6000611c9f3361229a565b905090565b60095460ff1615611cc75760405162461bcd60e51b81526004016108c79061389d565b678ac7230489e80000841015611d125760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b60448201526064016108c7565b6001600160401b038316629e340011801590611d3b575063013c68006001600160401b03841611155b611d575760405162461bcd60e51b81526004016108c7906138c7565b811580611d6c5750336001600160a01b038216145b611daf5760405162461bcd60e51b81526020600482015260146024820152733932b637b1b59037b7363c903337b91039b2b63360611b60448201526064016108c7565b6001600160a01b038116600090815260036020526040902054600a11611e085760405162461bcd60e51b815260206004820152600e60248201526d746f6f206d616e79206c6f636b7360901b60448201526064016108c7565b611e1181612879565b611e466001600160a01b037f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc16333087612d47565b6000611e5a846001600160401b03166125d5565b90506000611e6733611c4a565b9050670de0b6b3a7640000811115611eb957336000908152600560205260409020805460ff19166001179055611ea66001600160801b03831682613011565b3360009081526004602052604081205591505b6000611ec586426139a9565b905060008515612040576001600160a01b038516600090815260036020526040812054905b81811015611f74576001600160a01b038716600090815260036020526040902080546001600160401b038616919083908110611f2857611f286138f2565b60009182526020909120600160029092020101546001600160401b031610611f625760405162461bcd60e51b81526004016108c7906139d0565b80611f6c8161391e565b915050611eea565b506001600160a01b0386166000908152600360205260408120611f96916132b1565b6001600160a01b0386166000908152600260205260408120546008805491929091611fc290849061394a565b90915550506001600160a01b03861660009081526002602090815260408083208390556001909152902054612005908790611ffe908c90613937565b8588612f26565b6001600160a01b038616600090815260016020526040902054612038906001600160801b03871690611030908c90613937565b915050612062565b61204c85898487612f26565b61205f886001600160801b038616612d1e565b90505b87600760008282546120749190613937565b92505081905550806008600082825461208d9190613937565b90915550506001600160a01b038516600090815260016020526040812080548a92906120ba908490613937565b90915550506001600160a01b038516600090815260026020526040812080548392906120e7908490613937565b9091555050604080518981526001600160401b03841660208201528715158183015290516001600160a01b038716917fca8d506eda84f8ed07c2908ae102299d34888ef5e19b97f56e4d6fcd1104c31e919081900360600190a25050505050505050565b60008061215733612879565b5050336000818152600d6020908152604080832054600f9092529091205490916121ac907f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd526001600160a01b03169084612ef6565b6121e06001600160a01b037f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b163383612ef6565b336000818152600d60209081526040808320839055600f82528083209290925581518581529081018490527f1ac537f0ad67b64ac68a04587ff3a4cb6977de22eb2c37ee560897a92c6d07c7910160405180910390a29091565b6003602052816000526040600020818154811061225657600080fd5b6000918252602090912060029091020180546001909101549092506001600160401b0380821692506001600160801b03600160401b83041691600160c01b90041684565b60006001600160a01b0382166122e85760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b2103232b9ba34b730ba34b7b760691b60448201526064016108c7565b6122f133612879565b33600090815260036020526040812080548291905b80156124e95761231760018261394a565b60095490915060ff1680612359575042828281548110612339576123396138f2565b60009182526020909120600160029092020101546001600160401b031611155b156124e457818181548110612370576123706138f2565b9060005260206000209060020201600001548461238d9190613937565b93506123e48282815481106123a4576123a46138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316838381548110610ce657610ce66138f2565b6123ee9084613937565b825490935082906124019060019061394a565b81548110612411576124116138f2565b9060005260206000209060020201828281548110612431576124316138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b0390911617905581548290806124c5576124c5613993565b6000828152602081206002600019909301928302018181556001015590555b612306565b83600760008282546124fb919061394a565b925050819055508260086000828254612514919061394a565b9091555050336000908152600160205260408120805486929061253890849061394a565b9091555050336000908152600260205260408120805485929061255c90849061394a565b9091555061259690506001600160a01b037f0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc168786612ef6565b60405184815233907fb291e2a2847a5ad6d47409943306c6d6e8c63a9855b849701b868191e94789709060200160405180910390a25091949350505050565b6000670de0b6b3a764000061263c6126136125f7629e340063013c6800613a27565b612604629e340087613a27565b6001600160801b031690613033565b61262d670de0b6b3a76400006714d1120d7b160000613a27565b6001600160801b031690613011565b610d649190613a07565b60005b8151811015610d3257612696828281518110612667576126676138f2565b602002602001015160000151838381518110612685576126856138f2565b602002602001015160200151611896565b806126a08161391e565b915050612649565b6126b061281f565b6001600160a01b0381166127155760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108c7565b61271e81612dcb565b50565b602083015151835160009190825b8281101561281457612742600283613a5d565b61ffff166000036127a3578587602001518281518110612764576127646138f2565b6020026020010151604051602001612786929190918252602082015260400190565b6040516020818303038152906040528051906020012095506127f5565b866020015181815181106127b9576127b96138f2565b6020026020010151866040516020016127dc929190918252602082015260400190565b6040516020818303038152906040528051906020012095505b612800600283613a7e565b91508061280c8161391e565b91505061272f565b505050911492915050565b6000546001600160a01b03163314610f325760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b6001600160a01b038116600090815260026020908152604080832054600a54600b54600c90945291909320549091906128bd906128b6908461394a565b8490612d1e565b6001600160a01b0385166000908152600d6020526040812080549091906128e5908490613937565b90915550506001600160a01b0384166000908152600c60209081526040808320859055600e90915290205461291e906128b6908361394a565b6001600160a01b0385166000908152600f602052604081208054909190612946908490613937565b90915550506001600160a01b038085166000908152600e602090815260408083208590558051639845755960e01b8152905192937f0000000000000000000000002790ec478f150a98f5d96755601a26403df57eae16926398457559926004808401939192918290030181865afa1580156129c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e9919061395d565b60405163bf928f8b60e01b81526001600160a01b0387811660048301529192509082169063bf928f8b90602401600060405180830381600087803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b505050505050505050565b6000612a5b3384612e1b565b90506000612a71836001600160401b03166125d5565b90506000612a7f84426139a9565b3360009081526003602052604090208054919250906001600160401b03831690829086908110612ab157612ab16138f2565b60009182526020909120600160029092020101546001600160401b031610612aeb5760405162461bcd60e51b81526004016108c7906139d0565b6000818581548110612aff57612aff6138f2565b90600052602060002090600202016000015490506000612b6a838781548110612b2a57612b2a6138f2565b906000526020600020906002020160010160089054906101000a90046001600160801b03166001600160801b0316848881548110610ce657610ce66138f2565b83549091508390612b7d9060019061394a565b81548110612b8d57612b8d6138f2565b9060005260206000209060020201838781548110612bad57612bad6138f2565b6000918252602090912082546002909202019081556001918201805492909101805467ffffffffffffffff1981166001600160401b03948516908117835583546001600160801b03600160401b9182900416026001600160c01b031990921617178082559154600160c01b908190049093169092026001600160c01b039091161790558254839080612c4157612c41613993565b600082815260208120600260001990930192830201818155600101559055612c6b33838688612f26565b6000612c80836001600160801b038816612d1e565b90508181600854612c919190613937565b612c9b919061394a565b600855336000908152600260205260409020548290612cbb908390613937565b612cc5919061394a565b33600081815260026020526040908190209290925590517fe2d155d9d74decc198a9a9b4f5bddb24ee0842ee745c9ce57e3573b971e50d9d90612d0b9086815260200190565b60405180910390a2505050505050505050565b6000612d2c6012600a613b83565b612d368385613b8f565b612d409190613ba6565b9392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610c269085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261304c565b600081612dc16012600a613b83565b612d369085613b8f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600090815260036020526040812054815b81811015612eb8576001600160a01b038516600090815260036020526040902080546001600160401b038616919083908110612e7457612e746138f2565b6000918252602090912060029091020160010154600160c01b90046001600160401b031603612ea6579150610d649050565b80612eb08161391e565b915050612e36565b5060405162461bcd60e51b81526020600482015260126024820152711b1bd8dac8191bd95cdb89dd08195e1a5cdd60721b60448201526064016108c7565b6040516001600160a01b038316602482015260448101829052610f1090849063a9059cbb60e01b90606401612d7b565b6006546001600160a01b038516600090815260036020908152604080832081516080810183528881526001600160401b038881168286019081526001600160801b03808a1695840195865297821660608401818152855460018181018855968a529790982093516002909702909301958655519483018054945196518216600160c01b026001600160c01b0397909816600160401b026001600160c01b031990951695909116949094179290921793909316939093179055612fe99082906139a9565b6006805467ffffffffffffffff19166001600160401b03929092169190911790555050505050565b600061301f6012600a613b83565b6130298385613bba565b612d409190613be5565b6000816130426012600a613b83565b6130299085613bba565b60006130a1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131219092919063ffffffff16565b90508051600014806130c25750808060200190518101906130c29190613bff565b610f105760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108c7565b60606131308484600085613138565b949350505050565b6060824710156131995760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108c7565b600080866001600160a01b031685876040516131b59190613c40565b60006040518083038185875af1925050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b509150915061320887838387613213565b979650505050505050565b6060831561328257825160000361327b576001600160a01b0385163b61327b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108c7565b5081613130565b61313083838151156132975781518083602001fd5b8060405162461bcd60e51b81526004016108c79190613c5c565b508054600082556002029060005260206000209081019061271e91905b808211156132e857600080825560018201556002016132ce565b5090565b6001600160a01b038116811461271e57600080fd5b60006020828403121561331357600080fd5b8135612d40816132ec565b602080825282518282018190526000919060409081850190868401855b8281101561338a57815180518552868101516001600160401b0390811688870152868201516001600160801b03168787015260609182015116908501526080909301929085019060010161333b565b5091979650505050505050565b600080604083850312156133aa57600080fd5b8235915060208301356001600160401b038111156133c757600080fd5b8301604081860312156133d957600080fd5b809150509250929050565b60008083601f8401126133f657600080fd5b5081356001600160401b0381111561340d57600080fd5b6020830191508360208260051b850101111561342857600080fd5b9250929050565b80356001600160401b038116811461344657600080fd5b919050565b60008060006040848603121561346057600080fd5b83356001600160401b0381111561347657600080fd5b613482868287016133e4565b909450925061349590506020850161342f565b90509250925092565b600080604083850312156134b157600080fd5b823591506134c16020840161342f565b90509250929050565b600080604083850312156134dd57600080fd5b50508035926020909101359150565b801515811461271e57600080fd5b60008060006060848603121561350f57600080fd5b8335925061351f6020850161342f565b9150604084013561352f816134ec565b809150509250925092565b6000806040838503121561354d57600080fd5b6135568361342f565b91506134c16020840161342f565b60008060006040848603121561357957600080fd5b8335613584816132ec565b925060208401356001600160401b0381111561359f57600080fd5b6135ab868287016133e4565b9497909650939450505050565b6000602082840312156135ca57600080fd5b612d408261342f565b600080604083850312156135e657600080fd5b8235613556816132ec565b6000806000806080858703121561360757600080fd5b843593506136176020860161342f565b92506040850135613627816134ec565b91506060850135613637816132ec565b939692955090935050565b6000806040838503121561365557600080fd5b8235613660816132ec565b946020939093013593505050565b60006020828403121561368057600080fd5b81356001600160801b0381168114612d4057600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156136cf576136cf613697565b60405290565b604051601f8201601f191681016001600160401b03811182821017156136fd576136fd613697565b604052919050565b60006001600160401b0382111561371e5761371e613697565b5060051b60200190565b6000602080838503121561373b57600080fd5b82356001600160401b0381111561375157600080fd5b8301601f8101851361376257600080fd5b803561377561377082613705565b6136d5565b81815260069190911b8201830190838101908783111561379457600080fd5b928401925b8284101561320857604084890312156137b25760008081fd5b6137ba6136ad565b84356137c5816132ec565b81526137d285870161342f565b8187015282526040939093019290840190613799565b6000604082360312156137fa57600080fd5b6138026136ad565b823561ffff8116811461381457600080fd5b81526020838101356001600160401b0381111561383057600080fd5b840136601f82011261384157600080fd5b803561384f61377082613705565b81815260059190911b8201830190838101903683111561386e57600080fd5b928401925b8284101561388c57833582529284019290840190613873565b938501939093525091949350505050565b60208082526010908201526f1b1bd8dad95c881cdd5cdc195b99195960821b604082015260600190565b6020808252601190820152701b1bd8dac81d1a5b59481a5b9d985b1a59607a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161393057613930613908565b5060010190565b80820180821115610d6457610d64613908565b81810381811115610d6457610d64613908565b60006020828403121561396f57600080fd5b8151612d40816132ec565b60006020828403121561398c57600080fd5b5051919050565b634e487b7160e01b600052603160045260246000fd5b6001600160401b038181168382160190808211156139c9576139c9613908565b5092915050565b6020808252601e908201527f63616e6e6f74206d6f76652074686520756e6c6f636b2074696d652075700000604082015260600190565b6001600160801b038181168382160190808211156139c9576139c9613908565b6001600160801b038281168282160390808211156139c9576139c9613908565b634e487b7160e01b600052601260045260246000fd5b600061ffff80841680613a7257613a72613a47565b92169190910692915050565b600061ffff80841680613a9357613a93613a47565b92169190910492915050565b600181815b80851115613ada578160001904821115613ac057613ac0613908565b80851615613acd57918102915b93841c9390800290613aa4565b509250929050565b600082613af157506001610d64565b81613afe57506000610d64565b8160018114613b145760028114613b1e57613b3a565b6001915050610d64565b60ff841115613b2f57613b2f613908565b50506001821b610d64565b5060208310610133831016604e8410600b8410161715613b5d575081810a610d64565b613b678383613a9f565b8060001904821115613b7b57613b7b613908565b029392505050565b6000612d408383613ae2565b8082028115828204841417610d6457610d64613908565b600082613bb557613bb5613a47565b500490565b6001600160801b03818116838216028082169190828114613bdd57613bdd613908565b505092915050565b60006001600160801b0380841680613a9357613a93613a47565b600060208284031215613c1157600080fd5b8151612d40816134ec565b60005b83811015613c37578181015183820152602001613c1f565b50506000910152565b60008251613c52818460208701613c1c565b9190910192915050565b6020815260008251806020840152613c7b816040850160208701613c1c565b601f01601f1916919091016040019291505056fea2646970667358221220110a4a0bdcb2a334a38a1327bc995e846ea2733286b8c500341b4b85048b6e7164736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002790ec478f150a98f5d96755601a26403df57eae0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc000000000000000000000000b27dc5f8286f063f11491c8f349053cb37718bea000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd520000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2bdb5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c5
-----Decoded View---------------
Arg [0] : _controller (address): 0x2790EC478f150a98F5D96755601a26403DF57EaE
Arg [1] : _cncToken (address): 0x9aE380F0272E2162340a5bB646c354271c0F5cFC
Arg [2] : _treasury (address): 0xB27DC5f8286f063F11491c8f349053cB37718bea
Arg [3] : _crv (address): 0xD533a949740bb3306d119CC777fa900bA034cd52
Arg [4] : _cvx (address): 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B
Arg [5] : _merkleRoot (bytes32): 0xdb5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c5
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000002790ec478f150a98f5d96755601a26403df57eae
Arg [1] : 0000000000000000000000009ae380f0272e2162340a5bb646c354271c0f5cfc
Arg [2] : 000000000000000000000000b27dc5f8286f063f11491c8f349053cb37718bea
Arg [3] : 000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd52
Arg [4] : 0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b
Arg [5] : db5e1bfbc1c8e7f169a5d5ca031d8a814267b7fe0af8f3eca2dc0a8a942719c5
Loading...
Loading
Loading...
Loading
Net Worth in USD
$13.11
Net Worth in ETH
0.00445
Token Allocations
CNC
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.00163 | 8,038.0374 | $13.11 |
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.