编译器
0.8.13+commit.abaa5c0e
文件 1 的 12:IBribe.sol
pragma solidity 0.8.13;
interface IBribe {
function _deposit(uint amount, uint tokenId) external;
function _withdraw(uint amount, uint tokenId) external;
function getRewardForOwner(uint tokenId, address[] memory tokens) external;
function notifyRewardAmount(address token, uint amount) external;
function left(address token) external view returns (uint);
}
文件 2 的 12:IBribeFactory.sol
pragma solidity 0.8.13;
interface IBribeFactory {
function createExternalBribe(address[] memory) external returns (address);
}
文件 3 的 12:IERC20.sol
pragma solidity 0.8.13;
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint amount) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function balanceOf(address) external view returns (uint);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
文件 4 的 12:IGauge.sol
pragma solidity 0.8.13;
interface IGauge {
function notifyRewardAmount(address token, uint amount) external;
function getReward(address account, address[] memory tokens) external;
function left(address token) external view returns (uint);
function stake() external view returns (address);
}
文件 5 的 12:IGaugeFactory.sol
pragma solidity 0.8.13;
interface IGaugeFactory {
function createGauge(address, address, address, bool, address[] memory) external returns (address);
}
文件 6 的 12:IMinter.sol
pragma solidity 0.8.13;
interface IMinter {
function update_period() external returns (uint);
}
文件 7 的 12:IPair.sol
pragma solidity 0.8.13;
interface IPair {
function metadata() external view returns (uint dec0, uint dec1, uint r0, uint r1, bool st, address t0, address t1);
function tokens() external returns (address, address);
function token0() external returns (address);
function token1() external returns (address);
function externalBribe() external returns (address);
function transferFrom(address src, address dst, uint amount) external returns (bool);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function burn(address to) external returns (uint amount0, uint amount1);
function mint(address to) external returns (uint liquidity);
function getReserves() external view returns (uint _reserve0, uint _reserve1, uint _blockTimestampLast);
function getAmountOut(uint, address) external view returns (uint);
function setHasGauge(bool value) external;
function setExternalBribe(address _externalBribe) external;
function hasGauge() external view returns (bool);
function stable() external view returns (bool);
function prices(address tokenIn, uint amountIn, uint points) external view returns (uint[] memory);
}
文件 8 的 12:IPairFactory.sol
pragma solidity 0.8.13;
interface IPairFactory {
function allPairsLength() external view returns (uint);
function isPair(address pair) external view returns (bool);
function isPaused() external view returns (bool);
function pairCodeHash() external pure returns (bytes32);
function getFee(address pair) external view returns (uint256);
function getPair(address tokenA, address token, bool stable) external view returns (address);
function getInitializable() external view returns (address, address, bool);
function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);
function voter() external view returns (address);
function tank() external view returns (address);
}
文件 9 的 12:IVoter.sol
pragma solidity 0.8.13;
interface IVoter {
function _ve() external view returns (address);
function governor() external view returns (address);
function emergencyCouncil() external view returns (address);
function attachTokenToGauge(uint _tokenId, address account) external;
function detachTokenFromGauge(uint _tokenId, address account) external;
function emitDeposit(uint _tokenId, address account, uint amount) external;
function emitWithdraw(uint _tokenId, address account, uint amount) external;
function isWhitelisted(address token) external view returns (bool);
function notifyRewardAmount(uint amount) external;
function distribute(address _gauge) external;
function gauges(address) external view returns (address);
}
文件 10 的 12:IVotingEscrow.sol
pragma solidity 0.8.13;
interface IVotingEscrow {
struct Point {
int128 bias;
int128 slope;
uint256 ts;
uint256 blk;
}
function token() external view returns (address);
function team() external returns (address);
function epoch() external view returns (uint);
function point_history(uint loc) external view returns (Point memory);
function user_point_history(uint tokenId, uint loc) external view returns (Point memory);
function user_point_epoch(uint tokenId) external view returns (uint);
function ownerOf(uint) external view returns (address);
function isApprovedOrOwner(address, uint) external view returns (bool);
function transferFrom(address, address, uint) external;
function voting(uint tokenId) external;
function abstain(uint tokenId) external;
function attach(uint tokenId) external;
function detach(uint tokenId) external;
function checkpoint() external;
function deposit_for(uint tokenId, uint value) external;
function create_lock_for(uint, uint, address) external returns (uint);
function balanceOfNFT(uint) external view returns (uint);
function totalSupply() external view returns (uint);
}
文件 11 的 12:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 12 的 12:Voter.sol
pragma solidity 0.8.13;
import 'openzeppelin-contracts/contracts/utils/math/Math.sol';
import 'contracts/interfaces/IBribe.sol';
import 'contracts/interfaces/IBribeFactory.sol';
import 'contracts/interfaces/IGauge.sol';
import 'contracts/interfaces/IGaugeFactory.sol';
import 'contracts/interfaces/IERC20.sol';
import 'contracts/interfaces/IMinter.sol';
import 'contracts/interfaces/IPair.sol';
import 'contracts/interfaces/IPairFactory.sol';
import 'contracts/interfaces/IVoter.sol';
import 'contracts/interfaces/IVotingEscrow.sol';
contract Voter is IVoter {
address public immutable _ve;
address internal immutable base;
address[] public factories;
address[] public gaugeFactories;
address public bribefactory;
uint internal constant DURATION = 7 days;
address public minter;
address public governor;
address public emergencyCouncil;
uint public totalWeight;
address[] public pools;
address[] public killedGauges;
mapping(address => address) public gauges;
mapping(address => address) public poolForGauge;
mapping(address => address) public external_bribes;
mapping(address => uint256) public weights;
mapping(uint => mapping(address => uint256)) public votes;
mapping(uint => address[]) public poolVote;
mapping(uint => uint) public usedWeights;
mapping(uint => uint) public lastVoted;
mapping(address => bool) public isGauge;
mapping(address => bool) public isWhitelisted;
mapping(address => bool) public isAlive;
mapping(address => bool) public isFactory;
mapping(address => bool) public isGaugeFactory;
event GaugeCreated(address indexed gauge, address creator, address indexed external_bribe, address indexed pool);
event GaugeKilledTotally(address indexed gauge);
event GaugePaused(address indexed gauge);
event GaugeRestarted(address indexed gauge);
event Voted(address indexed voter, uint tokenId, uint256 weight);
event Abstained(uint tokenId, uint256 weight);
event Deposit(address indexed lp, address indexed gauge, uint tokenId, uint amount);
event Withdraw(address indexed lp, address indexed gauge, uint tokenId, uint amount);
event NotifyReward(address indexed sender, address indexed reward, uint amount);
event DistributeReward(address indexed sender, address indexed gauge, uint amount);
event Attach(address indexed owner, address indexed gauge, uint tokenId);
event Detach(address indexed owner, address indexed gauge, uint tokenId);
event Whitelisted(address indexed whitelister, address indexed token);
event Blacklisted(address indexed blacklister, address indexed token);
event BribeFactorySet(address indexed setter, address newBribeFatory);
event ExternalBribeSet(address indexed setter, address indexed gauge, address externalBribe);
event FactoryAdded(address indexed setter, address indexed pairFactory, address indexed gaugeFactory);
event FactoryReplaced(address indexed setter, address indexed pairFactory, address indexed gaugeFactory, uint256 pos);
event FactoryRemoved(address indexed setter, uint256 indexed pos);
constructor(address __ve, address _factory, address _gauges, address _bribes) {
_ve = __ve;
base = IVotingEscrow(__ve).token();
factories.push(_factory);
isFactory[_factory] = true;
gaugeFactories.push(_gauges);
isGaugeFactory[_gauges] = true;
bribefactory = _bribes;
minter = msg.sender;
governor = msg.sender;
emergencyCouncil = msg.sender;
}
uint internal _unlocked = 1;
modifier lock() {
require(_unlocked == 1);
_unlocked = 2;
_;
_unlocked = 1;
}
modifier onlyNewEpoch(uint _tokenId) {
require((block.timestamp / DURATION) * DURATION > lastVoted[_tokenId], "TOKEN_ALREADY_VOTED_THIS_EPOCH");
_;
}
modifier onlyEmergencyCouncil() {
require(msg.sender == emergencyCouncil, "not emergencyCouncil");
_;
}
function initialize(address[] memory _tokens, address _minter) external {
require(msg.sender == minter);
for (uint i = 0; i < _tokens.length; i++) {
_whitelist(_tokens[i]);
}
minter = _minter;
}
function setGovernor(address _governor) public {
require(msg.sender == governor);
governor = _governor;
}
function setEmergencyCouncil(address _council) public {
require(msg.sender == governor);
emergencyCouncil = _council;
}
function setBribeFactory(address _bribeFactory) external onlyEmergencyCouncil {
bribefactory = _bribeFactory;
emit BribeFactorySet(msg.sender, _bribeFactory);
}
function setExternalBribeFor(address _gauge, address _external) external onlyEmergencyCouncil {
require(isGauge[_gauge]);
_setExternalBribe(_gauge, _external);
}
function _setExternalBribe(address _gauge, address _external) private {
external_bribes[_gauge] = _external;
address pool = poolForGauge[_gauge];
try IPair(pool).setExternalBribe(_external){} catch {}
emit ExternalBribeSet(msg.sender, _gauge, _external);
}
function addFactory(address _pairFactory, address _gaugeFactory) external onlyEmergencyCouncil {
require(_pairFactory != address(0), 'addr 0');
require(_gaugeFactory != address(0), 'addr 0');
require(!isGaugeFactory[_gaugeFactory], 'g.fact true');
factories.push(_pairFactory);
gaugeFactories.push(_gaugeFactory);
isFactory[_pairFactory] = true;
isGaugeFactory[_gaugeFactory] = true;
emit FactoryAdded(msg.sender, _pairFactory, _gaugeFactory);
}
function replaceFactory(address _pairFactory, address _gaugeFactory, uint256 _pos) external onlyEmergencyCouncil {
require(_pairFactory != address(0), 'addr 0');
require(_gaugeFactory != address(0), 'addr 0');
require(_pos < factoryLength() && _pos < gaugeFactoriesLength(), '_pos out of range');
require(isFactory[_pairFactory], 'factory false');
require(isGaugeFactory[_gaugeFactory], 'g.fact false');
address oldPF = factories[_pos];
address oldGF = gaugeFactories[_pos];
isFactory[oldPF] = false;
isGaugeFactory[oldGF] = false;
factories[_pos] = (_pairFactory);
gaugeFactories[_pos] = (_gaugeFactory);
isFactory[_pairFactory] = true;
isGaugeFactory[_gaugeFactory] = true;
emit FactoryReplaced(msg.sender, _pairFactory, _gaugeFactory, _pos);
}
function removeFactory(uint256 _pos) external onlyEmergencyCouncil {
require(_pos < factoryLength() && _pos < gaugeFactoriesLength(), '_pos out of range');
address oldPF = factories[_pos];
address oldGF = gaugeFactories[_pos];
require(isFactory[oldPF], 'factory false');
require(isGaugeFactory[oldGF], 'g.fact false');
factories[_pos] = address(0);
gaugeFactories[_pos] = address(0);
isFactory[oldPF] = false;
isGaugeFactory[oldGF] = false;
emit FactoryRemoved(msg.sender, _pos);
}
function reset(uint _tokenId) external onlyNewEpoch(_tokenId) {
require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));
_reset(_tokenId);
IVotingEscrow(_ve).abstain(_tokenId);
}
function _reset(uint _tokenId) internal {
address[] storage _poolVote = poolVote[_tokenId];
uint _poolVoteCnt = _poolVote.length;
uint256 _totalWeight = 0;
for (uint i = 0; i < _poolVoteCnt; i ++) {
address _pool = _poolVote[i];
uint256 _votes = votes[_tokenId][_pool];
if (_votes != 0) {
_updateFor(gauges[_pool]);
weights[_pool] -= _votes;
votes[_tokenId][_pool] -= _votes;
if (_votes > 0) {
IBribe(external_bribes[gauges[_pool]])._withdraw(uint256(_votes), _tokenId);
_totalWeight += _votes;
} else {
_totalWeight -= _votes;
}
emit Abstained(_tokenId, _votes);
}
}
totalWeight -= uint256(_totalWeight);
usedWeights[_tokenId] = 0;
delete poolVote[_tokenId];
}
function poke(uint _tokenId) external onlyNewEpoch(_tokenId) {
require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) || msg.sender == governor);
lastVoted[_tokenId] = block.timestamp;
address[] memory _poolVote = poolVote[_tokenId];
uint _poolCnt = _poolVote.length;
uint256[] memory _weights = new uint256[](_poolCnt);
for (uint i = 0; i < _poolCnt; i ++) {
_weights[i] = votes[_tokenId][_poolVote[i]];
}
_vote(_tokenId, _poolVote, _weights);
}
function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal {
_reset(_tokenId);
uint _poolCnt = _poolVote.length;
uint256 _weight = IVotingEscrow(_ve).balanceOfNFT(_tokenId);
uint256 _totalVoteWeight = 0;
uint256 _totalWeight = 0;
uint256 _usedWeight = 0;
for (uint i = 0; i < _poolCnt; i++) {
_totalVoteWeight += _weights[i];
}
for (uint i = 0; i < _poolCnt; i++) {
address _pool = _poolVote[i];
address _gauge = gauges[_pool];
if (isGauge[_gauge]) {
require(isAlive[_gauge], "gauge already dead");
uint256 _poolWeight = _weights[i] * _weight / _totalVoteWeight;
require(votes[_tokenId][_pool] == 0);
require(_poolWeight != 0);
_updateFor(_gauge);
poolVote[_tokenId].push(_pool);
weights[_pool] += _poolWeight;
votes[_tokenId][_pool] += _poolWeight;
IBribe(external_bribes[_gauge])._deposit(uint256(_poolWeight), _tokenId);
_usedWeight += _poolWeight;
_totalWeight += _poolWeight;
emit Voted(msg.sender, _tokenId, _poolWeight);
}
}
if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);
totalWeight += uint256(_totalWeight);
usedWeights[_tokenId] = uint256(_usedWeight);
}
function vote(uint tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external onlyNewEpoch(tokenId) {
require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, tokenId));
require(_poolVote.length == _weights.length);
lastVoted[tokenId] = block.timestamp;
_vote(tokenId, _poolVote, _weights);
}
function whitelist(address _token) public {
require(msg.sender == governor);
_whitelist(_token);
}
function _whitelist(address _token) internal {
require(!isWhitelisted[_token]);
isWhitelisted[_token] = true;
emit Whitelisted(msg.sender, _token);
}
function blacklist(address _token) public {
require(msg.sender == governor);
_blacklist(_token);
}
function _blacklist(address _token) internal {
require(isWhitelisted[_token]);
isWhitelisted[_token] = false;
emit Blacklisted(msg.sender, _token);
}
function createGauge(address _pool, uint256 _gaugeType) external returns (address) {
require(_gaugeType < factories.length, "gaugetype big");
require(gauges[_pool] == address(0x0), "exists");
address[] memory allowedRewards = new address[](3);
address[] memory internalRewards = new address[](2);
address tokenA;
address tokenB;
address _factory = factories[_gaugeType];
address _gaugeFactory = gaugeFactories[_gaugeType];
require(_factory != address(0));
require(_gaugeFactory != address(0));
bool isPair = IPairFactory(_factory).isPair(_pool);
if (isPair) {
tokenA = IPair(_pool).token0();
tokenB = IPair(_pool).token1();
allowedRewards[0] = tokenA;
allowedRewards[1] = tokenB;
internalRewards[0] = tokenA;
internalRewards[1] = tokenB;
if (base != tokenA && base != tokenB) {
allowedRewards[2] = base;
}
}
if (msg.sender != governor && msg.sender != emergencyCouncil) {
require(isPair, "!_pool");
require(isWhitelisted[tokenA] && isWhitelisted[tokenB], "!whitelisted");
}
address _external_bribe = IPair(_pool).externalBribe();
if(_external_bribe == address(0)) {
_external_bribe = IBribeFactory(bribefactory).createExternalBribe(allowedRewards);
}
address _gauge = IGaugeFactory(_gaugeFactory).createGauge(_pool, _external_bribe, _ve, isPair, allowedRewards);
IERC20(base).approve(_gauge, type(uint).max);
external_bribes[_gauge] = _external_bribe;
gauges[_pool] = _gauge;
poolForGauge[_gauge] = _pool;
isGauge[_gauge] = true;
isAlive[_gauge] = true;
_updateFor(_gauge);
if(claimable[_gauge] > 0) {
claimable[_gauge] = 0;
}
pools.push(_pool);
if (isPair) {
IPair(_pool).setHasGauge(true);
IPair(_pool).setExternalBribe(_external_bribe);
}
emit GaugeCreated(_gauge, msg.sender, _external_bribe, _pool);
return _gauge;
}
function pauseGauge(address _gauge) external {
require(msg.sender == emergencyCouncil, "not emergency council");
require(isAlive[_gauge], "gauge already dead");
isAlive[_gauge] = false;
claimable[_gauge] = 0;
address _pair = IGauge(_gauge).stake();
try IPair(_pair).setHasGauge(false) {} catch {}
emit GaugePaused(_gauge);
}
function restartGauge(address _gauge) external {
require(msg.sender == emergencyCouncil, "not emergency council");
require(!isAlive[_gauge], "gauge already alive");
isAlive[_gauge] = true;
address _pair = IGauge(_gauge).stake();
try IPair(_pair).setHasGauge(true) {} catch {}
emit GaugeRestarted(_gauge);
}
function killGaugeTotally(address _gauge) external {
require(msg.sender == emergencyCouncil, "not emergency council");
require(isAlive[_gauge], "gauge already dead");
address _pool = poolForGauge[_gauge];
delete isAlive[_gauge];
delete external_bribes[_gauge];
delete poolForGauge[_gauge];
delete isGauge[_gauge];
delete claimable[_gauge];
delete supplyIndex[_gauge];
delete gauges[_pool];
try IPair(_pool).setHasGauge(false) {} catch {}
killedGauges.push(_gauge);
emit GaugeKilledTotally(_gauge);
}
function attachTokenToGauge(uint tokenId, address account) external {
require(isGauge[msg.sender]);
require(isAlive[msg.sender]);
if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);
emit Attach(account, msg.sender, tokenId);
}
function emitDeposit(uint tokenId, address account, uint amount) external {
require(isGauge[msg.sender]);
require(isAlive[msg.sender]);
emit Deposit(account, msg.sender, tokenId, amount);
}
function detachTokenFromGauge(uint tokenId, address account) external {
if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);
emit Detach(account, msg.sender, tokenId);
}
function emitWithdraw(uint tokenId, address account, uint amount) external {
emit Withdraw(account, msg.sender, tokenId, amount);
}
function length() external view returns (uint) {
return pools.length;
}
function _factories() external view returns(address[] memory){
return factories;
}
function factoryLength() public view returns(uint){
return factories.length;
}
function _gaugeFactories() external view returns(address[] memory){
return gaugeFactories;
}
function gaugeFactoriesLength() public view returns(uint) {
return gaugeFactories.length;
}
function _killedGauges() external view returns(address[] memory){
return killedGauges;
}
function killedGaugesLength() public view returns(uint) {
return killedGauges.length;
}
uint internal index;
mapping(address => uint) internal supplyIndex;
mapping(address => uint) public claimable;
function notifyRewardAmount(uint amount) external {
_safeTransferFrom(base, msg.sender, address(this), amount);
uint256 _ratio = amount * 1e18 / totalWeight;
if (_ratio > 0) {
index += _ratio;
}
emit NotifyReward(msg.sender, base, amount);
}
function updateFor(address[] memory _gauges) external {
for (uint i = 0; i < _gauges.length; i++) {
_updateFor(_gauges[i]);
}
}
function updateForRange(uint start, uint end) public {
for (uint i = start; i < end; i++) {
_updateFor(gauges[pools[i]]);
}
}
function updateAll() external {
updateForRange(0, pools.length);
}
function updateGauge(address _gauge) external {
_updateFor(_gauge);
}
function _updateFor(address _gauge) internal {
address _pool = poolForGauge[_gauge];
uint256 _supplied = weights[_pool];
if (_supplied > 0) {
uint _supplyIndex = supplyIndex[_gauge];
uint _index = index;
supplyIndex[_gauge] = _index;
uint _delta = _index - _supplyIndex;
if (_delta > 0) {
uint _share = uint(_supplied) * _delta / 1e18;
if (isAlive[_gauge]) {
claimable[_gauge] += _share;
}
}
} else {
supplyIndex[_gauge] = index;
}
}
function claimRewards(address[] memory _gauges, address[][] memory _tokens) external {
for (uint i = 0; i < _gauges.length; i++) {
IGauge(_gauges[i]).getReward(msg.sender, _tokens[i]);
}
}
function claimBribes(address[] memory _bribes, address[][] memory _tokens, uint _tokenId) external {
require(IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId));
for (uint i = 0; i < _bribes.length; i++) {
IBribe(_bribes[i]).getRewardForOwner(_tokenId, _tokens[i]);
}
}
function distribute(address _gauge) public lock {
IMinter(minter).update_period();
_updateFor(_gauge);
uint _claimable = claimable[_gauge];
if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {
claimable[_gauge] = 0;
IGauge(_gauge).notifyRewardAmount(base, _claimable);
emit DistributeReward(msg.sender, _gauge, _claimable);
}
}
function distro() external {
distribute(0, pools.length);
}
function distribute() external {
distribute(0, pools.length);
}
function distribute(uint start, uint finish) public {
for (uint x = start; x < finish; x++) {
distribute(gauges[pools[x]]);
}
}
function distribute(address[] memory _gauges) external {
for (uint x = 0; x < _gauges.length; x++) {
distribute(_gauges[x]);
}
}
function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
}
{
"compilationTarget": {
"contracts/Voter.sol": "Voter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":solmate/=lib/solmate/src/",
":utils/=test/utils/"
]
}
[{"inputs":[{"internalType":"address","name":"__ve","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_gauges","type":"address"},{"internalType":"address","name":"_bribes","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Abstained","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Attach","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blacklister","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"Blacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":false,"internalType":"address","name":"newBribeFatory","type":"address"}],"name":"BribeFactorySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lp","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Detach","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DistributeReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"externalBribe","type":"address"}],"name":"ExternalBribeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":true,"internalType":"address","name":"pairFactory","type":"address"},{"indexed":true,"internalType":"address","name":"gaugeFactory","type":"address"}],"name":"FactoryAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":true,"internalType":"uint256","name":"pos","type":"uint256"}],"name":"FactoryRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":true,"internalType":"address","name":"pairFactory","type":"address"},{"indexed":true,"internalType":"address","name":"gaugeFactory","type":"address"},{"indexed":false,"internalType":"uint256","name":"pos","type":"uint256"}],"name":"FactoryReplaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":true,"internalType":"address","name":"external_bribe","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"GaugeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeKilledTotally","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeRestarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NotifyReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"whitelister","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"Whitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lp","type":"address"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"_factories","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_gaugeFactories","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_killedGauges","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"}],"name":"addFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"attachTokenToGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"blacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bribefactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_bribes","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claimBribes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"uint256","name":"_gaugeType","type":"uint256"}],"name":"createGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"detachTokenFromGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"finish","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distro","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyCouncil","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"external_bribes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"factories","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"gaugeFactories","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeFactoriesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address","name":"_minter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAlive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFactory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGauge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGaugeFactory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"killGaugeTotally","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"killedGauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"killedGaugesLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastVoted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"length","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"pauseGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolVote","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pos","type":"uint256"}],"name":"removeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"},{"internalType":"uint256","name":"_pos","type":"uint256"}],"name":"replaceFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"reset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"restartGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bribeFactory","type":"address"}],"name":"setBribeFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_council","type":"address"}],"name":"setEmergencyCouncil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_external","type":"address"}],"name":"setExternalBribeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"setGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"updateFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"updateForRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"updateGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"usedWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"_poolVote","type":"address[]"},{"internalType":"uint256[]","name":"_weights","type":"uint256[]"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"votes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"}]