Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 25646315 | 26 mins ago | 0 HYPE | |||||
| 25646315 | 26 mins ago | 0 HYPE | |||||
| 25646207 | 27 mins ago | 0 HYPE | |||||
| 25646207 | 27 mins ago | 0 HYPE | |||||
| 25646207 | 27 mins ago | 0 HYPE | |||||
| 25646207 | 27 mins ago | 0 HYPE | |||||
| 25646165 | 28 mins ago | 0 HYPE | |||||
| 25646165 | 28 mins ago | 0 HYPE | |||||
| 25642755 | 1 hr ago | 0 HYPE | |||||
| 25642755 | 1 hr ago | 0 HYPE | |||||
| 25636539 | 3 hrs ago | 0 HYPE | |||||
| 25636539 | 3 hrs ago | 0 HYPE | |||||
| 25636539 | 3 hrs ago | 0 HYPE | |||||
| 25636539 | 3 hrs ago | 0 HYPE | |||||
| 25631674 | 4 hrs ago | 0 HYPE | |||||
| 25631674 | 4 hrs ago | 0 HYPE | |||||
| 25631674 | 4 hrs ago | 0 HYPE | |||||
| 25631674 | 4 hrs ago | 0 HYPE | |||||
| 25631664 | 4 hrs ago | 0 HYPE | |||||
| 25631664 | 4 hrs ago | 0 HYPE | |||||
| 25631304 | 4 hrs ago | 0 HYPE | |||||
| 25631304 | 4 hrs ago | 0 HYPE | |||||
| 25631304 | 4 hrs ago | 0 HYPE | |||||
| 25631304 | 4 hrs ago | 0 HYPE | |||||
| 25631279 | 4 hrs ago | 0 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Bribe
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT OR GPL-3.0-or-later
pragma solidity 0.8.13;
import "./interfaces/IMinter.sol";
import "./interfaces/IVoter.sol";
import "./interfaces/IGaugeManager.sol";
import "./interfaces/IVotingEscrow.sol";
import "./interfaces/ITokenHandler.sol";
import {HybraTimeLibrary} from "./libraries/HybraTimeLibrary.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
contract Bribe is ReentrancyGuard {
using SafeERC20 for IERC20;
uint256 public WEEK;
/* ========== STATE VARIABLES ========== */
struct VotingRewardsPlot {
uint128 balanceOf;
uint32 timestamp;
}
struct VotingSupplyPlot {
uint128 supply;
uint32 timestamp;
}
mapping(address => mapping(uint256 => uint256)) public tokenRewardsPerEpoch;
address public voter;
address public gaugeManager;
address public immutable bribeFactory;
address public minter;
address public immutable ve;
address public owner;
ITokenHandler public tokenHandler;
string public TYPE;
uint256 public totalSupply;
mapping(uint256 => uint256) public balanceOf;
mapping(address => mapping(uint256 => uint256)) public lastEarn;
mapping(uint256 => mapping(uint256 => VotingRewardsPlot)) public votingRewardsPlots;
mapping(uint256 => uint256) public numVotingRewardsPlots;
mapping(uint256 => VotingSupplyPlot) public votingSupplyPlots;
uint256 public numVotingSupplyPlots;
mapping(address => bool) internal isBribeToken;
address[] public bribeTokens;
/* ========== CONSTRUCTOR ========== */
constructor(address _owner,address _voter,address _gaugeManager, address _bribeFactory, address _tokenHandler, address _token0, address _token1, string memory _type) {
require(_bribeFactory != address(0) && _voter != address(0) && _gaugeManager != address(0) && _owner != address(0), "ZA");
WEEK = HybraTimeLibrary.WEEK;
voter = _voter;
gaugeManager = _gaugeManager;
bribeFactory = _bribeFactory;
tokenHandler = ITokenHandler(_tokenHandler);
ve = IVoter(_voter)._ve();
minter = IGaugeManager(_gaugeManager).minter();
require(minter != address(0), "ZA");
owner = _owner;
TYPE = _type;
bribeTokens.push(_token0);
bribeTokens.push(_token1);
isBribeToken[_token0] = true;
isBribeToken[_token1] = true;
}
function getEpochStart() public view returns(uint256){
return IMinter(minter).active_period();
}
/// @notice get next epoch (where bribes are saved)
function getNextEpochStart() public view returns(uint256){
return HybraTimeLibrary.epochNext(block.timestamp);
}
/* ========== VIEWS ========== */
/// @notice get the length of the reward tokens
function rewardsListLength() external view returns(uint256) {
return bribeTokens.length;
}
/// @notice Read earned amount given a tokenID and _rewardToken
function earned(uint256 tokenId, address _rewardToken) public view returns(uint256){
if (numVotingRewardsPlots[tokenId] == 0) {
return 0;
}
uint256 reward = 0;
uint256 _supply = 1;
uint256 _currTs = HybraTimeLibrary.epochStart(lastEarn[_rewardToken][tokenId]); // take epoch last claimed in as starting point
uint256 _index = getPriorVotingRewardsIndex(tokenId, _currTs);
VotingRewardsPlot memory cp0 = votingRewardsPlots[tokenId][_index];
_currTs = Math.max(_currTs, HybraTimeLibrary.epochStart(cp0.timestamp));
uint256 numEpochs = (HybraTimeLibrary.epochStart(block.timestamp) - _currTs) / WEEK;
if (numEpochs > 0) {
for (uint256 i = 0; i < numEpochs; i++) {
_index = getPriorVotingRewardsIndex(tokenId, _currTs + WEEK - 1);
cp0 = votingRewardsPlots[tokenId][_index];
_supply = Math.max(votingSupplyPlots[getPriorVotingSupplyIndex(_currTs + WEEK - 1)].supply, 1);
reward += (cp0.balanceOf * tokenRewardsPerEpoch[_rewardToken][_currTs]) / _supply;
_currTs += WEEK;
}
}
return reward;
}
function getPriorVotingRewardsIndex(uint256 tokenId, uint256 timestamp) public view returns (uint256) {
uint256 nPlots = numVotingRewardsPlots[tokenId];
if (nPlots == 0) {
return 0;
}
if (votingRewardsPlots[tokenId][nPlots - 1].timestamp <= timestamp) {
return (nPlots - 1);
}
if (votingRewardsPlots[tokenId][0].timestamp > timestamp) {
return 0;
}
uint256 lower = 0;
uint256 upper = nPlots - 1;
while (upper > lower) {
uint256 center = upper - (upper - lower) / 2;
VotingRewardsPlot memory plot = votingRewardsPlots[tokenId][center];
if (plot.timestamp == timestamp) {
return center;
} else if (plot.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
function getPriorVotingSupplyIndex(uint256 timestamp) public view returns (uint256) {
uint256 nPlots = numVotingSupplyPlots;
if (nPlots == 0) {
return 0;
}
if (votingSupplyPlots[nPlots - 1].timestamp <= timestamp) {
return nPlots - 1;
}
if (votingSupplyPlots[0].timestamp > timestamp) {
return 0;
}
uint256 lower = 0;
uint256 upper = nPlots - 1;
while (upper > lower) {
uint256 center = upper - (upper - lower) / 2;
VotingSupplyPlot memory plot = votingSupplyPlots[center];
if (plot.timestamp == timestamp) return center;
else if (plot.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
function isRewardToken(address _rewardToken) external view returns (bool) {
return _isRewardToken(_rewardToken);
}
function _isRewardToken(address _rewardToken) internal view returns (bool) {
return isBribeToken[_rewardToken] || tokenHandler.isConnector(_rewardToken);
}
/* ========== MUTATIVE FUNCTIONS ========== */
/// @notice User votes deposit
/// @dev called on voter.vote() or voter.poke()
/// we save into owner "address" and not "tokenID".
/// Owner must reset before transferring token
function deposit(uint256 amount, uint256 tokenId) external nonReentrant {
require(amount > 0, "ZV");
require(msg.sender == voter, "NA");
totalSupply = totalSupply + amount;
balanceOf[tokenId] = balanceOf[tokenId] + amount;
_writeVotingRewardsPlot(tokenId, balanceOf[tokenId]);
_writeVotingSupplyPlot();
emit Staked(tokenId, amount);
}
function _writeVotingRewardsPlot(uint256 tokenId, uint256 balance) internal {
uint256 nPlots = numVotingRewardsPlots[tokenId];
uint32 ts = uint32(block.timestamp);
if (
nPlots > 0 &&
HybraTimeLibrary.epochStart(votingRewardsPlots[tokenId][nPlots - 1].timestamp) ==
HybraTimeLibrary.epochStart(ts)
) {
votingRewardsPlots[tokenId][nPlots - 1] = VotingRewardsPlot(uint128(balance), ts);
} else {
votingRewardsPlots[tokenId][nPlots] = VotingRewardsPlot(uint128(balance), ts);
numVotingRewardsPlots[tokenId] = nPlots + 1;
}
}
function _writeVotingSupplyPlot() internal {
uint256 nPlots = numVotingSupplyPlots;
uint32 ts = uint32(block.timestamp);
if (
nPlots > 0 &&
HybraTimeLibrary.epochStart(votingSupplyPlots[nPlots - 1].timestamp) ==
HybraTimeLibrary.epochStart(ts)
) {
votingSupplyPlots[nPlots - 1] = VotingSupplyPlot(uint128(totalSupply), ts);
} else {
votingSupplyPlots[nPlots] = VotingSupplyPlot(uint128(totalSupply), ts);
numVotingSupplyPlots = nPlots + 1;
}
}
/// @notice User votes withdrawal
/// @dev called on voter.reset()
function withdraw(uint256 amount, uint256 tokenId) external nonReentrant {
require(amount > 0, "ZV");
require(msg.sender == voter, "NA");
if (amount <= balanceOf[tokenId]) {
totalSupply -= amount;
balanceOf[tokenId] -= amount;
_writeVotingRewardsPlot(tokenId, balanceOf[tokenId]);
_writeVotingSupplyPlot();
emit Withdrawn(tokenId, amount);
}
}
/// @notice Claim the TOKENID rewards
function getReward(uint256 tokenId, address[] memory tokens) external nonReentrant {
address _owner = IVotingEscrow(ve).ownerOf(tokenId);
require(msg.sender == gaugeManager, "NA");
uint256 _length = tokens.length;
for (uint256 i = 0; i < _length; i++) {
uint256 _reward = earned(tokenId, tokens[i]);
lastEarn[tokens[i]][tokenId] = block.timestamp;
if (_reward > 0) {
IERC20(tokens[i]).safeTransfer(_owner, _reward);
}
}
}
/// @dev Rewards are saved into Current EPOCH mapping.
function notifyRewardAmount(address _rewardsToken, uint256 reward) external nonReentrant {
require(_isRewardToken(_rewardsToken), "!VERIFIED");
if(!isBribeToken[_rewardsToken]){
isBribeToken[_rewardsToken] = true;
bribeTokens.push(_rewardsToken);
}
IERC20(_rewardsToken).safeTransferFrom(msg.sender,address(this),reward);
uint256 epochStart = HybraTimeLibrary.epochStart(block.timestamp);
tokenRewardsPerEpoch[_rewardsToken][epochStart] += reward;
emit RewardAdded(_rewardsToken, reward, epochStart);
}
/* ========== RESTRICTED FUNCTIONS ========== */
/// @notice Recover some ERC20 from the contract and updated given bribe
function recoverERC20AndUpdateData(address tokenAddress, uint256 tokenAmount) external onlyAllowed {
require(tokenAmount <= IERC20(tokenAddress).balanceOf(address(this)), "TOO_MUCH");
uint256 _startTimestamp = IMinter(minter).active_period();
uint256 _lastReward = tokenRewardsPerEpoch[tokenAddress][_startTimestamp];
tokenRewardsPerEpoch[tokenAddress][_startTimestamp] = _lastReward - tokenAmount;
IERC20(tokenAddress).safeTransfer(owner, tokenAmount);
emit Recovered(tokenAddress, tokenAmount);
}
/// @notice Recover some ERC20 from the contract.
/// @dev Be careful --> if called then getReward() at last epoch will fail because some reward are missing!
/// Think about calling recoverERC20AndUpdateData()
function emergencyRecoverERC20(address tokenAddress, uint256 tokenAmount) external onlyAllowed {
require(tokenAmount <= IERC20(tokenAddress).balanceOf(address(this)), "TOO_MUCH");
IERC20(tokenAddress).safeTransfer(owner, tokenAmount);
emit Recovered(tokenAddress, tokenAmount);
}
/// @notice Set a new voter
function setVoter(address _Voter) external onlyAllowed {
require(_Voter != address(0), "ZA");
voter = _Voter;
}
/// @notice Set a new gaugeManager
function setGaugeManager(address _gaugeManager) external onlyAllowed {
require(_gaugeManager != address(0));
gaugeManager = _gaugeManager;
}
/// @notice Set a new minter
function setMinter(address _minter) external onlyAllowed {
require(_minter != address(0), "ZA");
minter = _minter;
}
/// @notice Set a new Owner
event SetOwner(address indexed _owner);
function setOwner(address _owner) external onlyAllowed {
require(_owner != address(0), "ZA");
owner = _owner;
emit SetOwner(_owner);
}
/* ========== MODIFIERS ========== */
modifier onlyAllowed() {
require( (msg.sender == owner || msg.sender == bribeFactory), "NA" );
_;
}
/* ========== EVENTS ========== */
event RewardAdded(address indexed rewardToken, uint256 reward, uint256 startTimestamp);
event Staked(uint256 indexed tokenId, uint256 amount);
event Withdrawn(uint256 indexed tokenId, uint256 amount);
event RewardPaid(address indexed user,address indexed rewardsToken,uint256 reward);
event Recovered(address indexed token, uint256 amount);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
interface IMinter {
function update_period() external returns (uint);
function check() external view returns(bool);
function period() external view returns(uint);
function active_period() external view returns(uint);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
interface IVoter {
function _ve() external view returns (address);
function factories() external view returns(address[] memory);
function usedWeights(uint id) external view returns(uint);
function lastVoted(uint id) external view returns(uint);
function poolVote(uint id, uint _index) external view returns(address _pair);
function votes(uint id, address _pool) external view returns(uint votes);
function vote(uint256 _tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external;
function poolVoteLength(uint tokenId) external view returns(uint);
function lastVotedTimestamp(uint id) external view returns(uint);
function length() external view returns (uint);
function weights(address _pool) external view returns(uint);
function poke(uint256 _tokenId) external;
function getEpochGovernor() external view returns (address);
function setEpochGovernor(address _epochGovernor) external;
function reset(uint256 _tokenId) external;
function totalWeight() external returns (uint256);
function getPoolVotes(uint tokenId) external view returns(address[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
interface IGaugeManager {
struct FarmingParam {
address farmingCenter;
address algebraEternalFarming;
address nfpm;
}
function fetchInternalBribeFromPool(address _pool) external returns (address);
function fetchExternalBribeFromPool(address _pool) external returns (address);
function isGaugeAliveForPool(address _pool) external returns (bool);
function notifyRewardAmount(uint amount) external;
function distributeAll() external;
function distributeFees() external;
function minter() external view returns(address);
function createGauge(address _pool, uint256 _gaugeType) external returns (address _gauge, address _internal_bribe, address _external_bribe);
function gauges(address _pair) external view returns (address);
function isGauge(address _gauge) external view returns (bool);
function poolForGauge(address _gauge) external view returns (address);
function internal_bribes(address _gauge) external view returns (address);
function external_bribes(address _gauge) external view returns (address);
function pools(uint256 i) external view returns(address);
function pools() external view returns(address[] memory);
function getHybraGovernor() external view returns (address);
function setHybraGovernor(address _blackGovernor) external;
function acceptAlgebraFeeChangeProposal (uint16 newAlgebraFee) external;
function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint256 _tokenId) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
interface IVotingEscrow {
struct Point {
int128 bias;
int128 slope; // # -dweight / dt
uint256 ts;
uint256 blk; // block
uint256 permanent;
}
struct LockedBalance {
int128 amount;
uint end;
bool isPermanent;
}
function create_lock_for(uint _value, uint _lock_duration, address _to) external returns (uint);
function locked(uint id) external view returns(LockedBalance memory);
function tokenOfOwnerByIndex(address _owner, uint _tokenIndex) external view returns (uint);
function token() external view returns (address);
function team() external returns (address);
function epoch() external view returns (uint);
function point_history(uint loc) external view returns (Point memory);
function user_point_history(uint tokenId, uint loc) external view returns (Point memory);
function permanentLockBalance() external view returns (uint256);
function user_point_epoch(uint tokenId) external view returns (uint);
function ownerOf(uint) external view returns (address);
function isApprovedOrOwner(address, uint) external view returns (bool);
function transferFrom(address, address, uint) external;
function voted(uint) external view returns (bool);
function attachments(uint) external view returns (uint);
function voting(uint tokenId) external;
function abstain(uint tokenId) external;
function attach(uint tokenId) external;
function detach(uint tokenId) external;
function approve(address _approved, uint _tokenId) external;
function checkpoint() external;
function deposit_for(uint tokenId, uint value) external;
function balanceOfNFT(uint _id) external view returns (uint);
function balanceOfNFTAt(uint _tokenId, uint _t) external view returns (uint);
function balanceOf(address _owner) external view returns (uint);
function totalSupply() external view returns (uint);
function totalSupplyAtT(uint256 _t) external view returns (uint);
function supply() external view returns (uint);
function avm() external view returns (address);
function decimals() external view returns(uint8);
function lockPermanent(uint _tokenId) external;
function unlockPermanent(uint _tokenId) external;
function increase_unlock_time(uint _tokenId, uint _lock_duration) external;
function multiSplit(uint _tokenId, uint[] memory _amounts) external returns (uint[] memory);
function safeTransferFrom(address _from, address _to, uint _tokenId) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
interface ITokenHandler {
function isWhitelisted(address token) external view returns (bool);
function isWhitelistedNFT(uint256 token) external view returns (bool);
function isConnector(address token) external view returns (bool);
function whitelistToken(address _token) external;
function blacklistToken(address _token) external;
function whiteListed(uint256 index) external returns (address);
function connectors(uint256 index) external returns (address);
function whiteListedTokensLength() external returns (uint256);
function connectorTokensLength() external returns (uint256);
function whiteListedTokens() external view returns(address[] memory tokens);
function connectorTokens() external view returns(address[] memory tokens);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
library HybraTimeLibrary {
// for testnet
uint256 internal constant WEEK = 1 weeks;
uint internal constant NO_VOTING_WINDOW = 3600;
uint256 internal constant MAX_LOCK_DURATION = 86400 * 365 * 2;
uint256 internal constant GENESIS_STAKING_MATURITY_TIME = 2 * 86400;
uint256 internal constant NO_GENESIS_DEPOSIT_WINDOW = 600;
// uint256 internal constant WEEK = 7 * 86400;
// uint internal constant NO_VOTING_WINDOW = 3600;
// uint256 internal constant MAX_LOCK_DURATION = 86400 * 365 * 4;
// uint256 internal constant GENESIS_STAKING_MATURITY_TIME = 180 * 86400;
// uint256 internal constant NO_GENESIS_DEPOSIT_WINDOW = 3 * 3600;
/// @dev Returns start of epoch based on current timestamp
function epochStart(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK);
}
}
/// @dev Returns start of next epoch / end of current epoch
function epochNext(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + WEEK;
}
}
/// @dev Returns start of voting window
function epochVoteStart(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + NO_VOTING_WINDOW;
}
}
/// @dev Returns end of voting window / beginning of unrestricted voting window
function epochVoteEnd(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return timestamp - (timestamp % WEEK) + WEEK - NO_VOTING_WINDOW;
}
}
/// @dev Returns the status if it is the last hour of the epoch
function isLastHour(uint256 timestamp) internal pure returns (bool) {
// return block.timestamp % 7 days >= 6 days + 23 hours;
return timestamp >= HybraTimeLibrary.epochVoteEnd(timestamp)
&& timestamp < HybraTimeLibrary.epochNext(timestamp);
}
/// @dev Returns duration in multiples of epoch
function epochMultiples(uint256 duration) internal pure returns (uint256) {
unchecked {
return (duration / WEEK) * WEEK;
}
}
/// @dev Returns duration in multiples of epoch
function isLastEpoch(uint256 timestamp, uint256 endTime) internal pure returns (bool) {
unchecked {
return endTime - WEEK <= timestamp && timestamp < endTime;
}
}
/// @dev Returns duration in multiples of epoch
function prevPreEpoch(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return epochStart(timestamp) - NO_GENESIS_DEPOSIT_WINDOW;
}
}
/// @dev Returns duration in multiples of epoch
function currPreEpoch(uint256 timestamp) internal pure returns (uint256) {
unchecked {
return epochNext(timestamp) - NO_GENESIS_DEPOSIT_WINDOW;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}{
"remappings": [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
"@cryptoalgebra/integral-core/=node_modules/@cryptoalgebra/integral-core/",
"@cryptoalgebra/integral-periphery/=node_modules/@cryptoalgebra/integral-periphery/",
"@cryptoalgebra/integral-base-plugin/=node_modules/@cryptoalgebra/integral-base-plugin/",
"@cryptoalgebra/integral-farming/=node_modules/@cryptoalgebra/integral-farming/",
"@ensdomains/=node_modules/@ensdomains/",
"@ethereum-waffle/=node_modules/@ethereum-waffle/",
"@uniswap/=node_modules/@uniswap/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"hardhat/=node_modules/hardhat/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address","name":"_gaugeManager","type":"address"},{"internalType":"address","name":"_bribeFactory","type":"address"},{"internalType":"address","name":"_tokenHandler","type":"address"},{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"string","name":"_type","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTimestamp","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardsToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"}],"name":"SetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"TYPE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bribeFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bribeTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"emergencyRecoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gaugeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEpochStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextEpochStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorVotingRewardsIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorVotingSupplyIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"isRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastEarn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"numVotingRewardsPlots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numVotingSupplyPlots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20AndUpdateData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gaugeManager","type":"address"}],"name":"setGaugeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_Voter","type":"address"}],"name":"setVoter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenHandler","outputs":[{"internalType":"contract ITokenHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenRewardsPerEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"votingRewardsPlots","outputs":[{"internalType":"uint128","name":"balanceOf","type":"uint128"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"votingSupplyPlots","outputs":[{"internalType":"uint128","name":"supply","type":"uint128"},{"internalType":"uint32","name":"timestamp","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c080604052346200018857620028648038038091620000208285620001b4565b833981016101008282031262000188576200003b82620001e7565b916020926200004c848301620001e7565b6200005a60408401620001e7565b6200006860608501620001e7565b906200007760808601620001e7565b926200008660a08701620001e7565b946200009560c08801620001e7565b60e088015190976001600160401b03919082821162000188570189601f82011215620001885780519182116200018d575b60405199620000df601f8401601f19168d018c620001b4565b828b528b838301011162000188579960009a5b828c1062000172575081620001109b1162000163575b505062000481565b60405161217c9081620006e882396080518181816103e9015281816104c60152818161070601528181610e8101528181610f32015281816110d801526112ff015260a05181818161054d0152611bf90152f35b6000918a010152388062000108565b8b81018201518b8d018301529a81019a620000f2565b600080fd5b620001976200019d565b620000c6565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017620001d857604052565b620001e26200019d565b604052565b51906001600160a01b03821682036200018857565b156200020457565b60405162461bcd60e51b81526020600482015260026024820152615a4160f01b6044820152606490fd5b9081602091031262000188576200024590620001e7565b90565b506040513d6000823e3d90fd5b90600182811c9216801562000287575b60208310146200027157565b634e487b7160e01b600052602260045260246000fd5b91607f169162000265565b601f81116200029f575050565b6000906008825260208220906020601f850160051c83019410620002e0575b601f0160051c01915b828110620002d457505050565b818155600101620002c7565b9092508290620002be565b80519091906001600160401b038111620003df575b62000318816200031260085462000255565b62000292565b602080601f83116001146200035757508192936000926200034b575b50508160011b916000199060031b1c191617600855565b01519050388062000334565b6008600052601f198316949091907ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3926000905b878210620003c6575050836001959610620003ac575b505050811b01600855565b015160001960f88460031b161c19169055388080620003a1565b806001859682949686015181550195019301906200038b565b620003e96200019d565b62000300565b6011546801000000000000000081101562000471575b60018101806011558110156200045b5760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b600052603260045260246000fd5b6200047b6200019d565b62000405565b96620006086200064b98620005cd6200060e9462000624986200063e986200063e9c9b98620004b06001600055565b6001600160a01b039283926200054f918491808316151580620006db575b80620006cf575b80620006c3575b620004e790620001fc565b620004f462093a80600155565b600380546001600160a01b0319166001600160a01b038a16179055600480546001600160a01b0319166001600160a01b03871617905560805260078054919092166001600160a01b03166001600160a01b0319909116179055565b6040518094638dd598fb60e01b825281600460209788968794165afa908115620006b3575b60009162000691575b5060a0526004604051809481936303aa30b960e11b8352165afa91821562000681575b6000926200064d575b5050600580546001600160a01b0319166001600160a01b0392909216919091179055565b600554620005e6906001600160a01b03161515620001fc565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b620002eb565b6200061981620003ef565b6200062484620003ef565b6001600160a01b0316600090815260106020526040902090565b805460ff19166001179055565b565b620006719250803d1062000679575b620006688183620001b4565b8101906200022e565b3880620005a9565b503d6200065c565b6200068b62000248565b620005a0565b620006ac9150833d85116200067957620006688183620001b4565b386200057d565b620006bd62000248565b62000574565b508983161515620004dc565b508285161515620004d5565b508288161515620004ce56fe60806040526004361015610013575b600080fd5b60003560e01c80630125bb32146102cf57806307546172146102c657806313af4035146102bd57806318160ddd146102b45780631b3d6e87146102ab5780631f850716146102a2578063441a3e701461029957806346c96aac146102905780634bc2a6571461028757806365c5f94a1461027e5780636b85568a146102755780636f05e50d1461026c5780637deeadc6146102635780638da5cb5b1461025a57806392777b291461025157806395f05a6e146102485780639cc7f7081461023f578063a4a3e03514610236578063b1c9b3511461022d578063b5fd73f814610224578063b66503cf1461021b578063bb24fe8a14610212578063c95bda7014610209578063cbda3cee14610200578063d8cfc7f0146101f7578063db9eb5e5146101ee578063e2bbb158146101e5578063e39c08fc146101dc578063e6886396146101d3578063eb4a78e0146101ca578063f25e55a5146101c1578063f4359ce5146101b8578063f5ae2240146101af578063f5f8d365146101a65763fca3b5aa1461019e57600080fd5b61000e61129a565b5061000e6111f4565b5061000e611189565b5061000e611153565b5061000e611107565b5061000e6110c1565b5061000e6110a2565b5061000e611077565b5061000e610fbb565b5061000e610f59565b5061000e610ed2565b5061000e610ea8565b5061000e610cd3565b5061000e610bcf565b5061000e6109ac565b5061000e61097a565b5061000e610958565b5061000e6108dc565b5061000e6108af565b5061000e61083b565b5061000e6107ef565b5061000e6107c5565b5061000e61079e565b5061000e61077f565b5061000e610752565b5061000e61072d565b5061000e6106a1565b5061000e610677565b5061000e61057c565b5061000e610536565b5061000e61050c565b5061000e6104ed565b5061000e61043a565b5061000e610410565b5061000e6102e9565b6001600160a01b0381160361000e57565b503461000e57604036600319011261000e57600435610307816102d8565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa286103a56024356103958160018060a01b0380600654169687331480156103e5575b6103529061195a565b6040516370a0823160e01b81523060048201529116969061038f906020816024818c5afa9081156103d8575b6000916103aa575b50831115611dea565b86611ea8565b6040519081529081906020820190565b0390a2005b6103cb915060203d81116103d1575b6103c38183610b56565b810190611326565b38610386565b503d6103b9565b6103e0611335565b61037e565b50337f0000000000000000000000000000000000000000000000000000000000000000831614610349565b503461000e57600036600319011261000e576005546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e57600060043561045a816102d8565b600654906001600160a01b0390338284161480156104c2575b61047c9061195a565b16809161048a821515611e21565b6001600160a01b03191617600655604051907f167d3e9c1016ab80e58802ca9da10ce5c6a0f4debc46a2e7a2cd9e56899a4fb58383a2f35b50337f0000000000000000000000000000000000000000000000000000000000000000831614610473565b503461000e57600036600319011261000e576020600954604051908152f35b503461000e57600036600319011261000e576007546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57604036600319011261000e5760243560043561059c611e52565b6105a7811515611929565b6105bc60018060a01b0360035416331461195a565b81600052600a6020526040600020548111156105df575b6105dd6001600055565b005b610660816106197f0c875c8d391179c5cf7ad8303d268efd50b8beb78b671f85cd54bfb91eb8ef409360095481811061066a575b03600955565b61062d84600052600a602052604060002090565b6106388282546113c0565b905561065861065185600052600a602052604060002090565b548561198b565b610395611af2565b0390a238806105d3565b61067261138c565b610613565b503461000e57600036600319011261000e576003546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e576004356106bf816102d8565b6006546001600160a01b039190821633148015610702575b6106e09061195a565b166106ec811515611e21565b600380546001600160a01b031916919091179055005b50337f00000000000000000000000000000000000000000000000000000000000000008316146106d7565b503461000e57600036600319011261000e57602060405162093a808042064203018152f35b503461000e57602036600319011261000e57600435600052600d6020526020604060002054604051908152f35b503461000e57600036600319011261000e576020600f54604051908152f35b503461000e57602036600319011261000e5760206107bd60043561178e565b604051908152f35b503461000e57600036600319011261000e576006546040516001600160a01b039091168152602090f35b503461000e57604036600319011261000e5760043561080d816102d8565b60018060a01b0316600052600260205260406000206024356000526020526020604060002054604051908152f35b503461000e57604036600319011261000e57600435600052600c60205260406000206024356000526020526108ab60406000205460405191816001600160801b0363ffffffff859460801c1691168390929163ffffffff6020916001600160801b03604085019616845216910152565b0390f35b503461000e57602036600319011261000e57600435600052600a6020526020604060002054604051908152f35b503461000e57600036600319011261000e57600554604051631a2732c160e31b81526020918290829060049082906001600160a01b03165afa90811561094b575b60009161092e575b50604051908152f35b6109459150823d81116103d1576103c38183610b56565b38610925565b610953611335565b61091d565b503461000e57604036600319011261000e5760206107bd602435600435611648565b503461000e57602036600319011261000e5760206109a260043561099d816102d8565b611894565b6040519015158152f35b503461000e57604036600319011261000e576004356109ca816102d8565b6024356109d5611e52565b6109de82611894565b15610ae557610a787f6a6f77044107a33658235d41bedbbaf2fe9ccdceb313143c947a5e76e1ec847491610a35610a31610a2a8660018060a01b03166000526010602052604060002090565b5460ff1690565b1590565b610aae575b6001600160a01b03841693610a8790610a5583303389611f05565b62093a804206420393849160018060a01b03166000526002602052604060002090565b90600052602052604060002090565b610a92828254611423565b9055604080519182526020820192909252a26105dd6001600055565b6001600160a01b0384166000908152601060205260409020610ad790805460ff19166001179055565b610ae084611d65565b610a3a565b60405162461bcd60e51b815260206004820152600960248201526808559154925192515160ba1b6044820152606490fd5b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff821117610b4957604052565b610b51610b16565b604052565b90601f8019910116810190811067ffffffffffffffff821117610b4957604052565b919091602080825283519081818401526000945b828610610bb9575050806040939411610bac575b601f01601f1916010190565b6000838284010152610ba0565b8581018201518487016040015294810194610b8c565b503461000e57600080600319360112610cd05760405190806008549060019180831c92808216928315610cc6575b6020928386108514610cb2578588526020880194908115610c965750600114610c3d575b6108ab87610c3181890382610b56565b60405191829182610b78565b600860005294509192917ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee35b838610610c855750505091019050610c31826108ab3880610c21565b805485870152948201948101610c69565b60ff19168552505050019150610c319050826108ab3880610c21565b634e487b7160e01b82526022600452602482fd5b93607f1693610bfd565b80fd5b503461000e57604036600319011261000e57600435610cf1816102d8565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa286103a560243560018060a01b03806006541633148015610e7d575b610d369061195a565b6040516370a0823160e01b81523060048201529085169490610e1190602090610d7a9082816024818c5afa908115610e70575b600091610e53575b50851115611dea565b6005546004908290610da290610d96906001600160a01b031681565b6001600160a01b031690565b604051631a2732c160e31b815292839182905afa918215610e46575b600092610e29575b5050610a78610df585610def84610a788860018060a01b03166000526002602052604060002090565b546113c0565b6001600160a01b03909416600090815260026020526040902090565b556006546103959082906001600160a01b031661038f565b610e3f9250803d106103d1576103c38183610b56565b3880610dc6565b610e4e611335565b610dbe565b610e6a9150833d85116103d1576103c38183610b56565b38610d71565b610e78611335565b610d69565b50337f0000000000000000000000000000000000000000000000000000000000000000821614610d2d565b503461000e57600036600319011261000e576004546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e57600435610ef0816102d8565b6006546001600160a01b039190821633148015610f2e575b610f119061195a565b16801561000e57600480546001600160a01b031916919091179055005b50337f0000000000000000000000000000000000000000000000000000000000000000831614610f08565b503461000e57602036600319011261000e57600435600052600e6020526108ab60406000205460405191816001600160801b0363ffffffff859460801c1691168390929163ffffffff6020916001600160801b03604085019616845216910152565b503461000e57604036600319011261000e57600435602435610fdb611e52565b610fe6821515611929565b610ffb60018060a01b0360035416331461195a565b61100782600954611423565b6009557f925435fa7e37e5d9555bb18ce0d62bb9627d0846942e58e5291e9a2dded462ed61106b600093838552600a602052611047816040872054611423565b848652600a602052604086205561065861065185600052600a602052604060002090565b0390a260018155604051f35b503461000e57604036600319011261000e5760206107bd60243561109a816102d8565b60043561144e565b503461000e57600036600319011261000e576020601154604051908152f35b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57604036600319011261000e57600435611125816102d8565b60018060a01b0316600052600b60205260406000206024356000526020526020604060002054604051908152f35b503461000e57600036600319011261000e576020600154604051908152f35b50634e487b7160e01b600052603260045260246000fd5b503461000e57602036600319011261000e5760043560115481101561000e5760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801546040516001600160a01b039091168152602090f35b604051906111f282610b2d565b565b503461000e57604036600319011261000e5767ffffffffffffffff60243581811161000e573660238201121561000e57806004013591821161128d575b8160051b906040519160209361124985830185610b56565b83526024848401918301019136831161000e57602401905b828210611274576105dd84600435611bc9565b8480918335611282816102d8565b815201910190611261565b611295610b16565b611231565b503461000e57602036600319011261000e576004356112b8816102d8565b6006546001600160a01b0391908216331480156112fb575b6112d99061195a565b166112e5811515611e21565b600580546001600160a01b031916919091179055005b50337f00000000000000000000000000000000000000000000000000000000000000008316146112d0565b9081602091031261000e575190565b506040513d6000823e3d90fd5b906040516040810181811067ffffffffffffffff82111761137f575b60405291546001600160801b038116835260801c63ffffffff166020830152565b611387610b16565b61135e565b50634e487b7160e01b600052601160045260246000fd5b600181106113b3575b6000190190565b6113bb61138c565b6113ac565b8181106113cb570390565b6113d361138c565b0390565b81156113e1570490565b634e487b7160e01b600052601260045260246000fd5b6001906000198114611407570190565b61140f61138c565b0190565b6001906001198111611407570190565b81198111611407570190565b8060001904821181151516611442570290565b61144a61138c565b0290565b61146281600052600d602052604060002090565b5415611641576000916114f661149d61149184610a788560018060a01b0316600052600b602052604060002090565b5462093a808106900390565b6114f06114e56114dc60206114d16114cc6114b8878b611648565b610a788b600052600c602052604060002090565b611342565b015163ffffffff1690565b63ffffffff1690565b62093a808106900390565b90612134565b6115078162093a80420642036113c0565b9161151560015480946113d7565b9384611524575b505050505090565b908594939294915b848310611539575061151c565b9091929394956116308561162a611636936116248361161f896001600160801b038f80610a786115fb6115ed8f6115dc6115cf6115bf6115ba6115976115b38f6115e897610a786115a26116179f6115976114cc9561159c92611423565b6113a3565b83611648565b91600052600c602052604060002090565b9e8a611423565b61178e565b600052600e602052604060002090565b546001600160801b031690565b6001600160801b031690565b612122565b97516001600160801b031690565b6001600160a01b03909516600090815260026020526040902090565b54911661142f565b6113d7565b90611423565b98611423565b936113f7565b91909493929461152c565b5050600090565b61165c81600052600d602052604060002090565b54918215611778578063ffffffff6116a861169b61168486600052600c602052604060002090565b61168d886113a3565b600052602052604060002090565b5460801c63ffffffff1690565b16111561178057806116dc6114dc61169b6116cd86600052600c602052604060002090565b60008052602052604060002090565b1161177857906116ed6000936113a3565b915b8383116116fc5750505090565b61171861171261170c86866113c0565b60011c90565b846113c0565b938461173d6114dc60206114d16114cc85610a788a600052600c602052604060002090565b80840361174d5750505050505090565b92809495969310600014611766575050925b91906116ef565b90945061177391506113a3565b61175f565b505050600090565b505061178b906113a3565b90565b600f54908115611641578063ffffffff6117ad61169b6115bf866113a3565b1611156118725760008052600e602052806117ea6114dc7fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c61169b565b11611641576117fa6000926113a3565b905b82821161180857505090565b61181e61181861170c85856113c0565b836113c0565b9261183e6114dc60206114d16114cc88600052600e602052604060002090565b80830361184c575050505090565b9180939492106000146118625750915b906117fc565b925061186d906113a3565b61185c565b5061178b906113a3565b9081602091031261000e5751801515810361000e5790565b6001600160a01b0390811660008181526010602052604090205460ff169182156118bd57505090565b602091925060075416916024604051809481936347f37d1d60e01b835260048301525afa90811561191c575b6000916118f4575090565b61178b915060203d8111611915575b61190d8183610b56565b81019061187c565b503d611903565b611924611335565b6118e9565b1561193057565b60405162461bcd60e51b81526020600482015260026024820152612d2b60f11b6044820152606490fd5b1561196157565b60405162461bcd60e51b81526020600482015260026024820152614e4160f01b6044820152606490fd5b906119a082600052600d602052604060002090565b5463ffffffff421681151580611aba575b15611a49579061168d611a096111f2956119f9611a0f956119ec6001600160801b036119db6111e5565b991689906001600160801b03169052565b63ffffffff166020880152565b600052600c602052604060002090565b916113a3565b815181546020909301516001600160a01b03199093166001600160801b03919091161760809290921b63ffffffff60801b16919091179055565b90611aa1611ab793611a89611aa694611a7c6001600160801b03611a6b6111e5565b941684906001600160801b03169052565b63ffffffff166020830152565b611a0f83610a7888600052600c602052604060002090565b611413565b91600052600d602052604060002090565b55565b50611ae46114e56114dc61169b611adb88600052600c602052604060002090565b61168d876113a3565b62093a8082068203146119b1565b600f5463ffffffff421681151580611ba5575b15611b5157611a0f6115bf6111f293611597611b296009546001600160801b031690565b94611b44611b356111e5565b6001600160801b039097168752565b63ffffffff166020860152565b6111f291611aa1611ba092611b8c611b716009546001600160801b031690565b91611a7c611b7d6111e5565b6001600160801b039094168452565b611a0f83600052600e602052604060002090565b600f55565b50611bbb6114e56114dc61169b6115bf866113a3565b62093a808206820314611b05565b919091611bd4611e52565b6040516331a9108f60e11b815260048101829052906020826024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa918215611d21575b600092611cf1575b50600454611c4c90611c45906001600160a01b0316610d96565b331461195a565b83519160005b838110611c69575050505090506111f26001600055565b80611c90611c8a611c7d611ccc948a611d43565b516001600160a01b031690565b8561144e565b42611cbf86610a78611ca5611c7d878e611d43565b6001600160a01b03166000908152600b6020526040902090565b5580611cd1575b506113f7565b611c52565b611ceb9084611ce6610d96611c7d868d611d43565b611ea8565b38611cc6565b611d1391925060203d8111611d1a575b611d0b8183610b56565b810190611d2e565b9038611c2b565b503d611d01565b611d29611335565b611c23565b9081602091031261000e575161178b816102d8565b6020918151811015611d58575b60051b010190565b611d60611172565b611d50565b60115468010000000000000000811015611ddd575b6001810180601155811015611dd0575b60116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b03909216919091179055565b611dd8611172565b611d8a565b611de5610b16565b611d7a565b15611df157565b60405162461bcd60e51b81526020600482015260086024820152670a89e9ebe9aaa86960c31b6044820152606490fd5b15611e2857565b60405162461bcd60e51b81526020600482015260026024820152615a4160f01b6044820152606490fd5b600260005414611e63576002600055565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b0390921660248301526044808301939093529181526111f2916080820167ffffffffffffffff811183821017611ef8575b604052611fbc565b611f00610b16565b611ef0565b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526111f29160a0820182811067ffffffffffffffff821117611ef857604052611fbc565b15611f6457565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b6040516111f2929161204f91906001600160a01b0316611fdb82610b2d565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af13d15612089573d9167ffffffffffffffff831161207c575b60405192612041601f8201601f1916880185610b56565b83523d60008785013e61208d565b8051918215928315612064575b505050611f5d565b612074935082018101910161187c565b38808061205c565b612084610b16565b61202a565b6060915b919290156120ef57508151156120a1575090565b3b156120aa5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156121025750805190602001fd5b60405162461bcd60e51b815290819061211e9060048301610b78565b0390fd5b600181111561212e5790565b50600190565b9080821115612141575090565b90509056fea2646970667358221220bd6baecf951ec8f190dc30b8b1f85a72e9c317a7807cf2a8a8ca037ec8af9b6464736f6c634300080d0033000000000000000000000000752cb4c9189e8beb10fcab5059c31781816530e80000000000000000000000005623f012d15eb828c12fe32e46d40adc2a9e4fa3000000000000000000000000742caa5ba7c92ca6cfebfd0e73c21739b3b65d5e0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f0000000000000000000000007babb795a02892eaf32dfb43ed59edcae59a19310000000000000000000000005555555555555555555555555555555555555555000000000000000000000000b8ce59fc3717ada4c02eadf9682a9e934f625ebb000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000394879627261204c5020466565733a2030786332326661643636363635333433643338353630386363343564326531343834663962613864366200000000000000
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b60003560e01c80630125bb32146102cf57806307546172146102c657806313af4035146102bd57806318160ddd146102b45780631b3d6e87146102ab5780631f850716146102a2578063441a3e701461029957806346c96aac146102905780634bc2a6571461028757806365c5f94a1461027e5780636b85568a146102755780636f05e50d1461026c5780637deeadc6146102635780638da5cb5b1461025a57806392777b291461025157806395f05a6e146102485780639cc7f7081461023f578063a4a3e03514610236578063b1c9b3511461022d578063b5fd73f814610224578063b66503cf1461021b578063bb24fe8a14610212578063c95bda7014610209578063cbda3cee14610200578063d8cfc7f0146101f7578063db9eb5e5146101ee578063e2bbb158146101e5578063e39c08fc146101dc578063e6886396146101d3578063eb4a78e0146101ca578063f25e55a5146101c1578063f4359ce5146101b8578063f5ae2240146101af578063f5f8d365146101a65763fca3b5aa1461019e57600080fd5b61000e61129a565b5061000e6111f4565b5061000e611189565b5061000e611153565b5061000e611107565b5061000e6110c1565b5061000e6110a2565b5061000e611077565b5061000e610fbb565b5061000e610f59565b5061000e610ed2565b5061000e610ea8565b5061000e610cd3565b5061000e610bcf565b5061000e6109ac565b5061000e61097a565b5061000e610958565b5061000e6108dc565b5061000e6108af565b5061000e61083b565b5061000e6107ef565b5061000e6107c5565b5061000e61079e565b5061000e61077f565b5061000e610752565b5061000e61072d565b5061000e6106a1565b5061000e610677565b5061000e61057c565b5061000e610536565b5061000e61050c565b5061000e6104ed565b5061000e61043a565b5061000e610410565b5061000e6102e9565b6001600160a01b0381160361000e57565b503461000e57604036600319011261000e57600435610307816102d8565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa286103a56024356103958160018060a01b0380600654169687331480156103e5575b6103529061195a565b6040516370a0823160e01b81523060048201529116969061038f906020816024818c5afa9081156103d8575b6000916103aa575b50831115611dea565b86611ea8565b6040519081529081906020820190565b0390a2005b6103cb915060203d81116103d1575b6103c38183610b56565b810190611326565b38610386565b503d6103b9565b6103e0611335565b61037e565b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f831614610349565b503461000e57600036600319011261000e576005546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e57600060043561045a816102d8565b600654906001600160a01b0390338284161480156104c2575b61047c9061195a565b16809161048a821515611e21565b6001600160a01b03191617600655604051907f167d3e9c1016ab80e58802ca9da10ce5c6a0f4debc46a2e7a2cd9e56899a4fb58383a2f35b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f831614610473565b503461000e57600036600319011261000e576020600954604051908152f35b503461000e57600036600319011261000e576007546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576040517f000000000000000000000000d7ed7792f71f3920dba01c544639fd546d87f4fd6001600160a01b03168152602090f35b503461000e57604036600319011261000e5760243560043561059c611e52565b6105a7811515611929565b6105bc60018060a01b0360035416331461195a565b81600052600a6020526040600020548111156105df575b6105dd6001600055565b005b610660816106197f0c875c8d391179c5cf7ad8303d268efd50b8beb78b671f85cd54bfb91eb8ef409360095481811061066a575b03600955565b61062d84600052600a602052604060002090565b6106388282546113c0565b905561065861065185600052600a602052604060002090565b548561198b565b610395611af2565b0390a238806105d3565b61067261138c565b610613565b503461000e57600036600319011261000e576003546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e576004356106bf816102d8565b6006546001600160a01b039190821633148015610702575b6106e09061195a565b166106ec811515611e21565b600380546001600160a01b031916919091179055005b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f8316146106d7565b503461000e57600036600319011261000e57602060405162093a808042064203018152f35b503461000e57602036600319011261000e57600435600052600d6020526020604060002054604051908152f35b503461000e57600036600319011261000e576020600f54604051908152f35b503461000e57602036600319011261000e5760206107bd60043561178e565b604051908152f35b503461000e57600036600319011261000e576006546040516001600160a01b039091168152602090f35b503461000e57604036600319011261000e5760043561080d816102d8565b60018060a01b0316600052600260205260406000206024356000526020526020604060002054604051908152f35b503461000e57604036600319011261000e57600435600052600c60205260406000206024356000526020526108ab60406000205460405191816001600160801b0363ffffffff859460801c1691168390929163ffffffff6020916001600160801b03604085019616845216910152565b0390f35b503461000e57602036600319011261000e57600435600052600a6020526020604060002054604051908152f35b503461000e57600036600319011261000e57600554604051631a2732c160e31b81526020918290829060049082906001600160a01b03165afa90811561094b575b60009161092e575b50604051908152f35b6109459150823d81116103d1576103c38183610b56565b38610925565b610953611335565b61091d565b503461000e57604036600319011261000e5760206107bd602435600435611648565b503461000e57602036600319011261000e5760206109a260043561099d816102d8565b611894565b6040519015158152f35b503461000e57604036600319011261000e576004356109ca816102d8565b6024356109d5611e52565b6109de82611894565b15610ae557610a787f6a6f77044107a33658235d41bedbbaf2fe9ccdceb313143c947a5e76e1ec847491610a35610a31610a2a8660018060a01b03166000526010602052604060002090565b5460ff1690565b1590565b610aae575b6001600160a01b03841693610a8790610a5583303389611f05565b62093a804206420393849160018060a01b03166000526002602052604060002090565b90600052602052604060002090565b610a92828254611423565b9055604080519182526020820192909252a26105dd6001600055565b6001600160a01b0384166000908152601060205260409020610ad790805460ff19166001179055565b610ae084611d65565b610a3a565b60405162461bcd60e51b815260206004820152600960248201526808559154925192515160ba1b6044820152606490fd5b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff821117610b4957604052565b610b51610b16565b604052565b90601f8019910116810190811067ffffffffffffffff821117610b4957604052565b919091602080825283519081818401526000945b828610610bb9575050806040939411610bac575b601f01601f1916010190565b6000838284010152610ba0565b8581018201518487016040015294810194610b8c565b503461000e57600080600319360112610cd05760405190806008549060019180831c92808216928315610cc6575b6020928386108514610cb2578588526020880194908115610c965750600114610c3d575b6108ab87610c3181890382610b56565b60405191829182610b78565b600860005294509192917ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee35b838610610c855750505091019050610c31826108ab3880610c21565b805485870152948201948101610c69565b60ff19168552505050019150610c319050826108ab3880610c21565b634e487b7160e01b82526022600452602482fd5b93607f1693610bfd565b80fd5b503461000e57604036600319011261000e57600435610cf1816102d8565b7f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa286103a560243560018060a01b03806006541633148015610e7d575b610d369061195a565b6040516370a0823160e01b81523060048201529085169490610e1190602090610d7a9082816024818c5afa908115610e70575b600091610e53575b50851115611dea565b6005546004908290610da290610d96906001600160a01b031681565b6001600160a01b031690565b604051631a2732c160e31b815292839182905afa918215610e46575b600092610e29575b5050610a78610df585610def84610a788860018060a01b03166000526002602052604060002090565b546113c0565b6001600160a01b03909416600090815260026020526040902090565b556006546103959082906001600160a01b031661038f565b610e3f9250803d106103d1576103c38183610b56565b3880610dc6565b610e4e611335565b610dbe565b610e6a9150833d85116103d1576103c38183610b56565b38610d71565b610e78611335565b610d69565b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f821614610d2d565b503461000e57600036600319011261000e576004546040516001600160a01b039091168152602090f35b503461000e57602036600319011261000e57600435610ef0816102d8565b6006546001600160a01b039190821633148015610f2e575b610f119061195a565b16801561000e57600480546001600160a01b031916919091179055005b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f831614610f08565b503461000e57602036600319011261000e57600435600052600e6020526108ab60406000205460405191816001600160801b0363ffffffff859460801c1691168390929163ffffffff6020916001600160801b03604085019616845216910152565b503461000e57604036600319011261000e57600435602435610fdb611e52565b610fe6821515611929565b610ffb60018060a01b0360035416331461195a565b61100782600954611423565b6009557f925435fa7e37e5d9555bb18ce0d62bb9627d0846942e58e5291e9a2dded462ed61106b600093838552600a602052611047816040872054611423565b848652600a602052604086205561065861065185600052600a602052604060002090565b0390a260018155604051f35b503461000e57604036600319011261000e5760206107bd60243561109a816102d8565b60043561144e565b503461000e57600036600319011261000e576020601154604051908152f35b503461000e57600036600319011261000e576040517f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f6001600160a01b03168152602090f35b503461000e57604036600319011261000e57600435611125816102d8565b60018060a01b0316600052600b60205260406000206024356000526020526020604060002054604051908152f35b503461000e57600036600319011261000e576020600154604051908152f35b50634e487b7160e01b600052603260045260246000fd5b503461000e57602036600319011261000e5760043560115481101561000e5760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801546040516001600160a01b039091168152602090f35b604051906111f282610b2d565b565b503461000e57604036600319011261000e5767ffffffffffffffff60243581811161000e573660238201121561000e57806004013591821161128d575b8160051b906040519160209361124985830185610b56565b83526024848401918301019136831161000e57602401905b828210611274576105dd84600435611bc9565b8480918335611282816102d8565b815201910190611261565b611295610b16565b611231565b503461000e57602036600319011261000e576004356112b8816102d8565b6006546001600160a01b0391908216331480156112fb575b6112d99061195a565b166112e5811515611e21565b600580546001600160a01b031916919091179055005b50337f0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f8316146112d0565b9081602091031261000e575190565b506040513d6000823e3d90fd5b906040516040810181811067ffffffffffffffff82111761137f575b60405291546001600160801b038116835260801c63ffffffff166020830152565b611387610b16565b61135e565b50634e487b7160e01b600052601160045260246000fd5b600181106113b3575b6000190190565b6113bb61138c565b6113ac565b8181106113cb570390565b6113d361138c565b0390565b81156113e1570490565b634e487b7160e01b600052601260045260246000fd5b6001906000198114611407570190565b61140f61138c565b0190565b6001906001198111611407570190565b81198111611407570190565b8060001904821181151516611442570290565b61144a61138c565b0290565b61146281600052600d602052604060002090565b5415611641576000916114f661149d61149184610a788560018060a01b0316600052600b602052604060002090565b5462093a808106900390565b6114f06114e56114dc60206114d16114cc6114b8878b611648565b610a788b600052600c602052604060002090565b611342565b015163ffffffff1690565b63ffffffff1690565b62093a808106900390565b90612134565b6115078162093a80420642036113c0565b9161151560015480946113d7565b9384611524575b505050505090565b908594939294915b848310611539575061151c565b9091929394956116308561162a611636936116248361161f896001600160801b038f80610a786115fb6115ed8f6115dc6115cf6115bf6115ba6115976115b38f6115e897610a786115a26116179f6115976114cc9561159c92611423565b6113a3565b83611648565b91600052600c602052604060002090565b9e8a611423565b61178e565b600052600e602052604060002090565b546001600160801b031690565b6001600160801b031690565b612122565b97516001600160801b031690565b6001600160a01b03909516600090815260026020526040902090565b54911661142f565b6113d7565b90611423565b98611423565b936113f7565b91909493929461152c565b5050600090565b61165c81600052600d602052604060002090565b54918215611778578063ffffffff6116a861169b61168486600052600c602052604060002090565b61168d886113a3565b600052602052604060002090565b5460801c63ffffffff1690565b16111561178057806116dc6114dc61169b6116cd86600052600c602052604060002090565b60008052602052604060002090565b1161177857906116ed6000936113a3565b915b8383116116fc5750505090565b61171861171261170c86866113c0565b60011c90565b846113c0565b938461173d6114dc60206114d16114cc85610a788a600052600c602052604060002090565b80840361174d5750505050505090565b92809495969310600014611766575050925b91906116ef565b90945061177391506113a3565b61175f565b505050600090565b505061178b906113a3565b90565b600f54908115611641578063ffffffff6117ad61169b6115bf866113a3565b1611156118725760008052600e602052806117ea6114dc7fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c61169b565b11611641576117fa6000926113a3565b905b82821161180857505090565b61181e61181861170c85856113c0565b836113c0565b9261183e6114dc60206114d16114cc88600052600e602052604060002090565b80830361184c575050505090565b9180939492106000146118625750915b906117fc565b925061186d906113a3565b61185c565b5061178b906113a3565b9081602091031261000e5751801515810361000e5790565b6001600160a01b0390811660008181526010602052604090205460ff169182156118bd57505090565b602091925060075416916024604051809481936347f37d1d60e01b835260048301525afa90811561191c575b6000916118f4575090565b61178b915060203d8111611915575b61190d8183610b56565b81019061187c565b503d611903565b611924611335565b6118e9565b1561193057565b60405162461bcd60e51b81526020600482015260026024820152612d2b60f11b6044820152606490fd5b1561196157565b60405162461bcd60e51b81526020600482015260026024820152614e4160f01b6044820152606490fd5b906119a082600052600d602052604060002090565b5463ffffffff421681151580611aba575b15611a49579061168d611a096111f2956119f9611a0f956119ec6001600160801b036119db6111e5565b991689906001600160801b03169052565b63ffffffff166020880152565b600052600c602052604060002090565b916113a3565b815181546020909301516001600160a01b03199093166001600160801b03919091161760809290921b63ffffffff60801b16919091179055565b90611aa1611ab793611a89611aa694611a7c6001600160801b03611a6b6111e5565b941684906001600160801b03169052565b63ffffffff166020830152565b611a0f83610a7888600052600c602052604060002090565b611413565b91600052600d602052604060002090565b55565b50611ae46114e56114dc61169b611adb88600052600c602052604060002090565b61168d876113a3565b62093a8082068203146119b1565b600f5463ffffffff421681151580611ba5575b15611b5157611a0f6115bf6111f293611597611b296009546001600160801b031690565b94611b44611b356111e5565b6001600160801b039097168752565b63ffffffff166020860152565b6111f291611aa1611ba092611b8c611b716009546001600160801b031690565b91611a7c611b7d6111e5565b6001600160801b039094168452565b611a0f83600052600e602052604060002090565b600f55565b50611bbb6114e56114dc61169b6115bf866113a3565b62093a808206820314611b05565b919091611bd4611e52565b6040516331a9108f60e11b815260048101829052906020826024816001600160a01b037f000000000000000000000000d7ed7792f71f3920dba01c544639fd546d87f4fd165afa918215611d21575b600092611cf1575b50600454611c4c90611c45906001600160a01b0316610d96565b331461195a565b83519160005b838110611c69575050505090506111f26001600055565b80611c90611c8a611c7d611ccc948a611d43565b516001600160a01b031690565b8561144e565b42611cbf86610a78611ca5611c7d878e611d43565b6001600160a01b03166000908152600b6020526040902090565b5580611cd1575b506113f7565b611c52565b611ceb9084611ce6610d96611c7d868d611d43565b611ea8565b38611cc6565b611d1391925060203d8111611d1a575b611d0b8183610b56565b810190611d2e565b9038611c2b565b503d611d01565b611d29611335565b611c23565b9081602091031261000e575161178b816102d8565b6020918151811015611d58575b60051b010190565b611d60611172565b611d50565b60115468010000000000000000811015611ddd575b6001810180601155811015611dd0575b60116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b03909216919091179055565b611dd8611172565b611d8a565b611de5610b16565b611d7a565b15611df157565b60405162461bcd60e51b81526020600482015260086024820152670a89e9ebe9aaa86960c31b6044820152606490fd5b15611e2857565b60405162461bcd60e51b81526020600482015260026024820152615a4160f01b6044820152606490fd5b600260005414611e63576002600055565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b60405163a9059cbb60e01b60208201526001600160a01b0390921660248301526044808301939093529181526111f2916080820167ffffffffffffffff811183821017611ef8575b604052611fbc565b611f00610b16565b611ef0565b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526111f29160a0820182811067ffffffffffffffff821117611ef857604052611fbc565b15611f6457565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b6040516111f2929161204f91906001600160a01b0316611fdb82610b2d565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af13d15612089573d9167ffffffffffffffff831161207c575b60405192612041601f8201601f1916880185610b56565b83523d60008785013e61208d565b8051918215928315612064575b505050611f5d565b612074935082018101910161187c565b38808061205c565b612084610b16565b61202a565b6060915b919290156120ef57508151156120a1575090565b3b156120aa5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156121025750805190602001fd5b60405162461bcd60e51b815290819061211e9060048301610b78565b0390fd5b600181111561212e5790565b50600190565b9080821115612141575090565b90509056fea2646970667358221220bd6baecf951ec8f190dc30b8b1f85a72e9c317a7807cf2a8a8ca037ec8af9b6464736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000752cb4c9189e8beb10fcab5059c31781816530e80000000000000000000000005623f012d15eb828c12fe32e46d40adc2a9e4fa3000000000000000000000000742caa5ba7c92ca6cfebfd0e73c21739b3b65d5e0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f0000000000000000000000007babb795a02892eaf32dfb43ed59edcae59a19310000000000000000000000005555555555555555555555555555555555555555000000000000000000000000b8ce59fc3717ada4c02eadf9682a9e934f625ebb000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000394879627261204c5020466565733a2030786332326661643636363635333433643338353630386363343564326531343834663962613864366200000000000000
-----Decoded View---------------
Arg [0] : _owner (address): 0x752Cb4C9189E8bEB10fcAB5059c31781816530E8
Arg [1] : _voter (address): 0x5623F012d15EB828C12fe32e46d40AdC2A9e4FA3
Arg [2] : _gaugeManager (address): 0x742CAA5bA7C92ca6CFeBfD0e73c21739b3b65d5e
Arg [3] : _bribeFactory (address): 0x2555F79AC6e8096c755096e3A8d175a4Bf5fC82F
Arg [4] : _tokenHandler (address): 0x7bAbb795a02892eAF32DFb43ED59eDCAE59a1931
Arg [5] : _token0 (address): 0x5555555555555555555555555555555555555555
Arg [6] : _token1 (address): 0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb
Arg [7] : _type (string): Hybra LP Fees: 0xc22fad66665343d385608cc45d2e1484f9ba8d6b
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000752cb4c9189e8beb10fcab5059c31781816530e8
Arg [1] : 0000000000000000000000005623f012d15eb828c12fe32e46d40adc2a9e4fa3
Arg [2] : 000000000000000000000000742caa5ba7c92ca6cfebfd0e73c21739b3b65d5e
Arg [3] : 0000000000000000000000002555f79ac6e8096c755096e3a8d175a4bf5fc82f
Arg [4] : 0000000000000000000000007babb795a02892eaf32dfb43ed59edcae59a1931
Arg [5] : 0000000000000000000000005555555555555555555555555555555555555555
Arg [6] : 000000000000000000000000b8ce59fc3717ada4c02eadf9682a9e934f625ebb
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000039
Arg [9] : 4879627261204c5020466565733a203078633232666164363636363533343364
Arg [10] : 3338353630386363343564326531343834663962613864366200000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.