Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexhandru authored Sep 5, 2024
2 parents 37a2a82 + 9c94b1a commit 1ee2456
Show file tree
Hide file tree
Showing 41 changed files with 291 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
144910
144608
2 changes: 1 addition & 1 deletion .forge-snapshots/addLiquidity CA fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
171199
170897
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 @@
274477
274175
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 @@
135252
135101
Original file line number Diff line number Diff line change
@@ -1 +1 @@
293102
292800
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 @@
106472
106321
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 @@
146038
145736
2 changes: 1 addition & 1 deletion .forge-snapshots/initialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
59966
60021
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24092
24006
Original file line number Diff line number Diff line change
@@ -1 +1 @@
98970
98819
2 changes: 1 addition & 1 deletion .forge-snapshots/simple addLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
161515
161364
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
123337
123186
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA custom curve + swap noop.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
127123
126821
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA fee on unspecified.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154782
154631
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
116709
116558
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 @@
139754
139603
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 @@
155178
155027
Original file line number Diff line number Diff line change
@@ -1 +1 @@
206434
206132
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 @@
139358
139207
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132346
132195
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with lp fee and protocol fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
169549
169398
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with return dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
145685
145534
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 @@
147965
147814
18 changes: 17 additions & 1 deletion docs/latex/main.bib
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,20 @@ @online{Buterin2021
title = "EIP-3529: Reduction in refunds",
url = "https://eips.ethereum.org/EIPS/eip-3529",
lastaccessed = "Jun 12, 2023",
}
}

@article{adams2024amm,
title={am-AMM: An Auction-Managed Automated Market Maker},
author={Adams, Austin and Moallemi, Ciamac and Reynolds, Sara and Robinson, Dan},
journal={arXiv preprint arXiv:2403.03367},
year={2024}
}

@online{riley2023,
author = "JT Riley and Dillon and Sara and Vectorized and Neodaoist",
year = "2023",
month = apr,
title = "ERC-6909: Minimal Multi-Token Interface",
url = "https://eips.ethereum.org/EIPS/eip-6909",
lastaccessed = "Aug 26, 2024",
}
95 changes: 53 additions & 42 deletions docs/latex/main.tex

Large diffs are not rendered by default.

Binary file modified docs/whitepaper-v4.pdf
Binary file not shown.
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ffi = true
fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}, { access = "read", path = "./out"}, {access = "read", path = "./test/bin"}]
solc = "0.8.26"
evm_version = "cancun"
gas_limit = "300000000"

[profile.default.fuzz]
runs = 1000
Expand Down
2 changes: 1 addition & 1 deletion src/NoDelegateCall.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: BUSL-1.1
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {CustomRevert} from "./libraries/CustomRevert.sol";
Expand Down
19 changes: 11 additions & 8 deletions src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim

mapping(PoolId id => Pool.State) internal _pools;

constructor(uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {}

/// @notice This will revert if the contract is locked
modifier onlyWhenUnlocked() {
if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith();
Expand Down Expand Up @@ -278,11 +276,14 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim

/// @inheritdoc IPoolManager
function sync(Currency currency) external onlyWhenUnlocked {
CurrencyReserves.requireNotSynced();
// address(0) is used for the native currency
if (currency.isAddressZero()) return;
uint256 balance = currency.balanceOfSelf();
CurrencyReserves.syncCurrencyAndReserves(currency, balance);
if (currency.isAddressZero()) {
// The reserves balance is not used for native settling, so we only need to reset the currency.
CurrencyReserves.resetCurrency();
} else {
uint256 balance = currency.balanceOfSelf();
CurrencyReserves.syncCurrencyAndReserves(currency, balance);
}
}

/// @inheritdoc IPoolManager
Expand Down Expand Up @@ -345,17 +346,19 @@ contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claim

function _settle(address recipient) internal returns (uint256 paid) {
Currency currency = CurrencyReserves.getSyncedCurrency();
// if not previously synced, expects native currency to be settled

// if not previously synced, or the syncedCurrency slot has been reset, expects native currency to be settled
if (currency.isAddressZero()) {
paid = msg.value;
} else {
if (msg.value > 0) NonzeroNativeValue.selector.revertWith();
// Reserves are guaranteed to be set, because currency and reserves are always set together
// Reserves are guaranteed to be set because currency and reserves are always set together
uint256 reservesBefore = CurrencyReserves.getSyncedReserves();
uint256 reservesNow = currency.balanceOfSelf();
paid = reservesNow - reservesBefore;
CurrencyReserves.resetCurrency();
}

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

Expand Down
15 changes: 9 additions & 6 deletions src/ProtocolFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {IProtocolFeeController} from "./interfaces/IProtocolFeeController.sol";
import {IProtocolFees} from "./interfaces/IProtocolFees.sol";
import {PoolKey} from "./types/PoolKey.sol";
import {ProtocolFeeLibrary} from "./libraries/ProtocolFeeLibrary.sol";
import {BipsLibrary} from "./libraries/BipsLibrary.sol";
import {Owned} from "solmate/src/auth/Owned.sol";
import {PoolId} from "./types/PoolId.sol";
import {Pool} from "./libraries/Pool.sol";
Expand All @@ -16,18 +17,19 @@ abstract contract ProtocolFees is IProtocolFees, Owned {
using ProtocolFeeLibrary for uint24;
using Pool for Pool.State;
using CustomRevert for bytes4;
using BipsLibrary for uint256;

/// @inheritdoc IProtocolFees
mapping(Currency currency => uint256 amount) public protocolFeesAccrued;

/// @inheritdoc IProtocolFees
IProtocolFeeController public protocolFeeController;

uint256 private immutable controllerGasLimit;
// a percentage of the block.gaslimit denoted in basis points, used as the gas limit for fee controller calls
// 100 bps is 1%, at 30M gas, the limit is 300K
uint256 private constant BLOCK_LIMIT_BPS = 100;

constructor(uint256 _controllerGasLimit) Owned(msg.sender) {
controllerGasLimit = _controllerGasLimit;
}
constructor() Owned(msg.sender) {}

/// @inheritdoc IProtocolFees
function setProtocolFeeController(IProtocolFeeController controller) external onlyOwner {
Expand Down Expand Up @@ -70,12 +72,13 @@ abstract contract ProtocolFees is IProtocolFees, Owned {
/// the success of this function is NOT checked on initialize and if the call fails, the protocol fees are set to 0.
function _fetchProtocolFee(PoolKey memory key) internal returns (uint24 protocolFee) {
if (address(protocolFeeController) != address(0)) {
uint256 controllerGasLimit = block.gaslimit.calculatePortion(BLOCK_LIMIT_BPS);

// note that EIP-150 mandates that calls requesting more than 63/64ths of remaining gas
// will be allotted no more than this amount, so controllerGasLimit must be set with this
// in mind.
if (gasleft() < controllerGasLimit) ProtocolFeeCannotBeFetched.selector.revertWith();

uint256 gasLimit = controllerGasLimit;
address toAddress = address(protocolFeeController);

bytes memory data = abi.encodeCall(IProtocolFeeController.protocolFeeForPool, (key));
Expand All @@ -84,7 +87,7 @@ abstract contract ProtocolFees is IProtocolFees, Owned {
uint256 returnData;
assembly ("memory-safe") {
// only load the first 32 bytes of the return data to prevent gas griefing
success := call(gasLimit, toAddress, 0, add(data, 0x20), mload(data), 0, 32)
success := call(controllerGasLimit, toAddress, 0, add(data, 0x20), mload(data), 0, 32)
// if success is false this wont actually be returned, instead 0 will be returned
returnData := mload(0)

Expand Down
3 changes: 2 additions & 1 deletion src/interfaces/IPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload {
/// 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, but can be skipped
/// for native tokens because the amount to settle is determined by the sent value.
/// @param currency The currency whose balance to sync
/// However, if an ERC20 token has been synced and not settled, and the caller instead wants to settle
/// native funds, this function can be called with the native currency to then be able to settle the native currency
function sync(Currency currency) external;

/// @notice Called by the user to net out some value owed to the user
Expand Down
17 changes: 17 additions & 0 deletions src/libraries/BipsLibrary.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title For calculating a percentage of an amount, using bips
library BipsLibrary {
uint256 internal constant BPS_DENOMINATOR = 10_000;

/// @notice emitted when an invalid percentage is provided
error InvalidBips();

/// @param amount The total amount to calculate a percentage of
/// @param bips The percentage to calculate, in bips
function calculatePortion(uint256 amount, uint256 bips) internal pure returns (uint256) {
if (bips > BPS_DENOMINATOR) revert InvalidBips();
return (amount * bips) / BPS_DENOMINATOR;
}
}
9 changes: 0 additions & 9 deletions src/libraries/CurrencyReserves.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,11 @@ import {CustomRevert} from "./CustomRevert.sol";
library CurrencyReserves {
using CustomRevert for bytes4;

/// @notice Thrown when a user has already synced a currency, but not yet settled
error AlreadySynced();

/// bytes32(uint256(keccak256("ReservesOf")) - 1)
bytes32 constant RESERVES_OF_SLOT = 0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95;
/// bytes32(uint256(keccak256("Currency")) - 1)
bytes32 constant CURRENCY_SLOT = 0x27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b9;

function requireNotSynced() internal view {
if (!getSyncedCurrency().isAddressZero()) {
AlreadySynced.selector.revertWith();
}
}

function getSyncedCurrency() internal view returns (Currency currency) {
assembly ("memory-safe") {
currency := tload(CURRENCY_SLOT)
Expand Down
2 changes: 0 additions & 2 deletions src/test/ProtocolFeesImplementation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ contract ProtocolFeesImplementation is ProtocolFees {
mapping(PoolId id => Pool.State) internal _pools;
bool internal isUnlocked;

constructor(uint256 _controllerGasLimit) ProtocolFees(_controllerGasLimit) {}

// Used to set the price of a pool to pretend that the pool has been initialized in order to successfully set a protocol fee
function setPrice(PoolKey memory key, uint160 sqrtPriceX96) public {
Pool.State storage pool = _getPool(key.toId());
Expand Down
14 changes: 9 additions & 5 deletions src/test/ProxyPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909

address internal immutable _delegateManager;

constructor(address delegateManager, uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {
constructor(address delegateManager) {
_delegateManager = delegateManager;
}

Expand Down Expand Up @@ -141,10 +141,14 @@ contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909

/// @inheritdoc IPoolManager
function sync(Currency currency) public {
CurrencyReserves.requireNotSynced();
if (currency.isAddressZero()) return;
uint256 balance = currency.balanceOfSelf();
CurrencyReserves.syncCurrencyAndReserves(currency, balance);
// address(0) is used for the native currency
if (currency.isAddressZero()) {
// The reserves balance is not used for native settling, so we only need to reset the currency.
CurrencyReserves.resetCurrency();
} else {
uint256 balance = currency.balanceOfSelf();
CurrencyReserves.syncCurrencyAndReserves(currency, balance);
}
}

/// @inheritdoc IPoolManager
Expand Down
4 changes: 2 additions & 2 deletions test/NoDelegateCall.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {Deployers} from "./utils/Deployers.sol";
contract TestDelegateCall is Test, Deployers, GasSnapshot {
// override to use ProxyPoolManager
function deployFreshManager() internal virtual override {
IPoolManager delegateManager = new PoolManager(500000);
manager = new ProxyPoolManager(address(delegateManager), 500000);
IPoolManager delegateManager = new PoolManager();
manager = new ProxyPoolManager(address(delegateManager));
}

NoDelegateCallTest noDelegateCallTest;
Expand Down
10 changes: 5 additions & 5 deletions test/PoolManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1135,16 +1135,16 @@ contract PoolManagerTest is Test, Deployers, GasSnapshot {
emptyUnlockRouter.unlock();
}

Action[] actions;
Action[] _actions;

function test_unlock_cannotBeCalledTwiceByCaller() public {
actions = [Action.NESTED_SELF_UNLOCK];
nestedActionRouter.unlock(abi.encode(actions));
_actions = [Action.NESTED_SELF_UNLOCK];
nestedActionRouter.unlock(abi.encode(_actions));
}

function test_unlock_cannotBeCalledTwiceByDifferentCallers() public {
actions = [Action.NESTED_EXECUTOR_UNLOCK];
nestedActionRouter.unlock(abi.encode(actions));
_actions = [Action.NESTED_EXECUTOR_UNLOCK];
nestedActionRouter.unlock(abi.encode(_actions));
}

// function testExtsloadForPoolPrice() public {
Expand Down
2 changes: 1 addition & 1 deletion test/ProtocolFeesImplementation.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ contract ProtocolFeesTest is Test, GasSnapshot, Deployers {
ProtocolFeesImplementation protocolFees;

function setUp() public {
protocolFees = new ProtocolFeesImplementation(5000);
protocolFees = new ProtocolFeesImplementation();
feeController = new ProtocolFeeControllerTest();
(currency0, currency1) = deployAndMint2Currencies();
MockERC20(Currency.unwrap(currency0)).transfer(address(protocolFees), 2 ** 255);
Expand Down
Loading

0 comments on commit 1ee2456

Please sign in to comment.