文件 1 的 12:BaseV2Bribes.sol
pragma solidity ^0.8.0;
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IGaugeVoter} from "../interfaces/IGaugeVoter.sol";
import {IRegistry} from "../interfaces/IRegistry.sol";
import {INFTLocker} from "../interfaces/INFTLocker.sol";
import {IBribeV2} from "../interfaces/IBribeV2.sol";
contract BaseV2Bribes is ReentrancyGuard, IBribeV2 {
IRegistry public immutable override registry;
uint256 public constant DURATION = 7 days;
uint256 public constant PRECISION = 10**18;
mapping(address => uint256) public rewardRate;
mapping(address => uint256) public periodFinish;
mapping(address => uint256) public lastUpdateTime;
mapping(address => uint256) public rewardPerTokenStored;
mapping(address => mapping(address => uint256)) public lastEarn;
mapping(address => mapping(address => uint256))
public userRewardPerTokenStored;
address[] public rewards;
mapping(address => bool) public isReward;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
struct Checkpoint {
uint256 timestamp;
uint256 balanceOf;
}
struct RewardPerTokenCheckpoint {
uint256 timestamp;
uint256 rewardPerToken;
}
struct SupplyCheckpoint {
uint256 timestamp;
uint256 supply;
}
mapping(address => mapping(uint256 => Checkpoint)) public checkpoints;
mapping(address => uint256) public numCheckpoints;
mapping(uint256 => SupplyCheckpoint) public supplyCheckpoints;
uint256 public supplyNumCheckpoints;
mapping(address => mapping(uint256 => RewardPerTokenCheckpoint))
public rewardPerTokenCheckpoints;
mapping(address => uint256) public rewardPerTokenNumCheckpoints;
constructor(address _registry) {
registry = IRegistry(_registry);
}
function getPriorBalanceIndex(address who, uint256 timestamp)
public
view
returns (uint256)
{
uint256 nCheckpoints = numCheckpoints[who];
if (nCheckpoints == 0) {
return 0;
}
if (checkpoints[who][nCheckpoints - 1].timestamp <= timestamp) {
return (nCheckpoints - 1);
}
if (checkpoints[who][0].timestamp > timestamp) {
return 0;
}
uint256 lower = 0;
uint256 upper = nCheckpoints - 1;
while (upper > lower) {
uint256 center = upper - (upper - lower) / 2;
Checkpoint memory cp = checkpoints[who][center];
if (cp.timestamp == timestamp) {
return center;
} else if (cp.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
function getPriorSupplyIndex(uint256 timestamp)
public
view
returns (uint256)
{
uint256 nCheckpoints = supplyNumCheckpoints;
if (nCheckpoints == 0) {
return 0;
}
if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) {
return (nCheckpoints - 1);
}
if (supplyCheckpoints[0].timestamp > timestamp) {
return 0;
}
uint256 lower = 0;
uint256 upper = nCheckpoints - 1;
while (upper > lower) {
uint256 center = upper - (upper - lower) / 2;
SupplyCheckpoint memory cp = supplyCheckpoints[center];
if (cp.timestamp == timestamp) {
return center;
} else if (cp.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return lower;
}
function getPriorRewardPerToken(address token, uint256 timestamp)
public
view
returns (uint256, uint256)
{
uint256 nCheckpoints = rewardPerTokenNumCheckpoints[token];
if (nCheckpoints == 0) {
return (0, 0);
}
if (
rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp <=
timestamp
) {
return (
rewardPerTokenCheckpoints[token][nCheckpoints - 1]
.rewardPerToken,
rewardPerTokenCheckpoints[token][nCheckpoints - 1].timestamp
);
}
if (rewardPerTokenCheckpoints[token][0].timestamp > timestamp) {
return (0, 0);
}
uint256 lower = 0;
uint256 upper = nCheckpoints - 1;
while (upper > lower) {
uint256 center = upper - (upper - lower) / 2;
RewardPerTokenCheckpoint memory cp = rewardPerTokenCheckpoints[
token
][center];
if (cp.timestamp == timestamp) {
return (cp.rewardPerToken, cp.timestamp);
} else if (cp.timestamp < timestamp) {
lower = center;
} else {
upper = center - 1;
}
}
return (
rewardPerTokenCheckpoints[token][lower].rewardPerToken,
rewardPerTokenCheckpoints[token][lower].timestamp
);
}
function _writeCheckpoint(address who, uint256 balance) internal {
uint256 _timestamp = block.timestamp;
uint256 _nCheckPoints = numCheckpoints[who];
if (
_nCheckPoints > 0 &&
checkpoints[who][_nCheckPoints - 1].timestamp == _timestamp
) {
checkpoints[who][_nCheckPoints - 1].balanceOf = balance;
} else {
checkpoints[who][_nCheckPoints] = Checkpoint(_timestamp, balance);
numCheckpoints[who] = _nCheckPoints + 1;
}
}
function _writeRewardPerTokenCheckpoint(
address token,
uint256 reward,
uint256 timestamp
) internal {
uint256 _nCheckPoints = rewardPerTokenNumCheckpoints[token];
if (
_nCheckPoints > 0 &&
rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp ==
timestamp
) {
rewardPerTokenCheckpoints[token][_nCheckPoints - 1]
.rewardPerToken = reward;
} else {
rewardPerTokenCheckpoints[token][
_nCheckPoints
] = RewardPerTokenCheckpoint(timestamp, reward);
rewardPerTokenNumCheckpoints[token] = _nCheckPoints + 1;
}
}
function _writeSupplyCheckpoint() internal {
uint256 _nCheckPoints = supplyNumCheckpoints;
uint256 _timestamp = block.timestamp;
if (
_nCheckPoints > 0 &&
supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp
) {
supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply;
} else {
supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(
_timestamp,
totalSupply
);
supplyNumCheckpoints = _nCheckPoints + 1;
}
}
function rewardsListLength() external view returns (uint256) {
return rewards.length;
}
function lastTimeRewardApplicable(address token)
public
view
returns (uint256)
{
return Math.min(block.timestamp, periodFinish[token]);
}
function getReward(address[] memory tokens) external nonReentrant {
for (uint256 i = 0; i < tokens.length; i++) {
(
rewardPerTokenStored[tokens[i]],
lastUpdateTime[tokens[i]]
) = _updateRewardPerToken(tokens[i]);
uint256 _reward = earned(tokens[i], msg.sender);
lastEarn[tokens[i]][msg.sender] = block.timestamp;
userRewardPerTokenStored[tokens[i]][
msg.sender
] = rewardPerTokenStored[tokens[i]];
if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);
emit ClaimRewards(msg.sender, tokens[i], _reward);
}
}
function getRewardForOwner(address _owner, address[] memory tokens)
external
override
nonReentrant
{
require(msg.sender == registry.gaugeVoter(), "not voter");
for (uint256 i = 0; i < tokens.length; i++) {
(
rewardPerTokenStored[tokens[i]],
lastUpdateTime[tokens[i]]
) = _updateRewardPerToken(tokens[i]);
uint256 _reward = earned(tokens[i], _owner);
lastEarn[tokens[i]][_owner] = block.timestamp;
userRewardPerTokenStored[tokens[i]][_owner] = rewardPerTokenStored[
tokens[i]
];
if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);
emit ClaimRewards(_owner, tokens[i], _reward);
}
}
function rewardPerToken(address token) public view returns (uint256) {
if (totalSupply == 0) {
return rewardPerTokenStored[token];
}
return
rewardPerTokenStored[token] +
(((lastTimeRewardApplicable(token) -
Math.min(lastUpdateTime[token], periodFinish[token])) *
rewardRate[token] *
PRECISION) / totalSupply);
}
function batchRewardPerToken(address token, uint256 maxRuns) external {
(
rewardPerTokenStored[token],
lastUpdateTime[token]
) = _batchRewardPerToken(token, maxRuns);
}
function _batchRewardPerToken(address token, uint256 maxRuns)
internal
returns (uint256, uint256)
{
uint256 _startTimestamp = lastUpdateTime[token];
uint256 reward = rewardPerTokenStored[token];
if (supplyNumCheckpoints == 0) {
return (reward, _startTimestamp);
}
if (rewardRate[token] == 0) {
return (reward, block.timestamp);
}
uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);
uint256 _endIndex = Math.min(supplyNumCheckpoints - 1, maxRuns);
for (uint256 i = _startIndex; i < _endIndex; i++) {
SupplyCheckpoint memory sp0 = supplyCheckpoints[i];
if (sp0.supply > 0) {
SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];
(uint256 _reward, uint256 endTime) = _calcRewardPerToken(
token,
sp1.timestamp,
sp0.timestamp,
sp0.supply,
_startTimestamp
);
reward += _reward;
_writeRewardPerTokenCheckpoint(token, reward, endTime);
_startTimestamp = endTime;
}
}
return (reward, _startTimestamp);
}
function _calcRewardPerToken(
address token,
uint256 timestamp1,
uint256 timestamp0,
uint256 supply,
uint256 startTimestamp
) internal view returns (uint256, uint256) {
uint256 endTime = Math.max(timestamp1, startTimestamp);
return (
(((Math.min(endTime, periodFinish[token]) -
Math.min(
Math.max(timestamp0, startTimestamp),
periodFinish[token]
)) *
rewardRate[token] *
PRECISION) / supply),
endTime
);
}
function _updateRewardPerToken(address token)
internal
returns (uint256, uint256)
{
uint256 _startTimestamp = lastUpdateTime[token];
uint256 reward = rewardPerTokenStored[token];
if (supplyNumCheckpoints == 0) {
return (reward, _startTimestamp);
}
if (rewardRate[token] == 0) {
return (reward, block.timestamp);
}
uint256 _startIndex = getPriorSupplyIndex(_startTimestamp);
uint256 _endIndex = supplyNumCheckpoints - 1;
if (_endIndex - _startIndex > 1) {
for (uint256 i = _startIndex; i < _endIndex - 1; i++) {
SupplyCheckpoint memory sp0 = supplyCheckpoints[i];
if (sp0.supply > 0) {
SupplyCheckpoint memory sp1 = supplyCheckpoints[i + 1];
(uint256 _reward, uint256 _endTime) = _calcRewardPerToken(
token,
sp1.timestamp,
sp0.timestamp,
sp0.supply,
_startTimestamp
);
reward += _reward;
_writeRewardPerTokenCheckpoint(token, reward, _endTime);
_startTimestamp = _endTime;
}
}
}
SupplyCheckpoint memory sp = supplyCheckpoints[_endIndex];
if (sp.supply > 0) {
(uint256 _reward, ) = _calcRewardPerToken(
token,
lastTimeRewardApplicable(token),
Math.max(sp.timestamp, _startTimestamp),
sp.supply,
_startTimestamp
);
reward += _reward;
_writeRewardPerTokenCheckpoint(token, reward, block.timestamp);
_startTimestamp = block.timestamp;
}
return (reward, _startTimestamp);
}
function earned(address token, address who) public view returns (uint256) {
uint256 _startTimestamp = Math.max(
lastEarn[token][who],
rewardPerTokenCheckpoints[token][0].timestamp
);
if (numCheckpoints[who] == 0) {
return 0;
}
uint256 _startIndex = getPriorBalanceIndex(who, _startTimestamp);
uint256 _endIndex = numCheckpoints[who] - 1;
uint256 reward = 0;
if (_endIndex - _startIndex > 1) {
for (uint256 i = _startIndex; i < _endIndex - 1; i++) {
Checkpoint memory cp0 = checkpoints[who][i];
Checkpoint memory cp1 = checkpoints[who][i + 1];
(uint256 _rewardPerTokenStored0, ) = getPriorRewardPerToken(
token,
cp0.timestamp
);
(uint256 _rewardPerTokenStored1, ) = getPriorRewardPerToken(
token,
cp1.timestamp
);
reward +=
(cp0.balanceOf *
(_rewardPerTokenStored1 - _rewardPerTokenStored0)) /
PRECISION;
}
}
Checkpoint memory cp = checkpoints[who][_endIndex];
(uint256 _rewardPerTokenStored, ) = getPriorRewardPerToken(
token,
cp.timestamp
);
reward +=
(cp.balanceOf *
(rewardPerToken(token) -
Math.max(
_rewardPerTokenStored,
userRewardPerTokenStored[token][who]
))) /
PRECISION;
return reward;
}
function _deposit(uint256 amount, address who) external override {
registry.ensureNotPaused();
require(msg.sender == registry.gaugeVoter(), "not voter");
totalSupply += amount;
balanceOf[who] += amount;
_writeCheckpoint(who, balanceOf[who]);
_writeSupplyCheckpoint();
emit Deposit(msg.sender, who, amount);
}
function _withdraw(uint256 amount, address who) external override {
registry.ensureNotPaused();
require(msg.sender == registry.gaugeVoter(), "not voter");
totalSupply -= amount;
balanceOf[who] -= amount;
_writeCheckpoint(who, balanceOf[who]);
_writeSupplyCheckpoint();
emit Withdraw(msg.sender, who, amount);
}
function left(address token) external view override returns (uint256) {
if (block.timestamp >= periodFinish[token]) return 0;
uint256 _remaining = periodFinish[token] - block.timestamp;
return _remaining * rewardRate[token];
}
function notifyRewardAmount(address token, uint256 amount)
external
override
nonReentrant
{
require(amount > 0, "amount = 0");
if (rewardRate[token] == 0)
_writeRewardPerTokenCheckpoint(token, 0, block.timestamp);
(
rewardPerTokenStored[token],
lastUpdateTime[token]
) = _updateRewardPerToken(token);
if (block.timestamp >= periodFinish[token]) {
_safeTransferFrom(token, msg.sender, address(this), amount);
rewardRate[token] = amount / DURATION;
} else {
uint256 _remaining = periodFinish[token] - block.timestamp;
uint256 _left = _remaining * rewardRate[token];
require(amount > _left, "amount < left");
_safeTransferFrom(token, msg.sender, address(this), amount);
rewardRate[token] = (amount + _left) / DURATION;
}
require(rewardRate[token] > 0, "rewardRate = 0");
uint256 balance = IERC20(token).balanceOf(address(this));
require(
rewardRate[token] <= balance / DURATION,
"Provided reward too high"
);
periodFinish[token] = block.timestamp + DURATION;
if (!isReward[token]) {
isReward[token] = true;
rewards.push(token);
}
emit NotifyReward(msg.sender, token, amount);
}
function _safeTransfer(
address token,
address to,
uint256 value
) internal {
require(token.code.length > 0, "invalid token code");
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"transfer failed"
);
}
function _safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
require(token.code.length > 0, "invalid token code");
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
IERC20.transferFrom.selector,
from,
to,
value
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"transferFrom failed"
);
}
}
文件 2 的 12:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 3 的 12:IBribeV2.sol
pragma solidity ^0.8.0;
import {IRegistry} from "./IRegistry.sol";
interface IBribeV2 {
function registry() external view returns (IRegistry);
function notifyRewardAmount(address token, uint256 amount) external;
function left(address token) external view returns (uint256);
function _deposit(uint256 amount, address tokenId) external;
function _withdraw(uint256 amount, address tokenId) external;
function getRewardForOwner(address tokenId, address[] memory tokens)
external;
event Deposit(address indexed from, address tokenId, uint256 amount);
event Withdraw(address indexed from, address tokenId, uint256 amount);
event NotifyReward(
address indexed from,
address indexed reward,
uint256 amount
);
event ClaimRewards(
address indexed from,
address indexed reward,
uint256 amount
);
}
文件 4 的 12:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 5 的 12:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from,
address to,
uint256 amount
) external returns (bool);
}
文件 6 的 12:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/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,
bytes calldata data
) external;
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 setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 7 的 12:IERC721Receiver.sol
pragma solidity ^0.8.0;
import "../token/ERC721/IERC721Receiver.sol";
文件 8 的 12:IGaugeVoter.sol
pragma solidity ^0.8.0;
import {IRegistry} from "./IRegistry.sol";
interface IGaugeVoter {
function attachTokenToGauge(uint256 _tokenId, address account) external;
function detachTokenFromGauge(uint256 _tokenId, address account) external;
function emitDeposit(
uint256 _tokenId,
address account,
uint256 amount
) external;
function emitWithdraw(
uint256 _tokenId,
address account,
uint256 amount
) external;
function distribute(address _gauge) external;
function registry() external view returns (IRegistry);
function notifyRewardAmount(uint256 amount) external;
event GaugeCreated(
address indexed gauge,
address creator,
address indexed bribe,
address indexed pool
);
event Voted(address indexed voter, uint256 tokenId, int256 weight);
event Abstained(uint256 tokenId, int256 weight);
event Deposit(
address indexed lp,
address indexed gauge,
uint256 tokenId,
uint256 amount
);
event Withdraw(
address indexed lp,
address indexed gauge,
uint256 tokenId,
uint256 amount
);
event NotifyReward(
address indexed sender,
address indexed reward,
uint256 amount
);
event DistributeReward(
address indexed sender,
address indexed gauge,
uint256 amount
);
event Attach(address indexed owner, address indexed gauge, uint256 tokenId);
event Detach(address indexed owner, address indexed gauge, uint256 tokenId);
event Whitelisted(
address indexed whitelister,
address indexed token,
bool value
);
}
文件 9 的 12:INFTLocker.sol
pragma solidity ^0.8.0;
import {IERC721} from "@openzeppelin/contracts/interfaces/IERC721.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
import {IRegistry} from "./IRegistry.sol";
interface INFTLocker is IERC721 {
function registry() external view returns (IRegistry);
function balanceOfNFT(uint256) external view returns (uint256);
function isStaked(uint256) external view returns (bool);
function epoch() external view returns (uint256);
function userPointEpoch(uint256) external view returns (uint256);
function userPointHistory(uint256, uint256)
external
view
returns (Point memory);
function pointHistory(uint256) external view returns (Point memory);
function totalSupplyWithoutDecay() external view returns (uint256);
function isApprovedOrOwner(address, uint256) external view returns (bool);
function totalSupply() external view returns (uint256);
function totalSupplyAt(uint256 _block) external view returns (uint256);
function merge(uint256 _from, uint256 _to) external;
function blockNumber() external view returns (uint256);
function checkpoint() external;
function depositFor(uint256 _tokenId, uint256 _value) external;
function createLockFor(
uint256 _value,
uint256 _lockDuration,
address _to,
bool _stakeNFT
) external returns (uint256);
function migrateTokenFor(
uint256 _value,
uint256 _lockDuration,
address _to
) external returns (uint256);
function createLock(
uint256 _value,
uint256 _lockDuration,
bool _stakeNFT
) external returns (uint256);
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
INCREASE_LOCK_AMOUNT,
INCREASE_UNLOCK_TIME,
MERGE_TYPE
}
struct Point {
int128 bias;
int128 slope;
uint256 ts;
uint256 blk;
}
struct LockedBalance {
int128 amount;
uint256 end;
uint256 start;
}
event Deposit(
address indexed provider,
uint256 tokenId,
uint256 value,
uint256 indexed locktime,
DepositType deposit_type,
uint256 ts
);
event Withdraw(
address indexed provider,
uint256 tokenId,
uint256 value,
uint256 ts
);
event Supply(uint256 prevSupply, uint256 supply);
}
文件 10 的 12:IRegistry.sol
pragma solidity ^0.8.0;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
interface IRegistry is IAccessControl {
event MahaChanged(address indexed whom, address _old, address _new);
event VoterChanged(address indexed whom, address _old, address _new);
event LockerChanged(address indexed whom, address _old, address _new);
event GovernorChanged(address indexed whom, address _old, address _new);
event StakerChanged(address indexed whom, address _old, address _new);
event EmissionControllerChanged(
address indexed whom,
address _old,
address _new
);
function maha() external view returns (address);
function gaugeVoter() external view returns (address);
function locker() external view returns (address);
function staker() external view returns (address);
function emissionController() external view returns (address);
function governor() external view returns (address);
function getAllAddresses()
external
view
returns (
address,
address,
address,
address,
address
);
function ensureNotPaused() external;
function setMAHA(address _new) external;
function setEmissionController(address _new) external;
function setStaker(address _new) external;
function setVoter(address _new) external;
function setLocker(address _new) external;
function setGovernor(address _new) external;
}
文件 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);
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;
uint256 x = a;
if (x >> 128 > 0) {
x >>= 128;
result <<= 64;
}
if (x >> 64 > 0) {
x >>= 64;
result <<= 32;
}
if (x >> 32 > 0) {
x >>= 32;
result <<= 16;
}
if (x >> 16 > 0) {
x >>= 16;
result <<= 8;
}
if (x >> 8 > 0) {
x >>= 8;
result <<= 4;
}
if (x >> 4 > 0) {
x >>= 4;
result <<= 2;
}
if (x >> 2 > 0) {
result <<= 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) {
uint256 result = sqrt(a);
if (rounding == Rounding.Up && result * result < a) {
result += 1;
}
return result;
}
}
文件 12 的 12:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/bribes/BaseV2Bribes.sol": "BaseV2Bribes"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_registry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"tokenId","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":"from","type":"address"},{"indexed":false,"internalType":"address","name":"tokenId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"who","type":"address"}],"name":"_deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"who","type":"address"}],"name":"_withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":"batchRewardPerToken","outputs":[],"stateMutability":"nonpayable","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":"balanceOf","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"who","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","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":"tokens","type":"address[]"}],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"getRewardForOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReward","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":"token","type":"address"}],"name":"lastTimeRewardApplicable","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":[{"internalType":"address","name":"","type":"address"}],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","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":"rewardPerToken","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":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsListLength","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":"supply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyNumCheckpoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"}]