-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Before after add/remove liquidity, remove all modifyPosition hooks #434
Conversation
…into before-after-mint
7ec6d8d
to
cee4d82
Compare
test/AccessLock.t.sol
Outdated
// TODO: Maybe due to a rounding issue, but balanceOfBefore0 == balanceOfAfter0 ? | ||
assertTrue(balanceOfBefore0 - balanceOfAfter0 <= 1); | ||
assertTrue(balanceOfBefore1 - balanceOfAfter1 - amount <= 1); |
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.
Not sure why I had an off by one issue here? Is it possible that it is a rounding issue?
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.
Ya should equal, that's werid
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.
I feel like theres improvements in efficiency of the internal code that can be made now that we have separation of add/remove liquidity functions.
For example, in the Pool library in modifyPosition
, it has to do checks
if (params.liquidityDelta > 0) {
/// aka if this is an ADD liquidity then do X
}
if (params.liquidityDelta < 0) {
/// aka if this is a REMOVE liquidity then do Y
}
this PR gives the nice separation of entry points, but then still leads to the same internal flow of checking whether liquidityDelta is positive or negative, even though that is actually known in advance
I think we should maybe investigate splitting pool logic into internal addLiquidity
and removeLiquidity
, where removeLiquidity
never has to do any of the params.liquidityDelta > 0
checks and vice versa?
@hensha256 Definitely agree! I can take a closer look at the Pool logic to see how that might simplify things. This would be as a follow up yeah? Not blocking |
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.
seems like a good structure although hard to give a full review knowing a lot of this will change with Alice's and Mark's changes... could you pull those in? 😄
Yeah will do! Might take me a sec to do the refactor/fix all the merge conflicts |
Yeah we can make it a followup, please can you open a github issue so we dont forget? |
…-after-add/removeLiquidity
b9f2398
to
832e6b1
Compare
3912e4a
to
435c914
Compare
src/libraries/Hooks.sol
Outdated
) internal returns (bool shouldExecute) { | ||
if (self.hasPermission(BEFORE_MODIFY_POSITION_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeModifyPosition.selector, msg.sender, key, params, hookData) | ||
); | ||
if (params.liquidityDelta >= 0) { | ||
if (key.hooks.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeAddLiquidity.selector, msg.sender, key, params, hookData) | ||
); | ||
} else { | ||
shouldExecute = true; | ||
} | ||
} else { | ||
return true; | ||
if (key.hooks.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeRemoveLiquidity.selector, msg.sender, key, params, hookData) | ||
); | ||
} else { | ||
shouldExecute = true; | ||
} |
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.
Feel like this looks a little ugly, could also change to something like:
/// @notice calls beforeModifyPosition hook if permissioned and validates return value
function beforeModifyPosition(
IHooks self,
PoolKey memory key,
IPoolManager.ModifyPositionParams memory params,
bytes calldata hookData
) internal returns (bool shouldExecute) {
if (params.liquidityDelta >= 0 && key.hooks.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) {
shouldExecute = self.callHookNoopable(
abi.encodeWithSelector(IHooks.beforeAddLiquidity.selector, msg.sender, key, params, hookData)
);
} else if (params.liquidityDelta < 0 && key.hooks.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) {
shouldExecute = self.callHookNoopable(
abi.encodeWithSelector(IHooks.beforeRemoveLiquidity.selector, msg.sender, key, params, hookData)
);
} else {
shouldExecute = true;
}
}
It's a little more gas ~100 but maybe that's ok?
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.
I think we should expose separate getters for querying beforeAdd/RemoveLiquidity and deprecating beforeModifiyPosition + afterModifyPosition so you don't need this conditional
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.
I think I prefer this branching. And @zhongeric I think Mark and I talked about this and we kinda liked having the beforeModifyPos/afterModifyPos as the entrypoints in the Hooks library so that we are removing the liquidityDelta logic from core codepaths
src/libraries/Hooks.sol
Outdated
) internal returns (bool shouldExecute) { | ||
if (self.hasPermission(BEFORE_MODIFY_POSITION_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeModifyPosition.selector, msg.sender, key, params, hookData) | ||
); | ||
if (params.liquidityDelta >= 0) { | ||
if (key.hooks.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeAddLiquidity.selector, msg.sender, key, params, hookData) | ||
); | ||
} else { | ||
shouldExecute = true; | ||
} | ||
} else { | ||
return true; | ||
if (key.hooks.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) { | ||
shouldExecute = self.callHookNoopable( | ||
abi.encodeWithSelector(IHooks.beforeRemoveLiquidity.selector, msg.sender, key, params, hookData) | ||
); | ||
} else { | ||
shouldExecute = true; | ||
} |
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.
I think we should expose separate getters for querying beforeAdd/RemoveLiquidity and deprecating beforeModifiyPosition + afterModifyPosition so you don't need this conditional
test/AccessLock.t.sol
Outdated
// TODO: Maybe due to a rounding issue, but balanceOfBefore0 == balanceOfAfter0 ? | ||
assertTrue(balanceOfBefore0 - balanceOfAfter0 <= 1); | ||
assertTrue(balanceOfBefore1 - balanceOfAfter1 - amount <= 1); |
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.
Ya should equal, that's werid
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.
One last overall
Should we be hitting the beforeAddLiquidity logic for liquidityParams of 0? I think in the worst case someone could revert on just collecting fees but not wanting to change their position. Either we don't call out to hooks or maybe have the 0 liquidityParams branch out to the afterAddLiquidity branch?
Also should we change name to modifyLiquidity()?
I removed any of the add/remove liquidity hook calls for a |
0db7782
to
8c5e457
Compare
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.
just last name change suggestion but looks rlly good!
src/interfaces/IPoolManager.sol
Outdated
/// @param params The parameters for modifying the liquidity | ||
/// @param hookData Any data to pass to the callback, via `ILockCallback(msg.sender).lockAcquired(data)` | ||
/// @return delta The balance delta of the liquidity | ||
function modifyLiquidity(PoolKey memory key, ModifyPositionParams memory params, bytes calldata hookData) |
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.
laaaast lil nit: ModifyLiquidityParams ?
@@ -161,12 +168,16 @@ library Hooks { | |||
IPoolManager.ModifyPositionParams memory params, | |||
bytes calldata hookData | |||
) internal returns (bool shouldExecute) { |
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.
and same name change on these functions? Just thinking so that they are all standardized
beforeModifyPosition -> beforeModifyLiquidity
afterModifyPosition -> afterModifyLiquidity
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.
fixed 👍
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.
🚢
…niswap#434) * Add before/after add/remove liquidity hooks --------- Co-authored-by: Eric Zhong <[email protected]>
Which issue does this pull request resolve?
This PR fixes #350. The main idea is:
Description of changes
We broke up the modify position hook into an
addLiquidity
andremoveLiquidity
hook. This allows for a better separation of permissions. The following changes were made to implement these hooks.