文件 1 的 28: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;
}
}
文件 2 的 28:ContextUpgradeable.sol
pragma solidity ^0.8.0;
import "../proxy/Initializable.sol";
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this;
return msg.data;
}
uint256[50] private __gap;
}
文件 3 的 28:ERC721HolderUpgradeable.sol
pragma solidity ^0.8.0;
import "./IERC721ReceiverUpgradeable.sol";
contract ERC721HolderUpgradeable is IERC721ReceiverUpgradeable {
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
文件 4 的 28:IBeacon.sol
pragma solidity ^0.8.0;
interface IBeacon {
function childImplementation() external view returns (address);
function upgradeChildTo(address newImplementation) external;
}
文件 5 的 28:IERC1155ReceiverUpgradeable.sol
pragma solidity ^0.8.0;
import "../interface/IERC165Upgradeable.sol";
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
)
external
returns(bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
returns(bytes4);
}
文件 6 的 28:IERC1155Upgradeable.sol
pragma solidity ^0.8.0;
import "../interface/IERC165Upgradeable.sol";
interface IERC1155Upgradeable is IERC165Upgradeable {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}
文件 7 的 28:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 8 的 28:IERC165Upgradeable.sol
pragma solidity ^0.8.0;
interface IERC165Upgradeable {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 28:IERC20.sol
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
文件 10 的 28:IERC20Upgradeable.sol
pragma solidity ^0.8.0;
interface IERC20Upgradeable {
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);
}
文件 11 的 28: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
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 12 的 28:IERC721ReceiverUpgradeable.sol
pragma solidity ^0.8.0;
interface IERC721ReceiverUpgradeable {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
文件 13 的 28:INFTXEligibility.sol
pragma solidity ^0.8.0;
interface INFTXEligibility {
function name() external pure returns (string memory);
function finalized() external view returns (bool);
function targetAsset() external pure returns (address);
function checkAllEligible(uint256[] calldata tokenIds)
external
view
returns (bool);
function checkEligible(uint256[] calldata tokenIds)
external
view
returns (bool[] memory);
function checkAllIneligible(uint256[] calldata tokenIds)
external
view
returns (bool);
function checkIsEligible(uint256 tokenId) external view returns (bool);
function __NFTXEligibility_init_bytes(bytes calldata configData) external;
function beforeMintHook(uint256[] calldata tokenIds) external;
function afterMintHook(uint256[] calldata tokenIds) external;
function beforeRedeemHook(uint256[] calldata tokenIds) external;
function afterRedeemHook(uint256[] calldata tokenIds) external;
}
文件 14 的 28:INFTXFeeDistributor.sol
pragma solidity ^0.8.0;
interface INFTXFeeDistributor {
struct FeeReceiver {
uint256 allocPoint;
address receiver;
bool isContract;
}
function nftxVaultFactory() external returns (address);
function lpStaking() external returns (address);
function treasury() external returns (address);
function defaultTreasuryAlloc() external returns (uint256);
function defaultLPAlloc() external returns (uint256);
function allocTotal(uint256 vaultId) external returns (uint256);
function specificTreasuryAlloc(uint256 vaultId) external returns (uint256);
function __FeeDistributor__init__(address _lpStaking, address _treasury) external;
function rescueTokens(address token) external;
function distribute(uint256 vaultId) external;
function addReceiver(uint256 _vaultId, uint256 _allocPoint, address _receiver, bool _isContract) external;
function initializeVaultReceivers(uint256 _vaultId) external;
function changeMultipleReceiverAlloc(
uint256[] memory _vaultIds,
uint256[] memory _receiverIdxs,
uint256[] memory allocPoints
) external;
function changeMultipleReceiverAddress(
uint256[] memory _vaultIds,
uint256[] memory _receiverIdxs,
address[] memory addresses,
bool[] memory isContracts
) external;
function changeReceiverAlloc(uint256 _vaultId, uint256 _idx, uint256 _allocPoint) external;
function changeReceiverAddress(uint256 _vaultId, uint256 _idx, address _address, bool _isContract) external;
function removeReceiver(uint256 _vaultId, uint256 _receiverIdx) external;
function setTreasuryAddress(address _treasury) external;
function setDefaultTreasuryAlloc(uint256 _allocPoint) external;
function setSpecificTreasuryAlloc(uint256 _vaultId, uint256 _allocPoint) external;
function setLPStakingAddress(address _lpStaking) external;
function setNFTXVaultFactory(address _factory) external;
function setDefaultLPAlloc(uint256 _allocPoint) external;
}
文件 15 的 28:INFTXLPStaking.sol
pragma solidity ^0.8.0;
interface INFTXLPStaking {
function nftxVaultFactory() external view returns (address);
function rewardDistTokenImpl() external view returns (address);
function stakingTokenProvider() external view returns (address);
function vaultToken(address _stakingToken) external view returns (address);
function stakingToken(address _vaultToken) external view returns (address);
function rewardDistributionToken(uint256 vaultId) external view returns (address);
function newRewardDistributionToken(uint256 vaultId) external view returns (address);
function oldRewardDistributionToken(uint256 vaultId) external view returns (address);
function unusedRewardDistributionToken(uint256 vaultId) external view returns (address);
function rewardDistributionTokenAddr(address stakingToken, address rewardToken) external view returns (address);
function __NFTXLPStaking__init(address _stakingTokenProvider) external;
function setNFTXVaultFactory(address newFactory) external;
function setStakingTokenProvider(address newProvider) external;
function addPoolForVault(uint256 vaultId) external;
function updatePoolForVault(uint256 vaultId) external;
function updatePoolForVaults(uint256[] calldata vaultId) external;
function receiveRewards(uint256 vaultId, uint256 amount) external returns (bool);
function deposit(uint256 vaultId, uint256 amount) external;
function timelockDepositFor(uint256 vaultId, address account, uint256 amount, uint256 timelockLength) external;
function exit(uint256 vaultId, uint256 amount) external;
function rescue(uint256 vaultId) external;
function withdraw(uint256 vaultId, uint256 amount) external;
function claimRewards(uint256 vaultId) external;
}
文件 16 的 28:INFTXStakingZap.sol
pragma solidity ^0.8.0;
import "./INFTXVault.sol";
import "./INFTXVaultFactory.sol";
import "./INFTXFeeDistributor.sol";
import "./INFTXLPStaking.sol";
import "./ITimelockRewardDistributionToken.sol";
import "./IUniswapV2Router01.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";
import "../token/IERC1155Upgradeable.sol";
import "../token/IERC20Upgradeable.sol";
import "../token/ERC721HolderUpgradeable.sol";
import "../token/IERC1155ReceiverUpgradeable.sol";
import "../util/OwnableUpgradeable.sol";
abstract contract IWETH {
function deposit() virtual external payable;
function transfer(address to, uint value) virtual external returns (bool);
function withdraw(uint) virtual external;
}
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;
}
}
abstract contract INFTXStakingZap is IERC721ReceiverUpgradeable, IERC1155ReceiverUpgradeable {
IWETH public immutable WETH;
INFTXLPStaking public immutable lpStaking;
INFTXVaultFactory public immutable nftxFactory;
IUniswapV2Router01 public immutable sushiRouter;
uint256 public lockTime;
constructor(address _nftxFactory, address _sushiRouter) {
nftxFactory = INFTXVaultFactory(_nftxFactory);
lpStaking = INFTXLPStaking(INFTXFeeDistributor(INFTXVaultFactory(_nftxFactory).feeDistributor()).lpStaking());
sushiRouter = IUniswapV2Router01(_sushiRouter);
WETH = IWETH(IUniswapV2Router01(_sushiRouter).WETH());
IERC20Upgradeable(address(IUniswapV2Router01(_sushiRouter).WETH())).approve(_sushiRouter, type(uint256).max);
}
function setLockTime(uint256 newLockTime) virtual external;
function addLiquidity721ETH(
uint256 vaultId,
uint256[] memory ids,
uint256 minWethIn
) virtual external payable returns (uint256);
function addLiquidity721ETHTo(
uint256 vaultId,
uint256[] memory ids,
uint256 minWethIn,
address to
) virtual external payable returns (uint256);
function addLiquidity1155ETH(
uint256 vaultId,
uint256[] memory ids,
uint256[] memory amounts,
uint256 minEthIn
) virtual external payable returns (uint256);
function addLiquidity1155ETHTo(
uint256 vaultId,
uint256[] memory ids,
uint256[] memory amounts,
uint256 minEthIn,
address to
) virtual external payable returns (uint256);
function addLiquidity721(
uint256 vaultId,
uint256[] memory ids,
uint256 minWethIn,
uint256 wethIn
) virtual external returns (uint256);
function addLiquidity721To(
uint256 vaultId,
uint256[] memory ids,
uint256 minWethIn,
uint256 wethIn,
address to
) virtual external returns (uint256);
function addLiquidity1155(
uint256 vaultId,
uint256[] memory ids,
uint256[] memory amounts,
uint256 minWethIn,
uint256 wethIn
) virtual external returns (uint256);
function addLiquidity1155To(
uint256 vaultId,
uint256[] memory ids,
uint256[] memory amounts,
uint256 minWethIn,
uint256 wethIn,
address to
) virtual external returns (uint256);
function lockedUntil(uint256 vaultId, address who) virtual external view returns (uint256);
function lockedLPBalance(uint256 vaultId, address who) virtual external view returns (uint256);
receive() virtual external payable;
}
文件 17 的 28:INFTXVault.sol
pragma solidity ^0.8.0;
import "../interface/INFTXEligibility.sol";
import "../token/IERC20Upgradeable.sol";
import "../interface/INFTXVaultFactory.sol";
interface INFTXVault is IERC20Upgradeable {
function manager() external view returns (address);
function assetAddress() external view returns (address);
function vaultFactory() external view returns (INFTXVaultFactory);
function eligibilityStorage() external view returns (INFTXEligibility);
function is1155() external view returns (bool);
function allowAllItems() external view returns (bool);
function enableMint() external view returns (bool);
function enableRandomRedeem() external view returns (bool);
function enableTargetRedeem() external view returns (bool);
function enableRandomSwap() external view returns (bool);
function enableTargetSwap() external view returns (bool);
function vaultId() external view returns (uint256);
function nftIdAt(uint256 holdingsIndex) external view returns (uint256);
function allHoldings() external view returns (uint256[] memory);
function totalHoldings() external view returns (uint256);
function mintFee() external view returns (uint256);
function randomRedeemFee() external view returns (uint256);
function targetRedeemFee() external view returns (uint256);
function randomSwapFee() external view returns (uint256);
function targetSwapFee() external view returns (uint256);
function vaultFees() external view returns (uint256, uint256, uint256, uint256, uint256);
event VaultInit(
uint256 indexed vaultId,
address assetAddress,
bool is1155,
bool allowAllItems
);
event ManagerSet(address manager);
event EligibilityDeployed(uint256 moduleIndex, address eligibilityAddr);
event EnableMintUpdated(bool enabled);
event EnableRandomRedeemUpdated(bool enabled);
event EnableTargetRedeemUpdated(bool enabled);
event EnableRandomSwapUpdated(bool enabled);
event EnableTargetSwapUpdated(bool enabled);
event Minted(uint256[] nftIds, uint256[] amounts, address to);
event Redeemed(uint256[] nftIds, uint256[] specificIds, address to);
event Swapped(
uint256[] nftIds,
uint256[] amounts,
uint256[] specificIds,
uint256[] redeemedIds,
address to
);
function __NFTXVault_init(
string calldata _name,
string calldata _symbol,
address _assetAddress,
bool _is1155,
bool _allowAllItems
) external;
function finalizeVault() external;
function setVaultMetadata(
string memory name_,
string memory symbol_
) external;
function setVaultFeatures(
bool _enableMint,
bool _enableRandomRedeem,
bool _enableTargetRedeem,
bool _enableRandomSwap,
bool _enableTargetSwap
) external;
function setFees(
uint256 _mintFee,
uint256 _randomRedeemFee,
uint256 _targetRedeemFee,
uint256 _randomSwapFee,
uint256 _targetSwapFee
) external;
function disableVaultFees() external;
function deployEligibilityStorage(
uint256 moduleIndex,
bytes calldata initData
) external returns (address);
function setManager(address _manager) external;
function mint(
uint256[] calldata tokenIds,
uint256[] calldata amounts
) external returns (uint256);
function mintTo(
uint256[] calldata tokenIds,
uint256[] calldata amounts,
address to
) external returns (uint256);
function redeem(uint256 amount, uint256[] calldata specificIds)
external
returns (uint256[] calldata);
function redeemTo(
uint256 amount,
uint256[] calldata specificIds,
address to
) external returns (uint256[] calldata);
function swap(
uint256[] calldata tokenIds,
uint256[] calldata amounts,
uint256[] calldata specificIds
) external returns (uint256[] calldata);
function swapTo(
uint256[] calldata tokenIds,
uint256[] calldata amounts,
uint256[] calldata specificIds,
address to
) external returns (uint256[] calldata);
function allValidNFTs(uint256[] calldata tokenIds)
external
view
returns (bool);
}
文件 18 的 28:INFTXVaultFactory.sol
pragma solidity ^0.8.0;
import "../proxy/IBeacon.sol";
interface INFTXVaultFactory is IBeacon {
function numVaults() external view returns (uint256);
function zapContract() external view returns (address);
function feeDistributor() external view returns (address);
function eligibilityManager() external view returns (address);
function vault(uint256 vaultId) external view returns (address);
function allVaults() external view returns (address[] memory);
function vaultsForAsset(address asset) external view returns (address[] memory);
function isLocked(uint256 id) external view returns (bool);
function excludedFromFees(address addr) external view returns (bool);
function factoryMintFee() external view returns (uint64);
function factoryRandomRedeemFee() external view returns (uint64);
function factoryTargetRedeemFee() external view returns (uint64);
function factoryRandomSwapFee() external view returns (uint64);
function factoryTargetSwapFee() external view returns (uint64);
function vaultFees(uint256 vaultId) external view returns (uint256, uint256, uint256, uint256, uint256);
event NewFeeDistributor(address oldDistributor, address newDistributor);
event NewZapContract(address oldZap, address newZap);
event FeeExclusion(address feeExcluded, bool excluded);
event NewEligibilityManager(address oldEligManager, address newEligManager);
event NewVault(uint256 indexed vaultId, address vaultAddress, address assetAddress);
event UpdateVaultFees(uint256 vaultId, uint256 mintFee, uint256 randomRedeemFee, uint256 targetRedeemFee, uint256 randomSwapFee, uint256 targetSwapFee);
event DisableVaultFees(uint256 vaultId);
event UpdateFactoryFees(uint256 mintFee, uint256 randomRedeemFee, uint256 targetRedeemFee, uint256 randomSwapFee, uint256 targetSwapFee);
function __NFTXVaultFactory_init(address _vaultImpl, address _feeDistributor) external;
function createVault(
string calldata name,
string calldata symbol,
address _assetAddress,
bool is1155,
bool allowAllItems
) external returns (uint256);
function setFeeDistributor(address _feeDistributor) external;
function setEligibilityManager(address _eligibilityManager) external;
function setZapContract(address _zapContract) external;
function setFeeExclusion(address _excludedAddr, bool excluded) external;
function setFactoryFees(
uint256 mintFee,
uint256 randomRedeemFee,
uint256 targetRedeemFee,
uint256 randomSwapFee,
uint256 targetSwapFee
) external;
function setVaultFees(
uint256 vaultId,
uint256 mintFee,
uint256 randomRedeemFee,
uint256 targetRedeemFee,
uint256 randomSwapFee,
uint256 targetSwapFee
) external;
function disableVaultFees(uint256 vaultId) external;
}
文件 19 的 28:IRewardDistributionToken.sol
pragma solidity ^0.8.0;
import "../token/IERC20Upgradeable.sol";
interface IRewardDistributionToken is IERC20Upgradeable {
function distributeRewards(uint amount) external;
function __RewardDistributionToken_init(IERC20Upgradeable _target, string memory _name, string memory _symbol) external;
function mint(address account, address to, uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
function withdrawReward(address user) external;
function dividendOf(address _owner) external view returns(uint256);
function withdrawnRewardOf(address _owner) external view returns(uint256);
function accumulativeRewardOf(address _owner) external view returns(uint256);
}
文件 20 的 28:ITimelockRewardDistributionToken.sol
pragma solidity ^0.8.0;
import "../token/IERC20Upgradeable.sol";
interface ITimelockRewardDistributionToken is IERC20Upgradeable {
function distributeRewards(uint amount) external;
function __TimelockRewardDistributionToken_init(IERC20Upgradeable _target, string memory _name, string memory _symbol) external;
function mint(address account, address to, uint256 amount) external;
function timelockMint(address account, uint256 amount, uint256 timelockLength) external;
function burnFrom(address account, uint256 amount) external;
function withdrawReward(address user) external;
function dividendOf(address _owner) external view returns(uint256);
function withdrawnRewardOf(address _owner) external view returns(uint256);
function accumulativeRewardOf(address _owner) external view returns(uint256);
function timelockUntil(address account) external view returns (uint256);
}
文件 21 的 28:IUniswapV2Router01.sol
pragma solidity ^0.8.0;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB)
external
pure
returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
文件 22 的 28:IVaultTokenUpgradeable.sol
pragma solidity ^0.8.0;
import "../token/IERC20Upgradeable.sol";
interface IVaultTokenUpgradeable is IERC20Upgradeable {
function mint(address to, uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
}
文件 23 的 28:Initializable.sol
pragma solidity ^0.8.0;
abstract contract Initializable {
bool private _initialized;
bool private _initializing;
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
文件 24 的 28: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());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
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);
}
}
文件 25 的 28:OwnableUpgradeable.sol
pragma solidity ^0.8.0;
import "./ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}
文件 26 的 28:PRBMath.sol
pragma solidity >=0.8.4;
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);
error PRBMath__MulDivSignedInputTooSmall();
error PRBMath__MulDivSignedOverflow(uint256 rAbs);
error PRBMathSD59x18__AbsInputTooSmall();
error PRBMathSD59x18__CeilOverflow(int256 x);
error PRBMathSD59x18__DivInputTooSmall();
error PRBMathSD59x18__DivOverflow(uint256 rAbs);
error PRBMathSD59x18__ExpInputTooBig(int256 x);
error PRBMathSD59x18__Exp2InputTooBig(int256 x);
error PRBMathSD59x18__FloorUnderflow(int256 x);
error PRBMathSD59x18__FromIntOverflow(int256 x);
error PRBMathSD59x18__FromIntUnderflow(int256 x);
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);
error PRBMathSD59x18__LogInputTooSmall(int256 x);
error PRBMathSD59x18__MulInputTooSmall();
error PRBMathSD59x18__MulOverflow(uint256 rAbs);
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);
error PRBMathSD59x18__SqrtNegativeInput(int256 x);
error PRBMathSD59x18__SqrtOverflow(int256 x);
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);
error PRBMathUD60x18__CeilOverflow(uint256 x);
error PRBMathUD60x18__ExpInputTooBig(uint256 x);
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);
error PRBMathUD60x18__FromUintOverflow(uint256 x);
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);
error PRBMathUD60x18__LogInputTooSmall(uint256 x);
error PRBMathUD60x18__SqrtOverflow(uint256 x);
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);
library PRBMath {
struct SD59x18 {
int256 value;
}
struct UD60x18 {
uint256 value;
}
uint256 internal constant SCALE = 1e18;
uint256 internal constant SCALE_LPOTD = 262144;
uint256 internal constant SCALE_INVERSE =
78156646155174841979727994598816262306175212592076161876661_508869554232690281;
function exp2(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = 0x800000000000000000000000000000000000000000000000;
if (x & 0x8000000000000000 > 0) {
result = (result * 0x16A09E667F3BCC909) >> 64;
}
if (x & 0x4000000000000000 > 0) {
result = (result * 0x1306FE0A31B7152DF) >> 64;
}
if (x & 0x2000000000000000 > 0) {
result = (result * 0x1172B83C7D517ADCE) >> 64;
}
if (x & 0x1000000000000000 > 0) {
result = (result * 0x10B5586CF9890F62A) >> 64;
}
if (x & 0x800000000000000 > 0) {
result = (result * 0x1059B0D31585743AE) >> 64;
}
if (x & 0x400000000000000 > 0) {
result = (result * 0x102C9A3E778060EE7) >> 64;
}
if (x & 0x200000000000000 > 0) {
result = (result * 0x10163DA9FB33356D8) >> 64;
}
if (x & 0x100000000000000 > 0) {
result = (result * 0x100B1AFA5ABCBED61) >> 64;
}
if (x & 0x80000000000000 > 0) {
result = (result * 0x10058C86DA1C09EA2) >> 64;
}
if (x & 0x40000000000000 > 0) {
result = (result * 0x1002C605E2E8CEC50) >> 64;
}
if (x & 0x20000000000000 > 0) {
result = (result * 0x100162F3904051FA1) >> 64;
}
if (x & 0x10000000000000 > 0) {
result = (result * 0x1000B175EFFDC76BA) >> 64;
}
if (x & 0x8000000000000 > 0) {
result = (result * 0x100058BA01FB9F96D) >> 64;
}
if (x & 0x4000000000000 > 0) {
result = (result * 0x10002C5CC37DA9492) >> 64;
}
if (x & 0x2000000000000 > 0) {
result = (result * 0x1000162E525EE0547) >> 64;
}
if (x & 0x1000000000000 > 0) {
result = (result * 0x10000B17255775C04) >> 64;
}
if (x & 0x800000000000 > 0) {
result = (result * 0x1000058B91B5BC9AE) >> 64;
}
if (x & 0x400000000000 > 0) {
result = (result * 0x100002C5C89D5EC6D) >> 64;
}
if (x & 0x200000000000 > 0) {
result = (result * 0x10000162E43F4F831) >> 64;
}
if (x & 0x100000000000 > 0) {
result = (result * 0x100000B1721BCFC9A) >> 64;
}
if (x & 0x80000000000 > 0) {
result = (result * 0x10000058B90CF1E6E) >> 64;
}
if (x & 0x40000000000 > 0) {
result = (result * 0x1000002C5C863B73F) >> 64;
}
if (x & 0x20000000000 > 0) {
result = (result * 0x100000162E430E5A2) >> 64;
}
if (x & 0x10000000000 > 0) {
result = (result * 0x1000000B172183551) >> 64;
}
if (x & 0x8000000000 > 0) {
result = (result * 0x100000058B90C0B49) >> 64;
}
if (x & 0x4000000000 > 0) {
result = (result * 0x10000002C5C8601CC) >> 64;
}
if (x & 0x2000000000 > 0) {
result = (result * 0x1000000162E42FFF0) >> 64;
}
if (x & 0x1000000000 > 0) {
result = (result * 0x10000000B17217FBB) >> 64;
}
if (x & 0x800000000 > 0) {
result = (result * 0x1000000058B90BFCE) >> 64;
}
if (x & 0x400000000 > 0) {
result = (result * 0x100000002C5C85FE3) >> 64;
}
if (x & 0x200000000 > 0) {
result = (result * 0x10000000162E42FF1) >> 64;
}
if (x & 0x100000000 > 0) {
result = (result * 0x100000000B17217F8) >> 64;
}
if (x & 0x80000000 > 0) {
result = (result * 0x10000000058B90BFC) >> 64;
}
if (x & 0x40000000 > 0) {
result = (result * 0x1000000002C5C85FE) >> 64;
}
if (x & 0x20000000 > 0) {
result = (result * 0x100000000162E42FF) >> 64;
}
if (x & 0x10000000 > 0) {
result = (result * 0x1000000000B17217F) >> 64;
}
if (x & 0x8000000 > 0) {
result = (result * 0x100000000058B90C0) >> 64;
}
if (x & 0x4000000 > 0) {
result = (result * 0x10000000002C5C860) >> 64;
}
if (x & 0x2000000 > 0) {
result = (result * 0x1000000000162E430) >> 64;
}
if (x & 0x1000000 > 0) {
result = (result * 0x10000000000B17218) >> 64;
}
if (x & 0x800000 > 0) {
result = (result * 0x1000000000058B90C) >> 64;
}
if (x & 0x400000 > 0) {
result = (result * 0x100000000002C5C86) >> 64;
}
if (x & 0x200000 > 0) {
result = (result * 0x10000000000162E43) >> 64;
}
if (x & 0x100000 > 0) {
result = (result * 0x100000000000B1721) >> 64;
}
if (x & 0x80000 > 0) {
result = (result * 0x10000000000058B91) >> 64;
}
if (x & 0x40000 > 0) {
result = (result * 0x1000000000002C5C8) >> 64;
}
if (x & 0x20000 > 0) {
result = (result * 0x100000000000162E4) >> 64;
}
if (x & 0x10000 > 0) {
result = (result * 0x1000000000000B172) >> 64;
}
if (x & 0x8000 > 0) {
result = (result * 0x100000000000058B9) >> 64;
}
if (x & 0x4000 > 0) {
result = (result * 0x10000000000002C5D) >> 64;
}
if (x & 0x2000 > 0) {
result = (result * 0x1000000000000162E) >> 64;
}
if (x & 0x1000 > 0) {
result = (result * 0x10000000000000B17) >> 64;
}
if (x & 0x800 > 0) {
result = (result * 0x1000000000000058C) >> 64;
}
if (x & 0x400 > 0) {
result = (result * 0x100000000000002C6) >> 64;
}
if (x & 0x200 > 0) {
result = (result * 0x10000000000000163) >> 64;
}
if (x & 0x100 > 0) {
result = (result * 0x100000000000000B1) >> 64;
}
if (x & 0x80 > 0) {
result = (result * 0x10000000000000059) >> 64;
}
if (x & 0x40 > 0) {
result = (result * 0x1000000000000002C) >> 64;
}
if (x & 0x20 > 0) {
result = (result * 0x10000000000000016) >> 64;
}
if (x & 0x10 > 0) {
result = (result * 0x1000000000000000B) >> 64;
}
if (x & 0x8 > 0) {
result = (result * 0x10000000000000006) >> 64;
}
if (x & 0x4 > 0) {
result = (result * 0x10000000000000003) >> 64;
}
if (x & 0x2 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
if (x & 0x1 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
result *= SCALE;
result >>= (191 - (x >> 64));
}
}
function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
if (x >= 2**128) {
x >>= 128;
msb += 128;
}
if (x >= 2**64) {
x >>= 64;
msb += 64;
}
if (x >= 2**32) {
x >>= 32;
msb += 32;
}
if (x >= 2**16) {
x >>= 16;
msb += 16;
}
if (x >= 2**8) {
x >>= 8;
msb += 8;
}
if (x >= 2**4) {
x >>= 4;
msb += 4;
}
if (x >= 2**2) {
x >>= 2;
msb += 2;
}
if (x >= 2**1) {
msb += 1;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
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) {
unchecked {
result = prod0 / denominator;
}
return result;
}
if (prod1 >= denominator) {
revert PRBMath__MulDivOverflow(prod1, denominator);
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
unchecked {
uint256 lpotdod = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, lpotdod)
prod0 := div(prod0, lpotdod)
lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
}
prod0 |= prod1 * lpotdod;
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 mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
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 >= SCALE) {
revert PRBMath__MulDivFixedPointOverflow(prod1);
}
uint256 remainder;
uint256 roundUpUnit;
assembly {
remainder := mulmod(x, y, SCALE)
roundUpUnit := gt(remainder, 499999999999999999)
}
if (prod1 == 0) {
unchecked {
result = (prod0 / SCALE) + roundUpUnit;
return result;
}
}
assembly {
result := add(
mul(
or(
div(sub(prod0, remainder), SCALE_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
),
SCALE_INVERSE
),
roundUpUnit
)
}
}
function mulDivSigned(
int256 x,
int256 y,
int256 denominator
) internal pure returns (int256 result) {
if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
revert PRBMath__MulDivSignedInputTooSmall();
}
uint256 ax;
uint256 ay;
uint256 ad;
unchecked {
ax = x < 0 ? uint256(-x) : uint256(x);
ay = y < 0 ? uint256(-y) : uint256(y);
ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
}
uint256 rAbs = mulDiv(ax, ay, ad);
if (rAbs > uint256(type(int256).max)) {
revert PRBMath__MulDivSignedOverflow(rAbs);
}
uint256 sx;
uint256 sy;
uint256 sd;
assembly {
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
sd := sgt(denominator, sub(0, 1))
}
result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
}
function sqrt(uint256 x) internal pure returns (uint256 result) {
if (x == 0) {
return 0;
}
uint256 xAux = uint256(x);
result = 1;
if (xAux >= 0x100000000000000000000000000000000) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 0x10000000000000000) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 0x100000000) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 0x10000) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 0x100) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 0x10) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 0x8) {
result <<= 1;
}
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
uint256 roundedDownResult = x / result;
return result >= roundedDownResult ? roundedDownResult : result;
}
}
}
文件 27 的 28:PRBMathUD60x18.sol
pragma solidity >=0.8.4;
import "./PRBMath.sol";
library PRBMathUD60x18 {
uint256 internal constant HALF_SCALE = 5e17;
uint256 internal constant LOG2_E = 1_442695040888963407;
uint256 internal constant MAX_UD60x18 =
115792089237316195423570985008687907853269984665640564039457_584007913129639935;
uint256 internal constant MAX_WHOLE_UD60x18 =
115792089237316195423570985008687907853269984665640564039457_000000000000000000;
uint256 internal constant SCALE = 1e18;
function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {
unchecked {
result = (x >> 1) + (y >> 1) + (x & y & 1);
}
}
function ceil(uint256 x) internal pure returns (uint256 result) {
if (x > MAX_WHOLE_UD60x18) {
revert PRBMathUD60x18__CeilOverflow(x);
}
assembly {
let remainder := mod(x, SCALE)
let delta := sub(SCALE, remainder)
result := add(x, mul(delta, gt(remainder, 0)))
}
}
function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = PRBMath.mulDiv(x, SCALE, y);
}
function e() internal pure returns (uint256 result) {
result = 2_718281828459045235;
}
function exp(uint256 x) internal pure returns (uint256 result) {
if (x >= 133_084258667509499441) {
revert PRBMathUD60x18__ExpInputTooBig(x);
}
unchecked {
uint256 doubleScaleProduct = x * LOG2_E;
result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
}
}
function exp2(uint256 x) internal pure returns (uint256 result) {
if (x >= 192e18) {
revert PRBMathUD60x18__Exp2InputTooBig(x);
}
unchecked {
uint256 x192x64 = (x << 64) / SCALE;
result = PRBMath.exp2(x192x64);
}
}
function floor(uint256 x) internal pure returns (uint256 result) {
assembly {
let remainder := mod(x, SCALE)
result := sub(x, mul(remainder, gt(remainder, 0)))
}
}
function frac(uint256 x) internal pure returns (uint256 result) {
assembly {
result := mod(x, SCALE)
}
}
function fromUint(uint256 x) internal pure returns (uint256 result) {
unchecked {
if (x > MAX_UD60x18 / SCALE) {
revert PRBMathUD60x18__FromUintOverflow(x);
}
result = x * SCALE;
}
}
function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {
if (x == 0) {
return 0;
}
unchecked {
uint256 xy = x * y;
if (xy / x != y) {
revert PRBMathUD60x18__GmOverflow(x, y);
}
result = PRBMath.sqrt(xy);
}
}
function inv(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = 1e36 / x;
}
}
function ln(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = (log2(x) * SCALE) / LOG2_E;
}
}
function log10(uint256 x) internal pure returns (uint256 result) {
if (x < SCALE) {
revert PRBMathUD60x18__LogInputTooSmall(x);
}
assembly {
switch x
case 1 { result := mul(SCALE, sub(0, 18)) }
case 10 { result := mul(SCALE, sub(1, 18)) }
case 100 { result := mul(SCALE, sub(2, 18)) }
case 1000 { result := mul(SCALE, sub(3, 18)) }
case 10000 { result := mul(SCALE, sub(4, 18)) }
case 100000 { result := mul(SCALE, sub(5, 18)) }
case 1000000 { result := mul(SCALE, sub(6, 18)) }
case 10000000 { result := mul(SCALE, sub(7, 18)) }
case 100000000 { result := mul(SCALE, sub(8, 18)) }
case 1000000000 { result := mul(SCALE, sub(9, 18)) }
case 10000000000 { result := mul(SCALE, sub(10, 18)) }
case 100000000000 { result := mul(SCALE, sub(11, 18)) }
case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := SCALE }
case 100000000000000000000 { result := mul(SCALE, 2) }
case 1000000000000000000000 { result := mul(SCALE, 3) }
case 10000000000000000000000 { result := mul(SCALE, 4) }
case 100000000000000000000000 { result := mul(SCALE, 5) }
case 1000000000000000000000000 { result := mul(SCALE, 6) }
case 10000000000000000000000000 { result := mul(SCALE, 7) }
case 100000000000000000000000000 { result := mul(SCALE, 8) }
case 1000000000000000000000000000 { result := mul(SCALE, 9) }
case 10000000000000000000000000000 { result := mul(SCALE, 10) }
case 100000000000000000000000000000 { result := mul(SCALE, 11) }
case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }
default {
result := MAX_UD60x18
}
}
if (result == MAX_UD60x18) {
unchecked {
result = (log2(x) * SCALE) / 3_321928094887362347;
}
}
}
function log2(uint256 x) internal pure returns (uint256 result) {
if (x < SCALE) {
revert PRBMathUD60x18__LogInputTooSmall(x);
}
unchecked {
uint256 n = PRBMath.mostSignificantBit(x / SCALE);
result = n * SCALE;
uint256 y = x >> n;
if (y == SCALE) {
return result;
}
for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {
y = (y * y) / SCALE;
if (y >= 2 * SCALE) {
result += delta;
y >>= 1;
}
}
}
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = PRBMath.mulDivFixedPoint(x, y);
}
function pi() internal pure returns (uint256 result) {
result = 3_141592653589793238;
}
function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {
if (x == 0) {
result = y == 0 ? SCALE : uint256(0);
} else {
result = exp2(mul(log2(x), y));
}
}
function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = y & 1 > 0 ? x : SCALE;
for (y >>= 1; y > 0; y >>= 1) {
x = PRBMath.mulDivFixedPoint(x, x);
if (y & 1 > 0) {
result = PRBMath.mulDivFixedPoint(result, x);
}
}
}
function scale() internal pure returns (uint256 result) {
result = SCALE;
}
function sqrt(uint256 x) internal pure returns (uint256 result) {
unchecked {
if (x > MAX_UD60x18 / SCALE) {
revert PRBMathUD60x18__SqrtOverflow(x);
}
result = PRBMath.sqrt(x * SCALE);
}
}
function toUint(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = x / SCALE;
}
}
}
文件 28 的 28:xRooStaking.sol
pragma solidity ^0.8.7;
import "../nftx/interface/INFTXVault.sol";
import "../nftx/interface/INFTXLPStaking.sol";
import "../nftx/interface/IUniswapV2Router01.sol";
import "../nftx/interface/IVaultTokenUpgradeable.sol";
import "../nftx/interface/IRewardDistributionToken.sol";
import {IWETH} from "../nftx/interface/INFTXStakingZap.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "prb-math/contracts/PRBMathUD60x18.sol";
contract xRooStaking is Ownable {
using PRBMathUD60x18 for uint256;
event Staked(
address indexed _user,
uint256 _stake,
uint256 _liquidity,
uint256 _weth
);
event Unstaked(address indexed _user, uint256 _stake, uint256 _liquidity);
INFTXVault public NFTXVault;
INFTXLPStaking public NFTXLPStaking;
IRewardDistributionToken public NFTXRewardDistributionToken;
uint256 constant base = 10**18;
uint256 NFTXRewardPerLiquidity;
IWETH public WETH;
IUniswapV2Router01 public sushiRouter;
IERC20 public SLPToken;
IERC20 public RTRewardToken;
IERC721 public RTStakedToken;
uint256 public rewardPeriod;
uint256 public periodicReward;
uint256 public lockTime;
bool public lockRTRewards = true;
struct UserData {
uint256 stake;
uint256 liquidity;
uint256 lastTimestamp;
int256 RTRewardModifier;
int256 NFTXRewardModifier;
uint256 NFTXRewardWithdrawn;
}
struct Dividend {
uint256 RTRewardToken;
uint256 NFTXRewardToken;
}
mapping(address => UserData) public users;
constructor(
address _NFTXVault,
address _NFTXLPStaking,
address _NFTXRewardDistributionToken,
address _sushiRouter,
address _SLPToken,
address _RTRewardToken,
address _RTStakedToken,
uint256 _rewardPeriod,
uint256 _periodicReward,
uint256 _lockTime
) {
RTRewardToken = IERC20(_RTRewardToken);
RTStakedToken = IERC721(_RTStakedToken);
rewardPeriod = _rewardPeriod;
periodicReward = _periodicReward;
lockTime = _lockTime;
updateExternalReferences(
_NFTXVault,
_NFTXLPStaking,
_NFTXRewardDistributionToken,
_sushiRouter,
_SLPToken
);
}
function updateExternalReferences(
address _NFTXVault,
address _NFTXLPStaking,
address _NFTXRewardDistributionToken,
address _sushiRouter,
address _SLPToken
) public onlyOwner {
NFTXVault = INFTXVault(_NFTXVault);
NFTXLPStaking = INFTXLPStaking(_NFTXLPStaking);
NFTXRewardDistributionToken = IRewardDistributionToken(
_NFTXRewardDistributionToken
);
WETH = IWETH(IUniswapV2Router01(_sushiRouter).WETH());
sushiRouter = IUniswapV2Router01(_sushiRouter);
SLPToken = IERC20(_SLPToken);
IERC20Upgradeable(address(WETH)).approve(
_sushiRouter,
type(uint256).max
);
SLPToken.approve(_sushiRouter, type(uint256).max);
NFTXRewardDistributionToken.approve(
address(NFTXLPStaking),
type(uint256).max
);
NFTXVault.approve(address(sushiRouter), type(uint256).max);
SLPToken.approve(address(NFTXLPStaking), type(uint256).max);
}
function setRTRewardToken(address _token) external onlyOwner {
RTRewardToken = IERC20(_token);
}
function setLock(bool _locked) external onlyOwner {
lockRTRewards = _locked;
}
function setLockTime(uint256 _lockTime) external onlyOwner {
require(_lockTime > 0);
lockTime = _lockTime;
}
function addLiquidityERC721(
uint256 _minWethIn,
uint256 _wethIn,
uint256[] calldata _ids
) external {
uint256 initialWETH = IERC20Upgradeable(address(WETH)).balanceOf(
address(this)
);
IERC20Upgradeable(address(WETH)).transferFrom(
msg.sender,
address(this),
_wethIn
);
_addLiquidityERC721(msg.sender, _minWethIn, _wethIn, _ids);
uint256 WETHRefund = IERC20Upgradeable(address(WETH)).balanceOf(
address(this)
) - initialWETH;
if (WETHRefund < _wethIn && WETHRefund > 0)
WETH.transfer(msg.sender, WETHRefund);
}
function addLiquidityERC721ETH(uint256 _minWethIn, uint256[] calldata _ids)
external
payable
{
uint256 initialWETH = IERC20Upgradeable(address(WETH)).balanceOf(
address(this)
);
WETH.deposit{value: msg.value}();
_addLiquidityERC721(msg.sender, _minWethIn, msg.value, _ids);
uint256 wethRefund = IERC20Upgradeable(address(WETH)).balanceOf(
address(this)
) - initialWETH;
if (wethRefund < msg.value && wethRefund > 0) {
WETH.withdraw(wethRefund);
(bool success, ) = payable(msg.sender).call{value: wethRefund}("");
require(success, "Refund failed");
}
}
function addLiquidityERC20(
uint256 _minWethIn,
uint256 _wethIn,
uint256 _amount
) external {
IERC20Upgradeable(address(WETH)).transferFrom(
msg.sender,
address(this),
_wethIn
);
(, uint256 amountWETH, ) = _addLiquidityERC20(
msg.sender,
_minWethIn,
_wethIn,
_amount
);
if (amountWETH < _wethIn && _wethIn - amountWETH > 0) {
WETH.transfer(msg.sender, _wethIn - amountWETH);
}
}
function addLiquidityERC20ETH(uint256 _minWethIn, uint256 _amount)
external
payable
{
WETH.deposit{value: msg.value}();
(, uint256 amountWETH, ) = _addLiquidityERC20(
msg.sender,
_minWethIn,
msg.value,
_amount
);
if (amountWETH < msg.value && msg.value - amountWETH > 0) {
WETH.withdraw(msg.value - amountWETH);
(bool sent, ) = payable(msg.sender).call{
value: msg.value - amountWETH
}("");
require(sent, "refund failed");
}
}
function removeLiquidity(uint256 _amountTokenMin, uint256 _amountWETHMin)
external
{
require(
users[msg.sender].lastTimestamp + lockTime < block.timestamp,
"Locked"
);
_removeLiquidity(msg.sender, _amountTokenMin, _amountWETHMin);
}
function claimRewards() external {
_claimRewards(msg.sender);
}
function dividendOf(address _user) external view returns (Dividend memory) {
return _dividendOf(_user);
}
function emergencyExit() external {
require(
users[msg.sender].lastTimestamp + lockTime < block.timestamp,
"Locked"
);
_emergencyExit(msg.sender);
}
function lockedUntil(address _user) external view returns (uint256) {
require(users[_user].lastTimestamp != 0, "N/A");
return users[_user].lastTimestamp + lockTime;
}
function _totalLiquidityStaked() internal view returns (uint256) {
return NFTXRewardDistributionToken.balanceOf(address(this));
}
function _emergencyExit(address _user) internal {
uint256 liquidity = users[_user].liquidity;
delete users[_user];
NFTXRewardDistributionToken.transfer(_user, liquidity);
}
function _claimContractNFTXRewards() internal {
uint256 currentRewards = NFTXVault.balanceOf(address(this));
uint256 dividend = NFTXRewardDistributionToken.dividendOf(
address(this)
);
if (dividend == 0) return;
NFTXLPStaking.claimRewards(NFTXVault.vaultId());
require(
NFTXVault.balanceOf(address(this)) == currentRewards + dividend,
"Unexpected balance"
);
NFTXRewardPerLiquidity += dividend.div(_totalLiquidityStaked());
}
function _addLiquidityERC721(
address _user,
uint256 _minWethIn,
uint256 _wethIn,
uint256[] calldata _ids
)
internal
returns (
uint256 amountToken,
uint256 amountWETH,
uint256 liquidity
)
{
_claimContractNFTXRewards();
uint256 initialRewardToken = NFTXVault.balanceOf(address(this));
for (uint256 i = 0; i < _ids.length; i++) {
RTStakedToken.transferFrom(_user, address(this), _ids[i]);
}
RTStakedToken.setApprovalForAll(address(NFTXVault), true);
NFTXVault.mint(_ids, new uint256[](0));
uint256 newTokens = NFTXVault.balanceOf(address(this)) -
initialRewardToken;
return _stakeAndUpdate(_user, _minWethIn, _wethIn, newTokens);
}
function _addLiquidityERC20(
address _user,
uint256 _minWethIn,
uint256 _wethIn,
uint256 _amount
)
internal
returns (
uint256 amountToken,
uint256 amountWETH,
uint256 liquidity
)
{
_claimContractNFTXRewards();
NFTXVault.transferFrom(_user, address(this), _amount);
return _stakeAndUpdate(_user, _minWethIn, _wethIn, _amount);
}
function _stakeAndUpdate(
address _user,
uint256 _minWethIn,
uint256 _wethIn,
uint256 _amount
)
internal
returns (
uint256 amountToken,
uint256 amountWETH,
uint256 liquidity
)
{
(
amountToken,
amountWETH,
liquidity
) = sushiRouter.addLiquidity(
address(NFTXVault),
address(WETH),
_amount,
_wethIn,
_amount,
_minWethIn,
address(this),
block.timestamp
);
NFTXLPStaking.deposit(NFTXVault.vaultId(), liquidity);
UserData memory userData = users[_user];
uint256 NFTXRewardModifier = liquidity.mul(NFTXRewardPerLiquidity);
uint256 currentNumPeriods = userData.lastTimestamp == 0
? 0
: (block.timestamp - userData.lastTimestamp) / rewardPeriod;
userData.liquidity += liquidity;
userData.RTRewardModifier += int256(
currentNumPeriods * periodicReward.mul(userData.stake)
);
userData.lastTimestamp = block.timestamp;
userData.stake += _amount;
userData.NFTXRewardModifier -= int256(NFTXRewardModifier);
users[_user] = userData;
if (amountToken < _amount) {
NFTXVault.transfer(_user, _amount - amountToken);
}
emit Staked(_user, _amount, liquidity, amountWETH);
}
function _dividendOf(address _user)
internal
view
returns (Dividend memory)
{
uint256 updatedNFTXRewardPerLiquidity = NFTXRewardPerLiquidity +
NFTXRewardDistributionToken.dividendOf(address(this)).div(
_totalLiquidityStaked()
);
int256 nftxReward = int256(
(users[_user].liquidity.mul(updatedNFTXRewardPerLiquidity))
) +
users[_user].NFTXRewardModifier -
int256(users[_user].NFTXRewardWithdrawn);
uint256 numPeriods = users[_user].lastTimestamp == 0
? 0
: (block.timestamp - users[_user].lastTimestamp) / rewardPeriod;
int256 rtReward = int256(
numPeriods * periodicReward.mul(users[_user].stake)
) + users[_user].RTRewardModifier;
require(nftxReward >= 0 && rtReward >= 0, "Negative Reward");
Dividend memory dividend;
dividend.NFTXRewardToken = uint256(nftxReward);
dividend.RTRewardToken = uint256(rtReward);
return dividend;
}
function _claimRewards(address _user) internal {
_claimContractNFTXRewards();
Dividend memory rewards = _dividendOf(_user);
if (rewards.NFTXRewardToken > 0) {
users[_user].NFTXRewardWithdrawn += rewards.NFTXRewardToken;
NFTXVault.transfer(_user, rewards.NFTXRewardToken);
}
if (rewards.RTRewardToken > 0 && !lockRTRewards) {
users[_user].RTRewardModifier -= int256(rewards.RTRewardToken);
RTRewardToken.transfer(_user, rewards.RTRewardToken);
}
}
function _removeLiquidity(
address _user,
uint256 _amountTokenMin,
uint256 _amountWETHMin
) internal {
uint256 amount = users[_user].liquidity;
uint256 stake = users[_user].stake;
_claimRewards(_user);
delete users[_user];
NFTXLPStaking.withdraw(NFTXVault.vaultId(), amount);
sushiRouter.removeLiquidity(
address(NFTXVault),
address(WETH),
amount,
_amountTokenMin,
_amountWETHMin,
_user,
block.timestamp
);
emit Unstaked(_user, stake, amount);
}
receive() external payable {
}
}
{
"compilationTarget": {
"contracts/xRooStaking.sol": "xRooStaking"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_NFTXVault","type":"address"},{"internalType":"address","name":"_NFTXLPStaking","type":"address"},{"internalType":"address","name":"_NFTXRewardDistributionToken","type":"address"},{"internalType":"address","name":"_sushiRouter","type":"address"},{"internalType":"address","name":"_SLPToken","type":"address"},{"internalType":"address","name":"_RTRewardToken","type":"address"},{"internalType":"address","name":"_RTStakedToken","type":"address"},{"internalType":"uint256","name":"_rewardPeriod","type":"uint256"},{"internalType":"uint256","name":"_periodicReward","type":"uint256"},{"internalType":"uint256","name":"_lockTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"}],"name":"PRBMath__MulDivFixedPointOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"PRBMath__MulDivOverflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"uint256","name":"_stake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_weth","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"uint256","name":"_stake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_liquidity","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"NFTXLPStaking","outputs":[{"internalType":"contract INFTXLPStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFTXRewardDistributionToken","outputs":[{"internalType":"contract IRewardDistributionToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFTXVault","outputs":[{"internalType":"contract INFTXVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RTRewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RTStakedToken","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLPToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWethIn","type":"uint256"},{"internalType":"uint256","name":"_wethIn","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addLiquidityERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWethIn","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addLiquidityERC20ETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWethIn","type":"uint256"},{"internalType":"uint256","name":"_wethIn","type":"uint256"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"addLiquidityERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWethIn","type":"uint256"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"addLiquidityERC721ETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"dividendOf","outputs":[{"components":[{"internalType":"uint256","name":"RTRewardToken","type":"uint256"},{"internalType":"uint256","name":"NFTXRewardToken","type":"uint256"}],"internalType":"struct xRooStaking.Dividend","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockRTRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"lockedUntil","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodicReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"_amountWETHMin","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_locked","type":"bool"}],"name":"setLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockTime","type":"uint256"}],"name":"setLockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setRTRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sushiRouter","outputs":[{"internalType":"contract IUniswapV2Router01","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_NFTXVault","type":"address"},{"internalType":"address","name":"_NFTXLPStaking","type":"address"},{"internalType":"address","name":"_NFTXRewardDistributionToken","type":"address"},{"internalType":"address","name":"_sushiRouter","type":"address"},{"internalType":"address","name":"_SLPToken","type":"address"}],"name":"updateExternalReferences","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"lastTimestamp","type":"uint256"},{"internalType":"int256","name":"RTRewardModifier","type":"int256"},{"internalType":"int256","name":"NFTXRewardModifier","type":"int256"},{"internalType":"uint256","name":"NFTXRewardWithdrawn","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]