Whitepaper:
v4-core/whitepaper-v4-draft.pdf at main · Uniswap/v4-core
Research:
Contracts:
https://github.com/Uniswap/v4-core
https://github.com/Uniswap/v4-periphery
Notes:
Architecture - Singleton: v2, v3 deployment of new pools involves deploying a new contract (through CREATE2
)
Native ETH: v2 does not support native ETH and requires ETH to be wrapped to WETH → comes with extra gas cost
Feature - Hooks: Uniswap V4 allows anyone to deploy new concentrated liquidity pools with custom functionality. It can be used to manage the swap fee of the pool as well as the withdrawal fees charged to liquidity providers. Hooks can modify pool parameters or add new features and functionality:
when creating a pool → users can set the customized hook contracts, currently, there are eight hook callbacks:
beforeInitialize
/ afterInitialize
beforeModifyPosition
/ afterModifyPosition
beforeSwap
/ afterSwap
beforeDonate
/ afterDonate
Flash accounting: implemented EIP-1153
v2 / v3 each action ending with a token transfer (such as providing liquidity & swapping). In v4, each operation updates an internal net balance, known as a delta
→ only making the transfer at the very end to save the gas cost.
Function take / settle
/// @inheritdoc IPoolManager
/// used to borow fund from the pool
function take(Currency currency, address to, uint256 amount) external override noDelegateCall onlyByLocker {
_accountDelta(currency, amount.toInt128());
reservesOf[currency] -= amount;
currency.transfer(to, amount);
}
/// @inheritdoc IPoolManager
/// used to deposit fund back to the pool
function settle(Currency currency) external payable override noDelegateCall onlyByLocker returns (uint256 paid) {
uint256 reservesBefore = reservesOf[currency];
reservesOf[currency] = currency.balanceOfSelf();
paid = reservesOf[currency] - reservesBefore;
// subtraction must be safe
_accountDelta(currency, -(paid.toInt128()));
}
this design made the internal accounting easier, e.g in swapping. To further reduce the gas cost in internal state update, the Uniswap team implemented EIP-1153 transient storage.
Governance Updates: 2 separate governance fee mechanisms**: swap fee and withdrawal fees.** v2 / v3 can set the swap fee percentage through the governance, with v4, if hook choose to turn on withdrawal fees for a pool, governance also has the ability to take up to a capped percentage of that withdrawal fee.
donate() → tipping design for the in-range liquidity provider
/// @inheritdoc IPoolManager
function donate(PoolKey memory key, uint256 amount0, uint256 amount1)
external
override
noDelegateCall
onlyByLocker
returns (BalanceDelta delta)
{
if (key.hooks.shouldCallBeforeDonate()) {
if (key.hooks.beforeDonate(msg.sender, key, amount0, amount1) != IHooks.beforeDonate.selector) {
revert Hooks.InvalidHookResponse();
}
}
delta = _getPool(key).donate(amount0, amount1); // -> donate action here
_accountPoolBalanceDelta(key, delta);
if (key.hooks.shouldCallAfterDonate()) {
if (key.hooks.afterDonate(msg.sender, key, amount0, amount1) != IHooks.afterDonate.selector) {
revert Hooks.InvalidHookResponse();
}
}
}
TWAMM Notes
This paper introduces a new type of automated market maker, or AMM, that helps traders on Ethereum efficiently execute large orders.