编译器
0.8.19+commit.7dd6d404
文件 1 的 16: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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 16:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 16:FixedPoint96.sol
pragma solidity >=0.4.0;
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}
文件 4 的 16:IDecentralizedIndex.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface IDecentralizedIndex is IERC20 {
enum IndexType {
WEIGHTED,
UNWEIGHTED
}
struct Config {
address partner;
bool hasTransferTax;
bool blacklistTKNpTKNPoolV2;
}
struct Fees {
uint16 burn;
uint16 bond;
uint16 debond;
uint16 buy;
uint16 sell;
uint16 partner;
}
struct IndexAssetInfo {
address token;
uint256 weighting;
uint256 basePriceUSDX96;
address c1;
uint256 q1;
}
event Create(address indexed newIdx, address indexed wallet);
event Initialize(address indexed wallet, address v2Pool);
event Bond(
address indexed wallet,
address indexed token,
uint256 amountTokensBonded,
uint256 amountTokensMinted
);
event Debond(address indexed wallet, uint256 amountDebonded);
event AddLiquidity(
address indexed wallet,
uint256 amountTokens,
uint256 amountDAI
);
event RemoveLiquidity(address indexed wallet, uint256 amountLiquidity);
event SetPartner(address indexed wallet, address newPartner);
event SetPartnerFee(address indexed wallet, uint16 newFee);
function BOND_FEE() external view returns (uint16);
function DEBOND_FEE() external view returns (uint16);
function FLASH_FEE_AMOUNT_DAI() external view returns (uint256);
function PAIRED_LP_TOKEN() external view returns (address);
function indexType() external view returns (IndexType);
function created() external view returns (uint256);
function lpStakingPool() external view returns (address);
function lpRewardsToken() external view returns (address);
function partner() external view returns (address);
function getIdxPriceUSDX96() external view returns (uint256, uint256);
function isAsset(address token) external view returns (bool);
function getAllAssets() external view returns (IndexAssetInfo[] memory);
function getInitialAmount(
address sToken,
uint256 sAmount,
address tToken
) external view returns (uint256);
function getTokenPriceUSDX96(address token) external view returns (uint256);
function processPreSwapFeesAndSwap() external;
function bond(address token, uint256 amount, uint256 amountMintMin) external;
function debond(
uint256 amount,
address[] memory token,
uint8[] memory percentage
) external;
function addLiquidityV2(
uint256 idxTokens,
uint256 daiTokens,
uint256 slippage,
uint256 deadline
) external returns (uint256);
function removeLiquidityV2(
uint256 lpTokens,
uint256 minTokens,
uint256 minDAI,
uint256 deadline
) external;
function flash(
address recipient,
address token,
uint256 amount,
bytes calldata data
) external;
}
文件 5 的 16:IDexAdapter.sol
pragma solidity ^0.8.19;
interface IDexAdapter {
function ASYNC_INITIALIZE() external view returns (bool);
function V2_ROUTER() external view returns (address);
function V3_ROUTER() external view returns (address);
function WETH() external view returns (address);
function getV3Pool(
address _token0,
address _token1,
int24 _tickSpacing
) external view returns (address _pool);
function getV3Pool(
address _token0,
address _token1,
uint24 _poolFee
) external view returns (address _pool);
function getV2Pool(
address _token0,
address _token1
) external view returns (address _pool);
function createV2Pool(
address _token0,
address _token1
) external returns (address _pool);
function swapV2Single(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function swapV3Single(
address _tokenIn,
address _tokenOut,
uint24 _fee,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
function extraRewardsHook(
address _token0,
address _token1
) external returns (address[] memory tokens, uint256[] memory amounts);
}
文件 6 的 16: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);
}
文件 7 的 16: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);
}
文件 8 的 16:IPEAS.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
interface IPEAS is IERC20 {
event Burn(address indexed user, uint256 amount);
function burn(uint256 amount) external;
}
文件 9 的 16:IProtocolFeeRouter.sol
pragma solidity ^0.8.19;
import './IProtocolFees.sol';
interface IProtocolFeeRouter {
function protocolFees() external view returns (IProtocolFees);
}
文件 10 的 16:IProtocolFees.sol
pragma solidity ^0.8.19;
interface IProtocolFees {
event SetYieldAdmin(uint256 newFee);
event SetYieldBurn(uint256 newFee);
function DEN() external view returns (uint256);
function yieldAdmin() external view returns (uint256);
function yieldBurn() external view returns (uint256);
}
文件 11 的 16:IRewardsWhitelister.sol
pragma solidity ^0.8.19;
interface IRewardsWhitelister {
function whitelist(address token) external view returns (bool);
function getFullWhitelist() external view returns (address[] memory);
}
文件 12 的 16:ITokenRewards.sol
pragma solidity ^0.8.19;
interface ITokenRewards {
event AddShares(address indexed wallet, uint256 amount);
event RemoveShares(address indexed wallet, uint256 amount);
event ClaimReward(address indexed wallet);
event DistributeReward(
address indexed wallet,
address indexed token,
uint256 amount
);
event DepositRewards(
address indexed wallet,
address indexed token,
uint256 amount
);
function totalShares() external view returns (uint256);
function totalStakers() external view returns (uint256);
function rewardsToken() external view returns (address);
function trackingToken() external view returns (address);
function depositFromPairedLpToken(
uint256 amount,
uint256 slippageOverride
) external;
function depositRewards(address token, uint256 amount) external;
function depositRewardsNoTransfer(address token, uint256 amount) external;
function claimReward(address wallet) external;
function setShares(
address wallet,
uint256 amount,
bool sharesRemoving
) external;
}
文件 13 的 16:IV3TwapUtilities.sol
pragma solidity ^0.8.19;
interface IV3TwapUtilities {
function getV3Pool(
address v3Factory,
address token0,
address token1
) external view returns (address);
function getV3Pool(
address v3Factory,
address token0,
address token1,
uint24 poolFee
) external view returns (address);
function getV3Pool(
address v3Factory,
address token0,
address token1,
int24 tickSpacing
) external view returns (address);
function getPoolPriceUSDX96(
address pricePool,
address nativeStablePool,
address WETH9
) external view returns (uint256);
function sqrtPriceX96FromPoolAndInterval(
address pool
) external view returns (uint160);
function priceX96FromSqrtPriceX96(
uint160 sqrtPriceX96
) external pure returns (uint256);
}
文件 14 的 16:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 15 的 16:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/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 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
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");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
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");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 16 的 16:TokenRewards.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/utils/Context.sol';
import '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';
import './interfaces/IDecentralizedIndex.sol';
import './interfaces/IDexAdapter.sol';
import './interfaces/IPEAS.sol';
import './interfaces/IRewardsWhitelister.sol';
import './interfaces/IProtocolFees.sol';
import './interfaces/IProtocolFeeRouter.sol';
import './interfaces/ITokenRewards.sol';
import './interfaces/IV3TwapUtilities.sol';
contract TokenRewards is ITokenRewards, Context {
using SafeERC20 for IERC20;
uint256 constant PRECISION = 10 ** 36;
uint24 constant REWARDS_POOL_FEE = 10000;
int24 constant REWARDS_TICK_SPACING = 200;
address immutable INDEX_FUND;
address immutable PAIRED_LP_TOKEN;
IProtocolFeeRouter immutable PROTOCOL_FEE_ROUTER;
IRewardsWhitelister immutable REWARDS_WHITELISTER;
IDexAdapter immutable DEX_ADAPTER;
IV3TwapUtilities immutable V3_TWAP_UTILS;
struct Reward {
uint256 excluded;
uint256 realized;
}
address public immutable override trackingToken;
address public immutable override rewardsToken;
uint256 public override totalShares;
uint256 public override totalStakers;
mapping(address => uint256) public shares;
mapping(address => mapping(address => Reward)) public rewards;
uint256 _rewardsSwapSlippage = 20;
mapping(address => uint256) _rewardsPerShare;
mapping(address => uint256) public rewardsDistributed;
mapping(address => uint256) public rewardsDeposited;
address[] _allRewardsTokens;
mapping(address => bool) _depositedRewardsToken;
constructor(
IProtocolFeeRouter _feeRouter,
IRewardsWhitelister _rewardsWhitelist,
IDexAdapter _dexHandler,
IV3TwapUtilities _v3TwapUtilities,
address _indexFund,
address _pairedLpToken,
address _trackingToken,
address _rewardsToken
) {
PROTOCOL_FEE_ROUTER = _feeRouter;
REWARDS_WHITELISTER = _rewardsWhitelist;
DEX_ADAPTER = _dexHandler;
V3_TWAP_UTILS = _v3TwapUtilities;
INDEX_FUND = _indexFund;
PAIRED_LP_TOKEN = _pairedLpToken;
trackingToken = _trackingToken;
rewardsToken = _rewardsToken;
}
function setShares(
address _wallet,
uint256 _amount,
bool _sharesRemoving
) external override {
require(_msgSender() == trackingToken, 'UNAUTHORIZED');
_setShares(_wallet, _amount, _sharesRemoving);
}
function _setShares(
address _wallet,
uint256 _amount,
bool _sharesRemoving
) internal {
_processFeesIfApplicable();
if (_sharesRemoving) {
_removeShares(_wallet, _amount);
emit RemoveShares(_wallet, _amount);
} else {
_addShares(_wallet, _amount);
emit AddShares(_wallet, _amount);
}
}
function _addShares(address _wallet, uint256 _amount) internal {
if (shares[_wallet] > 0) {
_distributeReward(_wallet);
}
uint256 sharesBefore = shares[_wallet];
totalShares += _amount;
shares[_wallet] += _amount;
if (sharesBefore == 0 && shares[_wallet] > 0) {
totalStakers++;
}
_resetExcluded(_wallet);
}
function _removeShares(address _wallet, uint256 _amount) internal {
require(shares[_wallet] > 0 && _amount <= shares[_wallet], 'RE');
_distributeReward(_wallet);
totalShares -= _amount;
shares[_wallet] -= _amount;
if (shares[_wallet] == 0) {
totalStakers--;
}
_resetExcluded(_wallet);
}
function _processFeesIfApplicable() internal {
IDecentralizedIndex(INDEX_FUND).processPreSwapFeesAndSwap();
}
function depositFromPairedLpToken(
uint256 _amountTknDepositing,
uint256 _slippageOverride
) public override {
require(PAIRED_LP_TOKEN != rewardsToken, 'R');
require(_slippageOverride <= 200, 'MS');
if (_amountTknDepositing > 0) {
IERC20(PAIRED_LP_TOKEN).safeTransferFrom(
_msgSender(),
address(this),
_amountTknDepositing
);
}
uint256 _amountTkn = IERC20(PAIRED_LP_TOKEN).balanceOf(address(this));
require(_amountTkn > 0, 'A');
uint256 _adminAmt = _getAdminFeeFromAmount(_amountTkn);
_amountTkn -= _adminAmt;
(address _token0, address _token1) = PAIRED_LP_TOKEN < rewardsToken
? (PAIRED_LP_TOKEN, rewardsToken)
: (rewardsToken, PAIRED_LP_TOKEN);
address _pool;
try DEX_ADAPTER.getV3Pool(_token0, _token1, REWARDS_POOL_FEE) returns (
address __pool
) {
_pool = __pool;
} catch {
_pool = DEX_ADAPTER.getV3Pool(_token0, _token1, REWARDS_TICK_SPACING);
}
uint160 _rewardsSqrtPriceX96 = V3_TWAP_UTILS
.sqrtPriceX96FromPoolAndInterval(_pool);
uint256 _rewardsPriceX96 = V3_TWAP_UTILS.priceX96FromSqrtPriceX96(
_rewardsSqrtPriceX96
);
uint256 _amountOut = _token0 == PAIRED_LP_TOKEN
? (_rewardsPriceX96 * _amountTkn) / FixedPoint96.Q96
: (_amountTkn * FixedPoint96.Q96) / _rewardsPriceX96;
uint256 _slippage = _slippageOverride > 0
? _slippageOverride
: _rewardsSwapSlippage;
_swapForRewards(
_amountTkn,
_amountOut,
_slippage,
_slippageOverride > 0,
_adminAmt
);
}
function depositRewards(address _token, uint256 _amount) external override {
_depositRewardsFromToken(_msgSender(), _token, _amount, true);
}
function depositRewardsNoTransfer(
address _token,
uint256 _amount
) external override {
require(_msgSender() == INDEX_FUND, 'AUTH');
_depositRewardsFromToken(_msgSender(), _token, _amount, false);
}
function _depositRewardsFromToken(
address _user,
address _token,
uint256 _amount,
bool _shouldTransfer
) internal {
require(_amount > 0, 'A');
require(_isValidRewardsToken(_token), 'V');
uint256 _finalAmt = _amount;
if (_shouldTransfer) {
uint256 _balBefore = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransferFrom(_user, address(this), _finalAmt);
_finalAmt = IERC20(_token).balanceOf(address(this)) - _balBefore;
}
uint256 _adminAmt = _getAdminFeeFromAmount(_finalAmt);
if (_adminAmt > 0) {
IERC20(_token).safeTransfer(
Ownable(address(V3_TWAP_UTILS)).owner(),
_adminAmt
);
_finalAmt -= _adminAmt;
}
_depositRewards(_token, _finalAmt);
}
function _depositRewards(address _token, uint256 _amountTotal) internal {
if (!_depositedRewardsToken[_token]) {
_depositedRewardsToken[_token] = true;
_allRewardsTokens.push(_token);
}
if (_amountTotal == 0) {
return;
}
if (totalShares == 0) {
require(_token == rewardsToken, 'R');
_burnRewards(_amountTotal);
return;
}
uint256 _depositAmount = _amountTotal;
if (_token == rewardsToken) {
(, uint256 _yieldBurnFee) = _getYieldFees();
if (_yieldBurnFee > 0) {
uint256 _burnAmount = (_amountTotal * _yieldBurnFee) /
PROTOCOL_FEE_ROUTER.protocolFees().DEN();
if (_burnAmount > 0) {
_burnRewards(_burnAmount);
_depositAmount -= _burnAmount;
}
}
}
rewardsDeposited[_token] += _depositAmount;
_rewardsPerShare[_token] += (PRECISION * _depositAmount) / totalShares;
emit DepositRewards(_msgSender(), _token, _depositAmount);
}
function _distributeReward(address _wallet) internal {
if (shares[_wallet] == 0) {
return;
}
for (uint256 _i; _i < _allRewardsTokens.length; _i++) {
address _token = _allRewardsTokens[_i];
uint256 _amount = getUnpaid(_token, _wallet);
rewards[_token][_wallet].realized += _amount;
rewards[_token][_wallet].excluded = _cumulativeRewards(
_token,
shares[_wallet]
);
if (_amount > 0) {
rewardsDistributed[_token] += _amount;
IERC20(_token).safeTransfer(_wallet, _amount);
emit DistributeReward(_wallet, _token, _amount);
}
}
}
function _resetExcluded(address _wallet) internal {
for (uint256 _i; _i < _allRewardsTokens.length; _i++) {
address _token = _allRewardsTokens[_i];
rewards[_token][_wallet].excluded = _cumulativeRewards(
_token,
shares[_wallet]
);
}
}
function _burnRewards(uint256 _burnAmount) internal {
try IPEAS(rewardsToken).burn(_burnAmount) {} catch {
IERC20(rewardsToken).safeTransfer(address(0xdead), _burnAmount);
}
}
function _isValidRewardsToken(address _token) internal view returns (bool) {
return _token == rewardsToken || REWARDS_WHITELISTER.whitelist(_token);
}
function _getAdminFeeFromAmount(
uint256 _amount
) internal view returns (uint256) {
(uint256 _yieldAdminFee, ) = _getYieldFees();
if (_yieldAdminFee == 0) {
return 0;
}
return
(_amount * _yieldAdminFee) / PROTOCOL_FEE_ROUTER.protocolFees().DEN();
}
function _getYieldFees()
internal
view
returns (uint256 _admin, uint256 _burn)
{
IProtocolFees _fees = PROTOCOL_FEE_ROUTER.protocolFees();
if (address(_fees) != address(0)) {
_admin = _fees.yieldAdmin();
_burn = _fees.yieldBurn();
}
}
function _swapForRewards(
uint256 _amountIn,
uint256 _amountOut,
uint256 _slippage,
bool _isSlipOverride,
uint256 _adminAmt
) internal {
uint256 _balBefore = IERC20(rewardsToken).balanceOf(address(this));
IERC20(PAIRED_LP_TOKEN).safeIncreaseAllowance(
address(DEX_ADAPTER),
_amountIn
);
try
DEX_ADAPTER.swapV3Single(
PAIRED_LP_TOKEN,
rewardsToken,
REWARDS_POOL_FEE,
_amountIn,
(_amountOut * (1000 - _slippage)) / 1000,
address(this)
)
{
if (_adminAmt > 0) {
IERC20(PAIRED_LP_TOKEN).safeTransfer(
Ownable(address(V3_TWAP_UTILS)).owner(),
_adminAmt
);
}
_rewardsSwapSlippage = 20;
_depositRewards(
rewardsToken,
IERC20(rewardsToken).balanceOf(address(this)) - _balBefore
);
} catch {
if (!_isSlipOverride && _rewardsSwapSlippage < 200) {
_rewardsSwapSlippage += 10;
}
IERC20(PAIRED_LP_TOKEN).safeDecreaseAllowance(
address(DEX_ADAPTER),
_amountIn
);
}
}
function claimReward(address _wallet) external override {
_distributeReward(_wallet);
emit ClaimReward(_wallet);
}
function getUnpaid(
address _token,
address _wallet
) public view returns (uint256) {
if (shares[_wallet] == 0) {
return 0;
}
uint256 earnedRewards = _cumulativeRewards(_token, shares[_wallet]);
uint256 rewardsExcluded = rewards[_token][_wallet].excluded;
if (earnedRewards <= rewardsExcluded) {
return 0;
}
return earnedRewards - rewardsExcluded;
}
function _cumulativeRewards(
address _token,
uint256 _share
) internal view returns (uint256) {
return (_share * _rewardsPerShare[_token]) / PRECISION;
}
}
{
"compilationTarget": {
"contracts/TokenRewards.sol": "TokenRewards"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IProtocolFeeRouter","name":"_feeRouter","type":"address"},{"internalType":"contract IRewardsWhitelister","name":"_rewardsWhitelist","type":"address"},{"internalType":"contract IDexAdapter","name":"_dexHandler","type":"address"},{"internalType":"contract IV3TwapUtilities","name":"_v3TwapUtilities","type":"address"},{"internalType":"address","name":"_indexFund","type":"address"},{"internalType":"address","name":"_pairedLpToken","type":"address"},{"internalType":"address","name":"_trackingToken","type":"address"},{"internalType":"address","name":"_rewardsToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AddShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"}],"name":"ClaimReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DistributeReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RemoveShares","type":"event"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountTknDepositing","type":"uint256"},{"internalType":"uint256","name":"_slippageOverride","type":"uint256"}],"name":"depositFromPairedLpToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositRewardsNoTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_wallet","type":"address"}],"name":"getUnpaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"excluded","type":"uint256"},{"internalType":"uint256","name":"realized","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_sharesRemoving","type":"bool"}],"name":"setShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trackingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]