文件 1 的 12:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(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 的 12:Governable.sol
pragma solidity 0.8.4;
contract Governable {
address public gov;
constructor() {
gov = msg.sender;
}
modifier onlyGov() {
require(msg.sender == gov, "Governable: forbidden");
_;
}
function setGov(address _gov) external onlyGov {
gov = _gov;
}
}
文件 3 的 12:IBlpManager.sol
pragma solidity 0.8.4;
interface IBlpManager {
function provideForAccount(
uint256 tokenXAmount,
uint256 minMint,
address account
) external returns (uint256 mint);
function withdrawForAccount(uint256 tokenXAmount, address account)
external
returns (uint256 burn);
function toTokenX(uint256 amount) external view returns (uint256);
}
文件 4 的 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);
}
文件 5 的 12:IMintable.sol
pragma solidity 0.8.4;
interface IMintable {
function isMinter(address _account) external returns (bool);
function setMinter(address _minter, bool _isActive) external;
function mint(address _account, uint256 _amount) external;
function burn(address _account, uint256 _amount) external;
}
文件 6 的 12:IRewardTracker.sol
pragma solidity 0.8.4;
interface IRewardTracker {
function depositBalances(address _account, address _depositToken)
external
view
returns (uint256);
function stakedAmounts(address _account) external view returns (uint256);
function updateRewards() external;
function stake(address _depositToken, uint256 _amount) external;
function stakeForAccount(
address _fundingAccount,
address _account,
address _depositToken,
uint256 _amount
) external;
function unstake(address _depositToken, uint256 _amount) external;
function unstakeForAccount(
address _account,
address _depositToken,
uint256 _amount,
address _receiver
) external;
function tokensPerInterval() external view returns (uint256);
function claim(address _receiver) external returns (uint256);
function claimForAccount(address _account, address _receiver)
external
returns (uint256);
function claimable(address _account) external view returns (uint256);
function averageStakedAmounts(address _account)
external
view
returns (uint256);
function cumulativeRewards(address _account)
external
view
returns (uint256);
}
文件 7 的 12:IVester.sol
pragma solidity 0.8.4;
interface IVester {
function rewardTracker() external view returns (address);
function claimForAccount(address _account, address _receiver)
external
returns (uint256);
function claimable(address _account) external view returns (uint256);
function cumulativeClaimAmounts(address _account)
external
view
returns (uint256);
function claimedAmounts(address _account) external view returns (uint256);
function pairAmounts(address _account) external view returns (uint256);
function getVestedAmount(address _account) external view returns (uint256);
function transferredAverageStakedAmounts(address _account)
external
view
returns (uint256);
function transferredCumulativeRewards(address _account)
external
view
returns (uint256);
function cumulativeRewardDeductions(address _account)
external
view
returns (uint256);
function bonusRewards(address _account) external view returns (uint256);
function transferStakeValues(address _sender, address _receiver) external;
function setTransferredAverageStakedAmounts(
address _account,
uint256 _amount
) external;
function setTransferredCumulativeRewards(address _account, uint256 _amount)
external;
function setCumulativeRewardDeductions(address _account, uint256 _amount)
external;
function setBonusRewards(address _account, uint256 _amount) external;
function getMaxVestableAmount(address _account)
external
view
returns (uint256);
function getCombinedAverageStakedAmount(address _account)
external
view
returns (uint256);
}
文件 8 的 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;
}
}
文件 9 的 12:RewardRouterV2.sol
pragma solidity 0.8.4;
import "SafeMath.sol";
import "SafeERC20.sol";
import "ReentrancyGuard.sol";
import "Address.sol";
import "IRewardTracker.sol";
import "IVester.sol";
import "IMintable.sol";
import "IBlpManager.sol";
import "Governable.sol";
contract RewardRouterV2 is ReentrancyGuard, Governable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Address for address payable;
bool public isInitialized;
address public usdc;
address public bfr;
address public esBfr;
address public bnBfr;
address public blp;
address public stakedBfrTracker;
address public bonusBfrTracker;
address public feeBfrTracker;
address public stakedBlpTracker;
address public feeBlpTracker;
address public blpManager;
address public bfrVester;
address public blpVester;
mapping(address => address) public pendingReceivers;
event StakeBfr(address account, address token, uint256 amount);
event UnstakeBfr(address account, address token, uint256 amount);
event StakeBlp(address account, uint256 amount);
event UnstakeBlp(address account, uint256 amount);
receive() external payable {
revert("Router: Can't receive eth");
}
function initialize(
address _usdc,
address _bfr,
address _esBfr,
address _bnBfr,
address _blp,
address _stakedBfrTracker,
address _bonusBfrTracker,
address _feeBfrTracker,
address _feeBlpTracker,
address _stakedBlpTracker,
address _bfrVester,
address _blpVester
) external onlyGov {
require(!isInitialized, "RewardRouter: already initialized");
isInitialized = true;
usdc = _usdc;
bfr = _bfr;
esBfr = _esBfr;
bnBfr = _bnBfr;
blp = _blp;
stakedBfrTracker = _stakedBfrTracker;
bonusBfrTracker = _bonusBfrTracker;
feeBfrTracker = _feeBfrTracker;
feeBlpTracker = _feeBlpTracker;
stakedBlpTracker = _stakedBlpTracker;
blpManager = _blp;
bfrVester = _bfrVester;
blpVester = _blpVester;
}
function withdrawToken(
address _token,
address _account,
uint256 _amount
) external onlyGov {
IERC20(_token).safeTransfer(_account, _amount);
}
function batchStakeBfrForAccount(
address[] memory _accounts,
uint256[] memory _amounts
) external nonReentrant onlyGov {
address _bfr = bfr;
for (uint256 i = 0; i < _accounts.length; i++) {
_stakeBfr(msg.sender, _accounts[i], _bfr, _amounts[i]);
}
}
function stakeBfrForAccount(address _account, uint256 _amount)
external
nonReentrant
onlyGov
{
_stakeBfr(msg.sender, _account, bfr, _amount);
}
function stakeBfr(uint256 _amount) external nonReentrant {
_stakeBfr(msg.sender, msg.sender, bfr, _amount);
}
function stakeEsBfr(uint256 _amount) external nonReentrant {
_stakeBfr(msg.sender, msg.sender, esBfr, _amount);
}
function unstakeBfr(uint256 _amount) external nonReentrant {
_unstakeBfr(msg.sender, bfr, _amount, true);
}
function unstakeEsBfr(uint256 _amount) external nonReentrant {
_unstakeBfr(msg.sender, esBfr, _amount, true);
}
function mintAndStakeBlp(uint256 _amount, uint256 _minBlp)
external
nonReentrant
returns (uint256)
{
require(_amount > 0, "RewardRouter: invalid _amount");
address account = msg.sender;
uint256 blpAmount = IBlpManager(blpManager).provideForAccount(
_amount,
_minBlp,
account
);
IRewardTracker(feeBlpTracker).stakeForAccount(
account,
account,
blp,
blpAmount
);
IRewardTracker(stakedBlpTracker).stakeForAccount(
account,
account,
feeBlpTracker,
blpAmount
);
emit StakeBlp(account, blpAmount);
return blpAmount;
}
function unstakeAndRedeemBlp(uint256 _blpAmount)
external
nonReentrant
returns (uint256)
{
require(_blpAmount > 0, "RewardRouter: invalid _blpAmount");
address account = msg.sender;
IRewardTracker(stakedBlpTracker).unstakeForAccount(
account,
feeBlpTracker,
_blpAmount,
account
);
IRewardTracker(feeBlpTracker).unstakeForAccount(
account,
blp,
_blpAmount,
account
);
uint256 amountOut = IBlpManager(blpManager).withdrawForAccount(
IBlpManager(blpManager).toTokenX(_blpAmount),
account
);
emit UnstakeBlp(account, _blpAmount);
return amountOut;
}
function claim() external nonReentrant {
address account = msg.sender;
IRewardTracker(feeBfrTracker).claimForAccount(account, account);
IRewardTracker(feeBlpTracker).claimForAccount(account, account);
IRewardTracker(stakedBfrTracker).claimForAccount(account, account);
IRewardTracker(stakedBlpTracker).claimForAccount(account, account);
}
function claimEsBfr() external nonReentrant {
address account = msg.sender;
IRewardTracker(stakedBfrTracker).claimForAccount(account, account);
IRewardTracker(stakedBlpTracker).claimForAccount(account, account);
}
function claimFees() external nonReentrant {
address account = msg.sender;
IRewardTracker(feeBfrTracker).claimForAccount(account, account);
IRewardTracker(feeBlpTracker).claimForAccount(account, account);
}
function compound() external nonReentrant {
_compound(msg.sender);
}
function compoundForAccount(address _account)
external
nonReentrant
onlyGov
{
_compound(_account);
}
function handleRewards(
bool _shouldClaimBfr,
bool _shouldStakeBfr,
bool _shouldClaimEsBfr,
bool _shouldStakeEsBfr,
bool _shouldStakeMultiplierPoints,
bool _shouldClaimUsdc
) external nonReentrant {
address account = msg.sender;
uint256 bfrAmount = 0;
if (_shouldClaimBfr) {
uint256 bfrAmount0 = IVester(bfrVester).claimForAccount(
account,
account
);
uint256 bfrAmount1 = IVester(blpVester).claimForAccount(
account,
account
);
bfrAmount = bfrAmount0.add(bfrAmount1);
}
if (_shouldStakeBfr && bfrAmount > 0) {
_stakeBfr(account, account, bfr, bfrAmount);
}
uint256 esBfrAmount = 0;
if (_shouldClaimEsBfr) {
uint256 esBfrAmount0 = IRewardTracker(stakedBfrTracker)
.claimForAccount(account, account);
uint256 esBfrAmount1 = IRewardTracker(stakedBlpTracker)
.claimForAccount(account, account);
esBfrAmount = esBfrAmount0.add(esBfrAmount1);
}
if (_shouldStakeEsBfr && esBfrAmount > 0) {
_stakeBfr(account, account, esBfr, esBfrAmount);
}
if (_shouldStakeMultiplierPoints) {
uint256 bnBfrAmount = IRewardTracker(bonusBfrTracker)
.claimForAccount(account, account);
if (bnBfrAmount > 0) {
IRewardTracker(feeBfrTracker).stakeForAccount(
account,
account,
bnBfr,
bnBfrAmount
);
}
}
if (_shouldClaimUsdc) {
IRewardTracker(feeBfrTracker).claimForAccount(account, account);
IRewardTracker(feeBlpTracker).claimForAccount(account, account);
}
}
function batchCompoundForAccounts(address[] memory _accounts)
external
nonReentrant
onlyGov
{
for (uint256 i = 0; i < _accounts.length; i++) {
_compound(_accounts[i]);
}
}
function signalTransfer(address _receiver) external nonReentrant {
require(
IERC20(bfrVester).balanceOf(msg.sender) == 0,
"RewardRouter: sender has vested tokens"
);
require(
IERC20(blpVester).balanceOf(msg.sender) == 0,
"RewardRouter: sender has vested tokens"
);
_validateReceiver(_receiver);
pendingReceivers[msg.sender] = _receiver;
}
function acceptTransfer(address _sender) external nonReentrant {
require(
IERC20(bfrVester).balanceOf(_sender) == 0,
"RewardRouter: sender has vested tokens"
);
require(
IERC20(blpVester).balanceOf(_sender) == 0,
"RewardRouter: sender has vested tokens"
);
address receiver = msg.sender;
require(
pendingReceivers[_sender] == receiver,
"RewardRouter: transfer not signalled"
);
delete pendingReceivers[_sender];
_validateReceiver(receiver);
_compound(_sender);
uint256 stakedBfr = IRewardTracker(stakedBfrTracker).depositBalances(
_sender,
bfr
);
if (stakedBfr > 0) {
_unstakeBfr(_sender, bfr, stakedBfr, false);
_stakeBfr(_sender, receiver, bfr, stakedBfr);
}
uint256 stakedEsBfr = IRewardTracker(stakedBfrTracker).depositBalances(
_sender,
esBfr
);
if (stakedEsBfr > 0) {
_unstakeBfr(_sender, esBfr, stakedEsBfr, false);
_stakeBfr(_sender, receiver, esBfr, stakedEsBfr);
}
uint256 stakedBnBfr = IRewardTracker(feeBfrTracker).depositBalances(
_sender,
bnBfr
);
if (stakedBnBfr > 0) {
IRewardTracker(feeBfrTracker).unstakeForAccount(
_sender,
bnBfr,
stakedBnBfr,
_sender
);
IRewardTracker(feeBfrTracker).stakeForAccount(
_sender,
receiver,
bnBfr,
stakedBnBfr
);
}
uint256 esBfrBalance = IERC20(esBfr).balanceOf(_sender);
if (esBfrBalance > 0) {
IERC20(esBfr).transferFrom(_sender, receiver, esBfrBalance);
}
uint256 blpAmount = IRewardTracker(feeBlpTracker).depositBalances(
_sender,
blp
);
if (blpAmount > 0) {
IRewardTracker(stakedBlpTracker).unstakeForAccount(
_sender,
feeBlpTracker,
blpAmount,
_sender
);
IRewardTracker(feeBlpTracker).unstakeForAccount(
_sender,
blp,
blpAmount,
_sender
);
IRewardTracker(feeBlpTracker).stakeForAccount(
_sender,
receiver,
blp,
blpAmount
);
IRewardTracker(stakedBlpTracker).stakeForAccount(
receiver,
receiver,
feeBlpTracker,
blpAmount
);
}
IVester(bfrVester).transferStakeValues(_sender, receiver);
IVester(blpVester).transferStakeValues(_sender, receiver);
}
function _validateReceiver(address _receiver) private view {
require(
IRewardTracker(stakedBfrTracker).averageStakedAmounts(_receiver) ==
0,
"RewardRouter: stakedBfrTracker.averageStakedAmounts > 0"
);
require(
IRewardTracker(stakedBfrTracker).cumulativeRewards(_receiver) == 0,
"RewardRouter: stakedBfrTracker.cumulativeRewards > 0"
);
require(
IRewardTracker(bonusBfrTracker).averageStakedAmounts(_receiver) ==
0,
"RewardRouter: bonusBfrTracker.averageStakedAmounts > 0"
);
require(
IRewardTracker(bonusBfrTracker).cumulativeRewards(_receiver) == 0,
"RewardRouter: bonusBfrTracker.cumulativeRewards > 0"
);
require(
IRewardTracker(feeBfrTracker).averageStakedAmounts(_receiver) == 0,
"RewardRouter: feeBfrTracker.averageStakedAmounts > 0"
);
require(
IRewardTracker(feeBfrTracker).cumulativeRewards(_receiver) == 0,
"RewardRouter: feeBfrTracker.cumulativeRewards > 0"
);
require(
IVester(bfrVester).transferredAverageStakedAmounts(_receiver) == 0,
"RewardRouter: bfrVester.transferredAverageStakedAmounts > 0"
);
require(
IVester(bfrVester).transferredCumulativeRewards(_receiver) == 0,
"RewardRouter: bfrVester.transferredCumulativeRewards > 0"
);
require(
IRewardTracker(stakedBlpTracker).averageStakedAmounts(_receiver) ==
0,
"RewardRouter: stakedBlpTracker.averageStakedAmounts > 0"
);
require(
IRewardTracker(stakedBlpTracker).cumulativeRewards(_receiver) == 0,
"RewardRouter: stakedBlpTracker.cumulativeRewards > 0"
);
require(
IRewardTracker(feeBlpTracker).averageStakedAmounts(_receiver) == 0,
"RewardRouter: feeBlpTracker.averageStakedAmounts > 0"
);
require(
IRewardTracker(feeBlpTracker).cumulativeRewards(_receiver) == 0,
"RewardRouter: feeBlpTracker.cumulativeRewards > 0"
);
require(
IVester(blpVester).transferredAverageStakedAmounts(_receiver) == 0,
"RewardRouter: bfrVester.transferredAverageStakedAmounts > 0"
);
require(
IVester(blpVester).transferredCumulativeRewards(_receiver) == 0,
"RewardRouter: bfrVester.transferredCumulativeRewards > 0"
);
require(
IERC20(bfrVester).balanceOf(_receiver) == 0,
"RewardRouter: bfrVester.balance > 0"
);
require(
IERC20(blpVester).balanceOf(_receiver) == 0,
"RewardRouter: blpVester.balance > 0"
);
}
function _compound(address _account) private {
_compoundBfr(_account);
_compoundBlp(_account);
}
function _compoundBfr(address _account) private {
uint256 esBfrAmount = IRewardTracker(stakedBfrTracker).claimForAccount(
_account,
_account
);
if (esBfrAmount > 0) {
_stakeBfr(_account, _account, esBfr, esBfrAmount);
}
uint256 bnBfrAmount = IRewardTracker(bonusBfrTracker).claimForAccount(
_account,
_account
);
if (bnBfrAmount > 0) {
IRewardTracker(feeBfrTracker).stakeForAccount(
_account,
_account,
bnBfr,
bnBfrAmount
);
}
}
function _compoundBlp(address _account) private {
uint256 esBfrAmount = IRewardTracker(stakedBlpTracker).claimForAccount(
_account,
_account
);
if (esBfrAmount > 0) {
_stakeBfr(_account, _account, esBfr, esBfrAmount);
}
}
function _stakeBfr(
address _fundingAccount,
address _account,
address _token,
uint256 _amount
) private {
require(_amount > 0, "RewardRouter: invalid _amount");
IRewardTracker(stakedBfrTracker).stakeForAccount(
_fundingAccount,
_account,
_token,
_amount
);
IRewardTracker(bonusBfrTracker).stakeForAccount(
_account,
_account,
stakedBfrTracker,
_amount
);
IRewardTracker(feeBfrTracker).stakeForAccount(
_account,
_account,
bonusBfrTracker,
_amount
);
emit StakeBfr(_account, _token, _amount);
}
function _unstakeBfr(
address _account,
address _token,
uint256 _amount,
bool _shouldReduceBnBfr
) private {
require(_amount > 0, "RewardRouter: invalid _amount");
uint256 balance = IRewardTracker(stakedBfrTracker).stakedAmounts(
_account
);
IRewardTracker(feeBfrTracker).unstakeForAccount(
_account,
bonusBfrTracker,
_amount,
_account
);
IRewardTracker(bonusBfrTracker).unstakeForAccount(
_account,
stakedBfrTracker,
_amount,
_account
);
IRewardTracker(stakedBfrTracker).unstakeForAccount(
_account,
_token,
_amount,
_account
);
if (_shouldReduceBnBfr) {
uint256 bnBfrAmount = IRewardTracker(bonusBfrTracker)
.claimForAccount(_account, _account);
if (bnBfrAmount > 0) {
IRewardTracker(feeBfrTracker).stakeForAccount(
_account,
_account,
bnBfr,
bnBfrAmount
);
}
uint256 stakedBnBfr = IRewardTracker(feeBfrTracker).depositBalances(
_account,
bnBfr
);
if (stakedBnBfr > 0) {
uint256 reductionAmount = stakedBnBfr.mul(_amount).div(balance);
IRewardTracker(feeBfrTracker).unstakeForAccount(
_account,
bnBfr,
reductionAmount,
_account
);
IMintable(bnBfr).burn(_account, reductionAmount);
}
}
emit UnstakeBfr(_account, _token, _amount);
}
}
文件 10 的 12:SafeERC20.sol
pragma solidity ^0.8.0;
import "IERC20.sol";
import "draft-IERC20Permit.sol";
import "Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
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");
}
}
}
文件 11 的 12:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 12 的 12:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"RewardRouterV2.sol": "RewardRouterV2"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1
},
"remappings": []
}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeBfr","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeBlp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakeBfr","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakeBlp","type":"event"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"acceptTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"}],"name":"batchCompoundForAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_accounts","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"batchStakeBfrForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bfr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bfrVester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blpManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blpVester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bnBfr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusBfrTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimEsBfr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"compoundForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"esBfr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBfrTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBlpTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldClaimBfr","type":"bool"},{"internalType":"bool","name":"_shouldStakeBfr","type":"bool"},{"internalType":"bool","name":"_shouldClaimEsBfr","type":"bool"},{"internalType":"bool","name":"_shouldStakeEsBfr","type":"bool"},{"internalType":"bool","name":"_shouldStakeMultiplierPoints","type":"bool"},{"internalType":"bool","name":"_shouldClaimUsdc","type":"bool"}],"name":"handleRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdc","type":"address"},{"internalType":"address","name":"_bfr","type":"address"},{"internalType":"address","name":"_esBfr","type":"address"},{"internalType":"address","name":"_bnBfr","type":"address"},{"internalType":"address","name":"_blp","type":"address"},{"internalType":"address","name":"_stakedBfrTracker","type":"address"},{"internalType":"address","name":"_bonusBfrTracker","type":"address"},{"internalType":"address","name":"_feeBfrTracker","type":"address"},{"internalType":"address","name":"_feeBlpTracker","type":"address"},{"internalType":"address","name":"_stakedBlpTracker","type":"address"},{"internalType":"address","name":"_bfrVester","type":"address"},{"internalType":"address","name":"_blpVester","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minBlp","type":"uint256"}],"name":"mintAndStakeBlp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingReceivers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gov","type":"address"}],"name":"setGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"signalTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeBfr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeBfrForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeEsBfr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakedBfrTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakedBlpTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blpAmount","type":"uint256"}],"name":"unstakeAndRedeemBlp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeBfr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeEsBfr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]