Source Code
Latest 25 from a total of 223 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Bribes | 23630806 | 19 hrs ago | IN | 0 ETH | 0.00015735 | ||||
Claim Bribes | 23627906 | 29 hrs ago | IN | 0 ETH | 0.00014604 | ||||
Claim Bribes | 23620029 | 2 days ago | IN | 0 ETH | 0.00002443 | ||||
Claim Bribes | 23608303 | 3 days ago | IN | 0 ETH | 0.00003754 | ||||
Claim Bribes | 23603990 | 4 days ago | IN | 0 ETH | 0.00001444 | ||||
Claim Bribes | 23600928 | 5 days ago | IN | 0 ETH | 0.00002169 | ||||
Claim Bribes | 23598976 | 5 days ago | IN | 0 ETH | 0.00020849 | ||||
Claim Bribes | 23598352 | 5 days ago | IN | 0 ETH | 0.00195909 | ||||
Process | 23596751 | 5 days ago | IN | 0 ETH | 0.00025536 | ||||
Claim Bribes | 23596268 | 5 days ago | IN | 0 ETH | 0.00460363 | ||||
Claim Bribes | 23593793 | 6 days ago | IN | 0 ETH | 0.00002497 | ||||
Claim Bribes | 23592930 | 6 days ago | IN | 0 ETH | 0.00131632 | ||||
Process | 23590916 | 6 days ago | IN | 0 ETH | 0.00019721 | ||||
Process | 23589418 | 6 days ago | IN | 0 ETH | 0.01211258 | ||||
Deposit Bribe | 23589411 | 6 days ago | IN | 0 ETH | 0.00023494 | ||||
Process | 23589106 | 6 days ago | IN | 0 ETH | 0.00011634 | ||||
Process | 23588927 | 6 days ago | IN | 0 ETH | 0.00016659 | ||||
Process | 23588923 | 6 days ago | IN | 0 ETH | 0.00016666 | ||||
Claim Bribes | 23572838 | 8 days ago | IN | 0 ETH | 0.00002185 | ||||
Claim Bribes | 23572767 | 8 days ago | IN | 0 ETH | 0.00003855 | ||||
Claim Bribes | 23561280 | 10 days ago | IN | 0 ETH | 0.00005387 | ||||
Claim Bribes | 23553774 | 11 days ago | IN | 0 ETH | 0.00006143 | ||||
Claim Bribes | 23552325 | 11 days ago | IN | 0 ETH | 0.00019231 | ||||
Claim Bribes | 23542985 | 13 days ago | IN | 0 ETH | 0.0000436 | ||||
Claim Bribes | 23541860 | 13 days ago | IN | 0 ETH | 0.00018324 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
QuestInitiative
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 100000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import { BribeInitiative } from "liquity-gov/src/BribeInitiative.sol"; import { Ownable2Step } from "openzeppelin-contracts/contracts/access/Ownable2Step.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IQuestBoard } from "./interfaces/IQuestBoard.sol"; contract QuestInitiative is BribeInitiative, Ownable2Step { using SafeERC20 for IERC20; uint48 public constant DEFAULT_DURATION = 2; uint256 private constant BPS = 10000; address public questBoard; uint256 public pendingBudget; uint256 public previousQuest; address public targetGauge; struct QuestSettings { uint256 minRewardPerVote; uint256 maxRewardPerVote; IQuestBoard.QuestVoteType voteType; IQuestBoard.QuestCloseType closeType; } QuestSettings public _questSettings; address[] public questVoterList; error CannotCreateQuest(); event QuestCreated(uint256 indexed questId); event SettingsRewardPerVoteUpdated(uint256 newMinRewardPerVote, uint256 newMaxRewardPerVote); event SettingsUpdated(); constructor( address _governance, address _bold, address _bribeToken, address _board, address _gauge ) BribeInitiative(_governance, _bold, _bribeToken) Ownable(msg.sender) { questBoard = _board; targetGauge = _gauge; } function questSettings() external view returns (QuestSettings memory) { return _questSettings; } function process() external { _pullBudget(); _createQuest(); } function pullBudget() external { _pullBudget(); } function _pullBudget() internal { uint256 amount = governance.claimForInitiative(address(this)); pendingBudget += amount; } function _recoverUnusedBudget(uint256 questId) internal { uint256 withdrawable = IQuestBoard(questBoard).questWithdrawableAmount(questId); if(withdrawable == 0) return; uint256 prevBalance = bold.balanceOf(address(this)); IQuestBoard(questBoard).withdrawUnusedRewards(questId, address(this)); uint256 received = bold.balanceOf(address(this)) - prevBalance; pendingBudget += received; } function _createQuest() internal { QuestSettings memory settings = _questSettings; if (previousQuest != 0) { uint48[] memory periods = IQuestBoard(questBoard).getAllPeriodsForQuestId(previousQuest); uint256 lastPeriod = periods[periods.length - 1]; // Previous Quest is not over, do not create a new one if (IQuestBoard(questBoard).getCurrentPeriod() <= lastPeriod) return; // Recover unused budget from previous Quest _recoverUnusedBudget(previousQuest); } uint256 feeRatio = IQuestBoard(questBoard).customPlatformFeeRatio(address(this)); if(feeRatio == 0) feeRatio = IQuestBoard(questBoard).platformFeeRatio(); uint256 amountOutAfterFee = (pendingBudget * BPS) / (BPS + feeRatio); uint256 feeAmount = (amountOutAfterFee * feeRatio) / BPS; pendingBudget -= (amountOutAfterFee + feeAmount); bold.safeIncreaseAllowance(address(questBoard), amountOutAfterFee + feeAmount); uint256 id = IQuestBoard(questBoard).createRangedQuest( targetGauge, address(bold), false, // Allows to create the Quest right now, and check the previous one is over before allowing to create a new one DEFAULT_DURATION, settings.minRewardPerVote, settings.maxRewardPerVote, amountOutAfterFee, feeAmount, settings.voteType, settings.closeType, questVoterList ); previousQuest = id; emit QuestCreated(id); } function updateQuestSettings( uint256 _minRewardPerVote, uint256 _maxRewardPerVote, IQuestBoard.QuestVoteType _voteType, IQuestBoard.QuestCloseType _closeType, address[] memory _voterList ) external onlyOwner { _questSettings = QuestSettings({ minRewardPerVote: _minRewardPerVote, maxRewardPerVote: _maxRewardPerVote, voteType: _voteType, closeType: _closeType }); delete questVoterList; uint256 length = _voterList.length; for (uint256 i = 0; i < length; i++) { questVoterList.push(_voterList[i]); } emit SettingsUpdated(); emit SettingsRewardPerVoteUpdated(_minRewardPerVote, _maxRewardPerVote); } function updateQuestRewardPerVote( uint256 _minRewardPerVote, uint256 _maxRewardPerVote ) external onlyOwner { _questSettings.minRewardPerVote = _minRewardPerVote; _questSettings.maxRewardPerVote = _maxRewardPerVote; emit SettingsRewardPerVoteUpdated(_minRewardPerVote, _maxRewardPerVote); } function updateQuestTypeSettings( IQuestBoard.QuestVoteType _voteType, IQuestBoard.QuestCloseType _closeType, address[] memory _voterList ) external onlyOwner { _questSettings.voteType = _voteType; _questSettings.closeType = _closeType; delete questVoterList; uint256 length = _voterList.length; for (uint256 i = 0; i < length; i++) { questVoterList.push(_voterList[i]); } emit SettingsUpdated(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IERC20} from "openzeppelin/contracts/interfaces/IERC20.sol"; import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IGovernance, UNREGISTERED_INITIATIVE} from "./interfaces/IGovernance.sol"; import {IInitiative} from "./interfaces/IInitiative.sol"; import {IBribeInitiative} from "./interfaces/IBribeInitiative.sol"; import {DoubleLinkedList} from "./utils/DoubleLinkedList.sol"; import {_lqtyToVotes} from "./utils/VotingPower.sol"; contract BribeInitiative is IInitiative, IBribeInitiative { using SafeERC20 for IERC20; using DoubleLinkedList for DoubleLinkedList.List; uint256 internal immutable EPOCH_START; uint256 internal immutable EPOCH_DURATION; /// @inheritdoc IBribeInitiative IGovernance public immutable governance; /// @inheritdoc IBribeInitiative IERC20 public immutable bold; /// @inheritdoc IBribeInitiative IERC20 public immutable bribeToken; /// @inheritdoc IBribeInitiative mapping(uint256 => Bribe) public bribeByEpoch; /// @inheritdoc IBribeInitiative mapping(address => mapping(uint256 => bool)) public claimedBribeAtEpoch; /// Double linked list of the total LQTY allocated at a given epoch DoubleLinkedList.List internal totalLQTYAllocationByEpoch; /// Double linked list of LQTY allocated by a user at a given epoch mapping(address => DoubleLinkedList.List) internal lqtyAllocationByUserAtEpoch; constructor(address _governance, address _bold, address _bribeToken) { require(_bribeToken != _bold, "BribeInitiative: bribe-token-cannot-be-bold"); governance = IGovernance(_governance); bold = IERC20(_bold); bribeToken = IERC20(_bribeToken); EPOCH_START = governance.EPOCH_START(); EPOCH_DURATION = governance.EPOCH_DURATION(); } modifier onlyGovernance() { require(msg.sender == address(governance), "BribeInitiative: invalid-sender"); _; } /// @inheritdoc IBribeInitiative function totalLQTYAllocatedByEpoch(uint256 _epoch) external view returns (uint256, uint256) { return (totalLQTYAllocationByEpoch.items[_epoch].lqty, totalLQTYAllocationByEpoch.items[_epoch].offset); } /// @inheritdoc IBribeInitiative function lqtyAllocatedByUserAtEpoch(address _user, uint256 _epoch) external view returns (uint256, uint256) { return ( lqtyAllocationByUserAtEpoch[_user].items[_epoch].lqty, lqtyAllocationByUserAtEpoch[_user].items[_epoch].offset ); } /// @inheritdoc IBribeInitiative function depositBribe(uint256 _boldAmount, uint256 _bribeTokenAmount, uint256 _epoch) external { uint256 epoch = governance.epoch(); require(_epoch >= epoch, "BribeInitiative: now-or-future-epochs"); bribeByEpoch[_epoch].remainingBoldAmount += _boldAmount; bribeByEpoch[_epoch].remainingBribeTokenAmount += _bribeTokenAmount; emit DepositBribe(msg.sender, _boldAmount, _bribeTokenAmount, _epoch); bold.safeTransferFrom(msg.sender, address(this), _boldAmount); bribeToken.safeTransferFrom(msg.sender, address(this), _bribeTokenAmount); } function _claimBribe( address _user, uint256 _epoch, uint256 _prevLQTYAllocationEpoch, uint256 _prevTotalLQTYAllocationEpoch ) internal returns (uint256 boldAmount, uint256 bribeTokenAmount) { require(_epoch < governance.epoch(), "BribeInitiative: cannot-claim-for-current-epoch"); require(!claimedBribeAtEpoch[_user][_epoch], "BribeInitiative: already-claimed"); Bribe memory bribe = bribeByEpoch[_epoch]; require(bribe.remainingBoldAmount != 0 || bribe.remainingBribeTokenAmount != 0, "BribeInitiative: no-bribe"); DoubleLinkedList.Item memory lqtyAllocation = lqtyAllocationByUserAtEpoch[_user].getItem(_prevLQTYAllocationEpoch); require( _prevLQTYAllocationEpoch <= _epoch && (lqtyAllocation.next > _epoch || lqtyAllocation.next == 0), "BribeInitiative: invalid-prev-lqty-allocation-epoch" ); DoubleLinkedList.Item memory totalLQTYAllocation = totalLQTYAllocationByEpoch.getItem(_prevTotalLQTYAllocationEpoch); require( _prevTotalLQTYAllocationEpoch <= _epoch && (totalLQTYAllocation.next > _epoch || totalLQTYAllocation.next == 0), "BribeInitiative: invalid-prev-total-lqty-allocation-epoch" ); require(totalLQTYAllocation.lqty > 0, "BribeInitiative: total-lqty-allocation-zero"); require(lqtyAllocation.lqty > 0, "BribeInitiative: lqty-allocation-zero"); // `Governance` guarantees that `votes` evaluates to 0 or greater for each initiative at the time of allocation. // Since the last possible moment to allocate within this epoch is 1 second before `epochEnd`, we have that: // - `lqtyAllocation.lqty > 0` implies `votes > 0` // - `totalLQTYAllocation.lqty > 0` implies `totalVotes > 0` uint256 epochEnd = EPOCH_START + _epoch * EPOCH_DURATION; uint256 totalVotes = _lqtyToVotes(totalLQTYAllocation.lqty, epochEnd, totalLQTYAllocation.offset); uint256 votes = _lqtyToVotes(lqtyAllocation.lqty, epochEnd, lqtyAllocation.offset); uint256 remainingVotes = totalVotes - bribe.claimedVotes; boldAmount = bribe.remainingBoldAmount * votes / remainingVotes; bribeTokenAmount = bribe.remainingBribeTokenAmount * votes / remainingVotes; bribe.remainingBoldAmount -= boldAmount; bribe.remainingBribeTokenAmount -= bribeTokenAmount; bribe.claimedVotes += votes; bribeByEpoch[_epoch] = bribe; claimedBribeAtEpoch[_user][_epoch] = true; emit ClaimBribe(_user, _epoch, boldAmount, bribeTokenAmount); } /// @inheritdoc IBribeInitiative function claimBribes(ClaimData[] calldata _claimData) external returns (uint256 boldAmount, uint256 bribeTokenAmount) { for (uint256 i = 0; i < _claimData.length; i++) { ClaimData memory claimData = _claimData[i]; (uint256 boldAmount_, uint256 bribeTokenAmount_) = _claimBribe( msg.sender, claimData.epoch, claimData.prevLQTYAllocationEpoch, claimData.prevTotalLQTYAllocationEpoch ); boldAmount += boldAmount_; bribeTokenAmount += bribeTokenAmount_; } if (boldAmount != 0) bold.safeTransfer(msg.sender, boldAmount); if (bribeTokenAmount != 0) bribeToken.safeTransfer(msg.sender, bribeTokenAmount); } /// @inheritdoc IInitiative function onRegisterInitiative(uint256) external virtual override onlyGovernance {} /// @inheritdoc IInitiative function onUnregisterInitiative(uint256) external virtual override onlyGovernance {} function _setTotalLQTYAllocationByEpoch(uint256 _epoch, uint256 _lqty, uint256 _offset, bool _insert) private { if (_insert) { totalLQTYAllocationByEpoch.insert(_epoch, _lqty, _offset, 0); } else { totalLQTYAllocationByEpoch.items[_epoch].lqty = _lqty; totalLQTYAllocationByEpoch.items[_epoch].offset = _offset; } emit ModifyTotalLQTYAllocation(_epoch, _lqty, _offset); } function _setLQTYAllocationByUserAtEpoch( address _user, uint256 _epoch, uint256 _lqty, uint256 _offset, bool _insert ) private { if (_insert) { lqtyAllocationByUserAtEpoch[_user].insert(_epoch, _lqty, _offset, 0); } else { lqtyAllocationByUserAtEpoch[_user].items[_epoch].lqty = _lqty; lqtyAllocationByUserAtEpoch[_user].items[_epoch].offset = _offset; } emit ModifyLQTYAllocation(_user, _epoch, _lqty, _offset); } /// @inheritdoc IBribeInitiative function getMostRecentUserEpoch(address _user) external view returns (uint256) { uint256 mostRecentUserEpoch = lqtyAllocationByUserAtEpoch[_user].getHead(); return mostRecentUserEpoch; } /// @inheritdoc IBribeInitiative function getMostRecentTotalEpoch() external view returns (uint256) { uint256 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); return mostRecentTotalEpoch; } function onAfterAllocateLQTY( uint256 _currentEpoch, address _user, IGovernance.UserState calldata, IGovernance.Allocation calldata _allocation, IGovernance.InitiativeState calldata _initiativeState ) external virtual onlyGovernance { uint256 mostRecentUserEpoch = lqtyAllocationByUserAtEpoch[_user].getHead(); uint256 mostRecentTotalEpoch = totalLQTYAllocationByEpoch.getHead(); _setTotalLQTYAllocationByEpoch( _currentEpoch, _initiativeState.voteLQTY, _initiativeState.voteOffset, mostRecentTotalEpoch != _currentEpoch // Insert if current > recent ); _setLQTYAllocationByUserAtEpoch( _user, _currentEpoch, _allocation.voteLQTY, _allocation.voteOffset, mostRecentUserEpoch != _currentEpoch // Insert if user current > recent ); } /// @inheritdoc IInitiative function onClaimForInitiative(uint256, uint256) external virtual override onlyGovernance {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../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 An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @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.encodeCall(token.transfer, (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.encodeCall(token.transferFrom, (from, to, 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); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @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.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @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); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @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(token).code.length > 0; } }
// SPDX-License-Identifier: None pragma solidity 0.8.24; interface IQuestBoard { enum QuestVoteType { NORMAL, BLACKLIST, WHITELIST } enum QuestCloseType { NORMAL, ROLLOVER, DISTRIBUTE } enum QuestRewardsType { FIXED, RANGE } /** @notice Struct with all the Quest types */ struct QuestTypes { QuestVoteType voteType; QuestRewardsType rewardsType; QuestCloseType closeType; } struct Quest { // Address of the Quest creator (caller of createQuest() method) address creator; // Address of the ERC20 used for rewards address rewardToken; // Address of the target Gauge address gauge; // Total number of periods for the Quest uint48 duration; // Timestamp where the 1st QuestPeriod starts uint48 periodStart; // Total amount of rewards paid for this Quest // If changes were made to the parameters of this Quest, this will account // any added reward amounts uint256 totalRewardAmount; // Total reward amount that can be distributed for each period uint256 rewardAmountPerPeriod; // Min Amount of reward for each vote (for 1 veToken) uint256 minRewardPerVote; // Max Amount of reward for each vote (for 1 veToken) uint256 maxRewardPerVote; // Min Target Bias for the Gauge uint256 minObjectiveVotes; // Max Target Bias for the Gauge uint256 maxObjectiveVotes; // Quest Types QuestTypes types; } function createFixedQuest( address gauge, address rewardToken, bool startNextPeriod, uint48 duration, uint256 rewardPerVote, uint256 totalRewardAmount, uint256 feeAmount, QuestVoteType voteType, QuestCloseType closeType, address[] calldata voterList ) external returns (uint256); function createRangedQuest( address gauge, address rewardToken, bool startNextPeriod, uint48 duration, uint256 minRewardPerVote, uint256 maxRewardPerVote, uint256 totalRewardAmount, uint256 feeAmount, QuestVoteType voteType, QuestCloseType closeType, address[] calldata voterList ) external returns (uint256); function platformFeeRatio() external view returns (uint256); function customPlatformFeeRatio(address) external view returns (uint256); function getAllPeriodsForQuestId(uint256 questID) external view returns (uint48[] memory); function getCurrentPeriod() external view returns (uint256); function questWithdrawableAmount(uint256 questID) external view returns (uint256); function withdrawUnusedRewards(uint256 questID, address recipient) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IERC20} from "openzeppelin/contracts/interfaces/IERC20.sol"; import {ILQTYStaking} from "./ILQTYStaking.sol"; import {PermitParams} from "../utils/Types.sol"; uint256 constant UNREGISTERED_INITIATIVE = type(uint256).max; interface IGovernance { enum HookStatus { Failed, Succeeded, NotCalled } /// @notice Emitted when a user deposits LQTY /// @param user The account depositing LQTY /// @param rewardRecipient The account receiving the LUSD/ETH rewards earned from staking in V1, if claimed /// @param lqtyAmount The amount of LQTY being deposited /// @return lusdReceived Amount of LUSD tokens received as a side-effect of staking new LQTY /// @return lusdSent Amount of LUSD tokens sent to `rewardRecipient` (may include previously received LUSD) /// @return ethReceived Amount of ETH received as a side-effect of staking new LQTY /// @return ethSent Amount of ETH sent to `rewardRecipient` (may include previously received ETH) event DepositLQTY( address indexed user, address rewardRecipient, uint256 lqtyAmount, uint256 lusdReceived, uint256 lusdSent, uint256 ethReceived, uint256 ethSent ); /// @notice Emitted when a user withdraws LQTY or claims V1 staking rewards /// @param user The account withdrawing LQTY or claiming V1 staking rewards /// @param recipient The account receiving the LQTY withdrawn, and if claimed, the LUSD/ETH rewards earned from staking in V1 /// @return lqtyReceived Amount of LQTY tokens actually withdrawn (may be lower than the `_lqtyAmount` passed to `withdrawLQTY`) /// @return lqtySent Amount of LQTY tokens sent to `recipient` (may include LQTY sent to the user's proxy from sources other than V1 staking) /// @return lusdReceived Amount of LUSD tokens received as a side-effect of staking new LQTY /// @return lusdSent Amount of LUSD tokens sent to `recipient` (may include previously received LUSD) /// @return ethReceived Amount of ETH received as a side-effect of staking new LQTY /// @return ethSent Amount of ETH sent to `recipient` (may include previously received ETH) event WithdrawLQTY( address indexed user, address recipient, uint256 lqtyReceived, uint256 lqtySent, uint256 lusdReceived, uint256 lusdSent, uint256 ethReceived, uint256 ethSent ); event SnapshotVotes(uint256 votes, uint256 forEpoch, uint256 boldAccrued); event SnapshotVotesForInitiative(address indexed initiative, uint256 votes, uint256 vetos, uint256 forEpoch); event RegisterInitiative(address initiative, address registrant, uint256 atEpoch, HookStatus hookStatus); event UnregisterInitiative(address initiative, uint256 atEpoch, HookStatus hookStatus); event AllocateLQTY( address indexed user, address indexed initiative, int256 deltaVoteLQTY, int256 deltaVetoLQTY, uint256 atEpoch, HookStatus hookStatus ); event ClaimForInitiative(address indexed initiative, uint256 bold, uint256 forEpoch, HookStatus hookStatus); struct Configuration { uint256 registrationFee; uint256 registrationThresholdFactor; uint256 unregistrationThresholdFactor; uint256 unregistrationAfterEpochs; uint256 votingThresholdFactor; uint256 minClaim; uint256 minAccrual; uint256 epochStart; uint256 epochDuration; uint256 epochVotingCutoff; } function registerInitialInitiatives(address[] memory _initiatives) external; /// @notice Address of the LQTY StakingV1 contract /// @return stakingV1 Address of the LQTY StakingV1 contract function stakingV1() external view returns (ILQTYStaking stakingV1); /// @notice Address of the LQTY token /// @return lqty Address of the LQTY token function lqty() external view returns (IERC20 lqty); /// @notice Address of the BOLD token /// @return bold Address of the BOLD token function bold() external view returns (IERC20 bold); /// @notice Timestamp at which the first epoch starts /// @return epochStart Timestamp at which the first epoch starts function EPOCH_START() external view returns (uint256 epochStart); /// @notice Duration of an epoch in seconds (e.g. 1 week) /// @return epochDuration Epoch duration function EPOCH_DURATION() external view returns (uint256 epochDuration); /// @notice Voting period of an epoch in seconds (e.g. 6 days) /// @return epochVotingCutoff Epoch voting cutoff function EPOCH_VOTING_CUTOFF() external view returns (uint256 epochVotingCutoff); /// @notice Minimum BOLD amount that has to be claimed, if an initiative doesn't have enough votes to meet the /// criteria then it's votes a excluded from the vote count and distribution /// @return minClaim Minimum claim amount function MIN_CLAIM() external view returns (uint256 minClaim); /// @notice Minimum amount of BOLD that have to be accrued for an epoch, otherwise accrual will be skipped for /// that epoch /// @return minAccrual Minimum amount of BOLD function MIN_ACCRUAL() external view returns (uint256 minAccrual); /// @notice Amount of BOLD to be paid in order to register a new initiative /// @return registrationFee Registration fee function REGISTRATION_FEE() external view returns (uint256 registrationFee); /// @notice Share of all votes that are necessary to register a new initiative /// @return registrationThresholdFactor Threshold factor function REGISTRATION_THRESHOLD_FACTOR() external view returns (uint256 registrationThresholdFactor); /// @notice Multiple of the voting threshold in vetos that are necessary to unregister an initiative /// @return unregistrationThresholdFactor Unregistration threshold factor function UNREGISTRATION_THRESHOLD_FACTOR() external view returns (uint256 unregistrationThresholdFactor); /// @notice Number of epochs an initiative has to be inactive before it can be unregistered /// @return unregistrationAfterEpochs Number of epochs function UNREGISTRATION_AFTER_EPOCHS() external view returns (uint256 unregistrationAfterEpochs); /// @notice Share of all votes that are necessary for an initiative to be included in the vote count /// @return votingThresholdFactor Voting threshold factor function VOTING_THRESHOLD_FACTOR() external view returns (uint256 votingThresholdFactor); /// @notice Returns the amount of BOLD accrued since last epoch (last snapshot) /// @return boldAccrued BOLD accrued function boldAccrued() external view returns (uint256 boldAccrued); struct VoteSnapshot { uint256 votes; // Votes at epoch transition uint256 forEpoch; // Epoch for which the votes are counted } struct InitiativeVoteSnapshot { uint256 votes; // Votes at epoch transition uint256 forEpoch; // Epoch for which the votes are counted uint256 lastCountedEpoch; // Epoch at which which the votes where counted last in the global snapshot uint256 vetos; // Vetos at epoch transition } /// @notice Returns the vote count snapshot of the previous epoch /// @return votes Number of votes /// @return forEpoch Epoch for which the votes are counted function votesSnapshot() external view returns (uint256 votes, uint256 forEpoch); /// @notice Returns the vote count snapshot for an initiative of the previous epoch /// @param _initiative Address of the initiative /// @return votes Number of votes /// @return forEpoch Epoch for which the votes are counted /// @return lastCountedEpoch Epoch at which which the votes where counted last in the global snapshot function votesForInitiativeSnapshot(address _initiative) external view returns (uint256 votes, uint256 forEpoch, uint256 lastCountedEpoch, uint256 vetos); struct Allocation { uint256 voteLQTY; // LQTY allocated vouching for the initiative uint256 voteOffset; // Offset associated with LQTY vouching for the initiative uint256 vetoLQTY; // LQTY vetoing the initiative uint256 vetoOffset; // Offset associated with LQTY vetoing the initiative uint256 atEpoch; // Epoch at which the allocation was last updated } struct UserState { uint256 unallocatedLQTY; // LQTY deposited and unallocated uint256 unallocatedOffset; // The offset sum corresponding to the unallocated LQTY uint256 allocatedLQTY; // LQTY allocated by the user to initatives uint256 allocatedOffset; // The offset sum corresponding to the allocated LQTY } struct InitiativeState { uint256 voteLQTY; // LQTY allocated vouching for the initiative uint256 voteOffset; // Offset associated with LQTY vouching for to the initative uint256 vetoLQTY; // LQTY allocated vetoing the initiative uint256 vetoOffset; // Offset associated with LQTY veoting the initative uint256 lastEpochClaim; } struct GlobalState { uint256 countedVoteLQTY; // Total LQTY that is included in vote counting uint256 countedVoteOffset; // Offset associated with the counted vote LQTY } /// @notice Returns the user's state /// @return unallocatedLQTY LQTY deposited and unallocated /// @return unallocatedOffset Offset associated with unallocated LQTY /// @return allocatedLQTY allocated by the user to initatives /// @return allocatedOffset Offset associated with allocated LQTY function userStates(address _user) external view returns (uint256 unallocatedLQTY, uint256 unallocatedOffset, uint256 allocatedLQTY, uint256 allocatedOffset); /// @notice Returns the initiative's state /// @param _initiative Address of the initiative /// @return voteLQTY LQTY allocated vouching for the initiative /// @return voteOffset Offset associated with voteLQTY /// @return vetoLQTY LQTY allocated vetoing the initiative /// @return vetoOffset Offset associated with vetoLQTY /// @return lastEpochClaim // Last epoch at which rewards were claimed function initiativeStates(address _initiative) external view returns (uint256 voteLQTY, uint256 voteOffset, uint256 vetoLQTY, uint256 vetoOffset, uint256 lastEpochClaim); /// @notice Returns the global state /// @return countedVoteLQTY Total LQTY that is included in vote counting /// @return countedVoteOffset Offset associated with countedVoteLQTY function globalState() external view returns (uint256 countedVoteLQTY, uint256 countedVoteOffset); /// @notice Returns the amount of voting and vetoing LQTY a user allocated to an initiative /// @param _user Address of the user /// @param _initiative Address of the initiative /// @return voteLQTY LQTY allocated vouching for the initiative /// @return voteOffset The offset associated with voteLQTY /// @return vetoLQTY allocated vetoing the initiative /// @return vetoOffset the offset associated with vetoLQTY /// @return atEpoch Epoch at which the allocation was last updated function lqtyAllocatedByUserToInitiative(address _user, address _initiative) external view returns (uint256 voteLQTY, uint256 voteOffset, uint256 vetoLQTY, uint256 vetoOffset, uint256 atEpoch); /// @notice Returns when an initiative was registered /// @param _initiative Address of the initiative /// @return atEpoch If `_initiative` is an active initiative, returns the epoch at which it was registered. /// If `_initiative` hasn't been registered, returns 0. /// If `_initiative` has been unregistered, returns `UNREGISTERED_INITIATIVE`. function registeredInitiatives(address _initiative) external view returns (uint256 atEpoch); /*////////////////////////////////////////////////////////////// STAKING //////////////////////////////////////////////////////////////*/ /// @notice Deposits LQTY /// @dev The caller has to approve their `UserProxy` address to spend the LQTY tokens /// @param _lqtyAmount Amount of LQTY to deposit function depositLQTY(uint256 _lqtyAmount) external; /// @notice Deposits LQTY /// @dev The caller has to approve their `UserProxy` address to spend the LQTY tokens /// @param _lqtyAmount Amount of LQTY to deposit /// @param _doSendRewards If true, send rewards claimed from LQTY staking /// @param _recipient Address to which the tokens should be sent function depositLQTY(uint256 _lqtyAmount, bool _doSendRewards, address _recipient) external; /// @notice Deposits LQTY via Permit /// @param _lqtyAmount Amount of LQTY to deposit /// @param _permitParams Permit parameters function depositLQTYViaPermit(uint256 _lqtyAmount, PermitParams calldata _permitParams) external; /// @notice Deposits LQTY via Permit /// @param _lqtyAmount Amount of LQTY to deposit /// @param _permitParams Permit parameters /// @param _doSendRewards If true, send rewards claimed from LQTY staking /// @param _recipient Address to which the tokens should be sent function depositLQTYViaPermit( uint256 _lqtyAmount, PermitParams calldata _permitParams, bool _doSendRewards, address _recipient ) external; /// @notice Withdraws LQTY and claims any accrued LUSD and ETH rewards from StakingV1 /// @param _lqtyAmount Amount of LQTY to withdraw function withdrawLQTY(uint256 _lqtyAmount) external; /// @notice Withdraws LQTY and claims any accrued LUSD and ETH rewards from StakingV1 /// @param _lqtyAmount Amount of LQTY to withdraw /// @param _doSendRewards If true, send rewards claimed from LQTY staking /// @param _recipient Address to which the tokens should be sent function withdrawLQTY(uint256 _lqtyAmount, bool _doSendRewards, address _recipient) external; /// @notice Claims staking rewards from StakingV1 without unstaking /// @dev Note: in the unlikely event that the caller's `UserProxy` holds any LQTY tokens, they will also be sent to `_rewardRecipient` /// @param _rewardRecipient Address that will receive the rewards /// @return lusdSent Amount of LUSD tokens sent to `_rewardRecipient` (may include previously received LUSD) /// @return ethSent Amount of ETH sent to `_rewardRecipient` (may include previously received ETH) function claimFromStakingV1(address _rewardRecipient) external returns (uint256 lusdSent, uint256 ethSent); /*////////////////////////////////////////////////////////////// VOTING //////////////////////////////////////////////////////////////*/ /// @notice Returns the current epoch number /// @return epoch Current epoch function epoch() external view returns (uint256 epoch); /// @notice Returns the timestamp at which the current epoch started /// @return epochStart Epoch start of the current epoch function epochStart() external view returns (uint256 epochStart); /// @notice Returns the number of seconds that have gone by since the current epoch started /// @return secondsWithinEpoch Seconds within the current epoch function secondsWithinEpoch() external view returns (uint256 secondsWithinEpoch); /// @notice Returns the voting power for an entity (i.e. user or initiative) at a given timestamp /// @param _lqtyAmount Amount of LQTY associated with the entity /// @param _timestamp Timestamp at which to calculate voting power /// @param _offset The entity's offset sum /// @return votes Number of votes function lqtyToVotes(uint256 _lqtyAmount, uint256 _timestamp, uint256 _offset) external pure returns (uint256); /// @dev Returns the most up to date voting threshold /// In contrast to `getLatestVotingThreshold` this function updates the snapshot /// This ensures that the value returned is always the latest function calculateVotingThreshold() external returns (uint256); /// @dev Utility function to compute the threshold votes without recomputing the snapshot /// Note that `boldAccrued` is a cached value, this function works correctly only when called after an accrual function calculateVotingThreshold(uint256 _votes) external view returns (uint256); /// @notice Return the most up to date global snapshot and state as well as a flag to notify whether the state can be updated /// This is a convenience function to always retrieve the most up to date state values function getTotalVotesAndState() external view returns (VoteSnapshot memory snapshot, GlobalState memory state, bool shouldUpdate); /// @dev Given an initiative address, return it's most up to date snapshot and state as well as a flag to notify whether the state can be updated /// This is a convenience function to always retrieve the most up to date state values function getInitiativeSnapshotAndState(address _initiative) external view returns ( InitiativeVoteSnapshot memory initiativeSnapshot, InitiativeState memory initiativeState, bool shouldUpdate ); /// @notice Voting threshold is the max. of either: /// - 4% of the total voting LQTY in the previous epoch /// - or the minimum number of votes necessary to claim at least MIN_CLAIM BOLD /// This value can be offsynch, use the non view `calculateVotingThreshold` to always retrieve the most up to date value /// @return votingThreshold Voting threshold function getLatestVotingThreshold() external view returns (uint256 votingThreshold); /// @notice Snapshots votes for the previous epoch and accrues funds for the current epoch /// @param _initiative Address of the initiative /// @return voteSnapshot Vote snapshot /// @return initiativeVoteSnapshot Vote snapshot of the initiative function snapshotVotesForInitiative(address _initiative) external returns (VoteSnapshot memory voteSnapshot, InitiativeVoteSnapshot memory initiativeVoteSnapshot); /*////////////////////////////////////////////////////////////// FSM //////////////////////////////////////////////////////////////*/ enum InitiativeStatus { NONEXISTENT, /// This Initiative Doesn't exist | This is never returned WARM_UP, /// This epoch was just registered SKIP, /// This epoch will result in no rewards and no unregistering CLAIMABLE, /// This epoch will result in claiming rewards CLAIMED, /// The rewards for this epoch have been claimed UNREGISTERABLE, /// Can be unregistered DISABLED // It was already Unregistered } function getInitiativeState(address _initiative) external returns (InitiativeStatus status, uint256 lastEpochClaim, uint256 claimableAmount); function getInitiativeState( address _initiative, VoteSnapshot memory _votesSnapshot, InitiativeVoteSnapshot memory _votesForInitiativeSnapshot, InitiativeState memory _initiativeState ) external view returns (InitiativeStatus status, uint256 lastEpochClaim, uint256 claimableAmount); /// @notice Registers a new initiative /// @param _initiative Address of the initiative function registerInitiative(address _initiative) external; // /// @notice Unregisters an initiative if it didn't receive enough votes in the last 4 epochs // /// or if it received more vetos than votes and the number of vetos are greater than 3 times the voting threshold // /// @param _initiative Address of the initiative function unregisterInitiative(address _initiative) external; /// @notice Allocates the user's LQTY to initiatives /// @dev The user can only allocate to active initiatives (older than 1 epoch) and has to have enough unallocated /// LQTY available, the initiatives listed must be unique, and towards the end of the epoch a user can only maintain or reduce their votes /// @param _initiativesToReset Addresses of the initiatives the caller was previously allocated to, must be reset to prevent desynch of voting power /// @param _initiatives Addresses of the initiatives to allocate to, can match or be different from `_resetInitiatives` /// @param _absoluteLQTYVotes LQTY to allocate to the initiatives as votes /// @param _absoluteLQTYVetos LQTY to allocate to the initiatives as vetos function allocateLQTY( address[] calldata _initiativesToReset, address[] memory _initiatives, int256[] memory _absoluteLQTYVotes, int256[] memory _absoluteLQTYVetos ) external; /// @notice Deallocates the user's LQTY from initiatives /// @param _initiativesToReset Addresses of initiatives to deallocate LQTY from /// @param _checkAll When true, the call will revert if there is still some allocated LQTY left after deallocating /// from all the addresses in `_initiativesToReset` function resetAllocations(address[] calldata _initiativesToReset, bool _checkAll) external; /// @notice Splits accrued funds according to votes received between all initiatives /// @param _initiative Addresse of the initiative /// @return claimed Amount of BOLD claimed function claimForInitiative(address _initiative) external returns (uint256 claimed); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IGovernance} from "./IGovernance.sol"; interface IInitiative { /// @notice Callback hook that is called by Governance after the initiative was successfully registered /// @param _atEpoch Epoch at which the initiative is registered function onRegisterInitiative(uint256 _atEpoch) external; /// @notice Callback hook that is called by Governance after the initiative was unregistered /// @param _atEpoch Epoch at which the initiative is unregistered function onUnregisterInitiative(uint256 _atEpoch) external; /// @notice Callback hook that is called by Governance after the LQTY allocation is updated by a user /// @param _currentEpoch Epoch at which the LQTY allocation is updated /// @param _user Address of the user that updated their LQTY allocation /// @param _userState User state /// @param _allocation Allocation state from user to initiative /// @param _initiativeState Initiative state function onAfterAllocateLQTY( uint256 _currentEpoch, address _user, IGovernance.UserState calldata _userState, IGovernance.Allocation calldata _allocation, IGovernance.InitiativeState calldata _initiativeState ) external; /// @notice Callback hook that is called by Governance after the claim for the last epoch was distributed /// to the initiative /// @param _claimEpoch Epoch at which the claim was distributed /// @param _bold Amount of BOLD that was distributed function onClaimForInitiative(uint256 _claimEpoch, uint256 _bold) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IERC20} from "openzeppelin/contracts/interfaces/IERC20.sol"; import {IGovernance} from "./IGovernance.sol"; interface IBribeInitiative { event DepositBribe(address depositor, uint256 boldAmount, uint256 bribeTokenAmount, uint256 epoch); event ModifyLQTYAllocation(address user, uint256 epoch, uint256 lqtyAllocated, uint256 offset); event ModifyTotalLQTYAllocation(uint256 epoch, uint256 totalLQTYAllocated, uint256 offset); event ClaimBribe(address user, uint256 epoch, uint256 boldAmount, uint256 bribeTokenAmount); /// @notice Address of the governance contract /// @return governance Adress of the governance contract function governance() external view returns (IGovernance governance); /// @notice Address of the BOLD token /// @return bold Address of the BOLD token function bold() external view returns (IERC20 bold); /// @notice Address of the bribe token /// @return bribeToken Address of the bribe token function bribeToken() external view returns (IERC20 bribeToken); struct Bribe { uint256 remainingBoldAmount; uint256 remainingBribeTokenAmount; // [scaled as 10 ** bribeToken.decimals()] uint256 claimedVotes; } /// @notice Amount of bribe tokens deposited for a given epoch /// @param _epoch Epoch at which the bribe was deposited /// @return remainingBoldAmount Amount of BOLD tokens that haven't been claimed yet /// @return remainingBribeTokenAmount Amount of bribe tokens that haven't been claimed yet /// @return claimedVotes Sum of voting power of users who have already claimed their bribes function bribeByEpoch(uint256 _epoch) external view returns (uint256 remainingBoldAmount, uint256 remainingBribeTokenAmount, uint256 claimedVotes); /// @notice Check if a user has claimed bribes for a given epoch /// @param _user Address of the user /// @param _epoch Epoch at which the bribe may have been claimed by the user /// @return claimed If the user has claimed the bribe function claimedBribeAtEpoch(address _user, uint256 _epoch) external view returns (bool claimed); /// @notice Total LQTY allocated to the initiative at a given epoch /// Voting power can be calculated as `totalLQTYAllocated * timestamp - offset` /// @param _epoch Epoch at which the LQTY was allocated /// @return totalLQTYAllocated Total LQTY allocated /// @return offset Voting power offset function totalLQTYAllocatedByEpoch(uint256 _epoch) external view returns (uint256 totalLQTYAllocated, uint256 offset); /// @notice LQTY allocated by a user to the initiative at a given epoch /// Voting power can be calculated as `lqtyAllocated * timestamp - offset` /// @param _user Address of the user /// @param _epoch Epoch at which the LQTY was allocated by the user /// @return lqtyAllocated LQTY allocated by the user /// @return offset Voting power offset function lqtyAllocatedByUserAtEpoch(address _user, uint256 _epoch) external view returns (uint256 lqtyAllocated, uint256 offset); /// @notice Deposit bribe tokens for a given epoch /// @dev The caller has to approve this contract to spend the BOLD and bribe tokens. /// The caller can only deposit bribes for future epochs /// @param _boldAmount Amount of BOLD tokens to deposit /// @param _bribeTokenAmount Amount of bribe tokens to deposit /// @param _epoch Epoch at which the bribe is deposited function depositBribe(uint256 _boldAmount, uint256 _bribeTokenAmount, uint256 _epoch) external; struct ClaimData { // Epoch at which the user wants to claim the bribes uint256 epoch; // Epoch at which the user updated the LQTY allocation for this initiative uint256 prevLQTYAllocationEpoch; // Epoch at which the total LQTY allocation is updated for this initiative uint256 prevTotalLQTYAllocationEpoch; } /// @notice Claim bribes for a user /// @dev The user can only claim bribes for past epochs. /// The arrays `_epochs`, `_prevLQTYAllocationEpochs` and `_prevTotalLQTYAllocationEpochs` should be sorted /// from oldest epoch to the newest. The length of the arrays has to be the same. /// @param _claimData Array specifying the epochs at which the user wants to claim the bribes function claimBribes(ClaimData[] calldata _claimData) external returns (uint256 boldAmount, uint256 bribeTokenAmount); /// @notice Given a user address return the last recorded epoch for their allocation function getMostRecentUserEpoch(address _user) external view returns (uint256); /// @notice Return the last recorded epoch for the system function getMostRecentTotalEpoch() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @title DoubleLinkedList /// @notice Implements a double linked list where the head is defined as the null item's prev pointer /// and the tail is defined as the null item's next pointer ([tail][prev][item][next][head]) library DoubleLinkedList { struct Item { uint256 lqty; uint256 offset; uint256 prev; uint256 next; } struct List { mapping(uint256 => Item) items; } error IdIsZero(); error ItemNotInList(); error ItemInList(); /// @notice Returns the head item id of the list /// @param list Linked list which contains the item /// @return _ Id of the head item function getHead(List storage list) internal view returns (uint256) { return list.items[0].prev; } /// @notice Returns the tail item id of the list /// @param list Linked list which contains the item /// @return _ Id of the tail item function getTail(List storage list) internal view returns (uint256) { return list.items[0].next; } /// @notice Returns the item id which follows item `id`. Returns the tail item id of the list if the `id` is 0. /// @param list Linked list which contains the items /// @param id Id of the current item /// @return _ Id of the current item's next item function getNext(List storage list, uint256 id) internal view returns (uint256) { return list.items[id].next; } /// @notice Returns the item id which precedes item `id`. Returns the head item id of the list if the `id` is 0. /// @param list Linked list which contains the items /// @param id Id of the current item /// @return _ Id of the current item's previous item function getPrev(List storage list, uint256 id) internal view returns (uint256) { return list.items[id].prev; } /// @notice Returns the value of item `id` /// @param list Linked list which contains the item /// @param id Id of the item /// @return LQTY associated with the item /// @return Offset associated with the item's LQTY function getLQTYAndOffset(List storage list, uint256 id) internal view returns (uint256, uint256) { return (list.items[id].lqty, list.items[id].offset); } /// @notice Returns the item `id` /// @param list Linked list which contains the item /// @param id Id of the item /// @return _ Item function getItem(List storage list, uint256 id) internal view returns (Item memory) { return list.items[id]; } /// @notice Returns whether the list contains item `id` /// @param list Linked list which should contain the item /// @param id Id of the item to check /// @return _ True if the list contains the item, false otherwise function contains(List storage list, uint256 id) internal view returns (bool) { if (id == 0) revert IdIsZero(); return (list.items[id].prev != 0 || list.items[id].next != 0 || list.items[0].next == id); } /// @notice Inserts an item with `id` in the list before item `next` /// - if `next` is 0, the item is inserted at the start (head) of the list /// @dev This function should not be called with an `id` that is already in the list. /// @param list Linked list which contains the next item and into which the new item will be inserted /// @param id Id of the item to insert /// @param lqty amount of LQTY /// @param offset associated with the LQTY amount /// @param next Id of the item which should follow item `id` function insert(List storage list, uint256 id, uint256 lqty, uint256 offset, uint256 next) internal { if (contains(list, id)) revert ItemInList(); if (next != 0 && !contains(list, next)) revert ItemNotInList(); uint256 prev = list.items[next].prev; list.items[prev].next = id; list.items[next].prev = id; list.items[id].prev = prev; list.items[id].next = next; list.items[id].lqty = lqty; list.items[id].offset = offset; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; function _lqtyToVotes(uint256 _lqtyAmount, uint256 _timestamp, uint256 _offset) pure returns (uint256) { uint256 prod = _lqtyAmount * _timestamp; return prod > _offset ? prod - _offset : 0; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @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 v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface ILQTYStaking { // --- Events -- event LQTYTokenAddressSet(address _lqtyTokenAddress); event LUSDTokenAddressSet(address _lusdTokenAddress); event TroveManagerAddressSet(address _troveManager); event BorrowerOperationsAddressSet(address _borrowerOperationsAddress); event ActivePoolAddressSet(address _activePoolAddress); event StakeChanged(address indexed staker, uint256 newStake); event StakingGainsWithdrawn(address indexed staker, uint256 LUSDGain, uint256 ETHGain); event F_ETHUpdated(uint256 _F_ETH); event F_LUSDUpdated(uint256 _F_LUSD); event TotalLQTYStakedUpdated(uint256 _totalLQTYStaked); event EtherSent(address _account, uint256 _amount); event StakerSnapshotsUpdated(address _staker, uint256 _F_ETH, uint256 _F_LUSD); // --- Functions --- function setAddresses( address _lqtyTokenAddress, address _lusdTokenAddress, address _troveManagerAddress, address _borrowerOperationsAddress, address _activePoolAddress ) external; function stake(uint256 _LQTYamount) external; function unstake(uint256 _LQTYamount) external; function increaseF_ETH(uint256 _ETHFee) external; function increaseF_LUSD(uint256 _LQTYFee) external; function getPendingETHGain(address _user) external view returns (uint256); function getPendingLUSDGain(address _user) external view returns (uint256); function stakes(address _user) external view returns (uint256); function totalLQTYStaked() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; struct PermitParams { address owner; address spender; uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; } uint256 constant WAD = 1e18;
{ "remappings": [ "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "liquity-gov/=lib/V2-gov/", "openzeppelin-contracts/contracts/=lib/V2-gov/lib/openzeppelin-contracts/contracts/", "uniswap/v4-core/=lib/V2-gov/lib/v4-core/", "@chimera/=lib/V2-gov/lib/chimera/src/", "@ensdomains/=lib/V2-gov/lib/v4-core/node_modules/@ensdomains/", "@openzeppelin/=lib/V2-gov/lib/v4-core/lib/openzeppelin-contracts/", "@openzeppelin/contracts/=lib/V2-gov/lib/openzeppelin-contracts/contracts/", "V2-gov/=lib/V2-gov/", "chimera/=lib/V2-gov/lib/chimera/src/", "erc4626-tests/=lib/V2-gov/lib/openzeppelin-contracts/lib/erc4626-tests/", "hardhat/=lib/V2-gov/lib/v4-core/node_modules/hardhat/", "openzeppelin/=lib/V2-gov/lib/openzeppelin-contracts/", "solmate/=lib/V2-gov/lib/v4-core/lib/solmate/", "v4-core/=lib/V2-gov/lib/v4-core/" ], "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_bold","type":"address"},{"internalType":"address","name":"_bribeToken","type":"address"},{"internalType":"address","name":"_board","type":"address"},{"internalType":"address","name":"_gauge","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"CannotCreateQuest","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"IdIsZero","type":"error"},{"inputs":[],"name":"ItemInList","type":"error"},{"inputs":[],"name":"ItemNotInList","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bribeTokenAmount","type":"uint256"}],"name":"ClaimBribe","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"boldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bribeTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"DepositBribe","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lqtyAllocated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"offset","type":"uint256"}],"name":"ModifyLQTYAllocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalLQTYAllocated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"offset","type":"uint256"}],"name":"ModifyTotalLQTYAllocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"questId","type":"uint256"}],"name":"QuestCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMinRewardPerVote","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxRewardPerVote","type":"uint256"}],"name":"SettingsRewardPerVoteUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"SettingsUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_DURATION","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_questSettings","outputs":[{"internalType":"uint256","name":"minRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"enum IQuestBoard.QuestVoteType","name":"voteType","type":"uint8"},{"internalType":"enum IQuestBoard.QuestCloseType","name":"closeType","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bold","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bribeByEpoch","outputs":[{"internalType":"uint256","name":"remainingBoldAmount","type":"uint256"},{"internalType":"uint256","name":"remainingBribeTokenAmount","type":"uint256"},{"internalType":"uint256","name":"claimedVotes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bribeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"prevLQTYAllocationEpoch","type":"uint256"},{"internalType":"uint256","name":"prevTotalLQTYAllocationEpoch","type":"uint256"}],"internalType":"struct IBribeInitiative.ClaimData[]","name":"_claimData","type":"tuple[]"}],"name":"claimBribes","outputs":[{"internalType":"uint256","name":"boldAmount","type":"uint256"},{"internalType":"uint256","name":"bribeTokenAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedBribeAtEpoch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_boldAmount","type":"uint256"},{"internalType":"uint256","name":"_bribeTokenAmount","type":"uint256"},{"internalType":"uint256","name":"_epoch","type":"uint256"}],"name":"depositBribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getMostRecentTotalEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getMostRecentUserEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"contract IGovernance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_epoch","type":"uint256"}],"name":"lqtyAllocatedByUserAtEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currentEpoch","type":"uint256"},{"internalType":"address","name":"_user","type":"address"},{"components":[{"internalType":"uint256","name":"unallocatedLQTY","type":"uint256"},{"internalType":"uint256","name":"unallocatedOffset","type":"uint256"},{"internalType":"uint256","name":"allocatedLQTY","type":"uint256"},{"internalType":"uint256","name":"allocatedOffset","type":"uint256"}],"internalType":"struct IGovernance.UserState","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"voteLQTY","type":"uint256"},{"internalType":"uint256","name":"voteOffset","type":"uint256"},{"internalType":"uint256","name":"vetoLQTY","type":"uint256"},{"internalType":"uint256","name":"vetoOffset","type":"uint256"},{"internalType":"uint256","name":"atEpoch","type":"uint256"}],"internalType":"struct IGovernance.Allocation","name":"_allocation","type":"tuple"},{"components":[{"internalType":"uint256","name":"voteLQTY","type":"uint256"},{"internalType":"uint256","name":"voteOffset","type":"uint256"},{"internalType":"uint256","name":"vetoLQTY","type":"uint256"},{"internalType":"uint256","name":"vetoOffset","type":"uint256"},{"internalType":"uint256","name":"lastEpochClaim","type":"uint256"}],"internalType":"struct IGovernance.InitiativeState","name":"_initiativeState","type":"tuple"}],"name":"onAfterAllocateLQTY","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"onClaimForInitiative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"onRegisterInitiative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"onUnregisterInitiative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingBudget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousQuest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"process","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pullBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"questBoard","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"questSettings","outputs":[{"components":[{"internalType":"uint256","name":"minRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"enum IQuestBoard.QuestVoteType","name":"voteType","type":"uint8"},{"internalType":"enum IQuestBoard.QuestCloseType","name":"closeType","type":"uint8"}],"internalType":"struct QuestInitiative.QuestSettings","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"questVoterList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epoch","type":"uint256"}],"name":"totalLQTYAllocatedByEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"_maxRewardPerVote","type":"uint256"}],"name":"updateQuestRewardPerVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"_maxRewardPerVote","type":"uint256"},{"internalType":"enum IQuestBoard.QuestVoteType","name":"_voteType","type":"uint8"},{"internalType":"enum IQuestBoard.QuestCloseType","name":"_closeType","type":"uint8"},{"internalType":"address[]","name":"_voterList","type":"address[]"}],"name":"updateQuestSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IQuestBoard.QuestVoteType","name":"_voteType","type":"uint8"},{"internalType":"enum IQuestBoard.QuestCloseType","name":"_closeType","type":"uint8"},{"internalType":"address[]","name":"_voterList","type":"address[]"}],"name":"updateQuestTypeSettings","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61012060405234801562000011575f80fd5b506040516200368f3803806200368f83398101604081905262000034916200029a565b33858585816001600160a01b0316816001600160a01b031603620000b35760405162461bcd60e51b815260206004820152602b60248201527f4272696265496e69746961746976653a2062726962652d746f6b656e2d63616e60448201526a1b9bdd0b58994b589bdb1960aa1b60648201526084015b60405180910390fd5b6001600160a01b0380841660c081905283821660e05290821661010052604080516346d62a6360e01b815290516346d62a63916004808201926020929091908290030181865afa1580156200010a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000130919062000306565b6080818152505060c0516001600160a01b031663a70b9f0c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000176573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200019c919062000306565b60a0525050506001600160a01b038116620001cd57604051631e4fbdf760e01b81525f6004820152602401620000aa565b620001d8816200020f565b50600680546001600160a01b039384166001600160a01b03199182161790915560098054929093169116179055506200031e915050565b600580546001600160a01b03191690556200022a816200022d565b50565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b80516001600160a01b038116811462000295575f80fd5b919050565b5f805f805f60a08688031215620002af575f80fd5b620002ba866200027e565b9450620002ca602087016200027e565b9350620002da604087016200027e565b9250620002ea606087016200027e565b9150620002fa608087016200027e565b90509295509295909350565b5f6020828403121562000317575f80fd5b5051919050565b60805160a05160c05160e051610100516132d1620003be5f395f818161032c01528181610ad20152610e4101525f81816103ed01528181610a9001528181610dfa01528181611fe5015281816120750152818161246901526125b401525f8181610353015281816105f6015281816107ee015281816108ca01528181610f180152818161126b015261133a01525f61184e01525f61187901526132d15ff3fe608060405234801561000f575f80fd5b5060043610610201575f3560e01c806379ba509711610123578063c1932ea4116100b8578063e30c397811610088578063e89946e21161006e578063e89946e214610544578063f0f2698d1461058e578063f2fde38b14610596575f80fd5b8063e30c397814610513578063e6fc378614610531575f80fd5b8063c1932ea4146104b9578063c297fa0f146104cc578063c33fb877146104eb578063c9ea8f27146104f3575f80fd5b806392a55aef116100f357806392a55aef14610484578063955161cd1461028a578063bb2fe6461461049b578063bf5b0ad5146104a4575f80fd5b806379ba50971461040f5780637c1f36271461041757806381c4fea5146104535780638da5cb5b14610466575f80fd5b806358c93f78116101995780636012c588116101695780636012c5881461039057806363efdf4a146103a3578063715018a6146103e0578063727d0f35146103e8575f80fd5b806358c93f78146103275780635aa6e6751461034e5780635bab17b1146103755780635ed9ede214610388575f80fd5b80632695d74d116101d45780632695d74d1461028a5780632ddac0171461029d5780633c815549146102cb57806344d39c1b14610314575f80fd5b80630135d5331461020557806313122798146102425780631e18de1a146102625780631e41a0f814610277575b5f80fd5b610218610213366004612b09565b6105a9565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6006546102189073ffffffffffffffffffffffffffffffffffffffff1681565b610275610270366004612b20565b6105de565b005b610275610285366004612c86565b610686565b610275610298366004612b09565b6107d6565b600a54600b54600c546102bb92919060ff8082169161010090041684565b6040516102399493929190612d46565b6102f96102d9366004612b09565b5f6020819052908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610239565b610275610322366004612b20565b610878565b6102187f000000000000000000000000000000000000000000000000000000000000000081565b6102187f000000000000000000000000000000000000000000000000000000000000000081565b610275610383366004612d7b565b6108c7565b610275610b00565b61027561039e366004612da4565b610b0a565b6103d06103b1366004612e15565b600160209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610239565b610275610cd8565b6102187f000000000000000000000000000000000000000000000000000000000000000081565b610275610ce9565b61043e610425366004612b09565b5f90815260026020526040902080546001909101549091565b60408051928352602083019190915201610239565b61043e610461366004612e3d565b610d5d565b60045473ffffffffffffffffffffffffffffffffffffffff16610218565b61048d60075481565b604051908152602001610239565b61048d60085481565b6104ac610e6f565b6040516102399190612eac565b6102756104c7366004612f03565b610f00565b6104d4600281565b60405165ffffffffffff9091168152602001610239565b61027561102e565b6009546102189073ffffffffffffffffffffffffffffffffffffffff1681565b60055473ffffffffffffffffffffffffffffffffffffffff16610218565b61048d61053f366004612f8a565b61103e565b61043e610552366004612e15565b73ffffffffffffffffffffffffffffffffffffffff919091165f9081526003602090815260408083209383529290522080546001909101549091565b61048d61107b565b6102756105a4366004612f8a565b6110af565b600d81815481106105b8575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e6465720060448201526064015b60405180910390fd5b5050565b61068e61115f565b600c80548491907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156106cb576106cb612ce4565b0217905550600c80548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600281111561070e5761070e612ce4565b021790555061071e600d5f612aa2565b80515f5b818110156107a757600d83828151811061073e5761073e612fa3565b6020908102919091018101518254600180820185555f9485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610722565b506040517f7c98a0e54e3d959a008c6978e0f8492849c33c7075f4b35e00ef60c0088c3707905f90a150505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610875576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e646572006044820152606401610679565b50565b61088061115f565b600a829055600b81905560408051838152602081018390527f41e8d332520308cb3ae775505e40854c4d5d7ebbed7d0d337166ca60bf7e4db4910160405180910390a15050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610931573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109559190612fd0565b9050808210156109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696265496e69746961746976653a206e6f772d6f722d6675747572652d6560448201527f706f6368730000000000000000000000000000000000000000000000000000006064820152608401610679565b5f8281526020819052604081208054869290610a04908490613014565b90915550505f8281526020819052604081206001018054859290610a29908490613014565b90915550506040805133815260208101869052908101849052606081018390527f8da751404c1c12bd225230d318ca0913aab7a5f98c004ae97cf1b7072e7f119d9060800160405180910390a1610ab873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330876111b2565b610afa73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330866111b2565b50505050565b610b0861123b565b565b610b1261115f565b6040518060800160405280868152602001858152602001846002811115610b3b57610b3b612ce4565b8152602001836002811115610b5257610b52612ce4565b90528051600a9081556020820151600b556040820151600c80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610ba257610ba2612ce4565b021790555060608201518160020160016101000a81548160ff02191690836002811115610bd157610bd1612ce4565b0217905550610be59150600d90505f612aa2565b80515f5b81811015610c6e57600d838281518110610c0557610c05612fa3565b6020908102919091018101518254600180820185555f9485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610be9565b506040517f7c98a0e54e3d959a008c6978e0f8492849c33c7075f4b35e00ef60c0088c3707905f90a160408051878152602081018790527f41e8d332520308cb3ae775505e40854c4d5d7ebbed7d0d337166ca60bf7e4db4910160405180910390a1505050505050565b610ce061115f565b610b085f611305565b600554339073ffffffffffffffffffffffffffffffffffffffff168114610d54576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610679565b61087581611305565b5f805f5b83811015610dd9575f858583818110610d7c57610d7c612fa3565b905060600201803603810190610d929190613027565b90505f80610dad33845f015185602001518660400151611336565b9092509050610dbc8287613014565b9550610dc88186613014565b94505060019092019150610d619050565b508115610e2157610e2173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163384611a69565b8015610e6857610e6873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611a69565b9250929050565b610e77612abd565b60408051608081018252600a80548252600b546020830152600c54919290919083019060ff166002811115610eae57610eae612ce4565b6002811115610ebf57610ebf612ce4565b81526020016002820160019054906101000a900460ff166002811115610ee757610ee7612ce4565b6002811115610ef857610ef8612ce4565b905250919050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e646572006044820152606401610679565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260036020908152604080832083805282529091206002908101549082527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d54909161101090889085359086013582851415611aac565b61102586888635602088013586831415611b23565b50505050505050565b61103661123b565b610b08611bff565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260036020908152604080832083805290915281206002015481905b9392505050565b5f80805260026020527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d5481905b92915050565b6110b761115f565b6005805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915561111a60045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b08576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610679565b60405173ffffffffffffffffffffffffffffffffffffffff8481166024830152838116604483015260648201839052610afa9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612126565b6040517fc20fb59e0000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063c20fb59e906024016020604051808303815f875af11580156112c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ea9190612fd0565b90508060075f8282546112fd9190613014565b909155505050565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610875816121ba565b5f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113c59190612fd0565b8510611453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4272696265496e69746961746976653a2063616e6e6f742d636c61696d2d666f60448201527f722d63757272656e742d65706f636800000000000000000000000000000000006064820152608401610679565b73ffffffffffffffffffffffffffffffffffffffff86165f90815260016020908152604080832088845290915290205460ff16156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4272696265496e69746961746976653a20616c72656164792d636c61696d65646044820152606401610679565b5f858152602081815260409182902082516060810184528154808252600183015493820193909352600290910154928101929092521515806115325750602081015115155b611598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4272696265496e69746961746976653a206e6f2d6272696265000000000000006044820152606401610679565b73ffffffffffffffffffffffffffffffffffffffff87165f9081526003602052604081206115c69087612230565b90508686111580156115e7575086816060015111806115e757506060810151155b611673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4272696265496e69746961746976653a20696e76616c69642d707265762d6c7160448201527f74792d616c6c6f636174696f6e2d65706f6368000000000000000000000000006064820152608401610679565b5f61167f600287612230565b90508786111580156116a0575087816060015111806116a057506060810151155b61172c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4272696265496e69746961746976653a20696e76616c69642d707265762d746f60448201527f74616c2d6c7174792d616c6c6f636174696f6e2d65706f6368000000000000006064820152608401610679565b80516117ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4272696265496e69746961746976653a20746f74616c2d6c7174792d616c6c6f60448201527f636174696f6e2d7a65726f0000000000000000000000000000000000000000006064820152608401610679565b8151611848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696265496e69746961746976653a206c7174792d616c6c6f636174696f6e60448201527f2d7a65726f0000000000000000000000000000000000000000000000000000006064820152608401610679565b5f6118737f00000000000000000000000000000000000000000000000000000000000000008a613081565b61189d907f0000000000000000000000000000000000000000000000000000000000000000613014565b90505f6118b2835f0151838560200151612297565b90505f6118c7855f0151848760200151612297565b90505f8660400151836118da9190613098565b90508082885f01516118ec9190613081565b6118f691906130ab565b9850808288602001516119099190613081565b61191391906130ab565b975088875f018181516119269190613098565b90525060208701805189919061193d908390613098565b905250604087018051839190611954908390613014565b91508181525050865f808e81526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506001805f8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8e81526020019081526020015f205f6101000a81548160ff0219169083151502179055507f520304589c9512f04f4c28f0a5f365d2620fea83386850175628ebfe3d52b6838d8d8b8b604051611a51949392919073ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092526040830152606082015260800190565b60405180910390a15050505050505094509492505050565b60405173ffffffffffffffffffffffffffffffffffffffff838116602483015260448201839052611aa791859182169063a9059cbb906064016111f4565b505050565b8015611ac557611ac060028585855f6122c5565b611adc565b5f8481526002602052604090208381556001018290555b60408051858152602081018590529081018390527ff3585f583ce8a74a5f014115d0a23ad6246464e971fe5701465b9976dc9c5bcd9060600160405180910390a150505050565b8015611b615773ffffffffffffffffffffffffffffffffffffffff85165f908152600360205260408120611b5c918690869086906122c5565b611b9a565b73ffffffffffffffffffffffffffffffffffffffff85165f90815260036020908152604080832087845290915290208381556001018290555b6040805173ffffffffffffffffffffffffffffffffffffffff8716815260208101869052908101849052606081018390527f3cf1dea48fd0f5e4db76fa66b9f662a7a8e3c185f34763189efc609691e327529060800160405180910390a15050505050565b60408051608081018252600a80548252600b546020830152600c545f9383019060ff166002811115611c3357611c33612ce4565b6002811115611c4457611c44612ce4565b81526020016002820160019054906101000a900460ff166002811115611c6c57611c6c612ce4565b6002811115611c7d57611c7d612ce4565b90525060085490915015611e1b576006546008546040517ff29e9aa700000000000000000000000000000000000000000000000000000000815260048101919091525f9173ffffffffffffffffffffffffffffffffffffffff169063f29e9aa7906024015f60405180830381865afa158015611cfb573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611d4091908101906130e3565b90505f8160018351611d529190613098565b81518110611d6257611d62612fa3565b602002602001015165ffffffffffff1690508060065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663086146d26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ddf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e039190612fd0565b11611e0d57505050565b611e1860085461239b565b50505b6006546040517f77dd7cf70000000000000000000000000000000000000000000000000000000081523060048201525f9173ffffffffffffffffffffffffffffffffffffffff16906377dd7cf790602401602060405180830381865afa158015611e87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eab9190612fd0565b9050805f03611f455760065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357ae1cec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f429190612fd0565b90505b5f611f5282612710613014565b612710600754611f629190613081565b611f6c91906130ab565b90505f612710611f7c8484613081565b611f8691906130ab565b9050611f928183613014565b60075f828254611fa29190613098565b909155505060065461200c9073ffffffffffffffffffffffffffffffffffffffff16611fce8385613014565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190612645565b6006546009548551602087015160408089015160608a015191517f29b6a4300000000000000000000000000000000000000000000000000000000081525f9673ffffffffffffffffffffffffffffffffffffffff908116966329b6a430966120ad9692909116947f0000000000000000000000000000000000000000000000000000000000000000948a94600294928e928e92909190600d90600401613182565b6020604051808303815f875af11580156120c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ed9190612fd0565b600881905560405190915081907ff2376f43586d93a15b606c89747962a511dee47a8afacda035909ddd4460b108905f90a25050505050565b5f61214773ffffffffffffffffffffffffffffffffffffffff8416836126f2565b905080515f1415801561216b5750808060200190518101906121699190613250565b155b15611aa7576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610679565b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b61225760405180608001604052805f81526020015f81526020015f81526020015f81525090565b505f908152602091825260409081902081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290565b5f806122a38486613081565b90508281116122b2575f6122bc565b6122bc8382613098565b95945050505050565b6122cf85856126ff565b15612306576040517f3c57789e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801580159061231c575061231a85826126ff565b155b15612353576040517fac9c4cae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f818152602095909552604080862060029081018054808952838920600390810189905591889055968852919096209586019490945592840192909255825560019190910155565b6006546040517f146bdb7d000000000000000000000000000000000000000000000000000000008152600481018390525f9173ffffffffffffffffffffffffffffffffffffffff169063146bdb7d90602401602060405180830381865afa158015612408573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242c9190612fd0565b9050805f03612439575050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156124c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124e79190612fd0565b6006546040517f8f4c72d80000000000000000000000000000000000000000000000000000000081526004810186905230602482015291925073ffffffffffffffffffffffffffffffffffffffff1690638f4c72d8906044015f604051808303815f87803b158015612557575f80fd5b505af1158015612569573d5f803e3d5ffd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f925083915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156125f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261d9190612fd0565b6126279190613098565b90508060075f82825461263a9190613014565b909155505050505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156126b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126dc9190612fd0565b9050610afa84846126ed8585613014565b612784565b606061107483835f61285b565b5f815f03612739576040517fee7efd5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8281526020849052604090206002015415158061276657505f8281526020849052604090206003015415155b806110745750505f8080526020929092526040909120600301541490565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052612810848261291a565b610afa5760405173ffffffffffffffffffffffffffffffffffffffff84811660248301525f604483015261285191869182169063095ea7b3906064016111f4565b610afa8482612126565b606081471015612899576040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152602401610679565b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516128c1919061326f565b5f6040518083038185875af1925050503d805f81146128fb576040519150601f19603f3d011682016040523d82523d5f602084013e612900565b606091505b50915091506129108683836129d1565b9695505050505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1684604051612942919061326f565b5f604051808303815f865af19150503d805f811461297b576040519150601f19603f3d011682016040523d82523d5f602084013e612980565b606091505b50915091508180156129aa5750805115806129aa5750808060200190518101906129aa9190613250565b80156122bc57505050505073ffffffffffffffffffffffffffffffffffffffff163b151590565b6060826129e6576129e182612a60565b611074565b8151158015612a0a575073ffffffffffffffffffffffffffffffffffffffff84163b155b15612a59576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610679565b5080611074565b805115612a705780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f8255905f5260205f20908101906108759190612af1565b60405180608001604052805f81526020015f81526020015f6002811115612ae657612ae6612ce4565b81526020015f905290565b5b80821115612b05575f8155600101612af2565b5090565b5f60208284031215612b19575f80fd5b5035919050565b5f8060408385031215612b31575f80fd5b50508035926020909101359150565b60038110610875575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612bc057612bc0612b4c565b604052919050565b5f67ffffffffffffffff821115612be157612be1612b4c565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114612c0e575f80fd5b919050565b5f82601f830112612c22575f80fd5b81356020612c37612c3283612bc8565b612b79565b8083825260208201915060208460051b870101935086841115612c58575f80fd5b602086015b84811015612c7b57612c6e81612beb565b8352918301918301612c5d565b509695505050505050565b5f805f60608486031215612c98575f80fd5b8335612ca381612b40565b92506020840135612cb381612b40565b9150604084013567ffffffffffffffff811115612cce575f80fd5b612cda86828701612c13565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110610875577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8481526020810184905260808101612d5d84612d11565b836040830152612d6c83612d11565b82606083015295945050505050565b5f805f60608486031215612d8d575f80fd5b505081359360208301359350604090920135919050565b5f805f805f60a08688031215612db8575f80fd5b85359450602086013593506040860135612dd181612b40565b92506060860135612de181612b40565b9150608086013567ffffffffffffffff811115612dfc575f80fd5b612e0888828901612c13565b9150509295509295909350565b5f8060408385031215612e26575f80fd5b612e2f83612beb565b946020939093013593505050565b5f8060208385031215612e4e575f80fd5b823567ffffffffffffffff80821115612e65575f80fd5b818501915085601f830112612e78575f80fd5b813581811115612e86575f80fd5b866020606083028501011115612e9a575f80fd5b60209290920196919550909350505050565b815181526020808301519082015260408201516080820190612ecd81612d11565b60408301526060830151612ee081612d11565b8060608401525092915050565b5f60a08284031215612efd575f80fd5b50919050565b5f805f805f858703610200811215612f19575f80fd5b86359550612f2960208801612beb565b945060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215612f5a575f80fd5b50604086019250612f6e8760c08801612eed565b9150612f7e876101608801612eed565b90509295509295909350565b5f60208284031215612f9a575f80fd5b61107482612beb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612fe0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156110a9576110a9612fe7565b5f60608284031215613037575f80fd5b6040516060810181811067ffffffffffffffff8211171561305a5761305a612b4c565b80604052508235815260208301356020820152604083013560408201528091505092915050565b80820281158282048414176110a9576110a9612fe7565b818103818111156110a9576110a9612fe7565b5f826130de577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f60208083850312156130f4575f80fd5b825167ffffffffffffffff81111561310a575f80fd5b8301601f8101851361311a575f80fd5b8051613128612c3282612bc8565b81815260059190911b82018301908381019087831115613146575f80fd5b928401925b8284101561317757835165ffffffffffff81168114613168575f80fd5b8252928401929084019061314b565b979650505050505050565b5f610160820173ffffffffffffffffffffffffffffffffffffffff808f168452808e1660208501528c1515604085015265ffffffffffff8c1660608501528a60808501528960a08501528860c08501528760e08501526131e187612d11565b866101008501526131f186612d11565b61012084018690526101606101408501528454918290525f85815260208120926101808601915b818110156132385784548416835260019485019460209093019201613218565b50508093505050509c9b505050505050505050505050565b5f60208284031215613260575f80fd5b81518015158114611074575f80fd5b5f82515f5b8181101561328e5760208186018101518583015201613274565b505f92019182525091905056fea26469706673582212201e6eeadc28b747cb8dc5800409798a8d5bce413b21d1225e9a8b6bec2376a3c064736f6c63430008180033000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee10000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef000000000000000000000000feb352930ca196a80b708cdd5dcb4eca94805dab0000000000000000000000005a099e2c2a41a5a0ad99e4971c711400eeef34db
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610201575f3560e01c806379ba509711610123578063c1932ea4116100b8578063e30c397811610088578063e89946e21161006e578063e89946e214610544578063f0f2698d1461058e578063f2fde38b14610596575f80fd5b8063e30c397814610513578063e6fc378614610531575f80fd5b8063c1932ea4146104b9578063c297fa0f146104cc578063c33fb877146104eb578063c9ea8f27146104f3575f80fd5b806392a55aef116100f357806392a55aef14610484578063955161cd1461028a578063bb2fe6461461049b578063bf5b0ad5146104a4575f80fd5b806379ba50971461040f5780637c1f36271461041757806381c4fea5146104535780638da5cb5b14610466575f80fd5b806358c93f78116101995780636012c588116101695780636012c5881461039057806363efdf4a146103a3578063715018a6146103e0578063727d0f35146103e8575f80fd5b806358c93f78146103275780635aa6e6751461034e5780635bab17b1146103755780635ed9ede214610388575f80fd5b80632695d74d116101d45780632695d74d1461028a5780632ddac0171461029d5780633c815549146102cb57806344d39c1b14610314575f80fd5b80630135d5331461020557806313122798146102425780631e18de1a146102625780631e41a0f814610277575b5f80fd5b610218610213366004612b09565b6105a9565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6006546102189073ffffffffffffffffffffffffffffffffffffffff1681565b610275610270366004612b20565b6105de565b005b610275610285366004612c86565b610686565b610275610298366004612b09565b6107d6565b600a54600b54600c546102bb92919060ff8082169161010090041684565b6040516102399493929190612d46565b6102f96102d9366004612b09565b5f6020819052908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610239565b610275610322366004612b20565b610878565b6102187f0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef81565b6102187f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee181565b610275610383366004612d7b565b6108c7565b610275610b00565b61027561039e366004612da4565b610b0a565b6103d06103b1366004612e15565b600160209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610239565b610275610cd8565b6102187f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d81565b610275610ce9565b61043e610425366004612b09565b5f90815260026020526040902080546001909101549091565b60408051928352602083019190915201610239565b61043e610461366004612e3d565b610d5d565b60045473ffffffffffffffffffffffffffffffffffffffff16610218565b61048d60075481565b604051908152602001610239565b61048d60085481565b6104ac610e6f565b6040516102399190612eac565b6102756104c7366004612f03565b610f00565b6104d4600281565b60405165ffffffffffff9091168152602001610239565b61027561102e565b6009546102189073ffffffffffffffffffffffffffffffffffffffff1681565b60055473ffffffffffffffffffffffffffffffffffffffff16610218565b61048d61053f366004612f8a565b61103e565b61043e610552366004612e15565b73ffffffffffffffffffffffffffffffffffffffff919091165f9081526003602090815260408083209383529290522080546001909101549091565b61048d61107b565b6102756105a4366004612f8a565b6110af565b600d81815481106105b8575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee11614610682576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e6465720060448201526064015b60405180910390fd5b5050565b61068e61115f565b600c80548491907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360028111156106cb576106cb612ce4565b0217905550600c80548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600281111561070e5761070e612ce4565b021790555061071e600d5f612aa2565b80515f5b818110156107a757600d83828151811061073e5761073e612fa3565b6020908102919091018101518254600180820185555f9485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610722565b506040517f7c98a0e54e3d959a008c6978e0f8492849c33c7075f4b35e00ef60c0088c3707905f90a150505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee11614610875576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e646572006044820152606401610679565b50565b61088061115f565b600a829055600b81905560408051838152602081018390527f41e8d332520308cb3ae775505e40854c4d5d7ebbed7d0d337166ca60bf7e4db4910160405180910390a15050565b5f7f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee173ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610931573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109559190612fd0565b9050808210156109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696265496e69746961746976653a206e6f772d6f722d6675747572652d6560448201527f706f6368730000000000000000000000000000000000000000000000000000006064820152608401610679565b5f8281526020819052604081208054869290610a04908490613014565b90915550505f8281526020819052604081206001018054859290610a29908490613014565b90915550506040805133815260208101869052908101849052606081018390527f8da751404c1c12bd225230d318ca0913aab7a5f98c004ae97cf1b7072e7f119d9060800160405180910390a1610ab873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d163330876111b2565b610afa73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef163330866111b2565b50505050565b610b0861123b565b565b610b1261115f565b6040518060800160405280868152602001858152602001846002811115610b3b57610b3b612ce4565b8152602001836002811115610b5257610b52612ce4565b90528051600a9081556020820151600b556040820151600c80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610ba257610ba2612ce4565b021790555060608201518160020160016101000a81548160ff02191690836002811115610bd157610bd1612ce4565b0217905550610be59150600d90505f612aa2565b80515f5b81811015610c6e57600d838281518110610c0557610c05612fa3565b6020908102919091018101518254600180820185555f9485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610be9565b506040517f7c98a0e54e3d959a008c6978e0f8492849c33c7075f4b35e00ef60c0088c3707905f90a160408051878152602081018790527f41e8d332520308cb3ae775505e40854c4d5d7ebbed7d0d337166ca60bf7e4db4910160405180910390a1505050505050565b610ce061115f565b610b085f611305565b600554339073ffffffffffffffffffffffffffffffffffffffff168114610d54576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610679565b61087581611305565b5f805f5b83811015610dd9575f858583818110610d7c57610d7c612fa3565b905060600201803603810190610d929190613027565b90505f80610dad33845f015185602001518660400151611336565b9092509050610dbc8287613014565b9550610dc88186613014565b94505060019092019150610d619050565b508115610e2157610e2173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d163384611a69565b8015610e6857610e6873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef163383611a69565b9250929050565b610e77612abd565b60408051608081018252600a80548252600b546020830152600c54919290919083019060ff166002811115610eae57610eae612ce4565b6002811115610ebf57610ebf612ce4565b81526020016002820160019054906101000a900460ff166002811115610ee757610ee7612ce4565b6002811115610ef857610ef8612ce4565b905250919050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee11614610f9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696265496e69746961746976653a20696e76616c69642d73656e646572006044820152606401610679565b73ffffffffffffffffffffffffffffffffffffffff84165f90815260036020908152604080832083805282529091206002908101549082527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d54909161101090889085359086013582851415611aac565b61102586888635602088013586831415611b23565b50505050505050565b61103661123b565b610b08611bff565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260036020908152604080832083805290915281206002015481905b9392505050565b5f80805260026020527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077d5481905b92915050565b6110b761115f565b6005805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915561111a60045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b08576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610679565b60405173ffffffffffffffffffffffffffffffffffffffff8481166024830152838116604483015260648201839052610afa9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612126565b6040517fc20fb59e0000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee173ffffffffffffffffffffffffffffffffffffffff169063c20fb59e906024016020604051808303815f875af11580156112c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ea9190612fd0565b90508060075f8282546112fd9190613014565b909155505050565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610875816121ba565b5f807f000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee173ffffffffffffffffffffffffffffffffffffffff1663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113c59190612fd0565b8510611453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4272696265496e69746961746976653a2063616e6e6f742d636c61696d2d666f60448201527f722d63757272656e742d65706f636800000000000000000000000000000000006064820152608401610679565b73ffffffffffffffffffffffffffffffffffffffff86165f90815260016020908152604080832088845290915290205460ff16156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4272696265496e69746961746976653a20616c72656164792d636c61696d65646044820152606401610679565b5f858152602081815260409182902082516060810184528154808252600183015493820193909352600290910154928101929092521515806115325750602081015115155b611598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4272696265496e69746961746976653a206e6f2d6272696265000000000000006044820152606401610679565b73ffffffffffffffffffffffffffffffffffffffff87165f9081526003602052604081206115c69087612230565b90508686111580156115e7575086816060015111806115e757506060810151155b611673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4272696265496e69746961746976653a20696e76616c69642d707265762d6c7160448201527f74792d616c6c6f636174696f6e2d65706f6368000000000000000000000000006064820152608401610679565b5f61167f600287612230565b90508786111580156116a0575087816060015111806116a057506060810151155b61172c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4272696265496e69746961746976653a20696e76616c69642d707265762d746f60448201527f74616c2d6c7174792d616c6c6f636174696f6e2d65706f6368000000000000006064820152608401610679565b80516117ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4272696265496e69746961746976653a20746f74616c2d6c7174792d616c6c6f60448201527f636174696f6e2d7a65726f0000000000000000000000000000000000000000006064820152608401610679565b8151611848576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696265496e69746961746976653a206c7174792d616c6c6f636174696f6e60448201527f2d7a65726f0000000000000000000000000000000000000000000000000000006064820152608401610679565b5f6118737f0000000000000000000000000000000000000000000000000000000000093a808a613081565b61189d907f00000000000000000000000000000000000000000000000000000000681bf400613014565b90505f6118b2835f0151838560200151612297565b90505f6118c7855f0151848760200151612297565b90505f8660400151836118da9190613098565b90508082885f01516118ec9190613081565b6118f691906130ab565b9850808288602001516119099190613081565b61191391906130ab565b975088875f018181516119269190613098565b90525060208701805189919061193d908390613098565b905250604087018051839190611954908390613014565b91508181525050865f808e81526020019081526020015f205f820151815f015560208201518160010155604082015181600201559050506001805f8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8e81526020019081526020015f205f6101000a81548160ff0219169083151502179055507f520304589c9512f04f4c28f0a5f365d2620fea83386850175628ebfe3d52b6838d8d8b8b604051611a51949392919073ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092526040830152606082015260800190565b60405180910390a15050505050505094509492505050565b60405173ffffffffffffffffffffffffffffffffffffffff838116602483015260448201839052611aa791859182169063a9059cbb906064016111f4565b505050565b8015611ac557611ac060028585855f6122c5565b611adc565b5f8481526002602052604090208381556001018290555b60408051858152602081018590529081018390527ff3585f583ce8a74a5f014115d0a23ad6246464e971fe5701465b9976dc9c5bcd9060600160405180910390a150505050565b8015611b615773ffffffffffffffffffffffffffffffffffffffff85165f908152600360205260408120611b5c918690869086906122c5565b611b9a565b73ffffffffffffffffffffffffffffffffffffffff85165f90815260036020908152604080832087845290915290208381556001018290555b6040805173ffffffffffffffffffffffffffffffffffffffff8716815260208101869052908101849052606081018390527f3cf1dea48fd0f5e4db76fa66b9f662a7a8e3c185f34763189efc609691e327529060800160405180910390a15050505050565b60408051608081018252600a80548252600b546020830152600c545f9383019060ff166002811115611c3357611c33612ce4565b6002811115611c4457611c44612ce4565b81526020016002820160019054906101000a900460ff166002811115611c6c57611c6c612ce4565b6002811115611c7d57611c7d612ce4565b90525060085490915015611e1b576006546008546040517ff29e9aa700000000000000000000000000000000000000000000000000000000815260048101919091525f9173ffffffffffffffffffffffffffffffffffffffff169063f29e9aa7906024015f60405180830381865afa158015611cfb573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611d4091908101906130e3565b90505f8160018351611d529190613098565b81518110611d6257611d62612fa3565b602002602001015165ffffffffffff1690508060065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663086146d26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ddf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e039190612fd0565b11611e0d57505050565b611e1860085461239b565b50505b6006546040517f77dd7cf70000000000000000000000000000000000000000000000000000000081523060048201525f9173ffffffffffffffffffffffffffffffffffffffff16906377dd7cf790602401602060405180830381865afa158015611e87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eab9190612fd0565b9050805f03611f455760065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166357ae1cec6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f429190612fd0565b90505b5f611f5282612710613014565b612710600754611f629190613081565b611f6c91906130ab565b90505f612710611f7c8484613081565b611f8691906130ab565b9050611f928183613014565b60075f828254611fa29190613098565b909155505060065461200c9073ffffffffffffffffffffffffffffffffffffffff16611fce8385613014565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d169190612645565b6006546009548551602087015160408089015160608a015191517f29b6a4300000000000000000000000000000000000000000000000000000000081525f9673ffffffffffffffffffffffffffffffffffffffff908116966329b6a430966120ad9692909116947f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d948a94600294928e928e92909190600d90600401613182565b6020604051808303815f875af11580156120c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ed9190612fd0565b600881905560405190915081907ff2376f43586d93a15b606c89747962a511dee47a8afacda035909ddd4460b108905f90a25050505050565b5f61214773ffffffffffffffffffffffffffffffffffffffff8416836126f2565b905080515f1415801561216b5750808060200190518101906121699190613250565b155b15611aa7576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610679565b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b61225760405180608001604052805f81526020015f81526020015f81526020015f81525090565b505f908152602091825260409081902081516080810183528154815260018201549381019390935260028101549183019190915260030154606082015290565b5f806122a38486613081565b90508281116122b2575f6122bc565b6122bc8382613098565b95945050505050565b6122cf85856126ff565b15612306576040517f3c57789e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801580159061231c575061231a85826126ff565b155b15612353576040517fac9c4cae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f818152602095909552604080862060029081018054808952838920600390810189905591889055968852919096209586019490945592840192909255825560019190910155565b6006546040517f146bdb7d000000000000000000000000000000000000000000000000000000008152600481018390525f9173ffffffffffffffffffffffffffffffffffffffff169063146bdb7d90602401602060405180830381865afa158015612408573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242c9190612fd0565b9050805f03612439575050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d73ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156124c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124e79190612fd0565b6006546040517f8f4c72d80000000000000000000000000000000000000000000000000000000081526004810186905230602482015291925073ffffffffffffffffffffffffffffffffffffffff1690638f4c72d8906044015f604051808303815f87803b158015612557575f80fd5b505af1158015612569573d5f803e3d5ffd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f925083915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d16906370a0823190602401602060405180830381865afa1580156125f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261d9190612fd0565b6126279190613098565b90508060075f82825461263a9190613014565b909155505050505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919085169063dd62ed3e90604401602060405180830381865afa1580156126b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126dc9190612fd0565b9050610afa84846126ed8585613014565b612784565b606061107483835f61285b565b5f815f03612739576040517fee7efd5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8281526020849052604090206002015415158061276657505f8281526020849052604090206003015415155b806110745750505f8080526020929092526040909120600301541490565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052612810848261291a565b610afa5760405173ffffffffffffffffffffffffffffffffffffffff84811660248301525f604483015261285191869182169063095ea7b3906064016111f4565b610afa8482612126565b606081471015612899576040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152602401610679565b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516128c1919061326f565b5f6040518083038185875af1925050503d805f81146128fb576040519150601f19603f3d011682016040523d82523d5f602084013e612900565b606091505b50915091506129108683836129d1565b9695505050505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1684604051612942919061326f565b5f604051808303815f865af19150503d805f811461297b576040519150601f19603f3d011682016040523d82523d5f602084013e612980565b606091505b50915091508180156129aa5750805115806129aa5750808060200190518101906129aa9190613250565b80156122bc57505050505073ffffffffffffffffffffffffffffffffffffffff163b151590565b6060826129e6576129e182612a60565b611074565b8151158015612a0a575073ffffffffffffffffffffffffffffffffffffffff84163b155b15612a59576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610679565b5080611074565b805115612a705780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5080545f8255905f5260205f20908101906108759190612af1565b60405180608001604052805f81526020015f81526020015f6002811115612ae657612ae6612ce4565b81526020015f905290565b5b80821115612b05575f8155600101612af2565b5090565b5f60208284031215612b19575f80fd5b5035919050565b5f8060408385031215612b31575f80fd5b50508035926020909101359150565b60038110610875575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612bc057612bc0612b4c565b604052919050565b5f67ffffffffffffffff821115612be157612be1612b4c565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114612c0e575f80fd5b919050565b5f82601f830112612c22575f80fd5b81356020612c37612c3283612bc8565b612b79565b8083825260208201915060208460051b870101935086841115612c58575f80fd5b602086015b84811015612c7b57612c6e81612beb565b8352918301918301612c5d565b509695505050505050565b5f805f60608486031215612c98575f80fd5b8335612ca381612b40565b92506020840135612cb381612b40565b9150604084013567ffffffffffffffff811115612cce575f80fd5b612cda86828701612c13565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110610875577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b8481526020810184905260808101612d5d84612d11565b836040830152612d6c83612d11565b82606083015295945050505050565b5f805f60608486031215612d8d575f80fd5b505081359360208301359350604090920135919050565b5f805f805f60a08688031215612db8575f80fd5b85359450602086013593506040860135612dd181612b40565b92506060860135612de181612b40565b9150608086013567ffffffffffffffff811115612dfc575f80fd5b612e0888828901612c13565b9150509295509295909350565b5f8060408385031215612e26575f80fd5b612e2f83612beb565b946020939093013593505050565b5f8060208385031215612e4e575f80fd5b823567ffffffffffffffff80821115612e65575f80fd5b818501915085601f830112612e78575f80fd5b813581811115612e86575f80fd5b866020606083028501011115612e9a575f80fd5b60209290920196919550909350505050565b815181526020808301519082015260408201516080820190612ecd81612d11565b60408301526060830151612ee081612d11565b8060608401525092915050565b5f60a08284031215612efd575f80fd5b50919050565b5f805f805f858703610200811215612f19575f80fd5b86359550612f2960208801612beb565b945060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215612f5a575f80fd5b50604086019250612f6e8760c08801612eed565b9150612f7e876101608801612eed565b90509295509295909350565b5f60208284031215612f9a575f80fd5b61107482612beb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612fe0575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156110a9576110a9612fe7565b5f60608284031215613037575f80fd5b6040516060810181811067ffffffffffffffff8211171561305a5761305a612b4c565b80604052508235815260208301356020820152604083013560408201528091505092915050565b80820281158282048414176110a9576110a9612fe7565b818103818111156110a9576110a9612fe7565b5f826130de577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b5f60208083850312156130f4575f80fd5b825167ffffffffffffffff81111561310a575f80fd5b8301601f8101851361311a575f80fd5b8051613128612c3282612bc8565b81815260059190911b82018301908381019087831115613146575f80fd5b928401925b8284101561317757835165ffffffffffff81168114613168575f80fd5b8252928401929084019061314b565b979650505050505050565b5f610160820173ffffffffffffffffffffffffffffffffffffffff808f168452808e1660208501528c1515604085015265ffffffffffff8c1660608501528a60808501528960a08501528860c08501528760e08501526131e187612d11565b866101008501526131f186612d11565b61012084018690526101606101408501528454918290525f85815260208120926101808601915b818110156132385784548416835260019485019460209093019201613218565b50508093505050509c9b505050505050505050505050565b5f60208284031215613260575f80fd5b81518015158114611074575f80fd5b5f82515f5b8181101561328e5760208186018101518583015201613274565b505f92019182525091905056fea26469706673582212201e6eeadc28b747cb8dc5800409798a8d5bce413b21d1225e9a8b6bec2376a3c064736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee10000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef000000000000000000000000feb352930ca196a80b708cdd5dcb4eca94805dab0000000000000000000000005a099e2c2a41a5a0ad99e4971c711400eeef34db
-----Decoded View---------------
Arg [0] : _governance (address): 0x807DEf5E7d057DF05C796F4bc75C3Fe82Bd6EeE1
Arg [1] : _bold (address): 0x6440f144b7e50D6a8439336510312d2F54beB01D
Arg [2] : _bribeToken (address): 0x5DE8ab7E27f6E7A1fFf3E5B337584Aa43961BEeF
Arg [3] : _board (address): 0xfEb352930cA196a80B708CDD5dcb4eCA94805daB
Arg [4] : _gauge (address): 0x5a099E2C2a41A5A0aD99e4971c711400Eeef34db
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000807def5e7d057df05c796f4bc75c3fe82bd6eee1
Arg [1] : 0000000000000000000000006440f144b7e50d6a8439336510312d2f54beb01d
Arg [2] : 0000000000000000000000005de8ab7e27f6e7a1fff3e5b337584aa43961beef
Arg [3] : 000000000000000000000000feb352930ca196a80b708cdd5dcb4eca94805dab
Arg [4] : 0000000000000000000000005a099e2c2a41a5a0ad99e4971c711400eeef34db
Loading...
Loading
Loading...
Loading

Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.003543 | 2,778,054.8239 | $9,841.34 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.