Skip to content
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

Implement Claims accounting as minimal balance #379

Merged
merged 38 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a7f428a
Add MinimalBalance
zhongeric Oct 30, 2023
d571ee6
Initial commmit
zhongeric Oct 30, 2023
31fb937
Router custodies Claims, has access to priviledged burnFrom anbd tests
zhongeric Oct 31, 2023
64f3222
updategas
zhongeric Oct 31, 2023
f20c0cc
remove 6909 lib
zhongeric Oct 31, 2023
e07d3e5
yarn snapshots
zhongeric Oct 31, 2023
2cc4bb3
Add gas snaps for swapping from claims balance
zhongeric Nov 1, 2023
8ac4c71
fix gas snaps by removing aux logic in router
zhongeric Nov 1, 2023
57f6910
gas
zhongeric Nov 1, 2023
20cc926
remove lib
zhongeric Nov 2, 2023
0eb8f80
Add transfer to minimalBalance, update tests
zhongeric Nov 2, 2023
f5f7036
nit: rename
zhongeric Nov 2, 2023
156b906
add back custom errors
zhongeric Nov 2, 2023
0fb4c0e
move addition out of unchecked
zhongeric Nov 2, 2023
f5b6908
Add transfer overflow check
zhongeric Nov 2, 2023
62379dc
Rename impl test
zhongeric Nov 2, 2023
8f6721d
nit comments
zhongeric Nov 2, 2023
e0c1eb9
comment#
zhongeric Nov 2, 2023
20ea785
Merge branch 'main' into minimal-balances
zhongeric Nov 6, 2023
caec8c0
Remove unused inheritance
zhongeric Nov 6, 2023
0be01db
remove comment
zhongeric Nov 6, 2023
b506694
Remove poolClaimTest
zhongeric Nov 6, 2023
f200569
fix interfaces
zhongeric Nov 6, 2023
37a17f5
Feedback
zhongeric Nov 7, 2023
56a4f22
Add address(0) and address(this) check for transfer
zhongeric Nov 7, 2023
cc32e04
remove address(0) check
zhongeric Nov 7, 2023
7a21d6b
Remove batchBurn
zhongeric Nov 7, 2023
0c9ed3d
Move mock claims to diff file
zhongeric Nov 7, 2023
95ba981
Add gas snaps for collect protocol fees
zhongeric Nov 7, 2023
a0b53cc
Add balance checks, make balances mapping private
zhongeric Nov 13, 2023
97bb3a3
Merge branch 'main' into minimal-balances
zhongeric Nov 13, 2023
505e02a
Fix imports
zhongeric Nov 13, 2023
7f7f980
fix fs perms
zhongeric Nov 13, 2023
ca7f811
Remove uint256 in mapping and use Currency
zhongeric Nov 13, 2023
0948233
Merge branch 'main' into minimal-balances
zhongeric Nov 13, 2023
b1a531c
Merge branch 'main' into minimal-balances
zhongeric Nov 14, 2023
44e5985
feedback
zhongeric Nov 14, 2023
49ca9a7
Add gas snaps
zhongeric Nov 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
85384
85229
2 changes: 1 addition & 1 deletion .forge-snapshots/cached dynamic fee, no hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
82539
82413
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 @@
95961
95883
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 @@
153292
153248
1 change: 1 addition & 0 deletions .forge-snapshots/erc20 collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
25011
2 changes: 1 addition & 1 deletion .forge-snapshots/gas overhead of no-op lock.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
58562
58439
2 changes: 1 addition & 1 deletion .forge-snapshots/initialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
38123
38079
2 changes: 1 addition & 1 deletion .forge-snapshots/mint with empty hook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
307130
307014
2 changes: 1 addition & 1 deletion .forge-snapshots/mint with native token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
275102
275044
2 changes: 1 addition & 1 deletion .forge-snapshots/mint.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
293738
293680
1 change: 1 addition & 0 deletions .forge-snapshots/native collect protocol fees.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
36677
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
29853
24460
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
49771
49645
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125033
124919
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
109721
109607
1 change: 1 addition & 0 deletions .forge-snapshots/swap burn claim for input.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
126321
1 change: 1 addition & 0 deletions .forge-snapshots/swap mint output as claim.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
166331
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 @@
84493
84338
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
49742
49616
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
49771
49645
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 @@
91231
91054
52 changes: 52 additions & 0 deletions contracts/Claims.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {Currency, CurrencyLibrary} from "./types/Currency.sol";
import {IClaims} from "./interfaces/IClaims.sol";

/// An intentionally barebones balance mapping only supporting mint/burn/transfer
contract Claims is IClaims {
using CurrencyLibrary for Currency;

// Mapping from Currency id to account balances
mapping(uint256 => mapping(address => uint256)) public balances;
hensha256 marked this conversation as resolved.
Show resolved Hide resolved

/// @inheritdoc IClaims
function balanceOf(address account, Currency currency) public view returns (uint256) {
return balances[currency.toId()][account];
}

/// @inheritdoc IClaims
function transfer(address to, Currency currency, uint256 amount) public {
zhongeric marked this conversation as resolved.
Show resolved Hide resolved
if (to == address(this)) revert InvalidAddress();

uint256 id = currency.toId();
if (amount > balances[id][msg.sender]) revert InsufficientBalance();
unchecked {
balances[id][msg.sender] -= amount;
}
balances[id][to] += amount;
emit Transfer(msg.sender, to, id, amount);
}

/// @notice Mint `amount` of currency `id` to `to`
/// @param to The address to mint to
/// @param id The id to mint
/// @param amount The amount to mint
function _mint(address to, uint256 id, uint256 amount) internal {
balances[id][to] += amount;
emit Mint(to, id, amount);
}

/// @notice Burn `amount` of currency `id` from `msg.sender`
/// @param id The id of the currency to burn
/// @param amount The amount to burn
/// @dev Will revert if the sender does not have enough balance
function _burn(uint256 id, uint256 amount) internal {
if (amount > balances[id][msg.sender]) revert InsufficientBalance();
unchecked {
balances[id][msg.sender] -= amount;
}
emit Burn(msg.sender, id, amount);
}
}
39 changes: 11 additions & 28 deletions contracts/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import {IHookFeeManager} from "./interfaces/IHookFeeManager.sol";
import {IPoolManager} from "./interfaces/IPoolManager.sol";
import {ILockCallback} from "./interfaces/callback/ILockCallback.sol";
import {Fees} from "./Fees.sol";
import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {Claims} from "./Claims.sol";
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
import {BalanceDelta} from "./types/BalanceDelta.sol";

/// @notice Holds the state for all pools
contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC1155, IERC1155Receiver {
contract PoolManager is IPoolManager, Fees, NoDelegateCall, Claims {
using PoolIdLibrary for PoolKey;
using SafeCast for *;
using Pool for *;
Expand Down Expand Up @@ -51,7 +50,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC1155, IERC1155Rec

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

constructor(uint256 controllerGasLimit) Fees(controllerGasLimit) ERC1155("") {}
constructor(uint256 controllerGasLimit) Fees(controllerGasLimit) {}

function _getPool(PoolKey memory key) private view returns (Pool.State storage) {
return pools[key.toId()];
Expand Down Expand Up @@ -323,12 +322,6 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC1155, IERC1155Rec
currency.transfer(to, amount);
}

/// @inheritdoc IPoolManager
function mint(Currency currency, address to, uint256 amount) external override noDelegateCall onlyByLocker {
_accountDelta(currency, amount.toInt128());
_mint(to, currency.toId(), amount, "");
}

/// @inheritdoc IPoolManager
function settle(Currency currency) external payable override noDelegateCall onlyByLocker returns (uint256 paid) {
uint256 reservesBefore = reservesOf[currency];
Expand All @@ -338,26 +331,16 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC1155, IERC1155Rec
_accountDelta(currency, -(paid.toInt128()));
}

function _burnAndAccount(Currency currency, uint256 amount) internal {
_burn(address(this), currency.toId(), amount);
_accountDelta(currency, -(amount.toInt128()));
}

function onERC1155Received(address, address, uint256 id, uint256 value, bytes calldata) external returns (bytes4) {
if (msg.sender != address(this)) revert NotPoolManagerToken();
_burnAndAccount(CurrencyLibrary.fromId(id), value);
return IERC1155Receiver.onERC1155Received.selector;
/// @inheritdoc IPoolManager
function mint(Currency currency, address to, uint256 amount) external noDelegateCall onlyByLocker {
_accountDelta(currency, amount.toInt128());
_mint(to, currency.toId(), amount);
}

function onERC1155BatchReceived(address, address, uint256[] calldata ids, uint256[] calldata values, bytes calldata)
external
returns (bytes4)
{
if (msg.sender != address(this)) revert NotPoolManagerToken();
for (uint256 i; i < ids.length; i++) {
_burnAndAccount(CurrencyLibrary.fromId(ids[i]), values[i]);
}
return IERC1155Receiver.onERC1155BatchReceived.selector;
/// @inheritdoc IPoolManager
function burn(Currency currency, uint256 amount) external noDelegateCall onlyByLocker {
_accountDelta(currency, -(amount.toInt128()));
_burn(currency.toId(), amount);
zhongeric marked this conversation as resolved.
Show resolved Hide resolved
}

function setProtocolFees(PoolKey memory key) external {
Expand Down
25 changes: 25 additions & 0 deletions contracts/interfaces/IClaims.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

interface IClaims {
error InsufficientBalance();
error InvalidAddress();

/// @notice Get the balance of `account` for `currency`
/// @param account The account to get the balance of
/// @param currency The currency to get the balance of
function balanceOf(address account, Currency currency) external returns (uint256);

/// @notice Transfer `amount` of `currency` from sender to `to`
/// @param to The address to transfer to
/// @param currency The currency to transfer
/// @param amount The amount to transfer
/// @dev Will revert if the sender does not have enough balance
function transfer(address to, Currency currency, uint256 amount) external;

event Mint(address indexed to, uint256 indexed id, uint256 amount);
event Burn(address indexed from, uint256 indexed id, uint256 amount);
event Transfer(address indexed from, address indexed to, uint256 indexed id, uint256 amount);
}
9 changes: 6 additions & 3 deletions contracts/interfaces/IPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ pragma solidity ^0.8.20;
import {Currency} from "../types/Currency.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {Pool} from "../libraries/Pool.sol";
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import {IHooks} from "./IHooks.sol";
import {IFees} from "./IFees.sol";
import {IClaims} from "./IClaims.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {PoolId} from "../types/PoolId.sol";
import {Position} from "../libraries/Position.sol";

interface IPoolManager is IFees, IERC1155 {
interface IPoolManager is IFees, IClaims {
/// @notice Thrown when currencies touched has exceeded max of 256
error MaxCurrenciesTouched();

Expand Down Expand Up @@ -176,9 +176,12 @@ interface IPoolManager is IFees, IERC1155 {
/// @dev Can also be used as a mechanism for _free_ flash loans
function take(Currency currency, address to, uint256 amount) external;

/// @notice Called by the user to move value into ERC1155 balance
/// @notice Called by the user to move value into Claims balance
function mint(Currency token, address to, uint256 amount) external;

/// @notice Called by the user to redeem their Claims balance
function burn(Currency token, uint256 amount) external;

/// @notice Called by the user to pay what is owed
function settle(Currency token) external payable returns (uint256 paid);

Expand Down
19 changes: 19 additions & 0 deletions contracts/test/MockClaims.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {Claims} from "../Claims.sol";
import {IClaims} from "../interfaces/IClaims.sol";
import {CurrencyLibrary, Currency} from "../types/Currency.sol";

contract MockClaims is Claims {
using CurrencyLibrary for Currency;

function mint(address to, Currency currency, uint256 amount) public {
_mint(to, currency.toId(), amount);
}

function burn(Currency currency, uint256 amount) public {
_burn(currency.toId(), amount);
}
}
27 changes: 8 additions & 19 deletions contracts/test/PoolSwapTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity ^0.8.20;

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

import {ILockCallback} from "../interfaces/callback/ILockCallback.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
Expand Down Expand Up @@ -45,6 +44,10 @@ contract PoolSwapTest is ILockCallback {
if (ethBalance > 0) CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
}

function _burnFromSelf(Currency currency, uint256 amount) internal {
zhongeric marked this conversation as resolved.
Show resolved Hide resolved
manager.burn(currency, amount);
}

function lockAcquired(bytes calldata rawData) external returns (bytes memory) {
require(msg.sender == address(manager));

Expand All @@ -64,21 +67,14 @@ contract PoolSwapTest is ILockCallback {
manager.settle(data.key.currency0);
}
} else {
// the received hook on this transfer will burn the tokens
manager.safeTransferFrom(
data.sender,
address(manager),
uint256(uint160(Currency.unwrap(data.key.currency0))),
uint128(delta.amount0()),
""
);
manager.burn(data.key.currency0, uint128(delta.amount0()));
}
}
if (delta.amount1() < 0) {
if (data.testSettings.withdrawTokens) {
manager.take(data.key.currency1, data.sender, uint128(-delta.amount1()));
} else {
manager.mint(data.key.currency1, data.sender, uint128(-delta.amount1()));
manager.mint(data.key.currency1, address(this), uint128(-delta.amount1()));
}
}
} else {
Expand All @@ -93,21 +89,14 @@ contract PoolSwapTest is ILockCallback {
manager.settle(data.key.currency1);
}
} else {
// the received hook on this transfer will burn the tokens
manager.safeTransferFrom(
data.sender,
address(manager),
uint256(uint160(Currency.unwrap(data.key.currency1))),
uint128(delta.amount1()),
""
);
manager.burn(data.key.currency1, uint128(delta.amount1()));
}
}
if (delta.amount0() < 0) {
if (data.testSettings.withdrawTokens) {
manager.take(data.key.currency0, data.sender, uint128(-delta.amount0()));
} else {
manager.mint(data.key.currency0, data.sender, uint128(-delta.amount0()));
manager.mint(data.key.currency0, address(this), uint128(-delta.amount0()));
}
}
}
Expand Down
Loading