-
Notifications
You must be signed in to change notification settings - Fork 45
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
BAL Hookathon - NFTLiquidityStakingHook #95
base: main
Are you sure you want to change the base?
Conversation
@0xTaneja is attempting to deploy a commit to the Matt Pereira's projects Team on Vercel. A member of the Team first needs to authorize it. |
Hey @rakpawel or @MattPereira , could you please review this when you get a chance? Thanks! |
function onAfterRemoveLiquidity( | ||
address router, | ||
uint256[] memory amountsOutScaled18, | ||
uint256 bptAmountIn, | ||
uint256[] memory balancesScaled18, | ||
bytes memory userData | ||
) external returns (bool success) { | ||
address user = router; | ||
address pool = msg.sender; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Help us understand why you're setting user
to equal the router
address? Wouldn't that mean you always have the same "user" which would be problematic for the _stakingInfoMap
logic below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the msg.sender
( in the context of who is calling the hook ) is actually the vault and not the pool. I think pool contracts mainly just do math and return results to the vault
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend checking out our hooks docs and hooks video
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Help us understand why you're setting
user
to equal therouter
address? Wouldn't that mean you always have the same "user" which would be problematic for the_stakingInfoMap
logic below?
Thank you for pointing this out. You're correct, and I've updated the code. In the onAfterRemoveLiquidity function, router is indeed the user's address in this context. I've left it as address user = router; for clarity, but it's no longer problematic as it correctly represents the user for each transaction.
I've updated the code to correctly identify the pool address. Now, instead of using msg.sender, we're using IPoolInfo(msg.sender).getPoolAddress() to get the actual pool address.
function simulateAddLiquidity(address user, address poolAddress, uint256 amount) internal { | ||
vm.prank(address(0)); | ||
(bool success, ) = address(hook).call( | ||
abi.encodeWithSignature( | ||
"onAfterAddLiquidity(address,address,uint256,uint256,bytes)", | ||
user, | ||
poolAddress, | ||
amount, | ||
amount, | ||
"" | ||
) | ||
); | ||
require(success, "onAfterAddLiquidity call failed"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is probably not an ideal way to simulate adding liquidity because the caller is the zero address instead of the vault, no tokens are being moved, and also the function signature doesnt seem to match the onAfterAddLiquidity
from the v3 interface for pool hooks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally I think you want to actually add liquidity by calling router.addLiquidity...
similar to how the FeeTakingHookExample test does it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally I think you want to actually add liquidity by calling
router.addLiquidity...
similar to how the FeeTakingHookExample test does it
You are absolutely right ! i watched hook videos and started to build by my own . i got errors , resolved them daily. but then i thought why not follow example codes so read them and build by my own!!
Thank you for this feedback. I've completely revamped the simulateAddLiquidity function in our test file. It now uses the vault as the caller instead of the zero address, and the function signature matches the onAfterAddLiquidity from the v3 interface.
mapping(uint256 => uint256) public nftTierToFeeDiscount; | ||
mapping(uint256 => uint256) public nftTierToVotingPower; | ||
mapping(uint256 => uint256) public nftTierToYieldBoost; | ||
mapping(uint256 => mapping(address => uint256)) private _votePowerCheckpoints; | ||
mapping(uint256 => uint256) private _totalSupplyCheckpoints; | ||
uint256 private _currentCheckpoint; | ||
|
||
mapping(address => mapping(uint256 => uint256)) private _ownedTokens; | ||
mapping(address => uint256) private _ownedTokensCount; | ||
|
||
uint256 public constant COOLDOWN_PERIOD = 7 days; | ||
uint256 public constant UPGRADE_COOLDOWN_PERIOD = 7 days; | ||
|
||
uint256 public constant BRONZE_TIER_THRESHOLD = 30 days; | ||
uint256 public constant SILVER_TIER_THRESHOLD = 90 days; | ||
uint256 public constant GOLD_TIER_THRESHOLD = 180 days; | ||
|
||
uint256 public constant BRONZE_TIER_AMOUNT = 1000 ether; | ||
uint256 public constant SILVER_TIER_AMOUNT = 5000 ether; | ||
uint256 public constant GOLD_TIER_AMOUNT = 10000 ether; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might consider using an enum
type to represent the different nft tiers and grouping related data about each tier into a struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might consider using an
enum
type to represent the different nft tiers and grouping related data about each tier into astruct
Thank you for this excellent suggestion. I've implemented it in the code. We now use an enum NFTTier to represent the different tiers, and a struct TierInfo to group related data about each tier.
I've made these changes and updated all relevant parts of the contract and test files to ensure consistency with these new implementations. Please let me know if you'd like me to clarify or expand on any of these changes.
I have tried to correct things which you have pointed . Also @MattPereira let implementation be aside ! What Do You think about my Idea ?? |
NFT Liquidity Staking Hook - BAL Hookathon Submission
An innovative Balancer V3 hook designed to reward liquidity providers with NFTs based on their staking activity. The NFTs unlock DeFi perks, such as fee discounts, governance participation, and boosted rewards, encouraging long-term liquidity provision and engagement.
🪧 Table of Contents
📖 Overview
The NFT Liquidity Staking Hook is a custom Balancer V3 hook designed to boost user engagement by issuing NFTs as rewards to liquidity providers (LPs). These NFTs offer unique DeFi perks, such as:
By implementing this hook, liquidity pools can increase long-term engagement, attract larger liquidity, and foster community loyalty.
✨ Features
🎖 NFT Tiers and Perks
The NFTs awarded through the NFT Liquidity Staking Hook are tiered to reflect a provider’s activity:
🛠 Architecture
NFTLiquidityStakingHook Contract
NFTGovernor Contract
contracts, providing a basic governance structure.
NFTMetadata
RewardToken
🚀 Usage
Deploying the Contracts
Setup
Integrating with a Pool
NFTLiquidityStakingHook
to a Balancer pool by interacting with the Vault.💡 Example Use Case
Scenario: Imagine Bob is a liquidity provider who deposits 50 ETH into a Balancer pool with the NFT Liquidity Staking Hook enabled.
🏦 Benefits
For Users
For Pool Creators
🧪 Testing
The testing suite for the
NFTLiquidityStakingHook
was built using Foundry and covers scenarios like:🛠 Development Notes
📌 Roadmap
Future improvements to the NFT Liquidity Staking Hook include:
📜 License
This project is licensed under the MIT License.
Thank you for considering the NFT Liquidity Staking Hook for the BAL Hookathon. I look forward to your feedback!