编译器
0.6.12+commit.27d51765
文件 1 的 9:Address.sol
pragma solidity ^0.6.2;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 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) private 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 的 9:Governable.sol
pragma solidity 0.6.12;
contract Governable {
address public gov;
constructor() public {
gov = msg.sender;
}
modifier onlyGov() {
require(msg.sender == gov, "Governable: forbidden");
_;
}
function setGov(address _gov) external onlyGov {
gov = _gov;
}
}
文件 3 的 9:IERC20.sol
pragma solidity 0.6.12;
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);
}
文件 4 的 9:IMintable.sol
pragma solidity 0.6.12;
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;
}
文件 5 的 9:IRewardTracker.sol
pragma solidity 0.6.12;
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);
}
文件 6 的 9:ReentrancyGuard.sol
pragma solidity 0.6.12;
contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 7 的 9:SafeERC20.sol
pragma solidity 0.6.12;
import "./IERC20.sol";
import "../math/SafeMath.sol";
import "../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
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).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_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");
}
}
}
文件 8 的 9:SafeMath.sol
pragma solidity 0.6.12;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 9 的 9:VEILStakingRouter.sol
pragma solidity 0.6.12;
import "./libraries/math/SafeMath.sol";
import "./libraries/token/IERC20.sol";
import "./libraries/token/SafeERC20.sol";
import "./libraries/utils/ReentrancyGuard.sol";
import "./libraries/utils/Address.sol";
import "./interfaces/IRewardTracker.sol";
import "./interfaces/IMintable.sol";
import "./access/Governable.sol";
contract VEILStakingRouter is ReentrancyGuard, Governable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
using Address for address payable;
bool public isInitialized;
address public stakingToken;
address public stakingTokenTracker;
address public revenueToken;
address public revenueTokenTracker;
address public bonusToken;
address public bonusTokenTracker;
event Stake(address account, address token, uint256 amount);
event Unstake(address account, address token, uint256 amount);
receive() external payable {
require(msg.sender == revenueToken, "Router: invalid sender");
}
function initialize(
address _revenueToken,
address _stakingToken,
address _bnToken,
address _stakingTokenTracker,
address _bonusTokenTracker,
address _revenueTokenTracker
) external onlyGov {
require(!isInitialized, "RewardRouter: already initialized");
isInitialized = true;
revenueToken = _revenueToken;
stakingToken = _stakingToken;
bonusToken = _bnToken;
stakingTokenTracker = _stakingTokenTracker;
bonusTokenTracker = _bonusTokenTracker;
revenueTokenTracker = _revenueTokenTracker;
}
function withdrawToken(address _token, address _account, uint256 _amount) external onlyGov {
IERC20(_token).safeTransfer(_account, _amount);
}
function batchStakeForAccount(address[] memory _accounts, uint256[] memory _amounts)
external
nonReentrant
onlyGov
{
address _stakingToken = stakingToken;
for (uint256 i = 0; i < _accounts.length; i++) {
_stake(msg.sender, _accounts[i], _stakingToken, _amounts[i]);
}
}
function stakeForAccount(address _account, uint256 _amount) external nonReentrant onlyGov {
_stake(msg.sender, _account, stakingToken, _amount);
}
function stake(uint256 _amount) external nonReentrant {
_stake(msg.sender, msg.sender, stakingToken, _amount);
}
function unstake(uint256 _amount) external nonReentrant {
_unstake(msg.sender, stakingToken, _amount, true);
}
function claim() external nonReentrant {
address account = msg.sender;
IRewardTracker(revenueTokenTracker).claimForAccount(account, account);
IRewardTracker(stakingTokenTracker).claimForAccount(account, account);
}
function claimNativeRewards() external nonReentrant {
address account = msg.sender;
IRewardTracker(stakingTokenTracker).claimForAccount(account, account);
}
function claimRevenueToken() external nonReentrant {
address account = msg.sender;
IRewardTracker(revenueTokenTracker).claimForAccount(account, account);
}
function compound() external nonReentrant {
_compound(msg.sender);
}
function compoundBoth() external nonReentrant {
_compound_both(msg.sender);
}
function compoundForAccount(address _account) external nonReentrant onlyGov {
_compound(_account);
}
function batchCompoundForAccounts(address[] memory _accounts) external nonReentrant onlyGov {
for (uint256 i = 0; i < _accounts.length; i++) {
_compound(_accounts[i]);
}
}
function handleRewards(
bool _shouldClaimNativeRewards,
bool _shouldStakeMultiplierPoints,
bool _shouldClaimRevenueToken
) external nonReentrant {
address account = msg.sender;
uint256 nativeRewardsAmount = 0;
if (_shouldClaimNativeRewards) {
nativeRewardsAmount = IRewardTracker(stakingTokenTracker).claimForAccount(account, account);
}
if (_shouldStakeMultiplierPoints) {
uint256 bnTokenAmount = IRewardTracker(bonusTokenTracker).claimForAccount(account, account);
if (bnTokenAmount > 0) {
IRewardTracker(revenueTokenTracker).stakeForAccount(account, account, bonusToken, bnTokenAmount);
}
}
if (_shouldClaimRevenueToken) {
IRewardTracker(revenueTokenTracker).claimForAccount(account, account);
}
}
function _compound(address _account) private {
uint256 revenueTokenAmount = IRewardTracker(revenueTokenTracker).claimForAccount(_account, _account);
if (revenueTokenAmount > 0) {
_stake(_account, _account, stakingToken, revenueTokenAmount);
}
uint256 bnTokenAmount = IRewardTracker(bonusTokenTracker).claimForAccount(_account, _account);
if (bnTokenAmount > 0) {
IRewardTracker(revenueTokenTracker).stakeForAccount(_account, _account, bonusToken, bnTokenAmount);
}
}
function _compound_both(address _account) private {
uint256 nativeRewardsAmount = IRewardTracker(stakingTokenTracker).claimForAccount(_account, _account);
if (nativeRewardsAmount > 0) {
_stake(_account, _account, stakingToken, nativeRewardsAmount);
}
uint256 revenueTokenAmount = IRewardTracker(revenueTokenTracker).claimForAccount(_account, _account);
if (revenueTokenAmount > 0) {
_stake(_account, _account, stakingToken, revenueTokenAmount);
}
uint256 bnTokenAmount = IRewardTracker(bonusTokenTracker).claimForAccount(_account, _account);
if (bnTokenAmount > 0) {
IRewardTracker(revenueTokenTracker).stakeForAccount(_account, _account, bonusToken, bnTokenAmount);
}
}
function _stake(address _fundingAccount, address _account, address _token, uint256 _amount) private {
require(_amount > 0, "RewardRouter: invalid _amount");
IRewardTracker(stakingTokenTracker).stakeForAccount(_fundingAccount, _account, _token, _amount);
IRewardTracker(bonusTokenTracker).stakeForAccount(_account, _account, stakingTokenTracker, _amount);
IRewardTracker(revenueTokenTracker).stakeForAccount(_account, _account, bonusTokenTracker, _amount);
emit Stake(_account, _token, _amount);
}
function _unstake(address _account, address _token, uint256 _amount, bool _shouldReduceBnBmx) private {
require(_amount > 0, "RewardRouter: invalid _amount");
uint256 balance = IRewardTracker(stakingTokenTracker).stakedAmounts(_account);
IRewardTracker(revenueTokenTracker).unstakeForAccount(_account, bonusTokenTracker, _amount, _account);
IRewardTracker(bonusTokenTracker).unstakeForAccount(_account, stakingTokenTracker, _amount, _account);
IRewardTracker(stakingTokenTracker).unstakeForAccount(_account, _token, _amount, _account);
if (_shouldReduceBnBmx) {
uint256 bnTokenAmount = IRewardTracker(bonusTokenTracker).claimForAccount(_account, _account);
if (bnTokenAmount > 0) {
IRewardTracker(revenueTokenTracker).stakeForAccount(_account, _account, bonusToken, bnTokenAmount);
}
uint256 stakedBnBmx = IRewardTracker(revenueTokenTracker).depositBalances(_account, bonusToken);
if (stakedBnBmx > 0) {
uint256 reductionAmount = stakedBnBmx.mul(_amount).div(balance);
IRewardTracker(revenueTokenTracker).unstakeForAccount(_account, bonusToken, reductionAmount, _account);
IMintable(bonusToken).burn(_account, reductionAmount);
}
}
emit Unstake(_account, _token, _amount);
}
}
{
"compilationTarget": {
"src/VEILStakingRouter.sol": "VEILStakingRouter"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/=lib/openzeppelin-contracts/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/"
]
}
[{"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":"Stake","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":"Unstake","type":"event"},{"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":"batchStakeForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bonusToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusTokenTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimNativeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRevenueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"compoundBoth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"compoundForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldClaimNativeRewards","type":"bool"},{"internalType":"bool","name":"_shouldStakeMultiplierPoints","type":"bool"},{"internalType":"bool","name":"_shouldClaimRevenueToken","type":"bool"}],"name":"handleRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_revenueToken","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"},{"internalType":"address","name":"_bnToken","type":"address"},{"internalType":"address","name":"_stakingTokenTracker","type":"address"},{"internalType":"address","name":"_bonusTokenTracker","type":"address"},{"internalType":"address","name":"_revenueTokenTracker","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revenueToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revenueTokenTracker","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":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingTokenTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","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"}]