-
Notifications
You must be signed in to change notification settings - Fork 47
Vault creation zap #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tomwade
wants to merge
25
commits into
master
Choose a base branch
from
feature/vault-creation-zap
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
2dbfeee
initial commit
tomwade 759eb16
Add return value
tomwade 3f0f31d
Bypass local stack variable issues
tomwade d40a421
Update minting flow
tomwade 4510387
Make _getBoolean pure
tomwade 7965c3c
Add 1155 support
tomwade 52b6994
Move fee allocation
tomwade 3e974f0
Add code commenting
tomwade 027b182
Fix documentation
tomwade c922830
Remove console logging
tomwade 1646d4c
Enable gas reporting
tomwade 9d91b51
Comments and 1155 test
tomwade 7f1b9a0
Fix 1155 recipient address going to vault
tomwade 0e1d587
Enable minting in 1155 test
tomwade 5209596
Add 1155 support
tomwade afd9b0f
Convert binary to uint
tomwade 5f43e57
All 0 value for eligibility index
tomwade e994d1d
Add deploy script
tomwade 37bb8c2
Add liquidity and inventory staking support
tomwade 1bec606
Use SushiHelper
tomwade c63f8c1
Add new test suite
tomwade 0c2d15f
Fix variable casing
tomwade 8606b13
Update LP staking to be a mock
tomwade adfbc2d
Additional test for 0 items in creation
tomwade 438e4c3
Update fee tests
tomwade File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
pragma solidity ^0.8.0; | ||
|
||
contract WETH { | ||
string public name = "Wrapped Ether"; | ||
string public symbol = "WETH"; | ||
uint8 public decimals = 18; | ||
|
||
event Approval(address indexed src, address indexed guy, uint wad); | ||
event Transfer(address indexed src, address indexed dst, uint wad); | ||
event Deposit(address indexed dst, uint wad); | ||
event Withdrawal(address indexed src, uint wad); | ||
|
||
mapping (address => uint) public balanceOf; | ||
mapping (address => mapping (address => uint)) public allowance; | ||
|
||
receive() external payable { | ||
deposit(); | ||
} | ||
|
||
function mint(address to, uint256 amount) public { | ||
balanceOf[to] += amount; | ||
} | ||
|
||
function deposit() public payable { | ||
balanceOf[msg.sender] += msg.value; | ||
emit Deposit(msg.sender, msg.value); | ||
} | ||
|
||
function withdraw(uint wad) public payable { | ||
require(balanceOf[msg.sender] >= wad); | ||
balanceOf[msg.sender] -= wad; | ||
payable(msg.sender).transfer(wad); | ||
emit Withdrawal(msg.sender, wad); | ||
} | ||
|
||
function totalSupply() public view returns (uint) { | ||
return address(this).balance; | ||
} | ||
|
||
function approve(address guy, uint wad) public returns (bool) { | ||
allowance[msg.sender][guy] = wad; | ||
emit Approval(msg.sender, guy, wad); | ||
return true; | ||
} | ||
|
||
function transfer(address dst, uint wad) public returns (bool) { | ||
return transferFrom(msg.sender, dst, wad); | ||
} | ||
|
||
function transferFrom(address src, address dst, uint wad) | ||
public | ||
returns (bool) | ||
{ | ||
require(balanceOf[src] >= wad); | ||
|
||
if (src != msg.sender && allowance[src][msg.sender] >= 0) { | ||
require(allowance[src][msg.sender] >= wad); | ||
allowance[src][msg.sender] -= wad; | ||
} | ||
|
||
balanceOf[src] -= wad; | ||
balanceOf[dst] += wad; | ||
|
||
emit Transfer(src, dst, wad); | ||
|
||
return true; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../interface/INFTXVault.sol"; | ||
import "../interface/INFTXVaultFactory.sol"; | ||
import "../token/IERC1155Upgradeable.sol"; | ||
import "../util/ReentrancyGuardUpgradeable.sol"; | ||
|
||
|
||
/** | ||
* @notice .. | ||
* | ||
* @author Twade | ||
*/ | ||
|
||
contract NFTXVaultCreationZap is ReentrancyGuardUpgradeable { | ||
|
||
/// @notice An interface for the NFTX Vault Factory contract | ||
INFTXVaultFactory public immutable vaultFactory; | ||
|
||
struct vaultInfo { | ||
string name; // ??/32 | ||
string symbol; // ??/32 | ||
address assetAddress; // 20/32 | ||
bool is1155; // 21/32 | ||
bool allowAllItems; // 22/32 | ||
} | ||
|
||
struct vaultFeesConfig { | ||
uint32 mintFee; | ||
uint32 randomRedeemFee; | ||
uint32 targetRedeemFee; | ||
uint32 randomSwapFee; | ||
uint32 targetSwapFee; | ||
} | ||
|
||
struct vaultEligibilityStorage { | ||
uint moduleIndex; | ||
bytes initData; | ||
} | ||
|
||
struct vaultTokens { | ||
uint[] assetTokenIds; | ||
uint[] assetTokenAmounts; | ||
} | ||
|
||
|
||
/** | ||
* @notice Initialises our zap by setting contract addresses onto their | ||
* respective interfaces. | ||
* | ||
* @param _vaultFactory NFTX Vault Factory contract address | ||
*/ | ||
|
||
constructor(address _vaultFactory) { | ||
vaultFactory = INFTXVaultFactory(_vaultFactory); | ||
} | ||
|
||
|
||
/** | ||
* @notice .. | ||
*/ | ||
|
||
function createVault( | ||
// Vault creation | ||
vaultInfo calldata vaultData, | ||
|
||
// Vault features | ||
uint vaultFeatures, | ||
tomwade marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Fee assignment | ||
vaultFeesConfig calldata vaultFees, | ||
|
||
// Eligibility storage | ||
vaultEligibilityStorage calldata eligibilityStorage, | ||
|
||
// Staking | ||
vaultTokens calldata assetTokens | ||
|
||
) external nonReentrant returns (uint vaultId_) { | ||
// Create our vault skeleton | ||
vaultId_ = vaultFactory.createVault( | ||
vaultData.name, | ||
vaultData.symbol, | ||
vaultData.assetAddress, | ||
vaultData.is1155, | ||
vaultData.allowAllItems | ||
); | ||
|
||
// Build our vault interface | ||
INFTXVault vault = INFTXVault(vaultFactory.vault(vaultId_)); | ||
|
||
// If we have specified vault features then update them | ||
if (vaultFeatures > 0) { | ||
vault.setVaultFeatures( | ||
_getBoolean(vaultFeatures, 0), | ||
_getBoolean(vaultFeatures, 1), | ||
_getBoolean(vaultFeatures, 2), | ||
_getBoolean(vaultFeatures, 3), | ||
_getBoolean(vaultFeatures, 4) | ||
); | ||
} | ||
|
||
// Set our vault fees | ||
vault.setFees( | ||
vaultFees.mintFee, | ||
vaultFees.randomRedeemFee, | ||
vaultFees.targetRedeemFee, | ||
vaultFees.randomSwapFee, | ||
vaultFees.targetSwapFee | ||
); | ||
|
||
// If we have a specified eligibility storage, add that on | ||
if (eligibilityStorage.moduleIndex > 0) { | ||
vault.deployEligibilityStorage( | ||
eligibilityStorage.moduleIndex, | ||
eligibilityStorage.initData | ||
); | ||
} | ||
|
||
// Mint and stake liquidity into the vault | ||
uint length = assetTokens.assetTokenIds.length; | ||
if (length > 0) { | ||
if (!vaultData.is1155) { | ||
for (uint i; i < length;) { | ||
_transferFromERC721(vaultData.assetAddress, assetTokens.assetTokenIds[i], address(vault)); | ||
unchecked { ++i; } | ||
} | ||
} else { | ||
// This is technically a check, so placing it before the effect. | ||
IERC1155Upgradeable(vaultData.assetAddress).safeBatchTransferFrom( | ||
msg.sender, | ||
address(this), | ||
assetTokens.assetTokenIds, | ||
assetTokens.assetTokenAmounts, | ||
"" | ||
); | ||
} | ||
|
||
// We can now mint our asset tokens, giving the vault our tokens | ||
vault.mintTo(assetTokens.assetTokenIds, assetTokens.assetTokenAmounts, msg.sender); | ||
tomwade marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
// Finalise our vault, preventing further edits | ||
vault.finalizeVault(); | ||
} | ||
|
||
|
||
/** | ||
* @notice Transfers our ERC721 tokens to a specified recipient. | ||
* | ||
* @param assetAddr Address of the asset being transferred | ||
* @param tokenId The ID of the token being transferred | ||
* @param to The address the token is being transferred to | ||
*/ | ||
|
||
function _transferFromERC721(address assetAddr, uint256 tokenId, address to) internal virtual { | ||
bytes memory data; | ||
|
||
if (assetAddr == 0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB) { | ||
// Fix here for frontrun attack. | ||
bytes memory punkIndexToAddress = abi.encodeWithSignature("punkIndexToAddress(uint256)", tokenId); | ||
(bool checkSuccess, bytes memory result) = address(assetAddr).staticcall(punkIndexToAddress); | ||
(address nftOwner) = abi.decode(result, (address)); | ||
require(checkSuccess && nftOwner == msg.sender, "Not the NFT owner"); | ||
data = abi.encodeWithSignature("buyPunk(uint256)", tokenId); | ||
} else { | ||
// We push to the vault to avoid an unneeded transfer. | ||
data = abi.encodeWithSignature("safeTransferFrom(address,address,uint256)", msg.sender, to, tokenId); | ||
} | ||
|
||
(bool success, bytes memory resultData) = address(assetAddr).call(data); | ||
require(success, string(resultData)); | ||
} | ||
|
||
|
||
/** | ||
* @notice .. | ||
* | ||
* @param _packedBools .. | ||
* @param _boolNumber .. | ||
* | ||
* @return .. | ||
*/ | ||
|
||
function _getBoolean(uint256 _packedBools, uint256 _boolNumber) internal pure returns(bool) { | ||
uint256 flag = (_packedBools >> _boolNumber) & uint256(1); | ||
return (flag == 1 ? true : false); | ||
} | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.