Latest 25 from a total of 939 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Unstake Inventor... | 24529134 | 5 days ago | IN | 0 ETH | 0.00002205 | ||||
| Unstake Inventor... | 24483693 | 11 days ago | IN | 0 ETH | 0.00003754 | ||||
| Unstake Inventor... | 24447717 | 16 days ago | IN | 0 ETH | 0.00001511 | ||||
| Unstake Inventor... | 24439762 | 17 days ago | IN | 0 ETH | 0.0000331 | ||||
| Unstake Inventor... | 24427535 | 19 days ago | IN | 0 ETH | 0.00012016 | ||||
| Unstake Inventor... | 24427517 | 19 days ago | IN | 0 ETH | 0.00007575 | ||||
| Unstake Inventor... | 24407087 | 22 days ago | IN | 0 ETH | 0.00065119 | ||||
| Unstake Inventor... | 24406314 | 22 days ago | IN | 0 ETH | 0.00003048 | ||||
| Unstake Inventor... | 24406312 | 22 days ago | IN | 0 ETH | 0.00004099 | ||||
| Unstake Inventor... | 24406298 | 22 days ago | IN | 0 ETH | 0.00004933 | ||||
| Unstake Inventor... | 24398348 | 23 days ago | IN | 0 ETH | 0.00014263 | ||||
| Unstake Inventor... | 24398337 | 23 days ago | IN | 0 ETH | 0.00010936 | ||||
| Unstake Inventor... | 24398330 | 23 days ago | IN | 0 ETH | 0.00086897 | ||||
| Unstake Inventor... | 24398315 | 23 days ago | IN | 0 ETH | 0.00025663 | ||||
| Unstake Inventor... | 24398304 | 23 days ago | IN | 0 ETH | 0.0001746 | ||||
| Unstake Inventor... | 24398295 | 23 days ago | IN | 0 ETH | 0.00015683 | ||||
| Unstake Inventor... | 24398284 | 23 days ago | IN | 0 ETH | 0.00016066 | ||||
| Unstake Inventor... | 24398277 | 23 days ago | IN | 0 ETH | 0.00016422 | ||||
| Unstake Inventor... | 24398271 | 23 days ago | IN | 0 ETH | 0.00028279 | ||||
| Unstake Inventor... | 24398264 | 23 days ago | IN | 0 ETH | 0.0001895 | ||||
| Unstake Inventor... | 24398239 | 23 days ago | IN | 0 ETH | 0.00012978 | ||||
| Unstake Inventor... | 24398222 | 23 days ago | IN | 0 ETH | 0.00025671 | ||||
| Unstake Inventor... | 24398206 | 23 days ago | IN | 0 ETH | 0.00023834 | ||||
| Unstake Inventor... | 24398187 | 23 days ago | IN | 0 ETH | 0.00022426 | ||||
| Unstake Inventor... | 24364014 | 28 days ago | IN | 0 ETH | 0.00093556 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NFTXUnstakingInventoryZap
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./util/Ownable.sol";
import "./util/ReentrancyGuard.sol";
import "./util/SafeERC20Upgradeable.sol";
import "./interface/INFTXVaultFactory.sol";
import "./interface/INFTXVault.sol";
import "./interface/IUniswapV2Router01.sol";
import "./token/IWETH.sol";
import "./NFTXInventoryStaking.sol";
contract NFTXUnstakingInventoryZap is Ownable, ReentrancyGuard {
using SafeERC20Upgradeable for IERC20Upgradeable;
INFTXVaultFactory public vaultFactory;
NFTXInventoryStaking public inventoryStaking;
IUniswapV2Router01 public sushiRouter;
IWETH public weth;
event InventoryUnstaked(
uint256 vaultId,
uint256 xTokensUnstaked,
uint256 numNftsRedeemed,
address unstaker
);
function setVaultFactory(address addr) public onlyOwner {
vaultFactory = INFTXVaultFactory(addr);
}
function setInventoryStaking(address addr) public onlyOwner {
inventoryStaking = NFTXInventoryStaking(addr);
}
function setSushiRouterAndWeth(address sushiRouterAddr) public onlyOwner {
sushiRouter = IUniswapV2Router01(sushiRouterAddr);
weth = IWETH(sushiRouter.WETH());
}
/**
* @param remainingPortionToUnstake Represents the ratio (in 1e18) of the remaining xTokens (left after claiming `numNfts`) balance of user to unstake
* if remainingPortionToUnstake = 1e18 => unstake entire user's balance
* if remainingPortionToUnstake = 0 => only unstake required xToken balance to claim `numNfts`, nothing extra
*/
function unstakeInventory(
uint256 vaultId,
uint256 numNfts,
uint256 remainingPortionToUnstake
) public payable {
require(remainingPortionToUnstake <= 1e18);
IERC20Upgradeable vToken = IERC20Upgradeable(
vaultFactory.vault(vaultId)
);
IERC20Upgradeable xToken = IERC20Upgradeable(
inventoryStaking.xTokenAddr(address(vToken))
);
uint256 reqVTokens = numNfts * 1e18;
// calculate `xTokensToPull` to pull
uint256 xTokensToPull;
uint256 xTokenUserBal = xToken.balanceOf(msg.sender);
if (remainingPortionToUnstake == 1e18) {
xTokensToPull = xTokenUserBal;
} else {
uint256 shareValue = inventoryStaking.xTokenShareValue(vaultId); // vTokens per xToken in wei
uint256 reqXTokens = (reqVTokens * 1e18) / shareValue;
// Check for rounding error being 1 less that expected amount
if ((reqXTokens * shareValue) / 1e18 < reqVTokens) {
reqXTokens += 1;
}
// If the user doesn't have enough xTokens then we just want to pull the
// balance of the user.
if (xTokenUserBal < reqXTokens) {
xTokensToPull = xTokenUserBal;
}
// If we have zero additional portion to unstake, then we only need to pull the required tokens
else if (remainingPortionToUnstake == 0) {
xTokensToPull = reqXTokens;
}
// Otherwise, calculate remaining xTokens to unstake using `remainingPortionToUnstake` ratio
else {
uint256 remainingXTokens = xToken.balanceOf(msg.sender) -
reqXTokens;
xTokensToPull =
reqXTokens +
((remainingXTokens * remainingPortionToUnstake) / 1e18);
}
}
// pull xTokens then unstake for vTokens
xToken.safeTransferFrom(msg.sender, address(this), xTokensToPull);
// If our inventory staking contract has an allowance less that the amount we need
// to pull, then we need to approve additional tokens.
if (
xToken.allowance(address(this), address(inventoryStaking)) <
xTokensToPull
) {
xToken.approve(address(inventoryStaking), type(uint256).max);
}
uint256 initialVTokenBal = vToken.balanceOf(address(this));
// Burn our xTokens to pull in our vTokens
inventoryStaking.withdraw(vaultId, xTokensToPull);
uint256 vTokensReceived = vToken.balanceOf(address(this)) -
initialVTokenBal;
uint256 missingVToken;
// If the amount of vTokens generated from our `inventoryStaking.withdraw` call
// is not sufficient to fulfill the claim on the specified number of NFTs, then
// we determine if we can claim some dust from the contract.
if (vTokensReceived < reqVTokens) {
// We can calculate the amount of vToken required by the contract to get
// it from the withdrawal amount to the amount required based on the number
// of NFTs.
missingVToken = reqVTokens - vTokensReceived;
/**
* reqVTokens = 1e18
* initialVTokenBal = 2
* vToken.balanceOf(address(this)) = 1000000000000000001
*
* 1000000000000000000 - (1000000000000000001 - 2) = 1
*/
}
// This dust value has to be less that 100 to ensure we aren't just being rinsed
// of dust.
require(missingVToken < 100, "not enough vTokens");
uint256 dustUsed;
if (missingVToken > initialVTokenBal) {
// If user has sufficient vTokens to account for missingVToken
// then get it from them to this contract
if (
vToken.balanceOf(msg.sender) >= missingVToken &&
vToken.allowance(msg.sender, address(this)) >= missingVToken
) {
vToken.safeTransferFrom(
msg.sender,
address(this),
missingVToken
);
} else {
// else we swap ETH from this contract to get `missingVToken`
address[] memory path = new address[](2);
path[0] = address(weth);
path[1] = address(vToken);
sushiRouter.swapETHForExactTokens{value: 1_000_000_000}(
missingVToken,
path,
address(this),
block.timestamp
);
}
} else {
dustUsed = missingVToken;
}
// reedem NFTs with vTokens, if requested
if (numNfts > 0) {
INFTXVault(address(vToken)).redeemTo(
numNfts,
new uint256[](0),
msg.sender
);
}
/**
* How this fixes underflow error:
* vToken.balanceOf(address(this)) = 1
* initialVTokenBal = 2
* dustUsed = missingVToken = 1
* vTokenRemainder = 1 - (2 - 1) = 0
*/
uint256 vTokenRemainder = vToken.balanceOf(address(this)) -
(initialVTokenBal - dustUsed);
// if vToken remainder more than dust then return to sender.
// happens when `remainingPortionToUnstake` is non-zero
if (vTokenRemainder > 100) {
vToken.safeTransfer(msg.sender, vTokenRemainder);
}
emit InventoryUnstaked(vaultId, xTokensToPull, numNfts, msg.sender);
}
function maxNftsUsingXToken(
uint256 vaultId,
address staker,
address slpToken
) public view returns (uint256 numNfts, bool shortByTinyAmount) {
if (inventoryStaking.timelockUntil(vaultId, staker) > block.timestamp) {
return (0, false);
}
address vTokenAddr = vaultFactory.vault(vaultId);
address xTokenAddr = inventoryStaking.xTokenAddr(vTokenAddr);
IERC20Upgradeable vToken = IERC20Upgradeable(vTokenAddr);
IERC20Upgradeable xToken = IERC20Upgradeable(xTokenAddr);
IERC20Upgradeable lpPair = IERC20Upgradeable(slpToken);
uint256 xTokenBal = xToken.balanceOf(staker);
uint256 shareValue = inventoryStaking.xTokenShareValue(vaultId);
uint256 vTokensA = (xTokenBal * shareValue) / 1e18;
uint256 vTokensB = ((xTokenBal * shareValue) / 1e18) + 99;
uint256 vTokensIntA = vTokensA / 1e18;
uint256 vTokensIntB = vTokensB / 1e18;
if (vTokensIntB > vTokensIntA) {
if (
vToken.balanceOf(msg.sender) >= 99 &&
vToken.allowance(msg.sender, address(this)) >= 99
) {
return (vTokensIntB, true);
} else if (lpPair.totalSupply() >= 10000) {
return (vTokensIntB, true);
} else if (vToken.balanceOf(address(this)) >= 99) {
return (vTokensIntB, true);
} else {
return (vTokensIntA, false);
}
} else {
return (vTokensIntA, false);
}
}
receive() external payable {}
function rescue(address token) external onlyOwner {
if (token == address(0)) {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
require(
success,
"Address: unable to send value, recipient may have reverted"
);
} else {
IERC20Upgradeable(token).safeTransfer(
msg.sender,
IERC20Upgradeable(token).balanceOf(address(this))
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./util/PausableUpgradeable.sol";
import "./util/SafeERC20Upgradeable.sol";
import "./util/Create2.sol";
import "./proxy/UpgradeableBeacon.sol";
import "./proxy/Create2BeaconProxy.sol";
import "./token/XTokenUpgradeable.sol";
import "./interface/INFTXInventoryStaking.sol";
import "./interface/INFTXVaultFactory.sol";
import "./interface/ITimelockExcludeList.sol";
// Author: 0xKiwi.
// Pausing codes for inventory staking are:
// 10: Deposit
contract NFTXInventoryStaking is
PausableUpgradeable,
UpgradeableBeacon,
INFTXInventoryStaking
{
using SafeERC20Upgradeable for IERC20Upgradeable;
// Small locktime to prevent flash deposits.
uint256 internal constant DEFAULT_LOCKTIME = 2;
bytes internal constant beaconCode = type(Create2BeaconProxy).creationCode;
INFTXVaultFactory public override nftxVaultFactory;
uint256 public inventoryLockTimeErc20;
ITimelockExcludeList public timelockExcludeList;
event XTokenCreated(uint256 vaultId, address baseToken, address xToken);
event Deposit(
uint256 vaultId,
uint256 baseTokenAmount,
uint256 xTokenAmount,
uint256 timelockUntil,
address sender
);
event Withdraw(
uint256 vaultId,
uint256 baseTokenAmount,
uint256 xTokenAmount,
address sender
);
event FeesReceived(uint256 vaultId, uint256 amount);
function __NFTXInventoryStaking_init(address _nftxVaultFactory)
external
virtual
override
initializer
{
__Ownable_init();
nftxVaultFactory = INFTXVaultFactory(_nftxVaultFactory);
address xTokenImpl = address(new XTokenUpgradeable());
__UpgradeableBeacon__init(xTokenImpl);
}
modifier onlyAdmin() {
require(
msg.sender == owner() ||
msg.sender == nftxVaultFactory.feeDistributor(),
"LPStaking: Not authorized"
);
_;
}
function setTimelockExcludeList(address addr) external onlyOwner {
timelockExcludeList = ITimelockExcludeList(addr);
}
function setInventoryLockTimeErc20(uint256 time) external onlyOwner {
require(time <= 14 days, "Lock too long");
inventoryLockTimeErc20 = time;
}
function isAddressTimelockExcluded(address addr, uint256 vaultId)
public
view
returns (bool)
{
if (address(timelockExcludeList) == address(0)) {
return false;
} else {
return timelockExcludeList.isExcluded(addr, vaultId);
}
}
function deployXTokenForVault(uint256 vaultId) public virtual override {
address baseToken = nftxVaultFactory.vault(vaultId);
address deployedXToken = xTokenAddr(address(baseToken));
if (isContract(deployedXToken)) {
return;
}
address xToken = _deployXToken(baseToken);
emit XTokenCreated(vaultId, baseToken, xToken);
}
function receiveRewards(uint256 vaultId, uint256 amount)
external
virtual
override
onlyAdmin
returns (bool)
{
address baseToken = nftxVaultFactory.vault(vaultId);
address deployedXToken = xTokenAddr(address(baseToken));
// Don't distribute rewards unless there are people to distribute to.
// Also added here if the distribution token is not deployed, just forfeit rewards for now.
if (
!isContract(deployedXToken) ||
XTokenUpgradeable(deployedXToken).totalSupply() == 0
) {
return false;
}
// We "pull" to the dividend tokens so the fee distributor only needs to approve this contract.
IERC20Upgradeable(baseToken).safeTransferFrom(
msg.sender,
deployedXToken,
amount
);
emit FeesReceived(vaultId, amount);
return true;
}
// Enter staking. Staking, get minted shares and
// locks base tokens and mints xTokens.
function deposit(uint256 vaultId, uint256 _amount)
external
virtual
override
{
onlyOwnerIfPaused(10);
uint256 timelockTime = isAddressTimelockExcluded(msg.sender, vaultId)
? 0
: inventoryLockTimeErc20;
(
IERC20Upgradeable baseToken,
XTokenUpgradeable xToken,
uint256 xTokensMinted
) = _timelockMintFor(vaultId, msg.sender, _amount, timelockTime);
// Lock the base token in the xtoken contract
baseToken.safeTransferFrom(msg.sender, address(xToken), _amount);
emit Deposit(vaultId, _amount, xTokensMinted, timelockTime, msg.sender);
}
function timelockMintFor(
uint256 vaultId,
uint256 amount,
address to,
uint256 timelockLength
) external virtual override returns (uint256) {
onlyOwnerIfPaused(10);
require(nftxVaultFactory.zapContracts(msg.sender), "Not staking zap");
require(
nftxVaultFactory.excludedFromFees(msg.sender),
"Not fee excluded"
);
(, , uint256 xTokensMinted) = _timelockMintFor(
vaultId,
to,
amount,
timelockLength
);
emit Deposit(vaultId, amount, xTokensMinted, timelockLength, to);
return xTokensMinted;
}
// Leave the bar. Claim back your tokens.
// Unlocks the staked + gained tokens and burns xTokens.
function withdraw(uint256 vaultId, uint256 _share)
external
virtual
override
{
IERC20Upgradeable baseToken = IERC20Upgradeable(
nftxVaultFactory.vault(vaultId)
);
XTokenUpgradeable xToken = XTokenUpgradeable(
xTokenAddr(address(baseToken))
);
uint256 baseTokensRedeemed = xToken.burnXTokens(msg.sender, _share);
emit Withdraw(vaultId, baseTokensRedeemed, _share, msg.sender);
}
function xTokenShareValue(uint256 vaultId)
external
view
virtual
override
returns (uint256)
{
IERC20Upgradeable baseToken = IERC20Upgradeable(
nftxVaultFactory.vault(vaultId)
);
XTokenUpgradeable xToken = XTokenUpgradeable(
xTokenAddr(address(baseToken))
);
require(address(xToken) != address(0), "XToken not deployed");
uint256 multiplier = 10**18;
return
xToken.totalSupply() > 0
? (multiplier * baseToken.balanceOf(address(xToken))) /
xToken.totalSupply()
: multiplier;
}
function timelockUntil(uint256 vaultId, address who)
external
view
returns (uint256)
{
XTokenUpgradeable xToken = XTokenUpgradeable(vaultXToken(vaultId));
return xToken.timelockUntil(who);
}
function balanceOf(uint256 vaultId, address who)
external
view
returns (uint256)
{
XTokenUpgradeable xToken = XTokenUpgradeable(vaultXToken(vaultId));
return xToken.balanceOf(who);
}
// Note: this function does not guarantee the token is deployed, we leave that check to elsewhere to save gas.
function xTokenAddr(address baseToken)
public
view
virtual
override
returns (address)
{
bytes32 salt = keccak256(abi.encodePacked(baseToken));
address tokenAddr = Create2.computeAddress(
salt,
keccak256(type(Create2BeaconProxy).creationCode)
);
return tokenAddr;
}
function vaultXToken(uint256 vaultId)
public
view
virtual
override
returns (address)
{
address baseToken = nftxVaultFactory.vault(vaultId);
address xToken = xTokenAddr(baseToken);
require(isContract(xToken), "XToken not deployed");
return xToken;
}
function _timelockMintFor(
uint256 vaultId,
address account,
uint256 _amount,
uint256 timelockLength
)
internal
returns (
IERC20Upgradeable,
XTokenUpgradeable,
uint256
)
{
deployXTokenForVault(vaultId);
IERC20Upgradeable baseToken = IERC20Upgradeable(
nftxVaultFactory.vault(vaultId)
);
XTokenUpgradeable xToken = XTokenUpgradeable(
(xTokenAddr(address(baseToken)))
);
uint256 xTokensMinted = xToken.mintXTokens(
account,
_amount,
timelockLength
);
return (baseToken, xToken, xTokensMinted);
}
function _deployXToken(address baseToken) internal returns (address) {
string memory symbol = IERC20Metadata(baseToken).symbol();
symbol = string(abi.encodePacked("x", symbol));
bytes32 salt = keccak256(abi.encodePacked(baseToken));
address deployedXToken = Create2.deploy(0, salt, beaconCode);
XTokenUpgradeable(deployedXToken).__XToken_init(
baseToken,
symbol,
symbol
);
return deployedXToken;
}
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size != 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface INFTXEligibility {
// Read functions.
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);
// Write functions.
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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./INFTXVaultFactory.sol";
interface INFTXInventoryStaking {
function nftxVaultFactory() external view returns (INFTXVaultFactory);
function vaultXToken(uint256 vaultId) external view returns (address);
function xTokenAddr(address baseToken) external view returns (address);
function xTokenShareValue(uint256 vaultId) external view returns (uint256);
function __NFTXInventoryStaking_init(address nftxFactory) external;
function deployXTokenForVault(uint256 vaultId) external;
function receiveRewards(uint256 vaultId, uint256 amount)
external
returns (bool);
function timelockMintFor(
uint256 vaultId,
uint256 amount,
address to,
uint256 timelockLength
) external returns (uint256);
function deposit(uint256 vaultId, uint256 _amount) external;
function withdraw(uint256 vaultId, uint256 _share) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../token/IERC20Upgradeable.sol";
import "./INFTXVaultFactory.sol";
import "./INFTXEligibility.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 CustomEligibilityDeployed(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;
// This function allows for an easy setup of any eligibility module contract from the EligibilityManager.
// It takes in ABI encoded parameters for the desired module. This is to make sure they can all follow
// a similar interface.
function deployEligibilityStorage(
uint256 moduleIndex,
bytes calldata initData
) external returns (address);
// The manager has control over options like fees and features
function setManager(address _manager) external;
function mint(
uint256[] calldata tokenIds,
uint256[] calldata amounts /* ignored for ERC721 vaults */
) external returns (uint256);
function mintTo(
uint256[] calldata tokenIds,
uint256[] calldata amounts, /* ignored for ERC721 vaults */
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, /* ignored for ERC721 vaults */
uint256[] calldata specificIds
) external returns (uint256[] calldata);
function swapTo(
uint256[] calldata tokenIds,
uint256[] calldata amounts, /* ignored for ERC721 vaults */
uint256[] calldata specificIds,
address to
) external returns (uint256[] calldata);
function allValidNFTs(uint256[] calldata tokenIds)
external
view
returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/IBeacon.sol";
interface INFTXVaultFactory is IBeacon {
// Read functions.
function numVaults() external view returns (uint256);
function zapContract() external view returns (address);
function zapContracts(address addr) external view returns (bool);
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 UpdatedZapContract(address zap, bool excluded);
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
);
// Write functions.
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, bool _excluded) 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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ITimelockExcludeList {
function isExcluded(address addr, uint256 vaultId)
external
view
returns (bool);
}// SPDX-License-Identifier: MIT
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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../util/Address.sol";
import "./Proxy.sol";
import "./IBeacon.sol";
/**
* @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
* Slightly modified to allow using beacon proxies with Create2.
*
* The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
* conflict with the storage layout of the implementation behind the proxy.
*
* _Available since v3.4._
*/
contract Create2BeaconProxy is Proxy {
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 private constant _BEACON_SLOT =
0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Initializes the proxy with `beacon`.
*
* If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
* will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
* constructor.
*
* Requirements:
*
* - `beacon` must be a contract with the interface {IBeacon}.
*/
constructor() payable {
assert(
_BEACON_SLOT ==
bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1)
);
_setBeacon(msg.sender, "");
}
/**
* @dev Returns the current beacon address.
*/
function _beacon() internal view virtual returns (address beacon) {
bytes32 slot = _BEACON_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
beacon := sload(slot)
}
}
/**
* @dev Returns the current implementation address of the associated beacon.
*/
function _implementation()
internal
view
virtual
override
returns (address)
{
return IBeacon(_beacon()).childImplementation();
}
/**
* @dev Changes the proxy to use a new beacon.
*
* If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
*
* Requirements:
*
* - `beacon` must be a contract.
* - The implementation returned by `beacon` must be a contract.
*/
function _setBeacon(address beacon, bytes memory data) internal virtual {
require(
Address.isContract(beacon),
"BeaconProxy: beacon is not a contract"
);
require(
Address.isContract(IBeacon(beacon).childImplementation()),
"BeaconProxy: beacon implementation is not a contract"
);
bytes32 slot = _BEACON_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, beacon)
}
if (data.length > 0) {
Address.functionDelegateCall(
_implementation(),
data,
"BeaconProxy: function call failed"
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function childImplementation() external view returns (address);
function upgradeChildTo(address newImplementation) external;
}// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(
_initializing || !_initialized,
"Initializable: contract is already initialized"
);
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
// solhint-disable-next-line no-inline-assembly
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(
gas(),
implementation,
0,
calldatasize(),
0,
0
)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable virtual {
_fallback();
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
* is empty.
*/
receive() external payable virtual {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overriden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IBeacon.sol";
import "../util/Address.sol";
import "../util/OwnableUpgradeable.sol";
/**
* @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
* implementation contract, which is where they will delegate all function calls.
*
* An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
*/
contract UpgradeableBeacon is IBeacon, OwnableUpgradeable {
address private _childImplementation;
/**
* @dev Emitted when the child implementation returned by the beacon is changed.
*/
event Upgraded(address indexed childImplementation);
/**
* @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
* beacon.
*/
function __UpgradeableBeacon__init(address childImplementation_)
public
initializer
{
_setChildImplementation(childImplementation_);
}
/**
* @dev Returns the current child implementation address.
*/
function childImplementation()
public
view
virtual
override
returns (address)
{
return _childImplementation;
}
/**
* @dev Upgrades the beacon to a new implementation.
*
* Emits an {Upgraded} event.
*
* Requirements:
*
* - msg.sender must be the owner of the contract.
* - `newChildImplementation` must be a contract.
*/
function upgradeChildTo(address newChildImplementation)
public
virtual
override
onlyOwner
{
_setChildImplementation(newChildImplementation);
}
/**
* @dev Sets the implementation contract address for this beacon
*
* Requirements:
*
* - `newChildImplementation` must be a contract.
*/
function _setChildImplementation(address newChildImplementation) private {
require(
Address.isContract(newChildImplementation),
"UpgradeableBeacon: child implementation is not a contract"
);
_childImplementation = newChildImplementation;
emit Upgraded(newChildImplementation);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/Initializable.sol";
import "../util/ContextUpgradeable.sol";
import "./IERC20Upgradeable.sol";
import "./IERC20Metadata.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20Upgradeable is
Initializable,
ContextUpgradeable,
IERC20Upgradeable,
IERC20Metadata
{
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_)
internal
initializer
{
__Context_init_unchained();
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_)
internal
initializer
{
_name = name_;
_symbol = symbol_;
}
function _setMetadata(string memory name_, string memory symbol_) internal {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account)
public
view
virtual
override
returns (uint256)
{
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount)
public
virtual
override
returns (bool)
{
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender)
public
view
virtual
override
returns (uint256)
{
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount)
public
virtual
override
returns (bool)
{
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(
currentAllowance >= amount,
"ERC20: transfer amount exceeds allowance"
);
_approve(sender, _msgSender(), currentAllowance - amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
returns (bool)
{
_approve(
_msgSender(),
spender,
_allowances[_msgSender()][spender] + addedValue
);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
returns (bool)
{
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(
currentAllowance >= subtractedValue,
"ERC20: decreased allowance below zero"
);
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(
senderBalance >= amount,
"ERC20: transfer amount exceeds balance"
);
_balances[sender] = senderBalance - amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
uint256[45] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount)
external
returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender)
external
view
returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWETH {
function balanceOf(address account) external view returns (uint256);
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../util/OwnableUpgradeable.sol";
import "../util/SafeERC20Upgradeable.sol";
import "../token/ERC20Upgradeable.sol";
// XTokens let uou come in with some vault tokens, and leave with more! The longer you stay, the more vault tokens you get.
//
// This contract handles swapping to and from xSushi, SushiSwap's staking token.
contract XTokenUpgradeable is OwnableUpgradeable, ERC20Upgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
uint256 internal constant MAX_TIMELOCK = 2592000;
IERC20Upgradeable public baseToken;
mapping(address => uint256) internal timelock;
event Timelocked(address user, uint256 until);
function __XToken_init(
address _baseToken,
string memory name,
string memory symbol
) public initializer {
__Ownable_init();
// string memory _name = INFTXInventoryStaking(msg.sender).nftxVaultFactory().vault();
__ERC20_init(name, symbol);
baseToken = IERC20Upgradeable(_baseToken);
}
// Needs to be called BEFORE new base tokens are deposited.
function mintXTokens(
address account,
uint256 _amount,
uint256 timelockLength
) external onlyOwner returns (uint256) {
// Gets the amount of Base Token locked in the contract
uint256 totalBaseToken = baseToken.balanceOf(address(this));
// Gets the amount of xTokens in existence
uint256 totalShares = totalSupply();
// If no xTokens exist, mint it 1:1 to the amount put in
if (totalShares == 0 || totalBaseToken == 0) {
_timelockMint(account, _amount, timelockLength);
return _amount;
}
// Calculate and mint the amount of xTokens the base tokens are worth. The ratio will change overtime, as xTokens are burned/minted and base tokens deposited + gained from fees / withdrawn.
else {
uint256 what = (_amount * totalShares) / totalBaseToken;
_timelockMint(account, what, timelockLength);
return what;
}
}
function burnXTokens(address who, uint256 _share)
external
onlyOwner
returns (uint256)
{
// Gets the amount of xToken in existence
uint256 totalShares = totalSupply();
// Calculates the amount of base tokens the xToken is worth
uint256 what = (_share * baseToken.balanceOf(address(this))) /
totalShares;
_burn(who, _share);
baseToken.safeTransfer(who, what);
return what;
}
function timelockAccount(address account, uint256 timelockLength)
public
virtual
onlyOwner
{
require(timelockLength < MAX_TIMELOCK, "Too long lock");
uint256 timelockFinish = block.timestamp + timelockLength;
if (timelockFinish > timelock[account]) {
timelock[account] = timelockFinish;
emit Timelocked(account, timelockFinish);
}
}
function _burn(address who, uint256 amount) internal override {
require(block.timestamp > timelock[who], "User locked");
super._burn(who, amount);
}
function timelockUntil(address account) public view returns (uint256) {
return timelock[account];
}
function _timelockMint(
address account,
uint256 amount,
uint256 timelockLength
) internal virtual {
timelockAccount(account, timelockLength);
_mint(account, amount);
}
function _transfer(
address from,
address to,
uint256 value
) internal override {
require(block.timestamp > timelock[from], "User locked");
super._transfer(from, to, value);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
"Address: insufficient balance"
);
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{value: amount}("");
require(
success,
"Address: unable to send value, recipient may have reverted"
);
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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"
);
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(
address(this).balance >= value,
"Address: insufficient balance for call"
);
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data)
internal
view
returns (bytes memory)
{
return
functionStaticCall(
target,
data,
"Address: low-level static call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return
functionDelegateCall(
target,
data,
"Address: low-level delegate call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/Initializable.sol";
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
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; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(
uint256 amount,
bytes32 salt,
bytes memory bytecode
) internal returns (address) {
address addr;
require(
address(this).balance >= amount,
"Create2: insufficient balance"
);
require(bytecode.length != 0, "Create2: bytecode length is zero");
// solhint-disable-next-line no-inline-assembly
assembly {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
}
require(addr != address(0), "Create2: Failed on deploy");
return addr;
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
* `bytecodeHash` or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash)
internal
view
returns (address)
{
return computeAddress(salt, bytecodeHash, address(this));
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(
bytes32 salt,
bytes32 bytecodeHash,
address deployer
) internal pure returns (address) {
bytes32 _data = keccak256(
abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)
);
return address(uint160(uint256(_data)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../testing/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../proxy/Initializable.sol";
import "./ContextUpgradeable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
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);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
contract PausableUpgradeable is OwnableUpgradeable {
function __Pausable_init() internal initializer {
__Ownable_init();
}
event SetPaused(uint256 lockId, bool paused);
event SetIsGuardian(address addr, bool isGuardian);
mapping(address => bool) public isGuardian;
mapping(uint256 => bool) public isPaused;
// 0 : createVault
// 1 : mint
// 2 : redeem
// 3 : swap
// 4 : flashloan
function onlyOwnerIfPaused(uint256 lockId) public view virtual {
require(!isPaused[lockId] || msg.sender == owner(), "Paused");
}
function unpause(uint256 lockId) public virtual onlyOwner {
isPaused[lockId] = false;
emit SetPaused(lockId, false);
}
function pause(uint256 lockId) public virtual {
require(isGuardian[msg.sender], "Can't pause");
isPaused[lockId] = true;
emit SetPaused(lockId, true);
}
function setIsGuardian(address addr, bool _isGuardian)
public
virtual
onlyOwner
{
isGuardian[addr] = _isGuardian;
emit SetIsGuardian(addr, _isGuardian);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Address.sol";
import "../token/IERC20Upgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using Address for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transfer.selector, to, value)
);
}
function safeTransferFrom(
IERC20Upgradeable token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
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(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
function safeDecreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(
oldAllowance >= value,
"SafeERC20: decreased allowance below zero"
);
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data)
private
{
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(
data,
"SafeERC20: low-level call failed"
);
if (returndata.length > 0) {
// Return data is optional
// solhint-disable-next-line max-line-length
require(
abi.decode(returndata, (bool)),
"SafeERC20: ERC20 operation did not succeed"
);
}
}
}{
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"xTokensUnstaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numNftsRedeemed","type":"uint256"},{"indexed":false,"internalType":"address","name":"unstaker","type":"address"}],"name":"InventoryUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"inventoryStaking","outputs":[{"internalType":"contract NFTXInventoryStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"slpToken","type":"address"}],"name":"maxNftsUsingXToken","outputs":[{"internalType":"uint256","name":"numNfts","type":"uint256"},{"internalType":"bool","name":"shortByTinyAmount","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setInventoryStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sushiRouterAddr","type":"address"}],"name":"setSushiRouterAndWeth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setVaultFactory","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":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"numNfts","type":"uint256"},{"internalType":"uint256","name":"remainingPortionToUnstake","type":"uint256"}],"name":"unstakeInventory","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"vaultFactory","outputs":[{"internalType":"contract INFTXVaultFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060018055611ff0806100656000396000f3fe6080604052600436106100d65760003560e01c806378caec371161007f578063c0c65a4e11610059578063c0c65a4e14610229578063d8a06f7314610249578063f2fde38b14610269578063fa8afbd91461028957600080fd5b806378caec37146101cb578063839006f2146101eb5780638da5cb5b1461020b57600080fd5b80636d13582c116100b05780636d13582c14610176578063715018a61461019657806374a1b0b0146101ab57600080fd5b80630eb188ae146100e25780633ea7fbdb1461011c5780633fc8cef31461013e57600080fd5b366100dd57005b600080fd5b3480156100ee57600080fd5b506101026100fd366004611d5c565b61029c565b604080519283529015156020830152015b60405180910390f35b34801561012857600080fd5b5061013c610137366004611c2c565b61083f565b005b34801561014a57600080fd5b5060055461015e906001600160a01b031681565b6040516001600160a01b039091168152602001610113565b34801561018257600080fd5b5060045461015e906001600160a01b031681565b3480156101a257600080fd5b5061013c6108c0565b3480156101b757600080fd5b5060035461015e906001600160a01b031681565b3480156101d757600080fd5b5061013c6101e6366004611c2c565b610964565b3480156101f757600080fd5b5061013c610206366004611c2c565b610a83565b34801561021757600080fd5b506000546001600160a01b031661015e565b34801561023557600080fd5b5061013c610244366004611c2c565b610c3e565b34801561025557600080fd5b5060025461015e906001600160a01b031681565b34801561027557600080fd5b5061013c610284366004611c2c565b610cba565b61013c610297366004611d9d565b610deb565b6003546040517fc23c6da0000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b038481166024830152600092839242929091169063c23c6da09060440160206040518083038186803b15801561030857600080fd5b505afa15801561031c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103409190611d44565b111561035157506000905080610837565b6002546040516340d1b7db60e11b8152600481018790526000916001600160a01b0316906381a36fb69060240160206040518083038186803b15801561039657600080fd5b505afa1580156103aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ce9190611c48565b60035460405163cda13d6760e01b81526001600160a01b0380841660048301529293506000929091169063cda13d679060240160206040518083038186803b15801561041957600080fd5b505afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104519190611c48565b6040516370a0823160e01b81526001600160a01b038881166004830152919250839183918891600091908416906370a082319060240160206040518083038186803b15801561049f57600080fd5b505afa1580156104b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d79190611d44565b6003546040516321b1fe6960e11b8152600481018e90529192506000916001600160a01b0390911690634363fcd29060240160206040518083038186803b15801561052157600080fd5b505afa158015610535573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105599190611d44565b90506000670de0b6b3a76400006105708385611f17565b61057a9190611ef7565b90506000670de0b6b3a76400006105918486611f17565b61059b9190611ef7565b6105a6906063611edf565b905060006105bc670de0b6b3a764000084611ef7565b905060006105d2670de0b6b3a764000084611ef7565b905081811115610821576040516370a0823160e01b81523360048201526063906001600160a01b038b16906370a082319060240160206040518083038186803b15801561061e57600080fd5b505afa158015610632573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106569190611d44565b101580156106e25750604051636eb1769f60e11b81523360048201523060248201526063906001600160a01b038b169063dd62ed3e9060440160206040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106df9190611d44565b10155b156106fd579b5060019a506108379950505050505050505050565b612710876001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561073957600080fd5b505afa15801561074d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107719190611d44565b1061078c579b5060019a506108379950505050505050505050565b6040516370a0823160e01b81523060048201526063906001600160a01b038b16906370a082319060240160206040518083038186803b1580156107ce57600080fd5b505afa1580156107e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108069190611d44565b10610821579b5060019a506108379950505050505050505050565b509a506000995061083798505050505050505050565b935093915050565b6000546001600160a01b0316331461089e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461091a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146109be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600480546001600160a01b0319166001600160a01b0383169081178255604080517fad5c46480000000000000000000000000000000000000000000000000000000081529051919263ad5c4648928282019260209290829003018186803b158015610a2857600080fd5b505afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a609190611c48565b600580546001600160a01b0319166001600160a01b039290921691909117905550565b6000546001600160a01b03163314610add5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b6001600160a01b038116610bad57604051600090339047908381818185875af1925050503d8060008114610b2d576040519150601f19603f3d011682016040523d82523d6000602084013e610b32565b606091505b5050905080610ba95760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610895565b5050565b6040516370a0823160e01b8152306004820152610c3b9033906001600160a01b038416906370a082319060240160206040518083038186803b158015610bf257600080fd5b505afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a9190611d44565b6001600160a01b03841691906118b1565b50565b6000546001600160a01b03163314610c985760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610d145760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b6001600160a01b038116610d905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610895565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b670de0b6b3a7640000811115610e0057600080fd5b6002546040516340d1b7db60e11b8152600481018590526000916001600160a01b0316906381a36fb69060240160206040518083038186803b158015610e4557600080fd5b505afa158015610e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7d9190611c48565b60035460405163cda13d6760e01b81526001600160a01b0380841660048301529293506000929091169063cda13d679060240160206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190611c48565b90506000610f1685670de0b6b3a7640000611f17565b6040516370a0823160e01b815233600482015290915060009081906001600160a01b038516906370a082319060240160206040518083038186803b158015610f5d57600080fd5b505afa158015610f71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f959190611d44565b905085670de0b6b3a76400001415610faf57809150611154565b6003546040516321b1fe6960e11b8152600481018a90526000916001600160a01b031690634363fcd29060240160206040518083038186803b158015610ff457600080fd5b505afa158015611008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102c9190611d44565b905060008161104386670de0b6b3a7640000611f17565b61104d9190611ef7565b905084670de0b6b3a76400006110638484611f17565b61106d9190611ef7565b10156110815761107e600182611edf565b90505b8083101561109157829350611151565b8761109e57809350611151565b6040516370a0823160e01b815233600482015260009082906001600160a01b038916906370a082319060240160206040518083038186803b1580156110e257600080fd5b505afa1580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a9190611d44565b6111249190611f36565b9050670de0b6b3a76400006111398a83611f17565b6111439190611ef7565b61114d9083611edf565b9450505b50505b6111696001600160a01b03851633308561195f565b600354604051636eb1769f60e11b81523060048201526001600160a01b039182166024820152839186169063dd62ed3e9060440160206040518083038186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ed9190611d44565b1015611295576003546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260001960248201529085169063095ea7b390604401602060405180830381600087803b15801561125b57600080fd5b505af115801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190611d24565b505b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a082319060240160206040518083038186803b1580156112d757600080fd5b505afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190611d44565b6003546040517f441a3e70000000000000000000000000000000000000000000000000000000008152600481018c9052602481018690529192506001600160a01b03169063441a3e7090604401600060405180830381600087803b15801561137657600080fd5b505af115801561138a573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092508391506001600160a01b038916906370a082319060240160206040518083038186803b1580156113d257600080fd5b505afa1580156113e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140a9190611d44565b6114149190611f36565b905060008582101561142d5761142a8287611f36565b90505b6064811061147d5760405162461bcd60e51b815260206004820152601260248201527f6e6f7420656e6f7567682076546f6b656e7300000000000000000000000000006044820152606401610895565b6000838211156116f9576040516370a0823160e01b815233600482015282906001600160a01b038b16906370a082319060240160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190611d44565b1015801561158b5750604051636eb1769f60e11b815233600482015230602482015282906001600160a01b038b169063dd62ed3e9060440160206040518083038186803b15801561155057600080fd5b505afa158015611564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115889190611d44565b10155b156115aa576115a56001600160a01b038a1633308561195f565b6116fc565b604080516002808252606082018352600092602083019080368337505060055482519293506001600160a01b0316918391506000906115f957634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050898160018151811061163b57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600480546040517ffb3bdb4100000000000000000000000000000000000000000000000000000000815292169163fb3bdb4191633b9aca009161169c91889187913091429101611e17565b6000604051808303818588803b1580156116b557600080fd5b505af11580156116c9573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526116f29190810190611c64565b50506116fc565b50805b8a156117af57604080516000815260208101918290527f9d54def6000000000000000000000000000000000000000000000000000000009091526001600160a01b038a1690639d54def690611757908e903360248201611e80565b600060405180830381600087803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117ad9190810190611c64565b505b60006117bb8286611f36565b6040516370a0823160e01b81523060048201526001600160a01b038c16906370a082319060240160206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118329190611d44565b61183c9190611f36565b9050606481111561185b5761185b6001600160a01b038b1633836118b1565b604080518e8152602081018990529081018d90523360608201527f2d80d681127a38ca715ea60cfd400ccbe674c857d140e3437d0da5dde6152fa39060800160405180910390a150505050505050505050505050565b6040516001600160a01b03831660248201526044810182905261195a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119b6565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119b09085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016118f6565b50505050565b6000611a0b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a9b9092919063ffffffff16565b80519091501561195a5780806020019051810190611a299190611d24565b61195a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610895565b6060611aaa8484600085611ab4565b90505b9392505050565b606082471015611b2c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610895565b843b611b7a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610895565b600080866001600160a01b03168587604051611b969190611dc8565b60006040518083038185875af1925050503d8060008114611bd3576040519150601f19603f3d011682016040523d82523d6000602084013e611bd8565b606091505b5091509150611be8828286611bf3565b979650505050505050565b60608315611c02575081611aad565b825115611c125782518084602001fd5b8160405162461bcd60e51b81526004016108959190611de4565b600060208284031215611c3d578081fd5b8135611aad81611fa5565b600060208284031215611c59578081fd5b8151611aad81611fa5565b60006020808385031215611c76578182fd5b825167ffffffffffffffff80821115611c8d578384fd5b818501915085601f830112611ca0578384fd5b815181811115611cb257611cb2611f8f565b8060051b604051601f19603f83011681018181108582111715611cd757611cd7611f8f565b604052828152858101935084860182860187018a1015611cf5578788fd5b8795505b83861015611d17578051855260019590950194938601938601611cf9565b5098975050505050505050565b600060208284031215611d35578081fd5b81518015158114611aad578182fd5b600060208284031215611d55578081fd5b5051919050565b600080600060608486031215611d70578182fd5b833592506020840135611d8281611fa5565b91506040840135611d9281611fa5565b809150509250925092565b600080600060608486031215611db1578283fd5b505081359360208301359350604090920135919050565b60008251611dda818460208701611f4d565b9190910192915050565b6020815260008251806020840152611e03816040850160208701611f4d565b601f01601f19169190910160400192915050565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611e605784516001600160a01b031683529383019391830191600101611e3b565b50506001600160a01b039690961660408501525050506060015292915050565b60006060820185835260206060818501528186518084526080860191508288019350845b81811015611ec057845183529383019391830191600101611ea4565b50508093505050506001600160a01b0383166040830152949350505050565b60008219821115611ef257611ef2611f79565b500190565b600082611f1257634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615611f3157611f31611f79565b500290565b600082821015611f4857611f48611f79565b500390565b60005b83811015611f68578181015183820152602001611f50565b838111156119b05750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c3b57600080fdfea26469706673582212209c26d2d4ade512a6c82e6720e8049833e5baa1771cd64aa2d401d2fabe08d86564736f6c63430008040033
Deployed Bytecode
0x6080604052600436106100d65760003560e01c806378caec371161007f578063c0c65a4e11610059578063c0c65a4e14610229578063d8a06f7314610249578063f2fde38b14610269578063fa8afbd91461028957600080fd5b806378caec37146101cb578063839006f2146101eb5780638da5cb5b1461020b57600080fd5b80636d13582c116100b05780636d13582c14610176578063715018a61461019657806374a1b0b0146101ab57600080fd5b80630eb188ae146100e25780633ea7fbdb1461011c5780633fc8cef31461013e57600080fd5b366100dd57005b600080fd5b3480156100ee57600080fd5b506101026100fd366004611d5c565b61029c565b604080519283529015156020830152015b60405180910390f35b34801561012857600080fd5b5061013c610137366004611c2c565b61083f565b005b34801561014a57600080fd5b5060055461015e906001600160a01b031681565b6040516001600160a01b039091168152602001610113565b34801561018257600080fd5b5060045461015e906001600160a01b031681565b3480156101a257600080fd5b5061013c6108c0565b3480156101b757600080fd5b5060035461015e906001600160a01b031681565b3480156101d757600080fd5b5061013c6101e6366004611c2c565b610964565b3480156101f757600080fd5b5061013c610206366004611c2c565b610a83565b34801561021757600080fd5b506000546001600160a01b031661015e565b34801561023557600080fd5b5061013c610244366004611c2c565b610c3e565b34801561025557600080fd5b5060025461015e906001600160a01b031681565b34801561027557600080fd5b5061013c610284366004611c2c565b610cba565b61013c610297366004611d9d565b610deb565b6003546040517fc23c6da0000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b038481166024830152600092839242929091169063c23c6da09060440160206040518083038186803b15801561030857600080fd5b505afa15801561031c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103409190611d44565b111561035157506000905080610837565b6002546040516340d1b7db60e11b8152600481018790526000916001600160a01b0316906381a36fb69060240160206040518083038186803b15801561039657600080fd5b505afa1580156103aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ce9190611c48565b60035460405163cda13d6760e01b81526001600160a01b0380841660048301529293506000929091169063cda13d679060240160206040518083038186803b15801561041957600080fd5b505afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104519190611c48565b6040516370a0823160e01b81526001600160a01b038881166004830152919250839183918891600091908416906370a082319060240160206040518083038186803b15801561049f57600080fd5b505afa1580156104b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d79190611d44565b6003546040516321b1fe6960e11b8152600481018e90529192506000916001600160a01b0390911690634363fcd29060240160206040518083038186803b15801561052157600080fd5b505afa158015610535573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105599190611d44565b90506000670de0b6b3a76400006105708385611f17565b61057a9190611ef7565b90506000670de0b6b3a76400006105918486611f17565b61059b9190611ef7565b6105a6906063611edf565b905060006105bc670de0b6b3a764000084611ef7565b905060006105d2670de0b6b3a764000084611ef7565b905081811115610821576040516370a0823160e01b81523360048201526063906001600160a01b038b16906370a082319060240160206040518083038186803b15801561061e57600080fd5b505afa158015610632573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106569190611d44565b101580156106e25750604051636eb1769f60e11b81523360048201523060248201526063906001600160a01b038b169063dd62ed3e9060440160206040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106df9190611d44565b10155b156106fd579b5060019a506108379950505050505050505050565b612710876001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561073957600080fd5b505afa15801561074d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107719190611d44565b1061078c579b5060019a506108379950505050505050505050565b6040516370a0823160e01b81523060048201526063906001600160a01b038b16906370a082319060240160206040518083038186803b1580156107ce57600080fd5b505afa1580156107e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108069190611d44565b10610821579b5060019a506108379950505050505050505050565b509a506000995061083798505050505050505050565b935093915050565b6000546001600160a01b0316331461089e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461091a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146109be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600480546001600160a01b0319166001600160a01b0383169081178255604080517fad5c46480000000000000000000000000000000000000000000000000000000081529051919263ad5c4648928282019260209290829003018186803b158015610a2857600080fd5b505afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a609190611c48565b600580546001600160a01b0319166001600160a01b039290921691909117905550565b6000546001600160a01b03163314610add5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b6001600160a01b038116610bad57604051600090339047908381818185875af1925050503d8060008114610b2d576040519150601f19603f3d011682016040523d82523d6000602084013e610b32565b606091505b5050905080610ba95760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610895565b5050565b6040516370a0823160e01b8152306004820152610c3b9033906001600160a01b038416906370a082319060240160206040518083038186803b158015610bf257600080fd5b505afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a9190611d44565b6001600160a01b03841691906118b1565b50565b6000546001600160a01b03163314610c985760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610d145760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610895565b6001600160a01b038116610d905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610895565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b670de0b6b3a7640000811115610e0057600080fd5b6002546040516340d1b7db60e11b8152600481018590526000916001600160a01b0316906381a36fb69060240160206040518083038186803b158015610e4557600080fd5b505afa158015610e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7d9190611c48565b60035460405163cda13d6760e01b81526001600160a01b0380841660048301529293506000929091169063cda13d679060240160206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190611c48565b90506000610f1685670de0b6b3a7640000611f17565b6040516370a0823160e01b815233600482015290915060009081906001600160a01b038516906370a082319060240160206040518083038186803b158015610f5d57600080fd5b505afa158015610f71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f959190611d44565b905085670de0b6b3a76400001415610faf57809150611154565b6003546040516321b1fe6960e11b8152600481018a90526000916001600160a01b031690634363fcd29060240160206040518083038186803b158015610ff457600080fd5b505afa158015611008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102c9190611d44565b905060008161104386670de0b6b3a7640000611f17565b61104d9190611ef7565b905084670de0b6b3a76400006110638484611f17565b61106d9190611ef7565b10156110815761107e600182611edf565b90505b8083101561109157829350611151565b8761109e57809350611151565b6040516370a0823160e01b815233600482015260009082906001600160a01b038916906370a082319060240160206040518083038186803b1580156110e257600080fd5b505afa1580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a9190611d44565b6111249190611f36565b9050670de0b6b3a76400006111398a83611f17565b6111439190611ef7565b61114d9083611edf565b9450505b50505b6111696001600160a01b03851633308561195f565b600354604051636eb1769f60e11b81523060048201526001600160a01b039182166024820152839186169063dd62ed3e9060440160206040518083038186803b1580156111b557600080fd5b505afa1580156111c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ed9190611d44565b1015611295576003546040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015260001960248201529085169063095ea7b390604401602060405180830381600087803b15801561125b57600080fd5b505af115801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190611d24565b505b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a082319060240160206040518083038186803b1580156112d757600080fd5b505afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190611d44565b6003546040517f441a3e70000000000000000000000000000000000000000000000000000000008152600481018c9052602481018690529192506001600160a01b03169063441a3e7090604401600060405180830381600087803b15801561137657600080fd5b505af115801561138a573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092508391506001600160a01b038916906370a082319060240160206040518083038186803b1580156113d257600080fd5b505afa1580156113e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140a9190611d44565b6114149190611f36565b905060008582101561142d5761142a8287611f36565b90505b6064811061147d5760405162461bcd60e51b815260206004820152601260248201527f6e6f7420656e6f7567682076546f6b656e7300000000000000000000000000006044820152606401610895565b6000838211156116f9576040516370a0823160e01b815233600482015282906001600160a01b038b16906370a082319060240160206040518083038186803b1580156114c857600080fd5b505afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190611d44565b1015801561158b5750604051636eb1769f60e11b815233600482015230602482015282906001600160a01b038b169063dd62ed3e9060440160206040518083038186803b15801561155057600080fd5b505afa158015611564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115889190611d44565b10155b156115aa576115a56001600160a01b038a1633308561195f565b6116fc565b604080516002808252606082018352600092602083019080368337505060055482519293506001600160a01b0316918391506000906115f957634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050898160018151811061163b57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039283166020918202929092010152600480546040517ffb3bdb4100000000000000000000000000000000000000000000000000000000815292169163fb3bdb4191633b9aca009161169c91889187913091429101611e17565b6000604051808303818588803b1580156116b557600080fd5b505af11580156116c9573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526116f29190810190611c64565b50506116fc565b50805b8a156117af57604080516000815260208101918290527f9d54def6000000000000000000000000000000000000000000000000000000009091526001600160a01b038a1690639d54def690611757908e903360248201611e80565b600060405180830381600087803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117ad9190810190611c64565b505b60006117bb8286611f36565b6040516370a0823160e01b81523060048201526001600160a01b038c16906370a082319060240160206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118329190611d44565b61183c9190611f36565b9050606481111561185b5761185b6001600160a01b038b1633836118b1565b604080518e8152602081018990529081018d90523360608201527f2d80d681127a38ca715ea60cfd400ccbe674c857d140e3437d0da5dde6152fa39060800160405180910390a150505050505050505050505050565b6040516001600160a01b03831660248201526044810182905261195a9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119b6565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119b09085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016118f6565b50505050565b6000611a0b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a9b9092919063ffffffff16565b80519091501561195a5780806020019051810190611a299190611d24565b61195a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610895565b6060611aaa8484600085611ab4565b90505b9392505050565b606082471015611b2c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610895565b843b611b7a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610895565b600080866001600160a01b03168587604051611b969190611dc8565b60006040518083038185875af1925050503d8060008114611bd3576040519150601f19603f3d011682016040523d82523d6000602084013e611bd8565b606091505b5091509150611be8828286611bf3565b979650505050505050565b60608315611c02575081611aad565b825115611c125782518084602001fd5b8160405162461bcd60e51b81526004016108959190611de4565b600060208284031215611c3d578081fd5b8135611aad81611fa5565b600060208284031215611c59578081fd5b8151611aad81611fa5565b60006020808385031215611c76578182fd5b825167ffffffffffffffff80821115611c8d578384fd5b818501915085601f830112611ca0578384fd5b815181811115611cb257611cb2611f8f565b8060051b604051601f19603f83011681018181108582111715611cd757611cd7611f8f565b604052828152858101935084860182860187018a1015611cf5578788fd5b8795505b83861015611d17578051855260019590950194938601938601611cf9565b5098975050505050505050565b600060208284031215611d35578081fd5b81518015158114611aad578182fd5b600060208284031215611d55578081fd5b5051919050565b600080600060608486031215611d70578182fd5b833592506020840135611d8281611fa5565b91506040840135611d9281611fa5565b809150509250925092565b600080600060608486031215611db1578283fd5b505081359360208301359350604090920135919050565b60008251611dda818460208701611f4d565b9190910192915050565b6020815260008251806020840152611e03816040850160208701611f4d565b601f01601f19169190910160400192915050565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611e605784516001600160a01b031683529383019391830191600101611e3b565b50506001600160a01b039690961660408501525050506060015292915050565b60006060820185835260206060818501528186518084526080860191508288019350845b81811015611ec057845183529383019391830191600101611ea4565b50508093505050506001600160a01b0383166040830152949350505050565b60008219821115611ef257611ef2611f79565b500190565b600082611f1257634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615611f3157611f31611f79565b500290565b600082821015611f4857611f48611f79565b500390565b60005b83811015611f68578181015183820152602001611f50565b838111156119b05750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c3b57600080fdfea26469706673582212209c26d2d4ade512a6c82e6720e8049833e5baa1771cd64aa2d401d2fabe08d86564736f6c63430008040033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.