Skip to content

Commit

Permalink
Merge and update snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
shuhuiluo committed Apr 21, 2024
2 parents e483fb1 + bd6cce2 commit 16181ad
Show file tree
Hide file tree
Showing 46 changed files with 711 additions and 215 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
264375
259285
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
139216
136628
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
144552
139462
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 1 token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
101147
98611
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 2 tokens.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132153
127061
2 changes: 1 addition & 1 deletion .forge-snapshots/erc20 collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24961
24938
2 changes: 1 addition & 1 deletion .forge-snapshots/native collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
36634
36611
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22366
22541
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
54720
53760
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146903
141532
2 changes: 1 addition & 1 deletion .forge-snapshots/removeLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
148370
137810
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap with native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132580
126802
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146475
138195
Original file line number Diff line number Diff line change
@@ -1 +1 @@
72112
71137
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
60134
61456
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
80275
79333
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn native 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
76142
75192
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint native output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
138642
135559
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
155290
152198
Original file line number Diff line number Diff line change
@@ -1 +1 @@
155727
158761
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
89365
90685
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
60112
61435
2 changes: 1 addition & 1 deletion .forge-snapshots/update dynamic fee in before swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
139991
131711
50 changes: 30 additions & 20 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {Lock} from "./libraries/Lock.sol";
import {CurrencyDelta} from "./libraries/CurrencyDelta.sol";
import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
import {PoolGetters} from "./libraries/PoolGetters.sol";
import {Reserves} from "./libraries/Reserves.sol";
import {Extsload} from "./Extsload.sol";

/// @notice Holds the state for all pools
Expand All @@ -35,16 +36,14 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
using CurrencyDelta for Currency;
using SwapFeeLibrary for uint24;
using PoolGetters for Pool.State;
using Reserves for Currency;

/// @inheritdoc IPoolManager
int24 public constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING;

/// @inheritdoc IPoolManager
int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING;

/// @inheritdoc IPoolManager
mapping(Currency currency => uint256) public override reservesOf;

mapping(PoolId id => Pool.State) public pools;

constructor(uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {}
Expand Down Expand Up @@ -146,18 +145,22 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
Lock.lock();
}

/// @inheritdoc IPoolManager
function sync(Currency currency) public returns (uint256 balance) {
balance = currency.balanceOfSelf();
currency.setReserves(balance);
}

function _accountDelta(Currency currency, int128 delta) internal {
if (delta == 0) return;

int256 current = currency.getDelta(msg.sender);
int256 next = current + delta;

unchecked {
if (next == 0) {
NonZeroDeltaCount.decrement();
} else if (current == 0) {
NonZeroDeltaCount.increment();
}
if (next == 0) {
NonZeroDeltaCount.decrement();
} else if (current == 0) {
NonZeroDeltaCount.increment();
}

currency.setDelta(msg.sender, next);
Expand Down Expand Up @@ -260,10 +263,11 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim

/// @inheritdoc IPoolManager
function take(Currency currency, address to, uint256 amount) external override onlyWhenUnlocked {
// subtraction must be safe
_accountDelta(currency, -(amount.toInt128()));
if (!currency.isNative()) reservesOf[currency] -= amount;
currency.transfer(to, amount);
unchecked {
// subtraction must be safe
_accountDelta(currency, -(amount.toInt128()));
currency.transfer(to, amount);
}
}

/// @inheritdoc IPoolManager
Expand All @@ -272,19 +276,20 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
paid = msg.value;
} else {
if (msg.value > 0) revert NonZeroNativeValue();
uint256 reservesBefore = reservesOf[currency];
reservesOf[currency] = currency.balanceOfSelf();
paid = reservesOf[currency] - reservesBefore;
uint256 reservesBefore = currency.getReserves();
uint256 reservesNow = sync(currency);
paid = reservesNow - reservesBefore;
}

_accountDelta(currency, paid.toInt128());
}

/// @inheritdoc IPoolManager
function mint(address to, uint256 id, uint256 amount) external override onlyWhenUnlocked {
// subtraction must be safe
_accountDelta(CurrencyLibrary.fromId(id), -(amount.toInt128()));
_mint(to, id, amount);
unchecked {
// subtraction must be safe
_accountDelta(CurrencyLibrary.fromId(id), -(amount.toInt128()));
_mint(to, id, amount);
}
}

/// @inheritdoc IPoolManager
Expand Down Expand Up @@ -312,6 +317,11 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim
return pools[id].getPoolBitmapInfo(word);
}

/// @notice Temporary view function. Replaceable by transient EXTSLOAD.
function getReserves(Currency currency) external view returns (uint256 balance) {
return currency.getReserves();
}

function getFeeGrowthGlobals(PoolId id)
external
view
Expand Down
6 changes: 3 additions & 3 deletions src/ProtocolFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ abstract contract ProtocolFees is IProtocolFees, Owned {
}

/// @inheritdoc IProtocolFees
function setProtocolFee(PoolKey memory key) external {
(bool success, uint24 newProtocolFee) = _fetchProtocolFee(key);
if (!success) revert ProtocolFeeControllerCallFailedOrInvalidResult();
function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external {
if (msg.sender != address(protocolFeeController)) revert InvalidCaller();
if (!newProtocolFee.validate()) revert InvalidProtocolFee();
PoolId id = key.toId();
_getPool(id).setProtocolFee(newProtocolFee);
emit ProtocolFeeUpdated(id, newProtocolFee);
Expand Down
8 changes: 6 additions & 2 deletions src/interfaces/IPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload {
view
returns (Position.Info memory position);

/// @notice Returns the reserves for a given ERC20 currency
function reservesOf(Currency currency) external view returns (uint256);
/// @notice Writes the current ERC20 balance of the specified currency to transient storage
/// This is used to checkpoint balances for the manager and derive deltas for the caller.
/// @dev This MUST be called before any ERC20 tokens are sent into the contract.
function sync(Currency currency) external returns (uint256 balance);

/// @notice Returns whether the contract is unlocked or not
function isUnlocked() external view returns (bool);
Expand Down Expand Up @@ -198,4 +200,6 @@ interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload {

/// @notice Updates the pools swap fees for the a pool that has enabled dynamic swap fees.
function updateDynamicSwapFee(PoolKey memory key, uint24 newDynamicSwapFee) external;

function getReserves(Currency currency) external view returns (uint256 balance);
}
11 changes: 5 additions & 6 deletions src/interfaces/IProtocolFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {PoolKey} from "../types/PoolKey.sol";
interface IProtocolFees {
/// @notice Thrown when not enough gas is provided to look up the protocol fee
error ProtocolFeeCannotBeFetched();
/// @notice Thrown when the call to fetch the protocol fee reverts or returns invalid data.
error ProtocolFeeControllerCallFailedOrInvalidResult();
/// @notice Thrown when protocol fee is set too high
error InvalidProtocolFee();

/// @notice Thrown when collectProtocolFees is not called by the controller.
/// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller.
error InvalidCaller();

event ProtocolFeeControllerUpdated(address protocolFeeController);
Expand All @@ -22,9 +22,8 @@ interface IProtocolFees {
/// @notice Given a currency address, returns the protocol fees accrued in that currency
function protocolFeesAccrued(Currency) external view returns (uint256);

/// @notice Sets the protocol's swap fee for the given pool
/// Protocol fees are always a portion of the LP swap fee that is owed. If that fee is 0, no protocol fees will accrue even if it is set to > 0.
function setProtocolFee(PoolKey memory key) external;
/// @notice Sets the protocol fee for the given pool
function setProtocolFee(PoolKey memory key, uint24) external;

/// @notice Sets the protocol fee controller
function setProtocolFeeController(IProtocolFeeController) external;
Expand Down
40 changes: 40 additions & 0 deletions src/libraries/CurrencySettleTake.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {Currency, CurrencyLibrary} from "../types/Currency.sol";
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";

library CurrencySettleTake {
using CurrencyLibrary for Currency;

/// @notice Settle (pay) a currency to the PoolManager
/// @param currency Currency to settle
/// @param manager IPoolManager to settle to
/// @param payer Address of the payer, the token sender
/// @param amount Amount to send
/// @param burn If true, burn the ERC-6909 token, otherwise ERC20-transfer to the PoolManager
function settle(Currency currency, IPoolManager manager, address payer, uint256 amount, bool burn) internal {
// for native currencies or burns, calling sync is not required
// short circuit for ERC-6909 burns to support ERC-6909-wrapped native tokens
if (burn) {
manager.burn(payer, currency.toId(), amount);
} else if (currency.isNative()) {
manager.settle{value: amount}(currency);
} else {
manager.sync(currency);
IERC20Minimal(Currency.unwrap(currency)).transferFrom(payer, address(manager), amount);
manager.settle(currency);
}
}

/// @notice Take (receive) a currency from the PoolManager
/// @param currency Currency to take
/// @param manager IPoolManager to take from
/// @param recipient Address of the recipient, the token receiver
/// @param amount Amount to receive
/// @param claims If true, mint the ERC-6909 token, otherwise ERC20-transfer from the PoolManager to recipient
function take(Currency currency, IPoolManager manager, address recipient, uint256 amount, bool claims) internal {
claims ? manager.mint(recipient, currency.toId(), amount) : manager.take(currency, recipient, amount);
}
}
40 changes: 40 additions & 0 deletions src/libraries/Reserves.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {Currency} from "../types/Currency.sol";

library Reserves {
/// uint256(keccak256("ReservesOf")) - 1
uint256 constant RESERVES_OF_SLOT = uint256(0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95);
/// @notice The transient reserves for pools with no balance is set to the max as a sentinel to track that it has been synced.
uint256 public constant ZERO_BALANCE = type(uint256).max;

/// @notice Thrown when someone has not called sync before calling settle for the first time.
error ReservesMustBeSynced();

function setReserves(Currency currency, uint256 value) internal {
if (value == 0) value = ZERO_BALANCE;
bytes32 key = _getKey(currency);
assembly {
tstore(key, value)
}
}

function getReserves(Currency currency) internal view returns (uint256 value) {
bytes32 key = _getKey(currency);
assembly {
value := tload(key)
}
if (value == 0) revert ReservesMustBeSynced();
if (value == ZERO_BALANCE) value = 0;
}

function _getKey(Currency currency) private pure returns (bytes32 key) {
uint256 slot = RESERVES_OF_SLOT;
assembly {
mstore(0, slot)
mstore(32, currency)
key := keccak256(0, 64)
}
}
}
Loading

0 comments on commit 16181ad

Please sign in to comment.