编译器
0.8.15+commit.e14f2714
文件 1 的 16:Address.sol
pragma solidity 0.8.15;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 16:CheckpointLib.sol
pragma solidity 0.8.15;
library CheckpointLib {
struct Checkpoint {
uint timestamp;
uint value;
}
function findLowerIndex(mapping(uint => Checkpoint) storage checkpoints, uint size, uint timestamp) internal view returns (uint) {
require(size != 0, "Empty checkpoints");
if (checkpoints[size - 1].timestamp <= timestamp) {
return (size - 1);
}
if (checkpoints[0].timestamp > timestamp) {
return 0;
}
uint lower = 0;
uint upper = size - 1;
while (upper > lower) {
uint center = upper - (upper - lower) / 2;
Checkpoint memory cp = checkpoints[center];
if (cp.timestamp == timestamp) {
return center;
} else if (cp.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
}
文件 3 的 16:Gauge.sol
pragma solidity 0.8.15;
import "../../interface/IGauge.sol";
import "../../interface/IPair.sol";
import "../../interface/IVoter.sol";
import "../../interface/IBribe.sol";
import "../../interface/IERC721.sol";
import "../../interface/IVe.sol";
import "./MultiRewardsPoolBase.sol";
contract Gauge is IGauge, MultiRewardsPoolBase {
using SafeERC20 for IERC20;
address public immutable ve;
address public immutable bribe;
address public immutable voter;
mapping(address => uint) public tokenIds;
uint public fees0;
uint public fees1;
event ClaimFees(address indexed from, uint claimed0, uint claimed1);
event VeTokenLocked(address indexed account, uint tokenId);
event VeTokenUnlocked(address indexed account, uint tokenId);
constructor(
address _stake,
address _bribe,
address _ve,
address _voter,
address[] memory _allowedRewardTokens
) MultiRewardsPoolBase(
_stake,
_voter,
_allowedRewardTokens
) {
bribe = _bribe;
ve = _ve;
voter = _voter;
}
function claimFees() external lock override returns (uint claimed0, uint claimed1) {
return _claimFees();
}
function _claimFees() internal returns (uint claimed0, uint claimed1) {
address _underlying = underlying;
(claimed0, claimed1) = IPair(_underlying).claimFees();
if (claimed0 > 0 || claimed1 > 0) {
uint _fees0 = fees0 + claimed0;
uint _fees1 = fees1 + claimed1;
(address _token0, address _token1) = IPair(_underlying).tokens();
if (_fees0 > IMultiRewardsPool(bribe).left(_token0)) {
fees0 = 0;
IERC20(_token0).safeIncreaseAllowance(bribe, _fees0);
IBribe(bribe).notifyRewardAmount(_token0, _fees0);
} else {
fees0 = _fees0;
}
if (_fees1 > IMultiRewardsPool(bribe).left(_token1)) {
fees1 = 0;
IERC20(_token1).safeIncreaseAllowance(bribe, _fees1);
IBribe(bribe).notifyRewardAmount(_token1, _fees1);
} else {
fees1 = _fees1;
}
emit ClaimFees(msg.sender, claimed0, claimed1);
}
}
function getReward(address account, address[] memory tokens) external override {
require(msg.sender == account || msg.sender == voter, "Forbidden");
IVoter(voter).distribute(address(this));
_getReward(account, tokens, account);
}
function depositAll(uint tokenId) external {
deposit(IERC20(underlying).balanceOf(msg.sender), tokenId);
}
function deposit(uint amount, uint tokenId) public {
if (tokenId > 0) {
_lockVeToken(msg.sender, tokenId);
}
_deposit(amount);
IVoter(voter).emitDeposit(tokenId, msg.sender, amount);
}
function withdrawAll() external {
withdraw(balanceOf[msg.sender]);
}
function withdraw(uint amount) public {
uint tokenId = 0;
if (amount == balanceOf[msg.sender]) {
tokenId = tokenIds[msg.sender];
}
withdrawToken(amount, tokenId);
IVoter(voter).emitWithdraw(tokenId, msg.sender, amount);
}
function withdrawToken(uint amount, uint tokenId) public {
if (tokenId > 0) {
_unlockVeToken(msg.sender, tokenId);
}
_withdraw(amount);
}
function _lockVeToken(address account, uint tokenId) internal {
require(IERC721(ve).ownerOf(tokenId) == account, "Not ve token owner");
if (tokenIds[account] == 0) {
tokenIds[account] = tokenId;
IVoter(voter).attachTokenToGauge(tokenId, account);
}
require(tokenIds[account] == tokenId, "Wrong token");
emit VeTokenLocked(account, tokenId);
}
function _unlockVeToken(address account, uint tokenId) internal {
require(tokenId == tokenIds[account], "Wrong token");
tokenIds[account] = 0;
IVoter(voter).detachTokenFromGauge(tokenId, account);
emit VeTokenUnlocked(account, tokenId);
}
function _derivedBalance(address account) internal override view returns (uint) {
uint _tokenId = tokenIds[account];
uint _balance = balanceOf[account];
uint _derived = _balance * 40 / 100;
uint _adjusted = 0;
uint _supply = IERC20(ve).totalSupply();
if (account == IERC721(ve).ownerOf(_tokenId) && _supply > 0) {
_adjusted = (totalSupply * IVe(ve).balanceOfNFT(_tokenId) / _supply) * 60 / 100;
}
return Math.min((_derived + _adjusted), _balance);
}
function notifyRewardAmount(address token, uint amount) external {
try Gauge(address(this)).claimFees() {} catch {}
_notifyRewardAmount(token, amount);
}
}
文件 4 的 16:IBribe.sol
pragma solidity 0.8.15;
interface IBribe {
function notifyRewardAmount(address token, uint amount) external;
function _deposit(uint amount, uint tokenId) external;
function _withdraw(uint amount, uint tokenId) external;
function getRewardForOwner(uint tokenId, address[] memory tokens) external;
}
文件 5 的 16:IERC165.sol
pragma solidity 0.8.15;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 16:IERC20.sol
pragma solidity 0.8.15;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 7 的 16:IERC721.sol
pragma solidity 0.8.15;
import "./IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 8 的 16:IGauge.sol
pragma solidity 0.8.15;
interface IGauge {
function notifyRewardAmount(address token, uint amount) external;
function getReward(address account, address[] memory tokens) external;
function claimFees() external returns (uint claimed0, uint claimed1);
}
文件 9 的 16:IMultiRewardsPool.sol
pragma solidity 0.8.15;
interface IMultiRewardsPool {
function underlying() external view returns (address);
function derivedSupply() external view returns (uint);
function derivedBalances(address account) external view returns (uint);
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function rewardTokens(uint id) external view returns (address);
function isRewardToken(address token) external view returns (bool);
function rewardTokensLength() external view returns (uint);
function derivedBalance(address account) external view returns (uint);
function left(address token) external view returns (uint);
function earned(address token, address account) external view returns (uint);
function registerRewardToken(address token) external;
function removeRewardToken(address token) external;
}
文件 10 的 16:IPair.sol
pragma solidity 0.8.15;
interface IPair {
struct Observation {
uint timestamp;
uint reserve0Cumulative;
uint reserve1Cumulative;
}
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 (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);
function getAmountOut(uint, address) external view returns (uint);
function claimFees() external returns (uint, uint);
function tokens() external view returns (address, address);
function token0() external view returns (address);
function token1() external view returns (address);
function stable() external view returns (bool);
function metadata() external view returns (
uint dec0,
uint dec1,
uint r0,
uint r1,
bool st,
address t0,
address t1
);
}
文件 11 的 16:IVe.sol
pragma solidity 0.8.15;
interface IVe {
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
INCREASE_LOCK_AMOUNT,
INCREASE_UNLOCK_TIME,
MERGE_TYPE
}
struct Point {
int128 bias;
int128 slope;
uint ts;
uint blk;
}
struct LockedBalance {
int128 amount;
uint end;
}
function token() external view returns (address);
function balanceOfNFT(uint) external view returns (uint);
function isApprovedOrOwner(address, uint) external view returns (bool);
function createLockFor(uint, uint, address) external returns (uint);
function userPointEpoch(uint tokenId) external view returns (uint);
function epoch() external view returns (uint);
function userPointHistory(uint tokenId, uint loc) external view returns (Point memory);
function pointHistory(uint loc) external view returns (Point memory);
function checkpoint() external;
function depositFor(uint tokenId, uint value) external;
function attachToken(uint tokenId) external;
function detachToken(uint tokenId) external;
function voting(uint tokenId) external;
function abstain(uint tokenId) external;
}
文件 12 的 16:IVoter.sol
pragma solidity 0.8.15;
interface IVoter {
function ve() 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 distribute(address _gauge) external;
function notifyRewardAmount(uint amount) external;
}
文件 13 的 16:Math.sol
pragma solidity 0.8.15;
library Math {
function max(uint a, uint b) internal pure returns (uint) {
return a >= b ? a : b;
}
function min(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
function positiveInt128(int128 value) internal pure returns (int128) {
return value < 0 ? int128(0) : value;
}
function closeTo(uint a, uint b, uint target) internal pure returns (bool) {
if (a > b) {
if (a - b <= target) {
return true;
}
} else {
if (b - a <= target) {
return true;
}
}
return false;
}
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 14 的 16:MultiRewardsPoolBase.sol
pragma solidity 0.8.15;
import "../../interface/IERC20.sol";
import "../../interface/IMultiRewardsPool.sol";
import "../../lib/Math.sol";
import "../../lib/SafeERC20.sol";
import "../../lib/CheckpointLib.sol";
import "../Reentrancy.sol";
abstract contract MultiRewardsPoolBase is Reentrancy, IMultiRewardsPool {
using SafeERC20 for IERC20;
using CheckpointLib for mapping(uint => CheckpointLib.Checkpoint);
address public operator;
address public immutable override underlying;
uint public override derivedSupply;
mapping(address => uint) public override derivedBalances;
uint internal constant DURATION = 7 days;
uint internal constant PRECISION = 10 ** 18;
uint internal constant MAX_REWARD_TOKENS = 10;
mapping(address => uint) public rewardRate;
mapping(address => uint) public periodFinish;
mapping(address => uint) public lastUpdateTime;
mapping(address => uint) public rewardPerTokenStored;
mapping(address => mapping(address => uint)) public lastEarn;
mapping(address => mapping(address => uint)) public userRewardPerTokenStored;
uint public override totalSupply;
mapping(address => uint) public override balanceOf;
address[] public override rewardTokens;
mapping(address => bool) public override isRewardToken;
mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public checkpoints;
mapping(address => uint) public numCheckpoints;
mapping(uint => CheckpointLib.Checkpoint) public supplyCheckpoints;
uint public supplyNumCheckpoints;
mapping(address => mapping(uint => CheckpointLib.Checkpoint)) public rewardPerTokenCheckpoints;
mapping(address => uint) public rewardPerTokenNumCheckpoints;
event Deposit(address indexed from, uint amount);
event Withdraw(address indexed from, uint amount);
event NotifyReward(address indexed from, address indexed reward, uint amount);
event ClaimRewards(address indexed from, address indexed reward, uint amount, address recepient);
constructor(address _stake, address _operator, address[] memory _allowedRewardTokens) {
underlying = _stake;
operator = _operator;
for (uint i; i < _allowedRewardTokens.length; i++) {
if (_allowedRewardTokens[i] != address(0)) {
_registerRewardToken(_allowedRewardTokens[i]);
}
}
}
modifier onlyOperator() {
require(msg.sender == operator, "Not operator");
_;
}
function rewardTokensLength() external view override returns (uint) {
return rewardTokens.length;
}
function rewardPerToken(address token) external view returns (uint) {
return _rewardPerToken(token);
}
function _rewardPerToken(address token) internal view returns (uint) {
if (derivedSupply == 0) {
return rewardPerTokenStored[token];
}
return rewardPerTokenStored[token]
+ (
(_lastTimeRewardApplicable(token) - Math.min(lastUpdateTime[token], periodFinish[token]))
* rewardRate[token]
/ derivedSupply
);
}
function derivedBalance(address account) external view override returns (uint) {
return _derivedBalance(account);
}
function left(address token) external view override returns (uint) {
if (block.timestamp >= periodFinish[token]) return 0;
uint _remaining = periodFinish[token] - block.timestamp;
return _remaining * rewardRate[token] / PRECISION;
}
function earned(address token, address account) external view override returns (uint) {
return _earned(token, account);
}
function registerRewardToken(address token) external onlyOperator {
_registerRewardToken(token);
}
function _registerRewardToken(address token) internal {
require(rewardTokens.length < MAX_REWARD_TOKENS, "Too many reward tokens");
require(!isRewardToken[token], "Already registered");
isRewardToken[token] = true;
rewardTokens.push(token);
}
function removeRewardToken(address token) external onlyOperator {
require(periodFinish[token] < block.timestamp, "Rewards not ended");
require(isRewardToken[token], "Not reward token");
isRewardToken[token] = false;
uint length = rewardTokens.length;
require(length > 3, "First 3 tokens should not be removed");
uint i = 3;
bool found = false;
for (; i < length; i++) {
address t = rewardTokens[i];
if (t == token) {
found = true;
break;
}
}
require(found, "First tokens forbidden to remove");
rewardTokens[i] = rewardTokens[length - 1];
rewardTokens.pop();
}
function _deposit(uint amount) internal virtual lock {
require(amount > 0, "Zero amount");
_increaseBalance(msg.sender, amount);
IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
emit Deposit(msg.sender, amount);
}
function _increaseBalance(address account, uint amount) internal virtual {
_updateRewardForAllTokens();
totalSupply += amount;
balanceOf[account] += amount;
_updateDerivedBalanceAndWriteCheckpoints(account);
}
function _withdraw(uint amount) internal lock virtual {
_decreaseBalance(msg.sender, amount);
IERC20(underlying).safeTransfer(msg.sender, amount);
emit Withdraw(msg.sender, amount);
}
function _decreaseBalance(address account, uint amount) internal virtual {
_updateRewardForAllTokens();
totalSupply -= amount;
balanceOf[account] -= amount;
_updateDerivedBalanceAndWriteCheckpoints(account);
}
function _getReward(address account, address[] memory tokens, address recipient) internal lock virtual {
for (uint i = 0; i < tokens.length; i++) {
(rewardPerTokenStored[tokens[i]], lastUpdateTime[tokens[i]]) = _updateRewardPerToken(tokens[i], type(uint).max, true);
uint _reward = _earned(tokens[i], account);
lastEarn[tokens[i]][account] = block.timestamp;
userRewardPerTokenStored[tokens[i]][account] = rewardPerTokenStored[tokens[i]];
if (_reward > 0) {
IERC20(tokens[i]).safeTransfer(recipient, _reward);
}
emit ClaimRewards(msg.sender, tokens[i], _reward, recipient);
}
_updateDerivedBalanceAndWriteCheckpoints(account);
}
function _updateDerivedBalanceAndWriteCheckpoints(address account) internal {
uint __derivedBalance = derivedBalances[account];
derivedSupply -= __derivedBalance;
__derivedBalance = _derivedBalance(account);
derivedBalances[account] = __derivedBalance;
derivedSupply += __derivedBalance;
_writeCheckpoint(account, __derivedBalance);
_writeSupplyCheckpoint();
}
function _earned(address token, address account) internal view returns (uint) {
if (numCheckpoints[account] == 0) {
return 0;
}
uint _startTimestamp = Math.max(lastEarn[token][account], rewardPerTokenCheckpoints[token][0].timestamp);
uint _startIndex = _getPriorBalanceIndex(account, _startTimestamp);
uint _endIndex = numCheckpoints[account] - 1;
uint reward = 0;
if (_endIndex > 0) {
for (uint i = _startIndex; i <= _endIndex - 1; i++) {
CheckpointLib.Checkpoint memory cp0 = checkpoints[account][i];
CheckpointLib.Checkpoint memory cp1 = checkpoints[account][i + 1];
(uint _rewardPerTokenStored0,) = _getPriorRewardPerToken(token, cp0.timestamp);
(uint _rewardPerTokenStored1,) = _getPriorRewardPerToken(token, cp1.timestamp);
reward += cp0.value * (_rewardPerTokenStored1 - _rewardPerTokenStored0) / PRECISION;
}
}
CheckpointLib.Checkpoint memory cp = checkpoints[account][_endIndex];
(uint _rewardPerTokenStored,) = _getPriorRewardPerToken(token, cp.timestamp);
reward += cp.value * (_rewardPerToken(token) - Math.max(_rewardPerTokenStored, userRewardPerTokenStored[token][account])) / PRECISION;
return reward;
}
function _derivedBalance(address account) internal virtual view returns (uint) {
return balanceOf[account];
}
function batchUpdateRewardPerToken(address token, uint maxRuns) external {
(rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, maxRuns, false);
}
function _updateRewardForAllTokens() internal {
uint length = rewardTokens.length;
for (uint i; i < length; i++) {
address token = rewardTokens[i];
(rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true);
}
}
function _updateRewardPerToken(address token, uint maxRuns, bool actualLast) internal returns (uint, uint) {
uint _startTimestamp = lastUpdateTime[token];
uint reward = rewardPerTokenStored[token];
if (supplyNumCheckpoints == 0) {
return (reward, _startTimestamp);
}
if (rewardRate[token] == 0) {
return (reward, block.timestamp);
}
uint _startIndex = _getPriorSupplyIndex(_startTimestamp);
uint _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);
if (_endIndex > 0) {
for (uint i = _startIndex; i <= _endIndex - 1; i++) {
CheckpointLib.Checkpoint memory sp0 = supplyCheckpoints[i];
if (sp0.value > 0) {
CheckpointLib.Checkpoint memory sp1 = supplyCheckpoints[i + 1];
(uint _reward, uint _endTime) = _calcRewardPerToken(
token,
sp1.timestamp,
sp0.timestamp,
sp0.value,
_startTimestamp
);
reward += _reward;
_writeRewardPerTokenCheckpoint(token, reward, _endTime);
_startTimestamp = _endTime;
}
}
}
if (actualLast) {
CheckpointLib.Checkpoint memory sp = supplyCheckpoints[_endIndex];
if (sp.value > 0) {
(uint _reward,) = _calcRewardPerToken(token, _lastTimeRewardApplicable(token), Math.max(sp.timestamp, _startTimestamp), sp.value, _startTimestamp);
reward += _reward;
_writeRewardPerTokenCheckpoint(token, reward, block.timestamp);
_startTimestamp = block.timestamp;
}
}
return (reward, _startTimestamp);
}
function _calcRewardPerToken(
address token,
uint lastSupplyTs1,
uint lastSupplyTs0,
uint supply,
uint startTimestamp
) internal view returns (uint, uint) {
uint endTime = Math.max(lastSupplyTs1, startTimestamp);
uint _periodFinish = periodFinish[token];
return (
(Math.min(endTime, _periodFinish) - Math.min(Math.max(lastSupplyTs0, startTimestamp), _periodFinish))
* rewardRate[token] / supply
, endTime);
}
function _lastTimeRewardApplicable(address token) internal view returns (uint) {
return Math.min(block.timestamp, periodFinish[token]);
}
function _notifyRewardAmount(address token, uint amount) internal lock virtual {
require(token != underlying, "Wrong token for rewards");
require(amount > 0, "Zero amount");
require(isRewardToken[token], "Token not allowed");
if (rewardRate[token] == 0) {
_writeRewardPerTokenCheckpoint(token, 0, block.timestamp);
}
(rewardPerTokenStored[token], lastUpdateTime[token]) = _updateRewardPerToken(token, type(uint).max, true);
if (block.timestamp >= periodFinish[token]) {
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
rewardRate[token] = amount * PRECISION / DURATION;
} else {
uint _remaining = periodFinish[token] - block.timestamp;
uint _left = _remaining * rewardRate[token];
require(amount > _left / PRECISION, "Amount should be higher than remaining rewards");
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
rewardRate[token] = (amount * PRECISION + _left) / DURATION;
}
periodFinish[token] = block.timestamp + DURATION;
emit NotifyReward(msg.sender, token, amount);
}
function getPriorBalanceIndex(address account, uint timestamp) external view returns (uint) {
return _getPriorBalanceIndex(account, timestamp);
}
function _getPriorBalanceIndex(address account, uint timestamp) internal view returns (uint) {
uint nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
return checkpoints[account].findLowerIndex(nCheckpoints, timestamp);
}
function getPriorSupplyIndex(uint timestamp) external view returns (uint) {
return _getPriorSupplyIndex(timestamp);
}
function _getPriorSupplyIndex(uint timestamp) internal view returns (uint) {
uint nCheckpoints = supplyNumCheckpoints;
if (nCheckpoints == 0) {
return 0;
}
return supplyCheckpoints.findLowerIndex(nCheckpoints, timestamp);
}
function getPriorRewardPerToken(address token, uint timestamp) external view returns (uint, uint) {
return _getPriorRewardPerToken(token, timestamp);
}
function _getPriorRewardPerToken(address token, uint timestamp) internal view returns (uint, uint) {
uint nCheckpoints = rewardPerTokenNumCheckpoints[token];
if (nCheckpoints == 0) {
return (0, 0);
}
mapping(uint => CheckpointLib.Checkpoint) storage cps = rewardPerTokenCheckpoints[token];
uint lower = cps.findLowerIndex(nCheckpoints, timestamp);
CheckpointLib.Checkpoint memory cp = cps[lower];
return (cp.value, cp.timestamp);
}
function _writeCheckpoint(address account, uint balance) internal {
uint _timestamp = block.timestamp;
uint _nCheckPoints = numCheckpoints[account];
if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) {
checkpoints[account][_nCheckPoints - 1].value = balance;
} else {
checkpoints[account][_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, balance);
numCheckpoints[account] = _nCheckPoints + 1;
}
}
function _writeRewardPerTokenCheckpoint(address token, uint reward, uint timestamp) internal {
uint _nCheckPoints = rewardPerTokenNumCheckpoints[token];
if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) {
rewardPerTokenCheckpoints[token][_nCheckPoints - 1].value = reward;
} else {
rewardPerTokenCheckpoints[token][_nCheckPoints] = CheckpointLib.Checkpoint(timestamp, reward);
rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;
}
}
function _writeSupplyCheckpoint() internal {
uint _nCheckPoints = supplyNumCheckpoints;
uint _timestamp = block.timestamp;
if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) {
supplyCheckpoints[_nCheckPoints - 1].value = derivedSupply;
} else {
supplyCheckpoints[_nCheckPoints] = CheckpointLib.Checkpoint(_timestamp, derivedSupply);
supplyNumCheckpoints = _nCheckPoints + 1;
}
}
}
文件 15 的 16:Reentrancy.sol
pragma solidity 0.8.15;
abstract contract Reentrancy {
uint internal _unlocked = 1;
modifier lock() {
require(_unlocked == 1, "Reentrant call");
_unlocked = 2;
_;
_unlocked = 1;
}
}
文件 16 的 16:SafeERC20.sol
pragma solidity 0.8.15;
import "../interface/IERC20.sol";
import "./Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint value
) internal {
uint newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
{
"compilationTarget": {
"contracts/base/reward/Gauge.sol": "Gauge"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_stake","type":"address"},{"internalType":"address","name":"_bribe","type":"address"},{"internalType":"address","name":"_ve","type":"address"},{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address[]","name":"_allowedRewardTokens","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimed0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimed1","type":"uint256"}],"name":"ClaimFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"reward","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recepient","type":"address"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","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":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"VeTokenLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"VeTokenUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maxRuns","type":"uint256"}],"name":"batchUpdateRewardPerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bribe","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"checkpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimed0","type":"uint256"},{"internalType":"uint256","name":"claimed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"derivedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"derivedBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"derivedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorBalanceIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorRewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getPriorSupplyIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRewardToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"lastEarn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"left","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"registerRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardPerTokenCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardTokensLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supplyCheckpoints","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]