Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| _become | 8112996 | 353 days ago | IN | 0 ETH | 0.00000061 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;
import "../Utils/ECDSA.sol";
import "../Utils/SafeBEP20.sol";
import "../Utils/IBEP20.sol";
import "./XVSVaultStorage.sol";
import "../Tokens/Prime/IPrime.sol";
import "../Utils/SafeCast.sol";
import "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol";
import "@venusprotocol/solidity-utilities/contracts/TimeManagerV5.sol";
import { XVSStore } from "./XVSStore.sol";
import { XVSVaultProxy } from "./XVSVaultProxy.sol";
/**
* @title XVS Vault
* @author Venus
* @notice The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.
*/
contract XVSVault is XVSVaultStorage, ECDSA, AccessControlledV5, TimeManagerV5 {
using SafeMath for uint256;
using SafeCast for uint256;
using SafeBEP20 for IBEP20;
/// @notice The upper bound for the lock period in a pool, 10 years
uint256 public constant MAX_LOCK_PERIOD = 60 * 60 * 24 * 365 * 10;
/// @notice Event emitted when deposit
event Deposit(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);
/// @notice Event emitted when execute withrawal
event ExecutedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);
/// @notice Event emitted when request withrawal
event RequestedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);
/// @notice An event thats emitted when an account changes its delegate
event DelegateChangedV2(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChangedV2(address indexed delegate, uint previousBalance, uint newBalance);
/// @notice An event emitted when the reward store address is updated
event StoreUpdated(address oldXvs, address oldStore, address newXvs, address newStore);
/// @notice An event emitted when the withdrawal locking period is updated for a pool
event WithdrawalLockingPeriodUpdated(address indexed rewardToken, uint indexed pid, uint oldPeriod, uint newPeriod);
/// @notice An event emitted when the reward amount per block or second is modified for a pool
event RewardAmountUpdated(address indexed rewardToken, uint oldReward, uint newReward);
/// @notice An event emitted when a new pool is added
event PoolAdded(
address indexed rewardToken,
uint indexed pid,
address indexed token,
uint allocPoints,
uint rewardPerBlockOrSecond,
uint lockPeriod
);
/// @notice An event emitted when a pool allocation points are updated
event PoolUpdated(address indexed rewardToken, uint indexed pid, uint oldAllocPoints, uint newAllocPoints);
/// @notice Event emitted when reward claimed
event Claim(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);
/// @notice Event emitted when vault is paused
event VaultPaused(address indexed admin);
/// @notice Event emitted when vault is resumed after pause
event VaultResumed(address indexed admin);
/// @notice Event emitted when protocol logs a debt to a user due to insufficient funds for pending reward distribution
event VaultDebtUpdated(
address indexed rewardToken,
address indexed userAddress,
uint256 oldOwedAmount,
uint256 newOwedAmount
);
/// @notice Emitted when prime token contract address is changed
event NewPrimeToken(
IPrime indexed oldPrimeToken,
IPrime indexed newPrimeToken,
address oldPrimeRewardToken,
address newPrimeRewardToken,
uint256 oldPrimePoolId,
uint256 newPrimePoolId
);
/**
* @notice XVSVault constructor
*/
constructor() public {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin, "only admin can");
_;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
*/
modifier nonReentrant() {
require(_notEntered, "re-entered");
_notEntered = false;
_;
_notEntered = true; // get a gas-refund post-Istanbul
}
/**
* @dev Prevents functions to execute when vault is paused.
*/
modifier isActive() {
require(!vaultPaused, "Vault is paused");
_;
}
/**
* @notice Pauses vault
*/
function pause() external {
_checkAccessAllowed("pause()");
require(!vaultPaused, "Vault is already paused");
vaultPaused = true;
emit VaultPaused(msg.sender);
}
/**
* @notice Resume vault
*/
function resume() external {
_checkAccessAllowed("resume()");
require(vaultPaused, "Vault is not paused");
vaultPaused = false;
emit VaultResumed(msg.sender);
}
/**
* @notice Returns the number of pools with the specified reward token
* @param rewardToken Reward token address
* @return Number of pools that distribute the specified token as a reward
*/
function poolLength(address rewardToken) external view returns (uint256) {
return poolInfos[rewardToken].length;
}
/**
* @notice Returns the number of reward tokens created per block or second
* @param _rewardToken Reward token address
* @return Number of reward tokens created per block or second
*/
function rewardTokenAmountsPerBlock(address _rewardToken) external view returns (uint256) {
return rewardTokenAmountsPerBlockOrSecond[_rewardToken];
}
/**
* @notice Add a new token pool
* @dev This vault DOES NOT support deflationary tokens — it expects that
* the amount of transferred tokens would equal the actually deposited
* amount. In practice this means that this vault DOES NOT support USDT
* and similar tokens (that do not provide these guarantees).
* @param _rewardToken Reward token address
* @param _allocPoint Number of allocation points assigned to this pool
* @param _token Staked token
* @param _rewardPerBlockOrSecond Initial reward per block or second, in terms of _rewardToken
* @param _lockPeriod A period between withdrawal request and a moment when it's executable
*/
function add(
address _rewardToken,
uint256 _allocPoint,
IBEP20 _token,
uint256 _rewardPerBlockOrSecond,
uint256 _lockPeriod
) external {
_checkAccessAllowed("add(address,uint256,address,uint256,uint256)");
_ensureNonzeroAddress(_rewardToken);
_ensureNonzeroAddress(address(_token));
require(address(xvsStore) != address(0), "Store contract address is empty");
require(_allocPoint > 0, "Alloc points must not be zero");
massUpdatePools(_rewardToken);
PoolInfo[] storage poolInfo = poolInfos[_rewardToken];
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
require(poolInfo[pid].token != _token, "Pool already added");
}
// We use balanceOf to get the supply amount, so shouldn't be possible to
// configure pools with different reward token but the same staked token
require(!isStakedToken[address(_token)], "Token exists in other pool");
totalAllocPoints[_rewardToken] = totalAllocPoints[_rewardToken].add(_allocPoint);
rewardTokenAmountsPerBlockOrSecond[_rewardToken] = _rewardPerBlockOrSecond;
poolInfo.push(
PoolInfo({
token: _token,
allocPoint: _allocPoint,
lastRewardBlockOrSecond: getBlockNumberOrTimestamp(),
accRewardPerShare: 0,
lockPeriod: _lockPeriod
})
);
isStakedToken[address(_token)] = true;
XVSStore(xvsStore).setRewardToken(_rewardToken, true);
emit PoolAdded(
_rewardToken,
poolInfo.length - 1,
address(_token),
_allocPoint,
_rewardPerBlockOrSecond,
_lockPeriod
);
}
/**
* @notice Update the given pool's reward allocation point
* @param _rewardToken Reward token address
* @param _pid Pool index
* @param _allocPoint Number of allocation points assigned to this pool
*/
function set(address _rewardToken, uint256 _pid, uint256 _allocPoint) external {
_checkAccessAllowed("set(address,uint256,uint256)");
_ensureValidPool(_rewardToken, _pid);
massUpdatePools(_rewardToken);
PoolInfo[] storage poolInfo = poolInfos[_rewardToken];
uint256 newTotalAllocPoints = totalAllocPoints[_rewardToken].sub(poolInfo[_pid].allocPoint).add(_allocPoint);
require(newTotalAllocPoints > 0, "Alloc points per reward token must not be zero");
uint256 oldAllocPoints = poolInfo[_pid].allocPoint;
poolInfo[_pid].allocPoint = _allocPoint;
totalAllocPoints[_rewardToken] = newTotalAllocPoints;
emit PoolUpdated(_rewardToken, _pid, oldAllocPoints, _allocPoint);
}
/**
* @notice Update the given reward token's amount per block or second
* @param _rewardToken Reward token address
* @param _rewardAmount Number of allocation points assigned to this pool
*/
function setRewardAmountPerBlockOrSecond(address _rewardToken, uint256 _rewardAmount) external {
_checkAccessAllowed("setRewardAmountPerBlockOrSecond(address,uint256)");
require(XVSStore(xvsStore).rewardTokens(_rewardToken), "Invalid reward token");
massUpdatePools(_rewardToken);
uint256 oldReward = rewardTokenAmountsPerBlockOrSecond[_rewardToken];
rewardTokenAmountsPerBlockOrSecond[_rewardToken] = _rewardAmount;
emit RewardAmountUpdated(_rewardToken, oldReward, _rewardAmount);
}
/**
* @notice Update the lock period after which a requested withdrawal can be executed
* @param _rewardToken Reward token address
* @param _pid Pool index
* @param _newPeriod New lock period
*/
function setWithdrawalLockingPeriod(address _rewardToken, uint256 _pid, uint256 _newPeriod) external {
_checkAccessAllowed("setWithdrawalLockingPeriod(address,uint256,uint256)");
_ensureValidPool(_rewardToken, _pid);
require(_newPeriod > 0 && _newPeriod < MAX_LOCK_PERIOD, "Invalid new locking period");
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
uint256 oldPeriod = pool.lockPeriod;
pool.lockPeriod = _newPeriod;
emit WithdrawalLockingPeriodUpdated(_rewardToken, _pid, oldPeriod, _newPeriod);
}
/**
* @notice Deposit XVSVault for XVS allocation
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _amount The amount to deposit to vault
*/
function deposit(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {
_ensureValidPool(_rewardToken, _pid);
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];
_updatePool(_rewardToken, _pid);
require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, msg.sender) == 0, "execute pending withdrawal");
if (user.amount > 0) {
uint256 pending = _computeReward(user, pool);
if (pending > 0) {
_transferReward(_rewardToken, msg.sender, pending);
emit Claim(msg.sender, _rewardToken, _pid, pending);
}
}
pool.token.safeTransferFrom(msg.sender, address(this), _amount);
user.amount = user.amount.add(_amount);
user.rewardDebt = _cumulativeReward(user, pool);
// Update Delegate Amount
if (address(pool.token) == xvsAddress) {
_moveDelegates(address(0), delegates[msg.sender], safe96(_amount, "XVSVault::deposit: votes overflow"));
}
if (primeRewardToken == _rewardToken && _pid == primePoolId) {
primeToken.xvsUpdated(msg.sender);
}
emit Deposit(msg.sender, _rewardToken, _pid, _amount);
}
/**
* @notice Claim rewards for pool
* @param _account The account for which to claim rewards
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
*/
function claim(address _account, address _rewardToken, uint256 _pid) external nonReentrant isActive {
_ensureValidPool(_rewardToken, _pid);
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
UserInfo storage user = userInfos[_rewardToken][_pid][_account];
_updatePool(_rewardToken, _pid);
require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, _account) == 0, "execute pending withdrawal");
if (user.amount > 0) {
uint256 pending = _computeReward(user, pool);
if (pending > 0) {
user.rewardDebt = _cumulativeReward(user, pool);
_transferReward(_rewardToken, _account, pending);
emit Claim(_account, _rewardToken, _pid, pending);
}
}
}
/**
* @notice Pushes withdrawal request to the requests array and updates
* the pending withdrawals amount. The requests are always sorted
* by unlock time (descending) so that the earliest to execute requests
* are always at the end of the array.
* @param _user The user struct storage pointer
* @param _requests The user's requests array storage pointer
* @param _amount The amount being requested
*/
function pushWithdrawalRequest(
UserInfo storage _user,
WithdrawalRequest[] storage _requests,
uint _amount,
uint _lockedUntil
) internal {
uint i = _requests.length;
_requests.push(WithdrawalRequest(0, 0, 1));
// Keep it sorted so that the first to get unlocked request is always at the end
for (; i > 0 && _requests[i - 1].lockedUntil <= _lockedUntil; --i) {
_requests[i] = _requests[i - 1];
}
_requests[i] = WithdrawalRequest(_amount, _lockedUntil.toUint128(), 1);
_user.pendingWithdrawals = _user.pendingWithdrawals.add(_amount);
}
/**
* @notice Pops the requests with unlock time < now from the requests
* array and deducts the computed amount from the user's pending
* withdrawals counter. Assumes that the requests array is sorted
* by unclock time (descending).
* @dev This function **removes** the eligible requests from the requests
* array. If this function is called, the withdrawal should actually
* happen (or the transaction should be reverted).
* @param _user The user struct storage pointer
* @param _requests The user's requests array storage pointer
* @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade (this amount should be
* sent to the user, otherwise the state would be inconsistent).
* @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade (this amount should be
* sent to the user, otherwise the state would be inconsistent).
*/
function popEligibleWithdrawalRequests(
UserInfo storage _user,
WithdrawalRequest[] storage _requests
) internal returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {
// Since the requests are sorted by their unlock time, we can just
// pop them from the array and stop at the first not-yet-eligible one
for (uint i = _requests.length; i > 0 && isUnlocked(_requests[i - 1]); --i) {
if (_requests[i - 1].afterUpgrade == 1) {
afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);
} else {
beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);
}
_requests.pop();
}
_user.pendingWithdrawals = _user.pendingWithdrawals.sub(
afterUpgradeWithdrawalAmount.add(beforeUpgradeWithdrawalAmount)
);
return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);
}
/**
* @notice Checks if the request is eligible for withdrawal.
* @param _request The request struct storage pointer
* @return True if the request is eligible for withdrawal, false otherwise
*/
function isUnlocked(WithdrawalRequest storage _request) private view returns (bool) {
return _request.lockedUntil <= block.timestamp;
}
/**
* @notice Execute withdrawal to XVSVault for XVS allocation
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
*/
function executeWithdrawal(address _rewardToken, uint256 _pid) external nonReentrant isActive {
_ensureValidPool(_rewardToken, _pid);
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];
WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];
uint256 beforeUpgradeWithdrawalAmount;
uint256 afterUpgradeWithdrawalAmount;
(beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount) = popEligibleWithdrawalRequests(user, requests);
require(beforeUpgradeWithdrawalAmount > 0 || afterUpgradeWithdrawalAmount > 0, "nothing to withdraw");
// Having both old-style and new-style requests is not allowed and shouldn't be possible
require(beforeUpgradeWithdrawalAmount == 0 || afterUpgradeWithdrawalAmount == 0, "inconsistent state");
if (beforeUpgradeWithdrawalAmount > 0) {
_updatePool(_rewardToken, _pid);
uint256 pending = user.amount.mul(pool.accRewardPerShare).div(1e12).sub(user.rewardDebt);
XVSStore(xvsStore).safeRewardTransfer(_rewardToken, msg.sender, pending);
user.amount = user.amount.sub(beforeUpgradeWithdrawalAmount);
user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(1e12);
pool.token.safeTransfer(address(msg.sender), beforeUpgradeWithdrawalAmount);
} else {
user.amount = user.amount.sub(afterUpgradeWithdrawalAmount);
totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].sub(
afterUpgradeWithdrawalAmount
);
pool.token.safeTransfer(address(msg.sender), afterUpgradeWithdrawalAmount);
}
emit ExecutedWithdrawal(
msg.sender,
_rewardToken,
_pid,
beforeUpgradeWithdrawalAmount.add(afterUpgradeWithdrawalAmount)
);
}
/**
* @notice Returns before and after upgrade pending withdrawal amount
* @param _requests The user's requests array storage pointer
* @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade
* @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade
*/
function getRequestedWithdrawalAmount(
WithdrawalRequest[] storage _requests
) internal view returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {
for (uint i = _requests.length; i > 0; --i) {
if (_requests[i - 1].afterUpgrade == 1) {
afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);
} else {
beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);
}
}
return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);
}
/**
* @notice Request withdrawal to XVSVault for XVS allocation
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _amount The amount to withdraw from the vault
*/
function requestWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {
_ensureValidPool(_rewardToken, _pid);
require(_amount > 0, "requested amount cannot be zero");
UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];
require(user.amount >= user.pendingWithdrawals.add(_amount), "requested amount is invalid");
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];
uint beforeUpgradeWithdrawalAmount;
(beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);
require(beforeUpgradeWithdrawalAmount == 0, "execute pending withdrawal");
_updatePool(_rewardToken, _pid);
uint256 pending = _computeReward(user, pool);
_transferReward(_rewardToken, msg.sender, pending);
uint lockedUntil = pool.lockPeriod.add(block.timestamp);
pushWithdrawalRequest(user, requests, _amount, lockedUntil);
totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].add(_amount);
user.rewardDebt = _cumulativeReward(user, pool);
// Update Delegate Amount
if (address(pool.token) == xvsAddress) {
_moveDelegates(
delegates[msg.sender],
address(0),
safe96(_amount, "XVSVault::requestWithdrawal: votes overflow")
);
}
if (primeRewardToken == _rewardToken && _pid == primePoolId) {
primeToken.xvsUpdated(msg.sender);
}
emit Claim(msg.sender, _rewardToken, _pid, pending);
emit RequestedWithdrawal(msg.sender, _rewardToken, _pid, _amount);
}
/**
* @notice Get unlocked withdrawal amount
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _user The User Address
* @return withdrawalAmount Amount that the user can withdraw
*/
function getEligibleWithdrawalAmount(
address _rewardToken,
uint256 _pid,
address _user
) external view returns (uint withdrawalAmount) {
_ensureValidPool(_rewardToken, _pid);
WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];
// Since the requests are sorted by their unlock time, we can take
// the entries from the end of the array and stop at the first
// not-yet-eligible one
for (uint i = requests.length; i > 0 && isUnlocked(requests[i - 1]); --i) {
withdrawalAmount = withdrawalAmount.add(requests[i - 1].amount);
}
return withdrawalAmount;
}
/**
* @notice Get requested amount
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _user The User Address
* @return Total amount of requested but not yet executed withdrawals (including both executable and locked ones)
*/
function getRequestedAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {
_ensureValidPool(_rewardToken, _pid);
UserInfo storage user = userInfos[_rewardToken][_pid][_user];
return user.pendingWithdrawals;
}
/**
* @notice Returns the array of withdrawal requests that have not been executed yet
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _user The User Address
* @return An array of withdrawal requests
*/
function getWithdrawalRequests(
address _rewardToken,
uint256 _pid,
address _user
) external view returns (WithdrawalRequest[] memory) {
_ensureValidPool(_rewardToken, _pid);
return withdrawalRequests[_rewardToken][_pid][_user];
}
/**
* @notice View function to see pending XVSs on frontend
* @param _rewardToken Reward token address
* @param _pid Pool index
* @param _user User address
* @return Reward the user is eligible for in this pool, in terms of _rewardToken
*/
function pendingReward(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {
_ensureValidPool(_rewardToken, _pid);
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
UserInfo storage user = userInfos[_rewardToken][_pid][_user];
uint256 accRewardPerShare = pool.accRewardPerShare;
uint256 supply = pool.token.balanceOf(address(this)).sub(totalPendingWithdrawals[_rewardToken][_pid]);
uint256 curBlockNumberOrSecond = getBlockNumberOrTimestamp();
uint256 rewardTokenPerBlockOrSecond = rewardTokenAmountsPerBlockOrSecond[_rewardToken];
if (curBlockNumberOrSecond > pool.lastRewardBlockOrSecond && supply != 0) {
uint256 multiplier = curBlockNumberOrSecond.sub(pool.lastRewardBlockOrSecond);
uint256 reward = multiplier.mul(rewardTokenPerBlockOrSecond).mul(pool.allocPoint).div(
totalAllocPoints[_rewardToken]
);
accRewardPerShare = accRewardPerShare.add(reward.mul(1e12).div(supply));
}
WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];
(, uint256 afterUpgradeWithdrawalAmount) = getRequestedWithdrawalAmount(requests);
return user.amount.sub(afterUpgradeWithdrawalAmount).mul(accRewardPerShare).div(1e12).sub(user.rewardDebt);
}
// Update reward variables for all pools. Be careful of gas spending!
function massUpdatePools(address _rewardToken) internal {
uint256 length = poolInfos[_rewardToken].length;
for (uint256 pid = 0; pid < length; ++pid) {
_updatePool(_rewardToken, pid);
}
}
/**
* @notice Update reward variables of the given pool to be up-to-date
* @param _rewardToken Reward token address
* @param _pid Pool index
*/
function updatePool(address _rewardToken, uint256 _pid) external isActive {
_ensureValidPool(_rewardToken, _pid);
_updatePool(_rewardToken, _pid);
}
// Update reward variables of the given pool to be up-to-date.
function _updatePool(address _rewardToken, uint256 _pid) internal {
PoolInfo storage pool = poolInfos[_rewardToken][_pid];
if (getBlockNumberOrTimestamp() <= pool.lastRewardBlockOrSecond) {
return;
}
uint256 supply = pool.token.balanceOf(address(this));
supply = supply.sub(totalPendingWithdrawals[_rewardToken][_pid]);
if (supply == 0) {
pool.lastRewardBlockOrSecond = getBlockNumberOrTimestamp();
return;
}
uint256 curBlockNumberOrSecond = getBlockNumberOrTimestamp();
uint256 multiplier = curBlockNumberOrSecond.sub(pool.lastRewardBlockOrSecond);
uint256 reward = multiplier.mul(rewardTokenAmountsPerBlockOrSecond[_rewardToken]).mul(pool.allocPoint).div(
totalAllocPoints[_rewardToken]
);
pool.accRewardPerShare = pool.accRewardPerShare.add(reward.mul(1e12).div(supply));
pool.lastRewardBlockOrSecond = getBlockNumberOrTimestamp();
}
function _ensureValidPool(address rewardToken, uint256 pid) internal view {
require(pid < poolInfos[rewardToken].length, "vault: pool exists?");
}
/**
* @notice Get user info with reward token address and pid
* @param _rewardToken Reward token address
* @param _pid Pool index
* @param _user User address
* @return amount Deposited amount
* @return rewardDebt Reward debt (technical value used to track past payouts)
* @return pendingWithdrawals Requested but not yet executed withdrawals
*/
function getUserInfo(
address _rewardToken,
uint256 _pid,
address _user
) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals) {
_ensureValidPool(_rewardToken, _pid);
UserInfo storage user = userInfos[_rewardToken][_pid][_user];
amount = user.amount;
rewardDebt = user.rewardDebt;
pendingWithdrawals = user.pendingWithdrawals;
}
/**
* @notice Gets the total pending withdrawal amount of a user before upgrade
* @param _rewardToken The Reward Token Address
* @param _pid The Pool Index
* @param _user The address of the user
* @return beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade
*/
function pendingWithdrawalsBeforeUpgrade(
address _rewardToken,
uint256 _pid,
address _user
) public view returns (uint256 beforeUpgradeWithdrawalAmount) {
WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];
(beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);
return beforeUpgradeWithdrawalAmount;
}
/**
* @notice Get the XVS stake balance of an account (excluding the pending withdrawals)
* @param account The address of the account to check
* @return The balance that user staked
*/
function getStakeAmount(address account) internal view returns (uint96) {
require(xvsAddress != address(0), "XVSVault::getStakeAmount: xvs address is not set");
PoolInfo[] storage poolInfo = poolInfos[xvsAddress];
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
if (address(poolInfo[pid].token) == address(xvsAddress)) {
UserInfo storage user = userInfos[xvsAddress][pid][account];
return safe96(user.amount.sub(user.pendingWithdrawals), "XVSVault::getStakeAmount: votes overflow");
}
}
return uint96(0);
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) external isActive {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(
address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
) external isActive {
bytes32 domainSeparator = keccak256(
abi.encode(DOMAIN_TYPEHASH, keccak256(bytes("XVSVault")), getChainId(), address(this))
);
bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
address signatory = ECDSA.recover(digest, v, r, s);
require(nonce == nonces[signatory]++, "XVSVault::delegateBySig: invalid nonce");
require(block.timestamp <= expiry, "XVSVault::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account) external view returns (uint96) {
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
function _delegate(address delegator, address delegatee) internal {
address currentDelegate = delegates[delegator];
uint96 delegatorBalance = getStakeAmount(delegator);
delegates[delegator] = delegatee;
emit DelegateChangedV2(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint96 srcRepNew = sub96(srcRepOld, amount, "XVSVault::_moveVotes: vote amount underflows");
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint96 dstRepNew = add96(dstRepOld, amount, "XVSVault::_moveVotes: vote amount overflows");
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {
uint32 blockNumberOrSecond = safe32(
getBlockNumberOrTimestamp(),
"XVSVault::_writeCheckpoint: block number or second exceeds 32 bits"
);
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlockOrSecond == blockNumberOrSecond) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumberOrSecond, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChangedV2(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2 ** 32, errorMessage);
return uint32(n);
}
function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {
require(n < 2 ** 96, errorMessage);
return uint96(n);
}
function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
/**
* @notice Determine the xvs stake balance for an account
* @param account The address of the account to check
* @param blockNumberOrSecond The block number or second to get the vote balance at
* @return The balance that user staked
*/
function getPriorVotes(address account, uint256 blockNumberOrSecond) external view returns (uint96) {
require(blockNumberOrSecond < getBlockNumberOrTimestamp(), "XVSVault::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlockOrSecond <= blockNumberOrSecond) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlockOrSecond > blockNumberOrSecond) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlockOrSecond == blockNumberOrSecond) {
return cp.votes;
} else if (cp.fromBlockOrSecond < blockNumberOrSecond) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
/*** Admin Functions ***/
function _become(XVSVaultProxy xvsVaultProxy) external {
require(msg.sender == xvsVaultProxy.admin(), "only proxy admin can change brains");
require(xvsVaultProxy._acceptImplementation() == 0, "change not authorized");
}
function setXvsStore(address _xvs, address _xvsStore) external onlyAdmin {
_ensureNonzeroAddress(_xvs);
_ensureNonzeroAddress(_xvsStore);
address oldXvsContract = xvsAddress;
address oldStore = xvsStore;
require(oldXvsContract == address(0), "already initialized");
xvsAddress = _xvs;
xvsStore = _xvsStore;
_notEntered = true;
emit StoreUpdated(oldXvsContract, oldStore, _xvs, _xvsStore);
}
/**
* @notice Sets the address of the prime token contract
* @param _primeToken address of the prime token contract
* @param _primeRewardToken address of reward token
* @param _primePoolId pool id for reward
*/
function setPrimeToken(IPrime _primeToken, address _primeRewardToken, uint256 _primePoolId) external onlyAdmin {
require(address(_primeToken) != address(0), "prime token cannot be zero address");
require(_primeRewardToken != address(0), "reward cannot be zero address");
_ensureValidPool(_primeRewardToken, _primePoolId);
emit NewPrimeToken(primeToken, _primeToken, primeRewardToken, _primeRewardToken, primePoolId, _primePoolId);
primeToken = _primeToken;
primeRewardToken = _primeRewardToken;
primePoolId = _primePoolId;
}
/**
* @dev Initializes the contract to use either blocks or seconds
* @param timeBased_ A boolean indicating whether the contract is based on time or block
* If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR
* @param blocksPerYear_ The number of blocks per year
*/
function initializeTimeManager(bool timeBased_, uint256 blocksPerYear_) external onlyAdmin {
_initializeTimeManager(timeBased_, blocksPerYear_);
}
/**
* @notice Sets the address of the access control of this contract
* @dev Admin function to set the access control address
* @param newAccessControlAddress New address for the access control
*/
function setAccessControl(address newAccessControlAddress) external onlyAdmin {
_setAccessControlManager(newAccessControlAddress);
}
/**
* @dev Reverts if the provided address is a zero address
* @param address_ Address to check
*/
function _ensureNonzeroAddress(address address_) internal pure {
require(address_ != address(0), "zero address not allowed");
}
/**
* @dev Transfers the reward to the user, taking into account the rewards store
* balance and the previous debt. If there are not enough rewards in the store,
* transfers the available funds and records the debt amount in pendingRewardTransfers.
* @param rewardToken Reward token address
* @param userAddress User address
* @param amount Reward amount, in reward tokens
*/
function _transferReward(address rewardToken, address userAddress, uint256 amount) internal {
address xvsStore_ = xvsStore;
uint256 storeBalance = IBEP20(rewardToken).balanceOf(xvsStore_);
uint256 debtDueToFailedTransfers = pendingRewardTransfers[rewardToken][userAddress];
uint256 fullAmount = amount.add(debtDueToFailedTransfers);
if (fullAmount <= storeBalance) {
if (debtDueToFailedTransfers != 0) {
pendingRewardTransfers[rewardToken][userAddress] = 0;
emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, 0);
}
XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, fullAmount);
return;
}
// Overflow isn't possible due to the check above
uint256 newOwedAmount = fullAmount - storeBalance;
pendingRewardTransfers[rewardToken][userAddress] = newOwedAmount;
emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, newOwedAmount);
XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, storeBalance);
}
/**
* @dev Computes cumulative reward for all user's shares
* @param user UserInfo storage struct
* @param pool PoolInfo storage struct
*/
function _cumulativeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {
return user.amount.sub(user.pendingWithdrawals).mul(pool.accRewardPerShare).div(1e12);
}
/**
* @dev Computes the reward for all user's shares
* @param user UserInfo storage struct
* @param pool PoolInfo storage struct
*/
function _computeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {
return _cumulativeReward(user, pool).sub(user.rewardDebt);
}
}// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.5.16;
import "./IAccessControlManagerV5.sol";
/**
* @title AccessControlledV5
* @author Venus
* @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.5.16)
* to integrate access controlled mechanism. It provides initialise methods and verifying access methods.
*/
contract AccessControlledV5 {
/// @notice Access control manager contract
IAccessControlManagerV5 private _accessControlManager;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
/// @notice Emitted when access control manager contract address is changed
event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);
/**
* @notice Returns the address of the access control manager contract
*/
function accessControlManager() external view returns (IAccessControlManagerV5) {
return _accessControlManager;
}
/**
* @dev Internal function to set address of AccessControlManager
* @param accessControlManager_ The new address of the AccessControlManager
*/
function _setAccessControlManager(address accessControlManager_) internal {
require(address(accessControlManager_) != address(0), "invalid acess control manager address");
address oldAccessControlManager = address(_accessControlManager);
_accessControlManager = IAccessControlManagerV5(accessControlManager_);
emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);
}
/**
* @notice Reverts if the call is not allowed by AccessControlManager
* @param signature Method signature
*/
function _checkAccessAllowed(string memory signature) internal view {
bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);
if (!isAllowedToCall) {
revert("Unauthorized");
}
}
}// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.5.16;
/**
* @title IAccessControlManagerV5
* @author Venus
* @notice Interface implemented by the `AccessControlManagerV5` contract.
*/
interface IAccessControlManagerV5 {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
/**
* @notice Gives a function call permission to one single account
* @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE
* May emit a {RoleGranted} event.
* @param contractAddress address of contract for which call permissions will be granted
* @param functionSig signature e.g. "functionName(uint,bool)"
*/
function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;
/**
* @notice Revokes an account's permission to a particular function call
* @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE
* May emit a {RoleRevoked} event.
* @param contractAddress address of contract for which call permissions will be revoked
* @param functionSig signature e.g. "functionName(uint,bool)"
*/
function revokeCallPermission(
address contractAddress,
string calldata functionSig,
address accountToRevoke
) external;
/**
* @notice Verifies if the given account can call a praticular contract's function
* @dev Since the contract is calling itself this function, we can get contracts address with msg.sender
* @param account address (eoa or contract) for which call permissions will be checked
* @param functionSig signature e.g. "functionName(uint,bool)"
* @return false if the user account cannot call the particular contract function
*
*/
function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);
function hasPermission(
address account,
address contractAddress,
string calldata functionSig
) external view returns (bool);
}// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.5.16;
contract TimeManagerV5 {
/// @dev The approximate number of seconds per year
uint256 public constant SECONDS_PER_YEAR = 31_536_000;
/// @notice Number of blocks per year or seconds per year
uint256 public blocksOrSecondsPerYear;
/// @dev Sets true when block timestamp is used
bool public isTimeBased;
/// @dev Sets true when contract is initialized
bool private isInitialized;
/// @notice Deprecated slot for _getCurrentSlot function pointer
bytes8 private __deprecatedSlot1;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[48] private __gap;
/**
* @dev Function to simply retrieve block number or block timestamp
* @return Current block number or block timestamp
*/
function getBlockNumberOrTimestamp() public view returns (uint256) {
return isTimeBased ? _getBlockTimestamp() : _getBlockNumber();
}
/**
* @dev Initializes the contract to use either blocks or seconds
* @param timeBased_ A boolean indicating whether the contract is based on time or block
* If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR
* @param blocksPerYear_ The number of blocks per year
*/
function _initializeTimeManager(bool timeBased_, uint256 blocksPerYear_) internal {
if (isInitialized) revert("Already initialized TimeManager");
if (!timeBased_ && blocksPerYear_ == 0) {
revert("Invalid blocks per year");
}
if (timeBased_ && blocksPerYear_ != 0) {
revert("Invalid time based configuration");
}
isTimeBased = timeBased_;
blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_;
isInitialized = true;
}
/**
* @dev Returns the current timestamp in seconds
* @return The current timestamp
*/
function _getBlockTimestamp() private view returns (uint256) {
return block.timestamp;
}
/**
* @dev Returns the current block number
* @return The current block number
*/
function _getBlockNumber() private view returns (uint256) {
return block.number;
}
}// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
/**
* @title IPrime
* @author Venus
* @notice Interface for Prime Token
*/
interface IPrime {
/**
* @notice Executed by XVSVault whenever user's XVSVault balance changes
* @param user the account address whose balance was updated
*/
function xvsUpdated(address user) external;
/**
* @notice accrues interest and updates score for an user for a specific market
* @param user the account address for which to accrue interest and update score
* @param market the market for which to accrue interest and update score
*/
function accrueInterestAndUpdateScore(address user, address market) external;
/**
* @notice Distributes income from market since last distribution
* @param vToken the market for which to distribute the income
*/
function accrueInterest(address vToken) external;
/**
* @notice Returns if user is a prime holder
* @param isPrimeHolder returns if the user is a prime holder
*/
function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);
}pragma solidity ^0.5.5;
/**
* @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
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
/**
* @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-call-value
// solium-disable-next-line security/no-call-value
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}// SPDX-License-Identifier: MIT
// Adapted from OpenZeppelin Contracts v4.3.2 (utils/cryptography/ECDSA.sol)
// SPDX-Copyright-Text: OpenZeppelin, 2021
// SPDX-Copyright-Text: Venus, 2021
pragma solidity ^0.5.16;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
contract ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the BEP20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {BEP20Detailed}.
*/
interface IBEP20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}pragma solidity ^0.5.0;
import "./SafeMath.sol";
import "./IBEP20.sol";
import "./Address.sol";
/**
* @title SafeBEP20
* @dev Wrappers around BEP20 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 SafeBEP20 for BEP20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeBEP20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IBEP20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IBEP20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IBEP20 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'
// solhint-disable-next-line max-line-length
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeBEP20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IBEP20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IBEP20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(
value,
"SafeBEP20: decreased allowance below zero"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @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(IBEP20 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.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeBEP20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeBEP20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeBEP20: BEP20 operation did not succeed");
}
}
}pragma solidity ^0.5.16;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2 ** 128, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2 ** 64, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2 ** 32, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2 ** 16, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2 ** 8, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2 ** 127 && value < 2 ** 127, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2 ** 63 && value < 2 ** 63, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2 ** 31 && value < 2 ** 31, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2 ** 15 && value < 2 ** 15, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2 ** 7 && value < 2 ** 7, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2 ** 255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}pragma solidity ^0.5.16;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return add(a, b, "SafeMath: addition overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}pragma solidity 0.5.16;
import "../Utils/SafeBEP20.sol";
import "../Utils/IBEP20.sol";
/**
* @title XVS Store
* @author Venus
* @notice XVS Store responsible for distributing XVS rewards
*/
contract XVSStore {
using SafeMath for uint256;
using SafeBEP20 for IBEP20;
/// @notice The Admin Address
address public admin;
/// @notice The pending admin address
address public pendingAdmin;
/// @notice The Owner Address
address public owner;
/// @notice The reward tokens
mapping(address => bool) public rewardTokens;
/// @notice Emitted when pendingAdmin is changed
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/// @notice Event emitted when admin changed
event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);
/// @notice Event emitted when owner changed
event OwnerTransferred(address indexed oldOwner, address indexed newOwner);
constructor() public {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin, "only admin can");
_;
}
modifier onlyOwner() {
require(msg.sender == owner, "only owner can");
_;
}
/**
* @notice Safely transfer rewards. Only active reward tokens can be sent using this function.
* Only callable by owner
* @dev Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.
* @param token Reward token to transfer
* @param _to Destination address of the reward
* @param _amount Amount to transfer
*/
function safeRewardTransfer(address token, address _to, uint256 _amount) external onlyOwner {
require(rewardTokens[token] == true, "only reward token can");
if (address(token) != address(0)) {
uint256 tokenBalance = IBEP20(token).balanceOf(address(this));
if (_amount > tokenBalance) {
IBEP20(token).safeTransfer(_to, tokenBalance);
} else {
IBEP20(token).safeTransfer(_to, _amount);
}
}
}
/**
* @notice Allows the admin to propose a new admin
* Only callable admin
* @param _admin Propose an account as admin of the XVS store
*/
function setPendingAdmin(address _admin) external onlyAdmin {
address oldPendingAdmin = pendingAdmin;
pendingAdmin = _admin;
emit NewPendingAdmin(oldPendingAdmin, _admin);
}
/**
* @notice Allows an account that is pending as admin to accept the role
* nly calllable by the pending admin
*/
function acceptAdmin() external {
require(msg.sender == pendingAdmin, "only pending admin");
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
admin = pendingAdmin;
pendingAdmin = address(0);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
emit AdminTransferred(oldAdmin, admin);
}
/**
* @notice Set the contract owner
* @param _owner The address of the owner to set
* Only callable admin
*/
function setNewOwner(address _owner) external onlyAdmin {
require(_owner != address(0), "new owner is the zero address");
address oldOwner = owner;
owner = _owner;
emit OwnerTransferred(oldOwner, _owner);
}
/**
* @notice Set or disable a reward token
* @param _tokenAddress The address of a token to set as active or inactive
* @param status Set whether a reward token is active or not
*/
function setRewardToken(address _tokenAddress, bool status) external {
require(msg.sender == admin || msg.sender == owner, "only admin or owner can");
rewardTokens[_tokenAddress] = status;
}
/**
* @notice Security function to allow the owner of the contract to withdraw from the contract
* @param _tokenAddress Reward token address to withdraw
* @param _amount Amount of token to withdraw
*/
function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external onlyOwner {
IBEP20(_tokenAddress).safeTransfer(address(msg.sender), _amount);
}
}pragma solidity ^0.5.16;
contract XVSVaultErrorReporter {
enum Error {
NO_ERROR,
UNAUTHORIZED
}
enum FailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_PENDING_IMPLEMENTATION_OWNER_CHECK
}
/**
* @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary
* contract-specific code that enables us to report opaque error codes from upgradeable contracts.
**/
event Failure(uint error, uint info, uint detail);
/**
* @dev use this when reporting a known error from the money market or a non-upgradeable collaborator
*/
function fail(Error err, FailureInfo info) internal returns (uint) {
emit Failure(uint(err), uint(info), 0);
return uint(err);
}
/**
* @dev use this when reporting an opaque error from an upgradeable collaborator contract
*/
function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {
emit Failure(uint(err), uint(info), opaqueError);
return uint(err);
}
}pragma solidity ^0.5.16;
import "./XVSVaultStorage.sol";
import "./XVSVaultErrorReporter.sol";
/**
* @title XVS Vault Proxy
* @author Venus
* @notice XVS Vault Proxy contract
*/
contract XVSVaultProxy is XVSVaultAdminStorage, XVSVaultErrorReporter {
/**
* @notice Emitted when pendingXVSVaultImplementation is changed
*/
event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);
/**
* @notice Emitted when pendingXVSVaultImplementation is accepted, which means XVS Vault implementation is updated
*/
event NewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Emitted when pendingAdmin is changed
*/
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Emitted when pendingAdmin is accepted, which means admin is updated
*/
event NewAdmin(address oldAdmin, address newAdmin);
constructor() public {
// Set admin to caller
admin = msg.sender;
}
/*** Admin Functions ***/
function _setPendingImplementation(address newPendingImplementation) public returns (uint) {
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);
}
address oldPendingImplementation = pendingXVSVaultImplementation;
pendingXVSVaultImplementation = newPendingImplementation;
emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);
return uint(Error.NO_ERROR);
}
/**
* @notice Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation
* @dev Admin function for new implementation to accept it's role as implementation
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _acceptImplementation() public returns (uint) {
// Check caller is pendingImplementation
if (msg.sender != pendingXVSVaultImplementation) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);
}
// Save current values for inclusion in log
address oldImplementation = implementation;
address oldPendingImplementation = pendingXVSVaultImplementation;
implementation = pendingXVSVaultImplementation;
pendingXVSVaultImplementation = address(0);
emit NewImplementation(oldImplementation, implementation);
emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);
return uint(Error.NO_ERROR);
}
/**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _setPendingAdmin(address newPendingAdmin) public returns (uint) {
// Check caller = admin
if (msg.sender != admin) {
return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);
}
// Save current value, if any, for inclusion in log
address oldPendingAdmin = pendingAdmin;
// Store pendingAdmin with value newPendingAdmin
pendingAdmin = newPendingAdmin;
// Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
return uint(Error.NO_ERROR);
}
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _acceptAdmin() public returns (uint) {
// Check caller is pendingAdmin
if (msg.sender != pendingAdmin) {
return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);
}
// Save current values for inclusion in log
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
// Store admin with value pendingAdmin
admin = pendingAdmin;
// Clear the pending value
pendingAdmin = address(0);
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
return uint(Error.NO_ERROR);
}
/**
* @dev Delegates execution to an implementation contract.
* It returns to the external caller whatever the implementation returns
* or forwards reverts.
*/
function() external payable {
// delegate all other functions to current implementation
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize)
switch success
case 0 {
revert(free_mem_ptr, returndatasize)
}
default {
return(free_mem_ptr, returndatasize)
}
}
}
}pragma solidity ^0.5.16;
import "../Utils/SafeMath.sol";
import "../Utils/IBEP20.sol";
import "../Tokens/Prime/IPrime.sol";
contract XVSVaultAdminStorage {
/**
* @notice Administrator for this contract
*/
address public admin;
/**
* @notice Pending administrator for this contract
*/
address public pendingAdmin;
/**
* @notice Active brains of XVS Vault
*/
address public implementation;
/**
* @notice Pending brains of XVS Vault
*/
address public pendingXVSVaultImplementation;
}
contract XVSVaultStorageV1 is XVSVaultAdminStorage {
/// @notice Guard variable for re-entrancy checks
bool internal _notEntered;
/// @notice The reward token store
address public xvsStore;
/// @notice The xvs token address
address public xvsAddress;
// Reward tokens created per block or second indentified by reward token address.
mapping(address => uint256) public rewardTokenAmountsPerBlockOrSecond;
/// @notice Info of each user.
struct UserInfo {
uint256 amount;
uint256 rewardDebt;
uint256 pendingWithdrawals;
}
// Info of each pool.
struct PoolInfo {
IBEP20 token; // Address of token contract to stake.
uint256 allocPoint; // How many allocation points assigned to this pool.
uint256 lastRewardBlockOrSecond; // Last block number or second that reward tokens distribution occurs.
uint256 accRewardPerShare; // Accumulated per share, times 1e12. See below.
uint256 lockPeriod; // Min time between withdrawal request and its execution.
}
// Infomation about a withdrawal request
struct WithdrawalRequest {
uint256 amount;
uint128 lockedUntil;
uint128 afterUpgrade;
}
// Info of each user that stakes tokens.
mapping(address => mapping(uint256 => mapping(address => UserInfo))) internal userInfos;
// Info of each pool.
mapping(address => PoolInfo[]) public poolInfos;
// Total allocation points. Must be the sum of all allocation points in all pools.
mapping(address => uint256) public totalAllocPoints;
// Info of requested but not yet executed withdrawals
mapping(address => mapping(uint256 => mapping(address => WithdrawalRequest[]))) internal withdrawalRequests;
/// @notice DEPRECATED A record of each accounts delegate (before the voting power fix)
mapping(address => address) private __oldDelegatesSlot;
/// @notice A checkpoint for marking number of votes from a given block or second
struct Checkpoint {
uint32 fromBlockOrSecond;
uint96 votes;
}
/// @notice DEPRECATED A record of votes checkpoints for each account, by index (before the voting power fix)
mapping(address => mapping(uint32 => Checkpoint)) private __oldCheckpointsSlot;
/// @notice DEPRECATED The number of checkpoints for each account (before the voting power fix)
mapping(address => uint32) private __oldNumCheckpointsSlot;
/// @notice A record of states for signing / validating signatures
mapping(address => uint) public nonces;
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH =
keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH =
keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
}
contract XVSVaultStorage is XVSVaultStorageV1 {
/// @notice A record of each accounts delegate
mapping(address => address) public delegates;
/// @notice A record of votes checkpoints for each account, by index
mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping(address => uint32) public numCheckpoints;
/// @notice Tracks pending withdrawals for all users for a particular reward token and pool id
mapping(address => mapping(uint256 => uint256)) public totalPendingWithdrawals;
/// @notice pause indicator for Vault
bool public vaultPaused;
/// @notice if the token is added to any of the pools
mapping(address => bool) public isStakedToken;
/// @notice Amount we owe to users because of failed transfer attempts
mapping(address => mapping(address => uint256)) public pendingRewardTransfers;
/// @notice Prime token contract address
IPrime public primeToken;
/// @notice Reward token for which prime token is issued for staking
address public primeRewardToken;
/// @notice Pool ID for which prime token is issued for staking
uint256 public primePoolId;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[46] private __gap;
}{
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChangedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChangedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExecutedWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAccessControlManager","type":"address"},{"indexed":false,"internalType":"address","name":"newAccessControlManager","type":"address"}],"name":"NewAccessControlManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPrime","name":"oldPrimeToken","type":"address"},{"indexed":true,"internalType":"contract IPrime","name":"newPrimeToken","type":"address"},{"indexed":false,"internalType":"address","name":"oldPrimeRewardToken","type":"address"},{"indexed":false,"internalType":"address","name":"newPrimeRewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldPrimePoolId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrimePoolId","type":"uint256"}],"name":"NewPrimeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"allocPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerBlockOrSecond","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"PoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldAllocPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAllocPoints","type":"uint256"}],"name":"PoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RequestedWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReward","type":"uint256"}],"name":"RewardAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldXvs","type":"address"},{"indexed":false,"internalType":"address","name":"oldStore","type":"address"},{"indexed":false,"internalType":"address","name":"newXvs","type":"address"},{"indexed":false,"internalType":"address","name":"newStore","type":"address"}],"name":"StoreUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldOwedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newOwedAmount","type":"uint256"}],"name":"VaultDebtUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"VaultPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"VaultResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPeriod","type":"uint256"}],"name":"WithdrawalLockingPeriodUpdated","type":"event"},{"constant":true,"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_LOCK_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SECONDS_PER_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract XVSVaultProxy","name":"xvsVaultProxy","type":"address"}],"name":"_become","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accessControlManager","outputs":[{"internalType":"contract IAccessControlManagerV5","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"},{"internalType":"contract IBEP20","name":"_token","type":"address"},{"internalType":"uint256","name":"_rewardPerBlockOrSecond","type":"uint256"},{"internalType":"uint256","name":"_lockPeriod","type":"uint256"}],"name":"add","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blocksOrSecondsPerYear","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlockOrSecond","type":"uint32"},{"internalType":"uint96","name":"votes","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"claim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"executeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBlockNumberOrTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getEligibleWithdrawalAmount","outputs":[{"internalType":"uint256","name":"withdrawalAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumberOrSecond","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getRequestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"pendingWithdrawals","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint128","name":"lockedUntil","type":"uint128"},{"internalType":"uint128","name":"afterUpgrade","type":"uint128"}],"internalType":"struct XVSVaultStorageV1.WithdrawalRequest[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"timeBased_","type":"bool"},{"internalType":"uint256","name":"blocksPerYear_","type":"uint256"}],"name":"initializeTimeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isStakedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isTimeBased","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"pendingRewardTransfers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingWithdrawalsBeforeUpgrade","outputs":[{"internalType":"uint256","name":"beforeUpgradeWithdrawalAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingXVSVaultImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfos","outputs":[{"internalType":"contract IBEP20","name":"token","type":"address"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlockOrSecond","type":"uint256"},{"internalType":"uint256","name":"accRewardPerShare","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"rewardToken","type":"address"}],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"primePoolId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"primeRewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"primeToken","outputs":[{"internalType":"contract IPrime","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"requestWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"rewardTokenAmountsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardTokenAmountsPerBlockOrSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_allocPoint","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newAccessControlAddress","type":"address"}],"name":"setAccessControl","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IPrime","name":"_primeToken","type":"address"},{"internalType":"address","name":"_primeRewardToken","type":"address"},{"internalType":"uint256","name":"_primePoolId","type":"uint256"}],"name":"setPrimeToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_rewardAmount","type":"uint256"}],"name":"setRewardAmountPerBlockOrSecond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_newPeriod","type":"uint256"}],"name":"setWithdrawalLockingPeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_xvs","type":"address"},{"internalType":"address","name":"_xvsStore","type":"address"}],"name":"setXvsStore","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalAllocPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalPendingWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"vaultPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"xvsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"xvsStore","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b0319163317905561578980620000336000396000f3fe608060405234801561001057600080fd5b50600436106103785760003560e01c806392e35000116101d3578063c7ad089511610104578063e7a324dc116100a2578063f55401621161007c578063f554016214610732578063f851a4401461073a578063fba1b1f914610742578063fe5a451a1461075557610378565b8063e7a324dc14610701578063e8f2be6f14610709578063f1127ed81461071157610378565b8063dae66bbe116100de578063dae66bbe146106d6578063de0368b2146106e9578063e1d146fb146106f1578063e6a69ab8146106f957610378565b8063c7ad0895146106a8578063cd9b94e7146106b0578063d7ae45e2146106c357610378565b8063add8933711610171578063b6a5fd2f1161014b578063b6a5fd2f1461064f578063c210259614610662578063c3c754a814610682578063c3cda5201461069557610378565b8063add893371461061f578063b4a0bdf314610627578063b4b5ea571461063c57610378565b80639e2b6c4d116101ad5780639e2b6c4d146105d3578063a09eab7a146105e6578063a6997762146105f9578063a9d69a691461060c57610378565b806392e350001461057a57806398e1b31b1461059e578063996cba68146105c057610378565b80635c19a95c116102ad57806373d025d61161024b5780637ecebe00116102255780637ecebe00146105395780638308d7e91461054c5780638456cb591461055f5780638ed7333d1461056757610378565b806373d025d6146104f1578063782d6fe1146105065780637ac924561461052657610378565b80635ff56315116102875780635ff56315146104a35780636857249c146104b65780636dd77cbd146104be5780636fcfff45146104d157610378565b80635c19a95c146104755780635c60da1b146104885780635f14e7001461049057610378565b806324f52bbf1161031a578063358ae036116102f4578063358ae036146104345780633d4180f91461043c5780634298bdbd1461044f578063587cde1e1461046257610378565b806324f52bbf1461040457806326782247146104195780632eda5c6c1461042157610378565b8063115b512f11610356578063115b512f146103c357806319129e5a146103d65780631d504dc6146103e957806320606b70146103fc57610378565b8063046f7da21461037d5780630af13728146103875780630efe6a8b146103b0575b600080fd5b61038561075d565b005b61039a6103953660046140be565b6107e8565b6040516103a791906150ae565b60405180910390f35b6103856103be366004614176565b61082e565b6103856103d1366004614176565b610b23565b6103856103e4366004613fcb565b610ed7565b6103856103f73660046142bd565b610f0d565b61039a61103e565b61040c611055565b6040516103a79190614f4c565b61040c611064565b61039a61042f366004613fcb565b611073565b61040c611092565b61039a61044a366004614007565b6110a1565b61039a61045d366004613fcb565b6110be565b61040c610470366004613fcb565b6110d0565b610385610483366004613fcb565b6110eb565b61040c611118565b61039a61049e36600461408e565b611127565b6103856104b1366004614007565b611144565b61039a611238565b61039a6104cc3660046140be565b61123e565b6104e46104df366004613fcb565b6112f3565b6040516103a7919061545c565b6104f961130b565b6040516103a791906150a0565b61051961051436600461408e565b611314565b6040516103a79190615485565b61038561053436600461408e565b61152a565b61039a610547366004613fcb565b611873565b61038561055a366004614176565b611885565b610385611a2b565b61038561057536600461408e565b611ab0565b61058d61058836600461408e565b611aeb565b6040516103a795949392919061511b565b6105b16105ac3660046140be565b611b40565b6040516103a793929190615441565b6103856105ce366004614041565b611b92565b6103856105e1366004614176565b611d24565b61039a6105f43660046140be565b611e0f565b61038561060736600461427d565b61205f565b61039a61061a3660046140be565b612093565b61040c6120d5565b61062f6120e4565b6040516103a7919061510d565b61051961064a366004613fcb565b6120f3565b61038561065d36600461408e565b612163565b6106756106703660046140be565b612289565b6040516103a7919061508f565b6104f9610690366004613fcb565b612343565b6103856106a33660046141a8565b612358565b6104f96124fc565b61039a6106be366004613fcb565b612505565b61039a6106d1366004613fcb565b612517565b6103856106e436600461429c565b612532565b61040c61263e565b61039a61264d565b61039a612674565b61039a61267c565b61039a612688565b61072461071f36600461422f565b61268e565b6040516103a792919061546a565b61039a6126c3565b61040c6126cb565b610385610750366004614101565b6126da565b61062f6129bf565b61078660405180604001604052806008815260200167726573756d65282960c01b8152506129ce565b60135460ff166107b15760405162461bcd60e51b81526004016107a8906151d8565b60405180910390fd5b6013805460ff1916905560405133907fd2619572a1464e0df0bb351d834fd47f3350984d7bfdb1ab69cfcb0b8e42141590600090a2565b60006107f48484612a70565b506001600160a01b0380841660009081526007602090815260408083208684528252808320938516835292905220600201545b9392505050565b600354600160a01b900460ff166108575760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff16156108875760405162461bcd60e51b81526004016107a8906151c8565b6108918383612a70565b6001600160a01b03831660009081526008602052604081208054849081106108b557fe5b600091825260208083206001600160a01b038816845260078252604080852088865283528085203386529092529220600590910290910191506108f88585612aa7565b610903858533612093565b156109205760405162461bcd60e51b81526004016107a8906152e8565b8054156109955760006109338284612c84565b9050801561099357610946863383612c98565b84866001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e946458460405161098a91906150ae565b60405180910390a45b505b81546109b2906001600160a01b031633308663ffffffff612f1116565b80546109c4908463ffffffff612f7216565b81556109d08183612fb4565b600182015560055482546001600160a01b0390811691161415610a3757336000908152600f60209081526040808320548151606081019092526021808352610a3794936001600160a01b0390921692610a329289929061562990830139612fe2565b613011565b6017546001600160a01b038681169116148015610a55575060185484145b15610abd576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610a8a903390600401614f5a565b600060405180830381600087803b158015610aa457600080fd5b505af1158015610ab8573d6000803e3d6000fd5b505050505b83856001600160a01b0316336001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d786604051610b0191906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b179055505050565b600354600160a01b900460ff16610b4c5760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff1615610b7c5760405162461bcd60e51b81526004016107a8906151c8565b610b868383612a70565b60008111610ba65760405162461bcd60e51b81526004016107a890615308565b6001600160a01b0383166000908152600760209081526040808320858452825280832033845290915290206002810154610be6908363ffffffff612f7216565b81541015610c065760405162461bcd60e51b81526004016107a8906153e8565b6001600160a01b0384166000908152600860205260408120805485908110610c2a57fe5b600091825260208083206001600160a01b0389168452600a825260408085208986528352808520338652909252908320600590920201925090610c6c826131a3565b5090508015610c8d5760405162461bcd60e51b81526004016107a8906152e8565b610c978787612aa7565b6000610ca38585612c84565b9050610cb0883383612c98565b6004840154600090610cc8904263ffffffff612f7216565b9050610cd686858984613247565b6001600160a01b03891660009081526012602090815260408083208b8452909152902054610d0a908863ffffffff612f7216565b6001600160a01b038a1660009081526012602090815260408083208c8452909152902055610d388686612fb4565b600187015560055485546001600160a01b0390811691161415610d9b57336000908152600f6020908152604080832054815160608101909252602b808352610d9b946001600160a01b03909216939192610a32928d92906155d690830139612fe2565b6017546001600160a01b038a81169116148015610db9575060185488145b15610e21576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610dee903390600401614f5a565b600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b505050505b87896001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464585604051610e6591906150ae565b60405180910390a487896001600160a01b0316336001600160a01b03167f88a254a0ef28a0b9e957ff600beae69870f6f924065147f3627c3f814e60ec118a604051610eb191906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b17905550505050505050565b6000546001600160a01b03163314610f015760405162461bcd60e51b81526004016107a890615368565b610f0a8161342b565b50565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4657600080fd5b505afa158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f7e9190810190613fe9565b6001600160a01b0316336001600160a01b031614610fae5760405162461bcd60e51b81526004016107a8906153f8565b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fe957600080fd5b505af1158015610ffd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061102191908101906142db565b15610f0a5760405162461bcd60e51b81526004016107a890615378565b60405161104a90614f36565b604051809103902081565b6004546001600160a01b031681565b6001546001600160a01b031681565b6001600160a01b0381166000908152600660205260409020545b919050565b6005546001600160a01b031681565b601560209081526000928352604080842090915290825290205481565b60096020526000908152604090205481565b600f602052600090815260409020546001600160a01b031681565b60135460ff161561110e5760405162461bcd60e51b81526004016107a8906151c8565b610f0a33826134b0565b6002546001600160a01b031681565b601260209081526000928352604080842090915290825290205481565b6000546001600160a01b0316331461116e5760405162461bcd60e51b81526004016107a890615368565b6111778261353f565b6111808161353f565b6005546004546001600160a01b03918216911681156111b15760405162461bcd60e51b81526004016107a8906152a8565b600580546001600160a01b038087166001600160a01b03199283161790925560048054928616929091169190911790556003805460ff60a01b1916600160a01b1790556040517f559f314bb90394a4a9ceb724f365b36a53587d894352c43d12901fd6801014569061122a908490849088908890614fcb565b60405180910390a150505050565b60795481565b600061124a8484612a70565b6001600160a01b038085166000908152600a60209081526040808320878452825280832093861683529290522080545b6000811180156112aa57506112aa82600183038154811061129757fe5b9060005260206000209060020201613565565b156112ea576112df8260018303815481106112c157fe5b6000918252602090912060029091020154849063ffffffff612f7216565b92506000190161127a565b50509392505050565b60116020526000908152604090205463ffffffff1681565b60135460ff1681565b600061131e61264d565b821061133c5760405162461bcd60e51b81526004016107a8906152b8565b6001600160a01b03831660009081526011602052604090205463ffffffff168061136a576000915050611524565b6001600160a01b038416600090815260106020908152604080832063ffffffff6000198601811685529252909120541683106113e6576001600160a01b03841660009081526010602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050611524565b6001600160a01b038416600090815260106020908152604080832083805290915290205463ffffffff16831015611421576000915050611524565b600060001982015b8163ffffffff168163ffffffff1611156114e457600282820363ffffffff16048103611453613f51565b506001600160a01b038716600090815260106020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b031691810191909152908714156114bf576020015194506115249350505050565b805163ffffffff168711156114d6578193506114dd565b6001820392505b5050611429565b506001600160a01b038516600090815260106020908152604080832063ffffffff909416835292905220546001600160601b03600160201b909104169150505b92915050565b600354600160a01b900460ff166115535760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff16156115835760405162461bcd60e51b81526004016107a8906151c8565b61158d8282612a70565b6001600160a01b03821660009081526008602052604081208054839081106115b157fe5b600091825260208083206001600160a01b038716808552600783526040808620888752845280862033808852908552818720928752600a8552818720898852855281872090875290935291842060059093020193509180611612848461357a565b9092509050811515806116255750600081115b6116415760405162461bcd60e51b81526004016107a890615388565b81158061164c575080155b6116685760405162461bcd60e51b81526004016107a890615188565b8115611781576116788787612aa7565b60006116be85600101546116b264e8d4a510006116a68a600301548a6000015461367190919063ffffffff16565b9063ffffffff6136ab16565b9063ffffffff6136ed16565b6004805460405163135b33cd60e31b81529293506001600160a01b031691639ad99e68916116f2918c913391879101614fa3565b600060405180830381600087803b15801561170c57600080fd5b505af1158015611720573d6000803e3d6000fd5b50508654611737925090508463ffffffff6136ed16565b808655600387015461175a9164e8d4a51000916116a6919063ffffffff61367116565b6001860155855461177b906001600160a01b0316338563ffffffff61372f16565b50611805565b8354611793908263ffffffff6136ed16565b84556001600160a01b03871660009081526012602090815260408083208984529091529020546117c9908263ffffffff6136ed16565b6001600160a01b0380891660009081526012602090815260408083208b845290915290209190915585546118059116338363ffffffff61372f16565b856001600160a01b038816337fe31da05fae6db869f5ea51f4b638aa6884070b6c87f18f63bd2291a12cb2f518611842868663ffffffff612f7216565b60405161184f91906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b1790555050505050565b600e6020526000908152604090205481565b6118c36040518060400160405280601c81526020017f73657428616464726573732c75696e743235362c75696e7432353629000000008152506129ce565b6118cd8383612a70565b6118d683613751565b6001600160a01b0383166000908152600860205260408120805490919061194f9084906119439085908890811061190957fe5b60009182526020808320600160059093020191909101546001600160a01b038b16835260099091526040909120549063ffffffff6136ed16565b9063ffffffff612f7216565b9050600081116119715760405162461bcd60e51b81526004016107a890615408565b600082858154811061197f57fe5b9060005260206000209060050201600101549050838386815481106119a057fe5b9060005260206000209060050201600101819055508160096000886001600160a01b03166001600160a01b031681526020019081526020016000208190555084866001600160a01b03167f6ee09c6cb801194690c195c69f465aaf7c80255cbeafaab9600f47ed79de2ca98387604051611a1b929190615433565b60405180910390a3505050505050565b611a53604051806040016040528060078152602001667061757365282960c81b8152506129ce565b60135460ff1615611a765760405162461bcd60e51b81526004016107a890615268565b6013805460ff1916600117905560405133907fdffada2889ebfab9224c24069d833f3de835d8cf99872d49e7b7ba5fccb7a46f90600090a2565b60135460ff1615611ad35760405162461bcd60e51b81526004016107a8906151c8565b611add8282612a70565b611ae78282612aa7565b5050565b60086020528160005260406000208181548110611b0457fe5b6000918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919085565b6000806000611b4f8686612a70565b5050506001600160a01b03928316600090815260076020908152604080832094835293815283822092909416815292529020805460018201546002909201549092565b600354600160a01b900460ff16611bbb5760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff1615611beb5760405162461bcd60e51b81526004016107a8906151c8565b611bf58282612a70565b6001600160a01b0382166000908152600860205260408120805483908110611c1957fe5b600091825260208083206001600160a01b0380881685526007835260408086208887528452808620918a1686529252922060059091029091019150611c5e8484612aa7565b611c69848487612093565b15611c865760405162461bcd60e51b81526004016107a8906152e8565b805415611d0a576000611c998284612c84565b90508015611d0857611cab8284612fb4565b6001830155611cbb858783612c98565b83856001600160a01b0316876001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464584604051611cff91906150ae565b60405180910390a45b505b50506003805460ff60a01b1916600160a01b179055505050565b611d4560405180606001604052806033815260200161568c603391396129ce565b611d4f8383612a70565b600081118015611d6257506312cc030081105b611d7e5760405162461bcd60e51b81526004016107a890615398565b6001600160a01b0383166000908152600860205260408120805484908110611da257fe5b9060005260206000209060050201905060008160040154905082826004018190555083856001600160a01b03167f0bcf80c5060ccf99b7a993c57a94b232fc2c5c04bd74c7c7d174595fee6bc31f8386604051611e00929190615433565b60405180910390a35050505050565b6000611e1b8484612a70565b6001600160a01b0384166000908152600860205260408120805485908110611e3f57fe5b600091825260208083206001600160a01b03808a168086526007845260408087208b885285528087208a8416885285528087206003600590970290940195860154918752601285528087208b885290945283862054855494516370a0823160e01b8152959750929590949093611f16939216906370a0823190611ec6903090600401614f4c565b60206040518083038186803b158015611ede57600080fd5b505afa158015611ef2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116b291908101906142db565b90506000611f2261264d565b6001600160a01b038a1660009081526006602052604090205460028701549192509082118015611f5157508215155b15611fe7576000611f6f8760020154846136ed90919063ffffffff16565b6001600160a01b038c1660009081526009602052604081205460018a01549293509091611fb791906116a690611fab868863ffffffff61367116565b9063ffffffff61367116565b9050611fe2611fd5866116a68464e8d4a5100063ffffffff61367116565b879063ffffffff612f7216565b955050505b6001600160a01b03808b166000908152600a602090815260408083208d84528252808320938c16835292905290812090612020826131a3565b91505061204f87600101546116b264e8d4a510006116a68a611fab878e600001546136ed90919063ffffffff16565b9c9b505050505050505050505050565b6000546001600160a01b031633146120895760405162461bcd60e51b81526004016107a890615368565b611ae78282613786565b6001600160a01b038084166000908152600a60209081526040808320868452825280832093851683529290529081206120cb816131a3565b5095945050505050565b6017546001600160a01b031681565b6047546001600160a01b031690565b6001600160a01b03811660009081526011602052604081205463ffffffff168061211e576000610827565b6001600160a01b0383166000908152601060209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03169392505050565b6121846040518060600160405280603081526020016156eb603091396129ce565b60048054604051633d6ac5b360e21b81526001600160a01b039091169163f5ab16cc916121b391869101614f4c565b60206040518083038186803b1580156121cb57600080fd5b505afa1580156121df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612203919081019061425f565b61221f5760405162461bcd60e51b81526004016107a890615358565b61222882613751565b6001600160a01b0382166000818152600660205260409081902080549084905590519091907fad96cee0d692f0250b98e085504f399da6733854908215f6203fe3c69366d9f59061227c9084908690615433565b60405180910390a2505050565b60606122958484612a70565b6001600160a01b038085166000908152600a602090815260408083208784528252808320938616835292815282822080548451818402810184019095528085529092909184015b828210156123365760008481526020908190206040805160608101825260028602909201805483526001908101546001600160801b0380821685870152600160801b909104169183019190915290835290920191016122dc565b5050505090509392505050565b60146020526000908152604090205460ff1681565b60135460ff161561237b5760405162461bcd60e51b81526004016107a8906151c8565b600060405161238990614f36565b604080519182900382208282019091526008825267161594d5985d5b1d60c21b6020909201919091527fddfcc46608a8bd52ebf900f03a24cc97b73a6046cec8c5d0f74a211e376e967a6123db613835565b306040516020016123ef94939291906150ca565b604051602081830303815290604052805190602001209050600060405161241590614f41565b604051908190038120612430918a908a908a906020016150bc565b6040516020818303038152906040528051906020012090506000828260405160200161245d929190614f05565b604051602081830303815290604052805190602001209050600061248382888888613839565b6001600160a01b0381166000908152600e6020526040902080546001810190915590915089146124c55760405162461bcd60e51b81526004016107a890615238565b874211156124e55760405162461bcd60e51b81526004016107a890615218565b6124ef818b6134b0565b505050505b505050505050565b607a5460ff1681565b60066020526000908152604090205481565b6001600160a01b031660009081526008602052604090205490565b6000546001600160a01b0316331461255c5760405162461bcd60e51b81526004016107a890615368565b6001600160a01b0383166125825760405162461bcd60e51b81526004016107a890615228565b6001600160a01b0382166125a85760405162461bcd60e51b81526004016107a8906152c8565b6125b28282612a70565b6016546017546018546040516001600160a01b03808816948116937f8def9436d6e31b89ed00948ba91d0cb6936eada5154cb1b45b55683fb9e492379361260193919092169188918890615024565b60405180910390a3601680546001600160a01b039485166001600160a01b0319918216179091556017805493909416921691909117909155601855565b6003546001600160a01b031681565b607a5460009060ff1661266757612662613863565b61266f565b61266f613867565b905090565b6301e1338081565b60405161104a90614f41565b60185481565b601060209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6312cc030081565b6000546001600160a01b031681565b6126fb6040518060600160405280602c815260200161571b602c91396129ce565b6127048561353f565b61270d8361353f565b6004546001600160a01b03166127355760405162461bcd60e51b81526004016107a8906151a8565b600084116127555760405162461bcd60e51b81526004016107a8906153a8565b61275e85613751565b6001600160a01b0385166000908152600860205260408120805490915b818110156127d957856001600160a01b031683828154811061279957fe5b60009182526020909120600590910201546001600160a01b031614156127d15760405162461bcd60e51b81526004016107a890615328565b60010161277b565b506001600160a01b03851660009081526014602052604090205460ff16156128135760405162461bcd60e51b81526004016107a890615298565b6001600160a01b03871660009081526009602052604090205461283c908763ffffffff612f7216565b6001600160a01b038089166000908152600960209081526040808320949094556006815290839020879055825160a081018452918816825281018890528391810161288561264d565b8152600060208083018290526040928301889052845460018082018755958352818320855160059092020180546001600160a01b0319166001600160a01b039283161781558583015181880155858501516002820155606086015160038201556080909501516004958601558a81168352601490915290829020805460ff1916851790558254915163fb66fb4d60e01b815291169263fb66fb4d9261292d928c929101615059565b600060405180830381600087803b15801561294757600080fd5b505af115801561295b573d6000803e3d6000fd5b50505050846001600160a01b03166001838054905003886001600160a01b03167fd7fa4bff1cd2253c0789c3291a786a6f6b1a3b4569a75af683a15d52abb6a0bf8988886040516129ae93929190615441565b60405180910390a450505050505050565b6016546001600160a01b031681565b6047546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90612a019033908690600401614f68565b60206040518083038186803b158015612a1957600080fd5b505afa158015612a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a51919081019061425f565b905080611ae75760405162461bcd60e51b81526004016107a8906151e8565b6001600160a01b0382166000908152600860205260409020548110611ae75760405162461bcd60e51b81526004016107a890615198565b6001600160a01b0382166000908152600860205260408120805483908110612acb57fe5b906000526020600020906005020190508060020154612ae861264d565b11612af35750611ae7565b80546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612b23903090600401614f4c565b60206040518083038186803b158015612b3b57600080fd5b505afa158015612b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b7391908101906142db565b6001600160a01b0385166000908152601260209081526040808320878452909152902054909150612bab90829063ffffffff6136ed16565b905080612bc957612bba61264d565b82600201819055505050611ae7565b6000612bd361264d565b90506000612bee8460020154836136ed90919063ffffffff16565b6001600160a01b03871660009081526009602090815260408083205460018901546006909352908320549394509192612c3792916116a691611fab90879063ffffffff61367116565b9050612c66612c55856116a68464e8d4a5100063ffffffff61367116565b60038701549063ffffffff612f7216565b6003860155612c7361264d565b856002018190555050505050505050565b600061082783600101546116b28585612fb4565b600480546040516370a0823160e01b81526001600160a01b03918216926000928716916370a0823191612ccd91869101614f4c565b60206040518083038186803b158015612ce557600080fd5b505afa158015612cf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d1d91908101906142db565b6001600160a01b038087166000908152601560209081526040808320938916835292905290812054919250612d58858363ffffffff612f7216565b9050828111612e36578115612dcb576001600160a01b038088166000818152601560209081526040808320948b1680845294909152808220829055517f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216091612dc291879190615418565b60405180910390a35b60405163135b33cd60e31b81526001600160a01b03851690639ad99e6890612dfb908a908a908690600401615009565b600060405180830381600087803b158015612e1557600080fd5b505af1158015612e29573d6000803e3d6000fd5b5050505050505050612f0c565b6001600160a01b038088166000818152601560209081526040808320948b168084529490915290819020868503908190559051909291907f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216090612e9c9087908690615433565b60405180910390a360405163135b33cd60e31b81526001600160a01b03861690639ad99e6890612ed4908b908b908990600401615009565b600060405180830381600087803b158015612eee57600080fd5b505af1158015612f02573d6000803e3d6000fd5b5050505050505050505b505050565b604051612f6c9085906323b872dd60e01b90612f3590879087908790602401615009565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261386b565b50505050565b600061082783836040518060400160405280601b81526020017f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815250613950565b600061082764e8d4a510006116a68460030154611fab876002015488600001546136ed90919063ffffffff16565b600081600160601b84106130095760405162461bcd60e51b81526004016107a89190615167565b509192915050565b816001600160a01b0316836001600160a01b03161415801561303c57506000816001600160601b0316115b15612f0c576001600160a01b038316156130f4576001600160a01b03831660009081526011602052604081205463ffffffff16908161307c5760006130bb565b6001600160a01b0385166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006130e282856040518060600160405280602c81526020016156bf602c9139613980565b90506130f0868484846139bf565b5050505b6001600160a01b03821615612f0c576001600160a01b03821660009081526011602052604081205463ffffffff16908161312f57600061316e565b6001600160a01b0384166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061319582856040518060600160405280602b81526020016155ab602b9139613b7b565b90506124f4858484846139bf565b805460009081905b8015613241578360018203815481106131c057fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156132235761321c8460018303815481106131fe57fe5b6000918252602090912060029091020154839063ffffffff612f7216565b9150613238565b6132358460018303815481106112c157fe5b92505b600019016131ab565b50915091565b8254604080516060810182526000808252602080830182815260019484018581528587018a5589845291909220925160028602909301928355905191909201805492516001600160801b03908116600160801b029281166001600160801b0319909416939093179092161790555b6000811180156132f05750818460018303815481106132d057fe5b60009182526020909120600160029092020101546001600160801b031611155b156133775783600182038154811061330457fe5b906000526020600020906002020184828154811061331e57fe5b600091825260209091208254600290920201908155600191820180549290910180546001600160801b0319166001600160801b03938416178082559154600160801b9081900484160291909216179055600019016132b5565b604051806060016040528084815260200161339184613bae565b6001600160801b0316815260200160016001600160801b03168152508482815481106133b957fe5b60009182526020918290208351600292830290910190815591830151600190920180546040909401516001600160801b03199094166001600160801b03938416178316600160801b939094169290920292909217905585015461341c9084612f72565b85600201819055505050505050565b6001600160a01b0381166134515760405162461bcd60e51b81526004016107a890615278565b604780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906134a49083908590614f88565b60405180910390a15050565b6001600160a01b038083166000908152600f6020526040812054909116906134d784613bd7565b6001600160a01b038581166000818152600f602052604080822080546001600160a01b031916898616908117909155905194955093928616927f0cc323ffec3ea49cbcddc0de1480978126d350c6a45dff33ad2f1cda6ae992619190a4612f6c828483613011565b6001600160a01b038116610f0a5760405162461bcd60e51b81526004016107a8906152d8565b60010154426001600160801b03909116111590565b805460009081905b60008111801561359f575061359f84600183038154811061129757fe5b15613640578360018203815481106135b357fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156135f8576135f18460018303815481106131fe57fe5b915061360d565b61360a8460018303815481106112c157fe5b92505b8380548061361757fe5b600082815260208120600019928301600281029091018281556001019190915590915501613582565b50613665613654828463ffffffff612f7216565b60028601549063ffffffff6136ed16565b60028501559250929050565b60008261368057506000611524565b8282028284828161368d57fe5b04146108275760405162461bcd60e51b81526004016107a890615318565b600061082783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613ced565b600061082783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613d24565b604051612f0c90849063a9059cbb60e01b90612f359086908690602401615074565b6001600160a01b038116600090815260086020526040812054905b81811015612f0c5761377e8382612aa7565b60010161376c565b607a54610100900460ff16156137ae5760405162461bcd60e51b81526004016107a8906153b8565b811580156137ba575080155b156137d75760405162461bcd60e51b81526004016107a890615338565b8180156137e357508015155b156138005760405162461bcd60e51b81526004016107a890615258565b607a805460ff191683151517905581613819578061381f565b6301e133805b6079555050607a805461ff001916610100179055565b4690565b600080600061384a87878787613d48565b9150915061385781613e28565b5090505b949350505050565b4390565b4290565b61387d826001600160a01b0316613ef1565b6138995760405162461bcd60e51b81526004016107a8906153d8565b60006060836001600160a01b0316836040516138b59190614ef9565b6000604051808303816000865af19150503d80600081146138f2576040519150601f19603f3d011682016040523d82523d6000602084013e6138f7565b606091505b5091509150816139195760405162461bcd60e51b81526004016107a8906153c8565b805115612f6c5780806020019051613934919081019061425f565b612f6c5760405162461bcd60e51b81526004016107a890615208565b600083830182858210156139775760405162461bcd60e51b81526004016107a89190615167565b50949350505050565b6000836001600160601b0316836001600160601b0316111582906139b75760405162461bcd60e51b81526004016107a89190615167565b505050900390565b60006139ea6139cc61264d565b60405180608001604052806042815260200161564a60429139613f2a565b905060008463ffffffff16118015613a3357506001600160a01b038516600090815260106020908152604080832063ffffffff6000198901811685529252909120548282169116145b15613a92576001600160a01b0385166000908152601060209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055613b31565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152601083528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252601190935292909220805460018801909316929091169190911790555b846001600160a01b03167f6adb589fed1e8542fb7a6b10f00a85e02265e77f9ae3ca8ff93b22983e1af9a08484604051613b6c929190615493565b60405180910390a25050505050565b6000838301826001600160601b0380871690831610156139775760405162461bcd60e51b81526004016107a89190615167565b6000600160801b8210613bd35760405162461bcd60e51b81526004016107a890615248565b5090565b6005546000906001600160a01b0316613c025760405162461bcd60e51b81526004016107a8906151f8565b6005546001600160a01b03166000908152600860205260408120805490915b81811015613ce25760055483546001600160a01b0390911690849083908110613c4657fe5b60009182526020909120600590910201546001600160a01b03161415613cda576005546001600160a01b039081166000908152600760209081526040808320858452825280832093891683529290522060028101548154613ccf91613cb1919063ffffffff6136ed16565b60405180606001604052806028815260200161560160289139612fe2565b94505050505061108d565b600101613c21565b506000949350505050565b60008183613d0e5760405162461bcd60e51b81526004016107a89190615167565b506000838581613d1a57fe5b0495945050505050565b600081848411156139b75760405162461bcd60e51b81526004016107a89190615167565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613d7f5750600090506003613e1f565b8460ff16601b14158015613d9757508460ff16601c14155b15613da85750600090506004613e1f565b600060018787878760405160008152602001604052604051613dcd94939291906150f2565b6020604051602081039080840390855afa158015613def573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613e1857506000915060019050613e1f565b9150600090505b94509492505050565b6000816004811115613e3657fe5b1415613e4157610f0a565b6001816004811115613e4f57fe5b1415613e6d5760405162461bcd60e51b81526004016107a890615178565b6002816004811115613e7b57fe5b1415613e995760405162461bcd60e51b81526004016107a8906151b8565b6003816004811115613ea757fe5b1415613ec55760405162461bcd60e51b81526004016107a890615288565b6004816004811115613ed357fe5b1415610f0a5760405162461bcd60e51b81526004016107a8906152f8565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061385b575050151592915050565b600081600160201b84106130095760405162461bcd60e51b81526004016107a89190615167565b604080518082019091526000808252602082015290565b803561152481615569565b805161152481615569565b80356115248161557d565b80516115248161557d565b803561152481615586565b80356115248161558f565b805161152481615586565b803561152481615598565b8035611524816155a1565b600060208284031215613fdd57600080fd5b600061385b8484613f68565b600060208284031215613ffb57600080fd5b600061385b8484613f73565b6000806040838503121561401a57600080fd5b60006140268585613f68565b925050602061403785828601613f68565b9150509250929050565b60008060006060848603121561405657600080fd5b60006140628686613f68565b935050602061407386828701613f68565b925050604061408486828701613f94565b9150509250925092565b600080604083850312156140a157600080fd5b60006140ad8585613f68565b925050602061403785828601613f94565b6000806000606084860312156140d357600080fd5b60006140df8686613f68565b93505060206140f086828701613f94565b925050604061408486828701613f68565b600080600080600060a0868803121561411957600080fd5b60006141258888613f68565b955050602061413688828901613f94565b945050604061414788828901613f9f565b935050606061415888828901613f94565b925050608061416988828901613f94565b9150509295509295909350565b60008060006060848603121561418b57600080fd5b60006141978686613f68565b935050602061407386828701613f94565b60008060008060008060c087890312156141c157600080fd5b60006141cd8989613f68565b96505060206141de89828a01613f94565b95505060406141ef89828a01613f94565b945050606061420089828a01613fc0565b935050608061421189828a01613f94565b92505060a061422289828a01613f94565b9150509295509295509295565b6000806040838503121561424257600080fd5b600061424e8585613f68565b925050602061403785828601613fb5565b60006020828403121561427157600080fd5b600061385b8484613f89565b6000806040838503121561429057600080fd5b60006140ad8585613f7e565b6000806000606084860312156142b157600080fd5b60006140628686613f9f565b6000602082840312156142cf57600080fd5b600061385b8484613f9f565b6000602082840312156142ed57600080fd5b600061385b8484613faa565b60006143058383614e99565b505060600190565b61431681615512565b82525050565b614316816154c1565b6000614330826154b4565b61433a81856154b8565b9350614345836154ae565b8060005b8381101561437357815161435d88826142f9565b9750614368836154ae565b925050600101614349565b509495945050505050565b614316816154cc565b614316816154d1565b61431661439c826154d1565b6154d1565b60006143ac826154b4565b6143b6818561108d565b93506143c6818560208601615533565b9290920192915050565b614316816154d4565b6143168161551d565b60006143ed826154b4565b6143f781856154b8565b9350614407818560208601615533565b6144108161555f565b9093019392505050565b60006144276018836154b8565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000815260200192915050565b60006144606012836154b8565b71696e636f6e73697374656e7420737461746560701b815260200192915050565b600061448e6013836154b8565b727661756c743a20706f6f6c206578697374733f60681b815260200192915050565b60006144bd601f836154b8565b7f53746f726520636f6e7472616374206164647265737320697320656d70747900815260200192915050565b60006144f6601f836154b8565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800815260200192915050565b600061452f600f836154b8565b6e15985d5b1d081a5cc81c185d5cd959608a1b815260200192915050565b600061455a6013836154b8565b7215985d5b1d081a5cc81b9bdd081c185d5cd959606a1b815260200192915050565b6000614589600c836154b8565b6b155b985d5d1a1bdc9a5e995960a21b815260200192915050565b60006145b16030836154b8565b7f5856535661756c743a3a6765745374616b65416d6f756e743a2078767320616481526f191c995cdcc81a5cc81b9bdd081cd95d60821b602082015260400192915050565b6000614603602a836154b8565b7f5361666542455032303a204245503230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b600061464f602a836154b8565b7f5856535661756c743a3a64656c656761746542795369673a207369676e6174758152691c9948195e1c1a5c995960b21b602082015260400192915050565b600061469b6022836154b8565b7f7072696d6520746f6b656e2063616e6e6f74206265207a65726f206164647265815261737360f01b602082015260400192915050565b60006146df6026836154b8565b7f5856535661756c743a3a64656c656761746542795369673a20696e76616c6964815265206e6f6e636560d01b602082015260400192915050565b600061472760028361108d565b61190160f01b815260020192915050565b60006147456027836154b8565b7f53616665436173743a2076616c756520646f65736e27742066697420696e20318152663238206269747360c81b602082015260400192915050565b600061478e6020836154b8565b7f496e76616c69642074696d6520626173656420636f6e66696775726174696f6e815260200192915050565b60006147c76017836154b8565b7f5661756c7420697320616c726561647920706175736564000000000000000000815260200192915050565b60006148006025836154b8565b7f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164815264647265737360d81b602082015260400192915050565b60006148476022836154b8565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c815261756560f01b602082015260400192915050565b600061488b601a836154b8565b7f546f6b656e2065786973747320696e206f7468657220706f6f6c000000000000815260200192915050565b60006148c46013836154b8565b72185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b815260200192915050565b60006148f3602b836154b8565b7f5856535661756c743a3a6765745072696f72566f7465733a206e6f742079657481526a0819195d195c9b5a5b995960aa1b602082015260400192915050565b6000614940601d836154b8565b7f7265776172642063616e6e6f74206265207a65726f2061646472657373000000815260200192915050565b60006149796018836154b8565b7f7a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000815260200192915050565b60006149b2601a836154b8565b7f657865637574652070656e64696e67207769746864726177616c000000000000815260200192915050565b60006149eb6022836154b8565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c815261756560f01b602082015260400192915050565b6000614a2f60438361108d565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430192915050565b6000614a9a601f836154b8565b7f72657175657374656420616d6f756e742063616e6e6f74206265207a65726f00815260200192915050565b6000614ad36021836154b8565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000614b166012836154b8565b71141bdbdb08185b1c9958591e48185919195960721b815260200192915050565b6000614b446017836154b8565b7f496e76616c696420626c6f636b73207065722079656172000000000000000000815260200192915050565b6000614b7d600a836154b8565b691c994b595b9d195c995960b21b815260200192915050565b6000614ba36014836154b8565b7324b73b30b634b2103932bbb0b932103a37b5b2b760611b815260200192915050565b6000614bd3600e836154b8565b6d37b7363c9030b236b4b71031b0b760911b815260200192915050565b6000614bfd6015836154b8565b7418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b815260200192915050565b6000614c2e6013836154b8565b726e6f7468696e6720746f20776974686472617760681b815260200192915050565b6000614c5d601a836154b8565b7f496e76616c6964206e6577206c6f636b696e6720706572696f64000000000000815260200192915050565b6000614c96601d836154b8565b7f416c6c6f6320706f696e7473206d757374206e6f74206265207a65726f000000815260200192915050565b6000614ccf601f836154b8565b7f416c726561647920696e697469616c697a65642054696d654d616e6167657200815260200192915050565b6000614d086020836154b8565b7f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b6000614d41603a8361108d565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0192915050565b6000614da0601f836154b8565b7f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614dd9601b836154b8565b7f72657175657374656420616d6f756e7420697320696e76616c69640000000000815260200192915050565b6000614e126022836154b8565b7f6f6e6c792070726f78792061646d696e2063616e206368616e676520627261698152616e7360f01b602082015260400192915050565b6000614e56602e836154b8565b7f416c6c6f6320706f696e7473207065722072657761726420746f6b656e206d7581526d7374206e6f74206265207a65726f60901b602082015260400192915050565b80516060830190614eaa8482614387565b506020820151614ebd6020850182614ecc565b506040820151612f6c60408501825b614316816154df565b614316816154f7565b61431681615500565b61431681615528565b61431681615506565b600061082782846143a1565b6000614f108261471a565b9150614f1c8285614390565b602082019150614f2c8284614390565b5060200192915050565b600061152482614a22565b600061152482614d34565b60208101611524828461431c565b60208101611524828461430d565b60408101614f76828561430d565b818103602083015261385b81846143e2565b60408101614f96828561431c565b610827602083018461431c565b60608101614fb1828661431c565b614fbe602083018561430d565b61385b6040830184614387565b60808101614fd9828761431c565b614fe6602083018661431c565b614ff3604083018561431c565b615000606083018461431c565b95945050505050565b60608101615017828661431c565b614fbe602083018561431c565b60808101615032828761431c565b61503f602083018661431c565b61504c6040830185614387565b6150006060830184614387565b60408101615067828561431c565b610827602083018461437e565b60408101615082828561431c565b6108276020830184614387565b602080825281016108278184614325565b60208101611524828461437e565b602081016115248284614387565b608081016150328287614387565b608081016150d88287614387565b6150e56020830186614387565b614ff36040830185614387565b608081016151008287614387565b61503f6020830186614ede565b6020810161152482846143d0565b60a0810161512982886143d0565b6151366020830187614387565b6151436040830186614387565b6151506060830185614387565b61515d6080830184614387565b9695505050505050565b6020808252810161082781846143e2565b602080825281016115248161441a565b6020808252810161152481614453565b6020808252810161152481614481565b60208082528101611524816144b0565b60208082528101611524816144e9565b6020808252810161152481614522565b602080825281016115248161454d565b602080825281016115248161457c565b60208082528101611524816145a4565b60208082528101611524816145f6565b6020808252810161152481614642565b602080825281016115248161468e565b60208082528101611524816146d2565b6020808252810161152481614738565b6020808252810161152481614781565b60208082528101611524816147ba565b60208082528101611524816147f3565b602080825281016115248161483a565b602080825281016115248161487e565b60208082528101611524816148b7565b60208082528101611524816148e6565b6020808252810161152481614933565b602080825281016115248161496c565b60208082528101611524816149a5565b60208082528101611524816149de565b6020808252810161152481614a8d565b6020808252810161152481614ac6565b6020808252810161152481614b09565b6020808252810161152481614b37565b6020808252810161152481614b70565b6020808252810161152481614b96565b6020808252810161152481614bc6565b6020808252810161152481614bf0565b6020808252810161152481614c21565b6020808252810161152481614c50565b6020808252810161152481614c89565b6020808252810161152481614cc2565b6020808252810161152481614cfb565b6020808252810161152481614d93565b6020808252810161152481614dcc565b6020808252810161152481614e05565b6020808252810161152481614e49565b604081016154268285614387565b61082760208301846143d9565b604081016150828285614387565b6060810161544f8286614387565b614fbe6020830185614387565b602081016115248284614ed5565b604081016154788285614ed5565b6108276020830184614ef0565b602081016115248284614ef0565b604081016154a18285614ee7565b6108276020830184614ee7565b60200190565b5190565b90815260200190565b6000611524826154eb565b151590565b90565b6000611524826154c1565b6001600160801b031690565b6001600160a01b031690565b63ffffffff1690565b60ff1690565b6001600160601b031690565b6000611524826154d4565b6000611524826154d1565b600061152482615506565b60005b8381101561554e578181015183820152602001615536565b83811115612f6c5750506000910152565b601f01601f191690565b615572816154c1565b8114610f0a57600080fd5b615572816154cc565b615572816154d1565b615572816154d4565b615572816154f7565b6155728161550056fe5856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f77735856535661756c743a3a726571756573745769746864726177616c3a20766f746573206f766572666c6f775856535661756c743a3a6765745374616b65416d6f756e743a20766f746573206f766572666c6f775856535661756c743a3a6465706f7369743a20766f746573206f766572666c6f775856535661756c743a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d626572206f72207365636f6e64206578636565647320333220626974737365745769746864726177616c4c6f636b696e67506572696f6428616464726573732c75696e743235362c75696e74323536295856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f7773736574526577617264416d6f756e74506572426c6f636b4f725365636f6e6428616464726573732c75696e743235362961646428616464726573732c75696e743235362c616464726573732c75696e743235362c75696e7432353629a365627a7a7231582053ba350123a86f07263e7bddf3bcee0f7cf11e72f5d2678781f0eb1ebd599dc16c6578706572696d656e74616cf564736f6c63430005100040
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103785760003560e01c806392e35000116101d3578063c7ad089511610104578063e7a324dc116100a2578063f55401621161007c578063f554016214610732578063f851a4401461073a578063fba1b1f914610742578063fe5a451a1461075557610378565b8063e7a324dc14610701578063e8f2be6f14610709578063f1127ed81461071157610378565b8063dae66bbe116100de578063dae66bbe146106d6578063de0368b2146106e9578063e1d146fb146106f1578063e6a69ab8146106f957610378565b8063c7ad0895146106a8578063cd9b94e7146106b0578063d7ae45e2146106c357610378565b8063add8933711610171578063b6a5fd2f1161014b578063b6a5fd2f1461064f578063c210259614610662578063c3c754a814610682578063c3cda5201461069557610378565b8063add893371461061f578063b4a0bdf314610627578063b4b5ea571461063c57610378565b80639e2b6c4d116101ad5780639e2b6c4d146105d3578063a09eab7a146105e6578063a6997762146105f9578063a9d69a691461060c57610378565b806392e350001461057a57806398e1b31b1461059e578063996cba68146105c057610378565b80635c19a95c116102ad57806373d025d61161024b5780637ecebe00116102255780637ecebe00146105395780638308d7e91461054c5780638456cb591461055f5780638ed7333d1461056757610378565b806373d025d6146104f1578063782d6fe1146105065780637ac924561461052657610378565b80635ff56315116102875780635ff56315146104a35780636857249c146104b65780636dd77cbd146104be5780636fcfff45146104d157610378565b80635c19a95c146104755780635c60da1b146104885780635f14e7001461049057610378565b806324f52bbf1161031a578063358ae036116102f4578063358ae036146104345780633d4180f91461043c5780634298bdbd1461044f578063587cde1e1461046257610378565b806324f52bbf1461040457806326782247146104195780632eda5c6c1461042157610378565b8063115b512f11610356578063115b512f146103c357806319129e5a146103d65780631d504dc6146103e957806320606b70146103fc57610378565b8063046f7da21461037d5780630af13728146103875780630efe6a8b146103b0575b600080fd5b61038561075d565b005b61039a6103953660046140be565b6107e8565b6040516103a791906150ae565b60405180910390f35b6103856103be366004614176565b61082e565b6103856103d1366004614176565b610b23565b6103856103e4366004613fcb565b610ed7565b6103856103f73660046142bd565b610f0d565b61039a61103e565b61040c611055565b6040516103a79190614f4c565b61040c611064565b61039a61042f366004613fcb565b611073565b61040c611092565b61039a61044a366004614007565b6110a1565b61039a61045d366004613fcb565b6110be565b61040c610470366004613fcb565b6110d0565b610385610483366004613fcb565b6110eb565b61040c611118565b61039a61049e36600461408e565b611127565b6103856104b1366004614007565b611144565b61039a611238565b61039a6104cc3660046140be565b61123e565b6104e46104df366004613fcb565b6112f3565b6040516103a7919061545c565b6104f961130b565b6040516103a791906150a0565b61051961051436600461408e565b611314565b6040516103a79190615485565b61038561053436600461408e565b61152a565b61039a610547366004613fcb565b611873565b61038561055a366004614176565b611885565b610385611a2b565b61038561057536600461408e565b611ab0565b61058d61058836600461408e565b611aeb565b6040516103a795949392919061511b565b6105b16105ac3660046140be565b611b40565b6040516103a793929190615441565b6103856105ce366004614041565b611b92565b6103856105e1366004614176565b611d24565b61039a6105f43660046140be565b611e0f565b61038561060736600461427d565b61205f565b61039a61061a3660046140be565b612093565b61040c6120d5565b61062f6120e4565b6040516103a7919061510d565b61051961064a366004613fcb565b6120f3565b61038561065d36600461408e565b612163565b6106756106703660046140be565b612289565b6040516103a7919061508f565b6104f9610690366004613fcb565b612343565b6103856106a33660046141a8565b612358565b6104f96124fc565b61039a6106be366004613fcb565b612505565b61039a6106d1366004613fcb565b612517565b6103856106e436600461429c565b612532565b61040c61263e565b61039a61264d565b61039a612674565b61039a61267c565b61039a612688565b61072461071f36600461422f565b61268e565b6040516103a792919061546a565b61039a6126c3565b61040c6126cb565b610385610750366004614101565b6126da565b61062f6129bf565b61078660405180604001604052806008815260200167726573756d65282960c01b8152506129ce565b60135460ff166107b15760405162461bcd60e51b81526004016107a8906151d8565b60405180910390fd5b6013805460ff1916905560405133907fd2619572a1464e0df0bb351d834fd47f3350984d7bfdb1ab69cfcb0b8e42141590600090a2565b60006107f48484612a70565b506001600160a01b0380841660009081526007602090815260408083208684528252808320938516835292905220600201545b9392505050565b600354600160a01b900460ff166108575760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff16156108875760405162461bcd60e51b81526004016107a8906151c8565b6108918383612a70565b6001600160a01b03831660009081526008602052604081208054849081106108b557fe5b600091825260208083206001600160a01b038816845260078252604080852088865283528085203386529092529220600590910290910191506108f88585612aa7565b610903858533612093565b156109205760405162461bcd60e51b81526004016107a8906152e8565b8054156109955760006109338284612c84565b9050801561099357610946863383612c98565b84866001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e946458460405161098a91906150ae565b60405180910390a45b505b81546109b2906001600160a01b031633308663ffffffff612f1116565b80546109c4908463ffffffff612f7216565b81556109d08183612fb4565b600182015560055482546001600160a01b0390811691161415610a3757336000908152600f60209081526040808320548151606081019092526021808352610a3794936001600160a01b0390921692610a329289929061562990830139612fe2565b613011565b6017546001600160a01b038681169116148015610a55575060185484145b15610abd576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610a8a903390600401614f5a565b600060405180830381600087803b158015610aa457600080fd5b505af1158015610ab8573d6000803e3d6000fd5b505050505b83856001600160a01b0316336001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d786604051610b0191906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b179055505050565b600354600160a01b900460ff16610b4c5760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff1615610b7c5760405162461bcd60e51b81526004016107a8906151c8565b610b868383612a70565b60008111610ba65760405162461bcd60e51b81526004016107a890615308565b6001600160a01b0383166000908152600760209081526040808320858452825280832033845290915290206002810154610be6908363ffffffff612f7216565b81541015610c065760405162461bcd60e51b81526004016107a8906153e8565b6001600160a01b0384166000908152600860205260408120805485908110610c2a57fe5b600091825260208083206001600160a01b0389168452600a825260408085208986528352808520338652909252908320600590920201925090610c6c826131a3565b5090508015610c8d5760405162461bcd60e51b81526004016107a8906152e8565b610c978787612aa7565b6000610ca38585612c84565b9050610cb0883383612c98565b6004840154600090610cc8904263ffffffff612f7216565b9050610cd686858984613247565b6001600160a01b03891660009081526012602090815260408083208b8452909152902054610d0a908863ffffffff612f7216565b6001600160a01b038a1660009081526012602090815260408083208c8452909152902055610d388686612fb4565b600187015560055485546001600160a01b0390811691161415610d9b57336000908152600f6020908152604080832054815160608101909252602b808352610d9b946001600160a01b03909216939192610a32928d92906155d690830139612fe2565b6017546001600160a01b038a81169116148015610db9575060185488145b15610e21576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610dee903390600401614f5a565b600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b505050505b87896001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464585604051610e6591906150ae565b60405180910390a487896001600160a01b0316336001600160a01b03167f88a254a0ef28a0b9e957ff600beae69870f6f924065147f3627c3f814e60ec118a604051610eb191906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b17905550505050505050565b6000546001600160a01b03163314610f015760405162461bcd60e51b81526004016107a890615368565b610f0a8161342b565b50565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4657600080fd5b505afa158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f7e9190810190613fe9565b6001600160a01b0316336001600160a01b031614610fae5760405162461bcd60e51b81526004016107a8906153f8565b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610fe957600080fd5b505af1158015610ffd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061102191908101906142db565b15610f0a5760405162461bcd60e51b81526004016107a890615378565b60405161104a90614f36565b604051809103902081565b6004546001600160a01b031681565b6001546001600160a01b031681565b6001600160a01b0381166000908152600660205260409020545b919050565b6005546001600160a01b031681565b601560209081526000928352604080842090915290825290205481565b60096020526000908152604090205481565b600f602052600090815260409020546001600160a01b031681565b60135460ff161561110e5760405162461bcd60e51b81526004016107a8906151c8565b610f0a33826134b0565b6002546001600160a01b031681565b601260209081526000928352604080842090915290825290205481565b6000546001600160a01b0316331461116e5760405162461bcd60e51b81526004016107a890615368565b6111778261353f565b6111808161353f565b6005546004546001600160a01b03918216911681156111b15760405162461bcd60e51b81526004016107a8906152a8565b600580546001600160a01b038087166001600160a01b03199283161790925560048054928616929091169190911790556003805460ff60a01b1916600160a01b1790556040517f559f314bb90394a4a9ceb724f365b36a53587d894352c43d12901fd6801014569061122a908490849088908890614fcb565b60405180910390a150505050565b60795481565b600061124a8484612a70565b6001600160a01b038085166000908152600a60209081526040808320878452825280832093861683529290522080545b6000811180156112aa57506112aa82600183038154811061129757fe5b9060005260206000209060020201613565565b156112ea576112df8260018303815481106112c157fe5b6000918252602090912060029091020154849063ffffffff612f7216565b92506000190161127a565b50509392505050565b60116020526000908152604090205463ffffffff1681565b60135460ff1681565b600061131e61264d565b821061133c5760405162461bcd60e51b81526004016107a8906152b8565b6001600160a01b03831660009081526011602052604090205463ffffffff168061136a576000915050611524565b6001600160a01b038416600090815260106020908152604080832063ffffffff6000198601811685529252909120541683106113e6576001600160a01b03841660009081526010602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050611524565b6001600160a01b038416600090815260106020908152604080832083805290915290205463ffffffff16831015611421576000915050611524565b600060001982015b8163ffffffff168163ffffffff1611156114e457600282820363ffffffff16048103611453613f51565b506001600160a01b038716600090815260106020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b031691810191909152908714156114bf576020015194506115249350505050565b805163ffffffff168711156114d6578193506114dd565b6001820392505b5050611429565b506001600160a01b038516600090815260106020908152604080832063ffffffff909416835292905220546001600160601b03600160201b909104169150505b92915050565b600354600160a01b900460ff166115535760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff16156115835760405162461bcd60e51b81526004016107a8906151c8565b61158d8282612a70565b6001600160a01b03821660009081526008602052604081208054839081106115b157fe5b600091825260208083206001600160a01b038716808552600783526040808620888752845280862033808852908552818720928752600a8552818720898852855281872090875290935291842060059093020193509180611612848461357a565b9092509050811515806116255750600081115b6116415760405162461bcd60e51b81526004016107a890615388565b81158061164c575080155b6116685760405162461bcd60e51b81526004016107a890615188565b8115611781576116788787612aa7565b60006116be85600101546116b264e8d4a510006116a68a600301548a6000015461367190919063ffffffff16565b9063ffffffff6136ab16565b9063ffffffff6136ed16565b6004805460405163135b33cd60e31b81529293506001600160a01b031691639ad99e68916116f2918c913391879101614fa3565b600060405180830381600087803b15801561170c57600080fd5b505af1158015611720573d6000803e3d6000fd5b50508654611737925090508463ffffffff6136ed16565b808655600387015461175a9164e8d4a51000916116a6919063ffffffff61367116565b6001860155855461177b906001600160a01b0316338563ffffffff61372f16565b50611805565b8354611793908263ffffffff6136ed16565b84556001600160a01b03871660009081526012602090815260408083208984529091529020546117c9908263ffffffff6136ed16565b6001600160a01b0380891660009081526012602090815260408083208b845290915290209190915585546118059116338363ffffffff61372f16565b856001600160a01b038816337fe31da05fae6db869f5ea51f4b638aa6884070b6c87f18f63bd2291a12cb2f518611842868663ffffffff612f7216565b60405161184f91906150ae565b60405180910390a450506003805460ff60a01b1916600160a01b1790555050505050565b600e6020526000908152604090205481565b6118c36040518060400160405280601c81526020017f73657428616464726573732c75696e743235362c75696e7432353629000000008152506129ce565b6118cd8383612a70565b6118d683613751565b6001600160a01b0383166000908152600860205260408120805490919061194f9084906119439085908890811061190957fe5b60009182526020808320600160059093020191909101546001600160a01b038b16835260099091526040909120549063ffffffff6136ed16565b9063ffffffff612f7216565b9050600081116119715760405162461bcd60e51b81526004016107a890615408565b600082858154811061197f57fe5b9060005260206000209060050201600101549050838386815481106119a057fe5b9060005260206000209060050201600101819055508160096000886001600160a01b03166001600160a01b031681526020019081526020016000208190555084866001600160a01b03167f6ee09c6cb801194690c195c69f465aaf7c80255cbeafaab9600f47ed79de2ca98387604051611a1b929190615433565b60405180910390a3505050505050565b611a53604051806040016040528060078152602001667061757365282960c81b8152506129ce565b60135460ff1615611a765760405162461bcd60e51b81526004016107a890615268565b6013805460ff1916600117905560405133907fdffada2889ebfab9224c24069d833f3de835d8cf99872d49e7b7ba5fccb7a46f90600090a2565b60135460ff1615611ad35760405162461bcd60e51b81526004016107a8906151c8565b611add8282612a70565b611ae78282612aa7565b5050565b60086020528160005260406000208181548110611b0457fe5b6000918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919085565b6000806000611b4f8686612a70565b5050506001600160a01b03928316600090815260076020908152604080832094835293815283822092909416815292529020805460018201546002909201549092565b600354600160a01b900460ff16611bbb5760405162461bcd60e51b81526004016107a890615348565b6003805460ff60a01b1916905560135460ff1615611beb5760405162461bcd60e51b81526004016107a8906151c8565b611bf58282612a70565b6001600160a01b0382166000908152600860205260408120805483908110611c1957fe5b600091825260208083206001600160a01b0380881685526007835260408086208887528452808620918a1686529252922060059091029091019150611c5e8484612aa7565b611c69848487612093565b15611c865760405162461bcd60e51b81526004016107a8906152e8565b805415611d0a576000611c998284612c84565b90508015611d0857611cab8284612fb4565b6001830155611cbb858783612c98565b83856001600160a01b0316876001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464584604051611cff91906150ae565b60405180910390a45b505b50506003805460ff60a01b1916600160a01b179055505050565b611d4560405180606001604052806033815260200161568c603391396129ce565b611d4f8383612a70565b600081118015611d6257506312cc030081105b611d7e5760405162461bcd60e51b81526004016107a890615398565b6001600160a01b0383166000908152600860205260408120805484908110611da257fe5b9060005260206000209060050201905060008160040154905082826004018190555083856001600160a01b03167f0bcf80c5060ccf99b7a993c57a94b232fc2c5c04bd74c7c7d174595fee6bc31f8386604051611e00929190615433565b60405180910390a35050505050565b6000611e1b8484612a70565b6001600160a01b0384166000908152600860205260408120805485908110611e3f57fe5b600091825260208083206001600160a01b03808a168086526007845260408087208b885285528087208a8416885285528087206003600590970290940195860154918752601285528087208b885290945283862054855494516370a0823160e01b8152959750929590949093611f16939216906370a0823190611ec6903090600401614f4c565b60206040518083038186803b158015611ede57600080fd5b505afa158015611ef2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116b291908101906142db565b90506000611f2261264d565b6001600160a01b038a1660009081526006602052604090205460028701549192509082118015611f5157508215155b15611fe7576000611f6f8760020154846136ed90919063ffffffff16565b6001600160a01b038c1660009081526009602052604081205460018a01549293509091611fb791906116a690611fab868863ffffffff61367116565b9063ffffffff61367116565b9050611fe2611fd5866116a68464e8d4a5100063ffffffff61367116565b879063ffffffff612f7216565b955050505b6001600160a01b03808b166000908152600a602090815260408083208d84528252808320938c16835292905290812090612020826131a3565b91505061204f87600101546116b264e8d4a510006116a68a611fab878e600001546136ed90919063ffffffff16565b9c9b505050505050505050505050565b6000546001600160a01b031633146120895760405162461bcd60e51b81526004016107a890615368565b611ae78282613786565b6001600160a01b038084166000908152600a60209081526040808320868452825280832093851683529290529081206120cb816131a3565b5095945050505050565b6017546001600160a01b031681565b6047546001600160a01b031690565b6001600160a01b03811660009081526011602052604081205463ffffffff168061211e576000610827565b6001600160a01b0383166000908152601060209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03169392505050565b6121846040518060600160405280603081526020016156eb603091396129ce565b60048054604051633d6ac5b360e21b81526001600160a01b039091169163f5ab16cc916121b391869101614f4c565b60206040518083038186803b1580156121cb57600080fd5b505afa1580156121df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612203919081019061425f565b61221f5760405162461bcd60e51b81526004016107a890615358565b61222882613751565b6001600160a01b0382166000818152600660205260409081902080549084905590519091907fad96cee0d692f0250b98e085504f399da6733854908215f6203fe3c69366d9f59061227c9084908690615433565b60405180910390a2505050565b60606122958484612a70565b6001600160a01b038085166000908152600a602090815260408083208784528252808320938616835292815282822080548451818402810184019095528085529092909184015b828210156123365760008481526020908190206040805160608101825260028602909201805483526001908101546001600160801b0380821685870152600160801b909104169183019190915290835290920191016122dc565b5050505090509392505050565b60146020526000908152604090205460ff1681565b60135460ff161561237b5760405162461bcd60e51b81526004016107a8906151c8565b600060405161238990614f36565b604080519182900382208282019091526008825267161594d5985d5b1d60c21b6020909201919091527fddfcc46608a8bd52ebf900f03a24cc97b73a6046cec8c5d0f74a211e376e967a6123db613835565b306040516020016123ef94939291906150ca565b604051602081830303815290604052805190602001209050600060405161241590614f41565b604051908190038120612430918a908a908a906020016150bc565b6040516020818303038152906040528051906020012090506000828260405160200161245d929190614f05565b604051602081830303815290604052805190602001209050600061248382888888613839565b6001600160a01b0381166000908152600e6020526040902080546001810190915590915089146124c55760405162461bcd60e51b81526004016107a890615238565b874211156124e55760405162461bcd60e51b81526004016107a890615218565b6124ef818b6134b0565b505050505b505050505050565b607a5460ff1681565b60066020526000908152604090205481565b6001600160a01b031660009081526008602052604090205490565b6000546001600160a01b0316331461255c5760405162461bcd60e51b81526004016107a890615368565b6001600160a01b0383166125825760405162461bcd60e51b81526004016107a890615228565b6001600160a01b0382166125a85760405162461bcd60e51b81526004016107a8906152c8565b6125b28282612a70565b6016546017546018546040516001600160a01b03808816948116937f8def9436d6e31b89ed00948ba91d0cb6936eada5154cb1b45b55683fb9e492379361260193919092169188918890615024565b60405180910390a3601680546001600160a01b039485166001600160a01b0319918216179091556017805493909416921691909117909155601855565b6003546001600160a01b031681565b607a5460009060ff1661266757612662613863565b61266f565b61266f613867565b905090565b6301e1338081565b60405161104a90614f41565b60185481565b601060209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6312cc030081565b6000546001600160a01b031681565b6126fb6040518060600160405280602c815260200161571b602c91396129ce565b6127048561353f565b61270d8361353f565b6004546001600160a01b03166127355760405162461bcd60e51b81526004016107a8906151a8565b600084116127555760405162461bcd60e51b81526004016107a8906153a8565b61275e85613751565b6001600160a01b0385166000908152600860205260408120805490915b818110156127d957856001600160a01b031683828154811061279957fe5b60009182526020909120600590910201546001600160a01b031614156127d15760405162461bcd60e51b81526004016107a890615328565b60010161277b565b506001600160a01b03851660009081526014602052604090205460ff16156128135760405162461bcd60e51b81526004016107a890615298565b6001600160a01b03871660009081526009602052604090205461283c908763ffffffff612f7216565b6001600160a01b038089166000908152600960209081526040808320949094556006815290839020879055825160a081018452918816825281018890528391810161288561264d565b8152600060208083018290526040928301889052845460018082018755958352818320855160059092020180546001600160a01b0319166001600160a01b039283161781558583015181880155858501516002820155606086015160038201556080909501516004958601558a81168352601490915290829020805460ff1916851790558254915163fb66fb4d60e01b815291169263fb66fb4d9261292d928c929101615059565b600060405180830381600087803b15801561294757600080fd5b505af115801561295b573d6000803e3d6000fd5b50505050846001600160a01b03166001838054905003886001600160a01b03167fd7fa4bff1cd2253c0789c3291a786a6f6b1a3b4569a75af683a15d52abb6a0bf8988886040516129ae93929190615441565b60405180910390a450505050505050565b6016546001600160a01b031681565b6047546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab90612a019033908690600401614f68565b60206040518083038186803b158015612a1957600080fd5b505afa158015612a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a51919081019061425f565b905080611ae75760405162461bcd60e51b81526004016107a8906151e8565b6001600160a01b0382166000908152600860205260409020548110611ae75760405162461bcd60e51b81526004016107a890615198565b6001600160a01b0382166000908152600860205260408120805483908110612acb57fe5b906000526020600020906005020190508060020154612ae861264d565b11612af35750611ae7565b80546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612b23903090600401614f4c565b60206040518083038186803b158015612b3b57600080fd5b505afa158015612b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b7391908101906142db565b6001600160a01b0385166000908152601260209081526040808320878452909152902054909150612bab90829063ffffffff6136ed16565b905080612bc957612bba61264d565b82600201819055505050611ae7565b6000612bd361264d565b90506000612bee8460020154836136ed90919063ffffffff16565b6001600160a01b03871660009081526009602090815260408083205460018901546006909352908320549394509192612c3792916116a691611fab90879063ffffffff61367116565b9050612c66612c55856116a68464e8d4a5100063ffffffff61367116565b60038701549063ffffffff612f7216565b6003860155612c7361264d565b856002018190555050505050505050565b600061082783600101546116b28585612fb4565b600480546040516370a0823160e01b81526001600160a01b03918216926000928716916370a0823191612ccd91869101614f4c565b60206040518083038186803b158015612ce557600080fd5b505afa158015612cf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d1d91908101906142db565b6001600160a01b038087166000908152601560209081526040808320938916835292905290812054919250612d58858363ffffffff612f7216565b9050828111612e36578115612dcb576001600160a01b038088166000818152601560209081526040808320948b1680845294909152808220829055517f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216091612dc291879190615418565b60405180910390a35b60405163135b33cd60e31b81526001600160a01b03851690639ad99e6890612dfb908a908a908690600401615009565b600060405180830381600087803b158015612e1557600080fd5b505af1158015612e29573d6000803e3d6000fd5b5050505050505050612f0c565b6001600160a01b038088166000818152601560209081526040808320948b168084529490915290819020868503908190559051909291907f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216090612e9c9087908690615433565b60405180910390a360405163135b33cd60e31b81526001600160a01b03861690639ad99e6890612ed4908b908b908990600401615009565b600060405180830381600087803b158015612eee57600080fd5b505af1158015612f02573d6000803e3d6000fd5b5050505050505050505b505050565b604051612f6c9085906323b872dd60e01b90612f3590879087908790602401615009565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261386b565b50505050565b600061082783836040518060400160405280601b81526020017f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815250613950565b600061082764e8d4a510006116a68460030154611fab876002015488600001546136ed90919063ffffffff16565b600081600160601b84106130095760405162461bcd60e51b81526004016107a89190615167565b509192915050565b816001600160a01b0316836001600160a01b03161415801561303c57506000816001600160601b0316115b15612f0c576001600160a01b038316156130f4576001600160a01b03831660009081526011602052604081205463ffffffff16908161307c5760006130bb565b6001600160a01b0385166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006130e282856040518060600160405280602c81526020016156bf602c9139613980565b90506130f0868484846139bf565b5050505b6001600160a01b03821615612f0c576001600160a01b03821660009081526011602052604081205463ffffffff16908161312f57600061316e565b6001600160a01b0384166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061319582856040518060600160405280602b81526020016155ab602b9139613b7b565b90506124f4858484846139bf565b805460009081905b8015613241578360018203815481106131c057fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156132235761321c8460018303815481106131fe57fe5b6000918252602090912060029091020154839063ffffffff612f7216565b9150613238565b6132358460018303815481106112c157fe5b92505b600019016131ab565b50915091565b8254604080516060810182526000808252602080830182815260019484018581528587018a5589845291909220925160028602909301928355905191909201805492516001600160801b03908116600160801b029281166001600160801b0319909416939093179092161790555b6000811180156132f05750818460018303815481106132d057fe5b60009182526020909120600160029092020101546001600160801b031611155b156133775783600182038154811061330457fe5b906000526020600020906002020184828154811061331e57fe5b600091825260209091208254600290920201908155600191820180549290910180546001600160801b0319166001600160801b03938416178082559154600160801b9081900484160291909216179055600019016132b5565b604051806060016040528084815260200161339184613bae565b6001600160801b0316815260200160016001600160801b03168152508482815481106133b957fe5b60009182526020918290208351600292830290910190815591830151600190920180546040909401516001600160801b03199094166001600160801b03938416178316600160801b939094169290920292909217905585015461341c9084612f72565b85600201819055505050505050565b6001600160a01b0381166134515760405162461bcd60e51b81526004016107a890615278565b604780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906134a49083908590614f88565b60405180910390a15050565b6001600160a01b038083166000908152600f6020526040812054909116906134d784613bd7565b6001600160a01b038581166000818152600f602052604080822080546001600160a01b031916898616908117909155905194955093928616927f0cc323ffec3ea49cbcddc0de1480978126d350c6a45dff33ad2f1cda6ae992619190a4612f6c828483613011565b6001600160a01b038116610f0a5760405162461bcd60e51b81526004016107a8906152d8565b60010154426001600160801b03909116111590565b805460009081905b60008111801561359f575061359f84600183038154811061129757fe5b15613640578360018203815481106135b357fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156135f8576135f18460018303815481106131fe57fe5b915061360d565b61360a8460018303815481106112c157fe5b92505b8380548061361757fe5b600082815260208120600019928301600281029091018281556001019190915590915501613582565b50613665613654828463ffffffff612f7216565b60028601549063ffffffff6136ed16565b60028501559250929050565b60008261368057506000611524565b8282028284828161368d57fe5b04146108275760405162461bcd60e51b81526004016107a890615318565b600061082783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613ced565b600061082783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613d24565b604051612f0c90849063a9059cbb60e01b90612f359086908690602401615074565b6001600160a01b038116600090815260086020526040812054905b81811015612f0c5761377e8382612aa7565b60010161376c565b607a54610100900460ff16156137ae5760405162461bcd60e51b81526004016107a8906153b8565b811580156137ba575080155b156137d75760405162461bcd60e51b81526004016107a890615338565b8180156137e357508015155b156138005760405162461bcd60e51b81526004016107a890615258565b607a805460ff191683151517905581613819578061381f565b6301e133805b6079555050607a805461ff001916610100179055565b4690565b600080600061384a87878787613d48565b9150915061385781613e28565b5090505b949350505050565b4390565b4290565b61387d826001600160a01b0316613ef1565b6138995760405162461bcd60e51b81526004016107a8906153d8565b60006060836001600160a01b0316836040516138b59190614ef9565b6000604051808303816000865af19150503d80600081146138f2576040519150601f19603f3d011682016040523d82523d6000602084013e6138f7565b606091505b5091509150816139195760405162461bcd60e51b81526004016107a8906153c8565b805115612f6c5780806020019051613934919081019061425f565b612f6c5760405162461bcd60e51b81526004016107a890615208565b600083830182858210156139775760405162461bcd60e51b81526004016107a89190615167565b50949350505050565b6000836001600160601b0316836001600160601b0316111582906139b75760405162461bcd60e51b81526004016107a89190615167565b505050900390565b60006139ea6139cc61264d565b60405180608001604052806042815260200161564a60429139613f2a565b905060008463ffffffff16118015613a3357506001600160a01b038516600090815260106020908152604080832063ffffffff6000198901811685529252909120548282169116145b15613a92576001600160a01b0385166000908152601060209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055613b31565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152601083528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252601190935292909220805460018801909316929091169190911790555b846001600160a01b03167f6adb589fed1e8542fb7a6b10f00a85e02265e77f9ae3ca8ff93b22983e1af9a08484604051613b6c929190615493565b60405180910390a25050505050565b6000838301826001600160601b0380871690831610156139775760405162461bcd60e51b81526004016107a89190615167565b6000600160801b8210613bd35760405162461bcd60e51b81526004016107a890615248565b5090565b6005546000906001600160a01b0316613c025760405162461bcd60e51b81526004016107a8906151f8565b6005546001600160a01b03166000908152600860205260408120805490915b81811015613ce25760055483546001600160a01b0390911690849083908110613c4657fe5b60009182526020909120600590910201546001600160a01b03161415613cda576005546001600160a01b039081166000908152600760209081526040808320858452825280832093891683529290522060028101548154613ccf91613cb1919063ffffffff6136ed16565b60405180606001604052806028815260200161560160289139612fe2565b94505050505061108d565b600101613c21565b506000949350505050565b60008183613d0e5760405162461bcd60e51b81526004016107a89190615167565b506000838581613d1a57fe5b0495945050505050565b600081848411156139b75760405162461bcd60e51b81526004016107a89190615167565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613d7f5750600090506003613e1f565b8460ff16601b14158015613d9757508460ff16601c14155b15613da85750600090506004613e1f565b600060018787878760405160008152602001604052604051613dcd94939291906150f2565b6020604051602081039080840390855afa158015613def573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613e1857506000915060019050613e1f565b9150600090505b94509492505050565b6000816004811115613e3657fe5b1415613e4157610f0a565b6001816004811115613e4f57fe5b1415613e6d5760405162461bcd60e51b81526004016107a890615178565b6002816004811115613e7b57fe5b1415613e995760405162461bcd60e51b81526004016107a8906151b8565b6003816004811115613ea757fe5b1415613ec55760405162461bcd60e51b81526004016107a890615288565b6004816004811115613ed357fe5b1415610f0a5760405162461bcd60e51b81526004016107a8906152f8565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061385b575050151592915050565b600081600160201b84106130095760405162461bcd60e51b81526004016107a89190615167565b604080518082019091526000808252602082015290565b803561152481615569565b805161152481615569565b80356115248161557d565b80516115248161557d565b803561152481615586565b80356115248161558f565b805161152481615586565b803561152481615598565b8035611524816155a1565b600060208284031215613fdd57600080fd5b600061385b8484613f68565b600060208284031215613ffb57600080fd5b600061385b8484613f73565b6000806040838503121561401a57600080fd5b60006140268585613f68565b925050602061403785828601613f68565b9150509250929050565b60008060006060848603121561405657600080fd5b60006140628686613f68565b935050602061407386828701613f68565b925050604061408486828701613f94565b9150509250925092565b600080604083850312156140a157600080fd5b60006140ad8585613f68565b925050602061403785828601613f94565b6000806000606084860312156140d357600080fd5b60006140df8686613f68565b93505060206140f086828701613f94565b925050604061408486828701613f68565b600080600080600060a0868803121561411957600080fd5b60006141258888613f68565b955050602061413688828901613f94565b945050604061414788828901613f9f565b935050606061415888828901613f94565b925050608061416988828901613f94565b9150509295509295909350565b60008060006060848603121561418b57600080fd5b60006141978686613f68565b935050602061407386828701613f94565b60008060008060008060c087890312156141c157600080fd5b60006141cd8989613f68565b96505060206141de89828a01613f94565b95505060406141ef89828a01613f94565b945050606061420089828a01613fc0565b935050608061421189828a01613f94565b92505060a061422289828a01613f94565b9150509295509295509295565b6000806040838503121561424257600080fd5b600061424e8585613f68565b925050602061403785828601613fb5565b60006020828403121561427157600080fd5b600061385b8484613f89565b6000806040838503121561429057600080fd5b60006140ad8585613f7e565b6000806000606084860312156142b157600080fd5b60006140628686613f9f565b6000602082840312156142cf57600080fd5b600061385b8484613f9f565b6000602082840312156142ed57600080fd5b600061385b8484613faa565b60006143058383614e99565b505060600190565b61431681615512565b82525050565b614316816154c1565b6000614330826154b4565b61433a81856154b8565b9350614345836154ae565b8060005b8381101561437357815161435d88826142f9565b9750614368836154ae565b925050600101614349565b509495945050505050565b614316816154cc565b614316816154d1565b61431661439c826154d1565b6154d1565b60006143ac826154b4565b6143b6818561108d565b93506143c6818560208601615533565b9290920192915050565b614316816154d4565b6143168161551d565b60006143ed826154b4565b6143f781856154b8565b9350614407818560208601615533565b6144108161555f565b9093019392505050565b60006144276018836154b8565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000815260200192915050565b60006144606012836154b8565b71696e636f6e73697374656e7420737461746560701b815260200192915050565b600061448e6013836154b8565b727661756c743a20706f6f6c206578697374733f60681b815260200192915050565b60006144bd601f836154b8565b7f53746f726520636f6e7472616374206164647265737320697320656d70747900815260200192915050565b60006144f6601f836154b8565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800815260200192915050565b600061452f600f836154b8565b6e15985d5b1d081a5cc81c185d5cd959608a1b815260200192915050565b600061455a6013836154b8565b7215985d5b1d081a5cc81b9bdd081c185d5cd959606a1b815260200192915050565b6000614589600c836154b8565b6b155b985d5d1a1bdc9a5e995960a21b815260200192915050565b60006145b16030836154b8565b7f5856535661756c743a3a6765745374616b65416d6f756e743a2078767320616481526f191c995cdcc81a5cc81b9bdd081cd95d60821b602082015260400192915050565b6000614603602a836154b8565b7f5361666542455032303a204245503230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b600061464f602a836154b8565b7f5856535661756c743a3a64656c656761746542795369673a207369676e6174758152691c9948195e1c1a5c995960b21b602082015260400192915050565b600061469b6022836154b8565b7f7072696d6520746f6b656e2063616e6e6f74206265207a65726f206164647265815261737360f01b602082015260400192915050565b60006146df6026836154b8565b7f5856535661756c743a3a64656c656761746542795369673a20696e76616c6964815265206e6f6e636560d01b602082015260400192915050565b600061472760028361108d565b61190160f01b815260020192915050565b60006147456027836154b8565b7f53616665436173743a2076616c756520646f65736e27742066697420696e20318152663238206269747360c81b602082015260400192915050565b600061478e6020836154b8565b7f496e76616c69642074696d6520626173656420636f6e66696775726174696f6e815260200192915050565b60006147c76017836154b8565b7f5661756c7420697320616c726561647920706175736564000000000000000000815260200192915050565b60006148006025836154b8565b7f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164815264647265737360d81b602082015260400192915050565b60006148476022836154b8565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c815261756560f01b602082015260400192915050565b600061488b601a836154b8565b7f546f6b656e2065786973747320696e206f7468657220706f6f6c000000000000815260200192915050565b60006148c46013836154b8565b72185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b815260200192915050565b60006148f3602b836154b8565b7f5856535661756c743a3a6765745072696f72566f7465733a206e6f742079657481526a0819195d195c9b5a5b995960aa1b602082015260400192915050565b6000614940601d836154b8565b7f7265776172642063616e6e6f74206265207a65726f2061646472657373000000815260200192915050565b60006149796018836154b8565b7f7a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000815260200192915050565b60006149b2601a836154b8565b7f657865637574652070656e64696e67207769746864726177616c000000000000815260200192915050565b60006149eb6022836154b8565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c815261756560f01b602082015260400192915050565b6000614a2f60438361108d565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430192915050565b6000614a9a601f836154b8565b7f72657175657374656420616d6f756e742063616e6e6f74206265207a65726f00815260200192915050565b6000614ad36021836154b8565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000614b166012836154b8565b71141bdbdb08185b1c9958591e48185919195960721b815260200192915050565b6000614b446017836154b8565b7f496e76616c696420626c6f636b73207065722079656172000000000000000000815260200192915050565b6000614b7d600a836154b8565b691c994b595b9d195c995960b21b815260200192915050565b6000614ba36014836154b8565b7324b73b30b634b2103932bbb0b932103a37b5b2b760611b815260200192915050565b6000614bd3600e836154b8565b6d37b7363c9030b236b4b71031b0b760911b815260200192915050565b6000614bfd6015836154b8565b7418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b815260200192915050565b6000614c2e6013836154b8565b726e6f7468696e6720746f20776974686472617760681b815260200192915050565b6000614c5d601a836154b8565b7f496e76616c6964206e6577206c6f636b696e6720706572696f64000000000000815260200192915050565b6000614c96601d836154b8565b7f416c6c6f6320706f696e7473206d757374206e6f74206265207a65726f000000815260200192915050565b6000614ccf601f836154b8565b7f416c726561647920696e697469616c697a65642054696d654d616e6167657200815260200192915050565b6000614d086020836154b8565b7f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b6000614d41603a8361108d565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0192915050565b6000614da0601f836154b8565b7f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614dd9601b836154b8565b7f72657175657374656420616d6f756e7420697320696e76616c69640000000000815260200192915050565b6000614e126022836154b8565b7f6f6e6c792070726f78792061646d696e2063616e206368616e676520627261698152616e7360f01b602082015260400192915050565b6000614e56602e836154b8565b7f416c6c6f6320706f696e7473207065722072657761726420746f6b656e206d7581526d7374206e6f74206265207a65726f60901b602082015260400192915050565b80516060830190614eaa8482614387565b506020820151614ebd6020850182614ecc565b506040820151612f6c60408501825b614316816154df565b614316816154f7565b61431681615500565b61431681615528565b61431681615506565b600061082782846143a1565b6000614f108261471a565b9150614f1c8285614390565b602082019150614f2c8284614390565b5060200192915050565b600061152482614a22565b600061152482614d34565b60208101611524828461431c565b60208101611524828461430d565b60408101614f76828561430d565b818103602083015261385b81846143e2565b60408101614f96828561431c565b610827602083018461431c565b60608101614fb1828661431c565b614fbe602083018561430d565b61385b6040830184614387565b60808101614fd9828761431c565b614fe6602083018661431c565b614ff3604083018561431c565b615000606083018461431c565b95945050505050565b60608101615017828661431c565b614fbe602083018561431c565b60808101615032828761431c565b61503f602083018661431c565b61504c6040830185614387565b6150006060830184614387565b60408101615067828561431c565b610827602083018461437e565b60408101615082828561431c565b6108276020830184614387565b602080825281016108278184614325565b60208101611524828461437e565b602081016115248284614387565b608081016150328287614387565b608081016150d88287614387565b6150e56020830186614387565b614ff36040830185614387565b608081016151008287614387565b61503f6020830186614ede565b6020810161152482846143d0565b60a0810161512982886143d0565b6151366020830187614387565b6151436040830186614387565b6151506060830185614387565b61515d6080830184614387565b9695505050505050565b6020808252810161082781846143e2565b602080825281016115248161441a565b6020808252810161152481614453565b6020808252810161152481614481565b60208082528101611524816144b0565b60208082528101611524816144e9565b6020808252810161152481614522565b602080825281016115248161454d565b602080825281016115248161457c565b60208082528101611524816145a4565b60208082528101611524816145f6565b6020808252810161152481614642565b602080825281016115248161468e565b60208082528101611524816146d2565b6020808252810161152481614738565b6020808252810161152481614781565b60208082528101611524816147ba565b60208082528101611524816147f3565b602080825281016115248161483a565b602080825281016115248161487e565b60208082528101611524816148b7565b60208082528101611524816148e6565b6020808252810161152481614933565b602080825281016115248161496c565b60208082528101611524816149a5565b60208082528101611524816149de565b6020808252810161152481614a8d565b6020808252810161152481614ac6565b6020808252810161152481614b09565b6020808252810161152481614b37565b6020808252810161152481614b70565b6020808252810161152481614b96565b6020808252810161152481614bc6565b6020808252810161152481614bf0565b6020808252810161152481614c21565b6020808252810161152481614c50565b6020808252810161152481614c89565b6020808252810161152481614cc2565b6020808252810161152481614cfb565b6020808252810161152481614d93565b6020808252810161152481614dcc565b6020808252810161152481614e05565b6020808252810161152481614e49565b604081016154268285614387565b61082760208301846143d9565b604081016150828285614387565b6060810161544f8286614387565b614fbe6020830185614387565b602081016115248284614ed5565b604081016154788285614ed5565b6108276020830184614ef0565b602081016115248284614ef0565b604081016154a18285614ee7565b6108276020830184614ee7565b60200190565b5190565b90815260200190565b6000611524826154eb565b151590565b90565b6000611524826154c1565b6001600160801b031690565b6001600160a01b031690565b63ffffffff1690565b60ff1690565b6001600160601b031690565b6000611524826154d4565b6000611524826154d1565b600061152482615506565b60005b8381101561554e578181015183820152602001615536565b83811115612f6c5750506000910152565b601f01601f191690565b615572816154c1565b8114610f0a57600080fd5b615572816154cc565b615572816154d1565b615572816154d4565b615572816154f7565b6155728161550056fe5856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f77735856535661756c743a3a726571756573745769746864726177616c3a20766f746573206f766572666c6f775856535661756c743a3a6765745374616b65416d6f756e743a20766f746573206f766572666c6f775856535661756c743a3a6465706f7369743a20766f746573206f766572666c6f775856535661756c743a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d626572206f72207365636f6e64206578636565647320333220626974737365745769746864726177616c4c6f636b696e67506572696f6428616464726573732c75696e743235362c75696e74323536295856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f7773736574526577617264416d6f756e74506572426c6f636b4f725365636f6e6428616464726573732c75696e743235362961646428616464726573732c75696e743235362c616464726573732c75696e743235362c75696e7432353629a365627a7a7231582053ba350123a86f07263e7bddf3bcee0f7cf11e72f5d2678781f0eb1ebd599dc16c6578706572696d656e74616cf564736f6c63430005100040
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.