-
Notifications
You must be signed in to change notification settings - Fork 472
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
Taking fee hook #121
Open
Jun1on
wants to merge
17
commits into
main
Choose a base branch
from
taking-fee-hook
base: main
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
Taking fee hook #121
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
7533101
add TakingFee hook
Jun1on c2c5e9d
update implementation to use ERC6909
Jun1on 2db7467
forge fmt
Jun1on 59da5a9
resolve nit
Jun1on 4628fe1
file name change
Jun1on da0ce08
fix bug
Jun1on 0a61b06
update constructor to take owner
Jun1on a526b2d
add more tests
Jun1on 852defc
add safecallback (#123)
snreynolds af6f768
Refactor for generalized FeeTaker abstract contract
Jun1on 3be9116
remove MAX_BIPS
Jun1on bd34d18
preemptively use library
Jun1on c1ccd70
update README
Jun1on 91a5185
add snapshots
Jun1on 173b3ac
gas optimization
Jun1on 35ba973
test _afterSwap extension
Jun1on cbaa07b
increase foundry gas_limit
Jun1on 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 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 @@ | ||
112467 |
This file contains 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 @@ | ||
86214 |
This file contains 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 @@ | ||
69428 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
311073 | ||
311181 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
122882 | ||
122990 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
80283 | ||
80220 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
1015169 | ||
1015181 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
110476 | ||
110566 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
239954 | ||
240044 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
45993 | ||
45930 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
79414 | ||
79351 |
This file contains 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 |
---|---|---|
@@ -1 +1 @@ | ||
122355 | ||
122336 |
This file contains 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 |
---|---|---|
|
@@ -21,5 +21,5 @@ jobs: | |
with: | ||
version: nightly | ||
|
||
- name: Run tests | ||
- name: Check format | ||
run: forge fmt --check |
This file contains 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
This file contains 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
This file contains 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,12 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
pragma solidity ^0.8.19; | ||
|
||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; | ||
|
||
contract ImmutableState { | ||
IPoolManager public immutable manager; | ||
|
||
constructor(IPoolManager _manager) { | ||
manager = _manager; | ||
} | ||
} |
This file contains 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,22 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol"; | ||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; | ||
import {ImmutableState} from "./ImmutableState.sol"; | ||
|
||
abstract contract SafeCallback is ImmutableState, IUnlockCallback { | ||
error NotManager(); | ||
|
||
modifier onlyByManager() { | ||
if (msg.sender != address(manager)) revert NotManager(); | ||
_; | ||
} | ||
|
||
/// @dev We force the onlyByManager modifier by exposing a virtual function after the onlyByManager check. | ||
function unlockCallback(bytes calldata data) external onlyByManager returns (bytes memory) { | ||
return _unlockCallback(data); | ||
} | ||
|
||
function _unlockCallback(bytes calldata data) internal virtual returns (bytes memory); | ||
} |
This file contains 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,104 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.24; | ||
|
||
import {BaseHook} from "../../BaseHook.sol"; | ||
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; | ||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; | ||
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; | ||
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; | ||
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; | ||
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; | ||
|
||
abstract contract FeeTaker is BaseHook { | ||
using SafeCast for uint256; | ||
|
||
bytes internal constant ZERO_BYTES = bytes(""); | ||
|
||
constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} | ||
|
||
/** | ||
* @notice This hook takes a fee from the unspecified token after a swap. | ||
* @dev This can be overridden if more permissions are needed. | ||
*/ | ||
function getHookPermissions() public pure virtual override returns (Hooks.Permissions memory) { | ||
return Hooks.Permissions({ | ||
beforeInitialize: false, | ||
afterInitialize: false, | ||
beforeAddLiquidity: false, | ||
afterAddLiquidity: false, | ||
beforeRemoveLiquidity: false, | ||
afterRemoveLiquidity: false, | ||
beforeSwap: false, | ||
afterSwap: true, | ||
beforeDonate: false, | ||
afterDonate: false, | ||
beforeSwapReturnDelta: false, | ||
afterSwapReturnDelta: true, | ||
afterAddLiquidityReturnDelta: false, | ||
afterRemoveLiquidityReturnDelta: false | ||
}); | ||
} | ||
|
||
function afterSwap( | ||
address sender, | ||
PoolKey calldata key, | ||
IPoolManager.SwapParams calldata params, | ||
BalanceDelta delta, | ||
bytes calldata hookData | ||
) external override onlyByManager returns (bytes4, int128) { | ||
//(Currency currencyUnspecified, amountUnspecified) = key.getUnspecified(params); | ||
|
||
// fee will be in the unspecified token of the swap | ||
bool currency0Specified = (params.amountSpecified < 0 == params.zeroForOne); | ||
(Currency currencyUnspecified, int128 amountUnspecified) = | ||
(currency0Specified) ? (key.currency1, delta.amount1()) : (key.currency0, delta.amount0()); | ||
// if exactOutput swap, get the absolute output amount | ||
if (amountUnspecified < 0) amountUnspecified = -amountUnspecified; | ||
|
||
uint256 feeAmount = _feeAmount(amountUnspecified); | ||
// mint ERC6909 instead of take to avoid edge case where PM doesn't have enough balance | ||
manager.mint(address(this), CurrencyLibrary.toId(currencyUnspecified), feeAmount); | ||
|
||
(bytes4 selector, int128 amount) = _afterSwap(sender, key, params, delta, hookData); | ||
return (selector, feeAmount.toInt128() + amount); | ||
} | ||
|
||
function withdraw(Currency[] calldata currencies) external { | ||
manager.unlock(abi.encode(currencies)); | ||
} | ||
|
||
function _unlockCallback(bytes calldata rawData) internal override returns (bytes memory) { | ||
Currency[] memory currencies = abi.decode(rawData, (Currency[])); | ||
uint256 length = currencies.length; | ||
for (uint256 i = 0; i < length;) { | ||
uint256 amount = manager.balanceOf(address(this), CurrencyLibrary.toId(currencies[i])); | ||
manager.burn(address(this), CurrencyLibrary.toId(currencies[i]), amount); | ||
manager.take(currencies[i], _recipient(), amount); | ||
unchecked { | ||
++i; | ||
} | ||
} | ||
return ZERO_BYTES; | ||
} | ||
|
||
/** | ||
* @dev This is a virtual function that should be overridden so it returns the fee charged for a given amount. | ||
*/ | ||
function _feeAmount(int128 amountUnspecified) internal view virtual returns (uint256); | ||
|
||
/** | ||
* @dev This is a virtual function that should be overridden so it returns the address to receive the fee. | ||
*/ | ||
function _recipient() internal view virtual returns (address); | ||
|
||
/** | ||
* @dev This can be overridden to add logic after a swap. | ||
*/ | ||
function _afterSwap(address, PoolKey memory, IPoolManager.SwapParams memory, BalanceDelta, bytes calldata) | ||
internal | ||
virtual | ||
returns (bytes4, int128) | ||
{ | ||
return (BaseHook.afterSwap.selector, 0); | ||
} | ||
} |
This file contains 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,35 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.24; | ||
|
||
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; | ||
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; | ||
import {Owned} from "solmate/auth/Owned.sol"; | ||
import {FeeTaker} from "./FeeTaker.sol"; | ||
|
||
contract FeeTaking is FeeTaker, Owned { | ||
using SafeCast for uint256; | ||
|
||
uint128 private constant TOTAL_BIPS = 10000; | ||
uint128 public immutable swapFeeBips; | ||
address public treasury; | ||
|
||
constructor(IPoolManager _poolManager, uint128 _swapFeeBips, address _owner, address _treasury) | ||
FeeTaker(_poolManager) | ||
Owned(_owner) | ||
{ | ||
swapFeeBips = _swapFeeBips; | ||
treasury = _treasury; | ||
} | ||
|
||
function setTreasury(address _treasury) external onlyOwner { | ||
treasury = _treasury; | ||
} | ||
|
||
function _feeAmount(int128 amountUnspecified) internal view override returns (uint256) { | ||
return uint128(amountUnspecified) * swapFeeBips / TOTAL_BIPS; | ||
} | ||
|
||
function _recipient() internal view override returns (address) { | ||
return treasury; | ||
} | ||
} |
Oops, something went wrong.
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.
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.
natspec