Skip to content

Commit

Permalink
merge in main; fix breaking changes
Browse files Browse the repository at this point in the history
  • Loading branch information
saucepoint committed Jun 3, 2024
2 parents 187fc3d + 5082779 commit 0f9936e
Show file tree
Hide file tree
Showing 35 changed files with 432 additions and 367 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeAddInitialLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
392801
311165
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeAddLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
187168
122974
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeFirstSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
136542
80287
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeInitialize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1041059
1015181
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeRemoveLiquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
175928
110572
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeRemoveLiquidityAndRebalance.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
364024
240050
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeSecondSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
97295
45997
2 changes: 1 addition & 1 deletion .forge-snapshots/FullRangeSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134817
79418
2 changes: 1 addition & 1 deletion .forge-snapshots/TWAMMSubmitOrder.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
122753
122359
22 changes: 22 additions & 0 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Semgrep
on:
workflow_dispatch: {}
pull_request: {}
push:
branches:
- main
schedule:
# random HH:MM to avoid a load spike on GitHub Actions at 00:00
- cron: '35 11 * * *'
jobs:
semgrep:
name: semgrep/ci
runs-on: ubuntu-20.04
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
container:
image: returntocorp/semgrep
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744
- run: semgrep ci
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
url = https://github.com/marktoda/forge-gas-snapshot
[submodule "lib/v4-core"]
path = lib/v4-core
url = git@github.com:Uniswap/v4-core.git
url = https://github.com/Uniswap/v4-core
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ There are many ways to contribute, but here are a few if you want a place to sta

## Opening an Issue

When opening an [issue](https://github.com/Uniswap/periphery-next/issues/new/choose), choose a template to start from: Bug Report or Feature Improvement. For bug reports, you should be able to reproduce the bug through tests or proof of concept integrations. For feature improvements, please title it with a concise problem statement and check that a similar request is not already open or already in progress. Not all issues may be deemed worth resolving, so please follow through with responding to any questions or comments that others may have regarding the issue.
When opening an [issue](https://github.com/Uniswap/v4-periphery/issues/new/choose), choose a template to start from: Bug Report or Feature Improvement. For bug reports, you should be able to reproduce the bug through tests or proof of concept integrations. For feature improvements, please title it with a concise problem statement and check that a similar request is not already open or already in progress. Not all issues may be deemed worth resolving, so please follow through with responding to any questions or comments that others may have regarding the issue.

Feel free to tag the issue as a “good first issue” for any clean-up related issues, or small scoped changes to help encourage pull requests from first time contributors!

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Uniswap v4 is a new automated market maker protocol that provides extensibility

## Contributing

If you’re interested in contributing please see the [contribution guidelines](https://github.com/Uniswap/periphery-next/blob/main/CONTRIBUTING.md)!
If you’re interested in contributing please see the [contribution guidelines](https://github.com/Uniswap/v4-periphery/blob/main/CONTRIBUTING.md)!

## Repository Structure

Expand All @@ -31,29 +31,29 @@ Eventually, some hooks that have been audited and are considered production-read
To utilize the contracts and deploy to a local testnet, you can install the code in your repo with forge:

```solidity
forge install https://github.com/Uniswap/periphery-next
forge install https://github.com/Uniswap/v4-periphery
```

If you are building hooks, it may be useful to inherit from the `BaseHook` contract:

```solidity
import {BaseHook} from 'periphery-next/contracts/BaseHook.sol';
import {BaseHook} from 'v4-periphery/contracts/BaseHook.sol';
contract CoolHook is BaseHook {
// Override the hook callbacks you want on your hook
function beforeModifyPosition(
function beforeAddLiquidity(
address,
IPoolManager.PoolKey calldata key,
IPoolManager.ModifyLiquidityParams calldata params
) external override onlyByManager returns (bytes4) {
// hook logic
return BaseHook.beforeModifyPosition.selector;
return BaseHook.beforeAddLiquidity.selector;
}
}
```

## License

The license for Uniswap V4 Periphery is the GNU General Public License (GPL 2.0), see [LICENSE](https://github.com/Uniswap/periphery-next/blob/main/LICENSE).
The license for Uniswap V4 Periphery is the GNU General Public License (GPL 2.0), see [LICENSE](https://github.com/Uniswap/v4-periphery/blob/main/LICENSE).
11 changes: 6 additions & 5 deletions contracts/BaseHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {SafeCallback} from "./base/SafeCallback.sol";
import {ImmutableState} from "./base/ImmutableState.sol";
import {BeforeSwapDelta} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";

abstract contract BaseHook is IHooks, SafeCallback {
error NotSelf();
Expand Down Expand Up @@ -40,7 +41,7 @@ abstract contract BaseHook is IHooks, SafeCallback {
Hooks.validateHookPermissions(_this, getHookPermissions());
}

function _lockAcquired(bytes calldata data) internal virtual override returns (bytes memory) {
function _unlockCallback(bytes calldata data) internal override virtual returns (bytes memory) {
(bool success, bytes memory returnData) = address(this).call(data);
if (success) return returnData;
if (returnData.length == 0) revert LockFailure();
Expand Down Expand Up @@ -86,7 +87,7 @@ abstract contract BaseHook is IHooks, SafeCallback {
IPoolManager.ModifyLiquidityParams calldata,
BalanceDelta,
bytes calldata
) external virtual returns (bytes4) {
) external virtual returns (bytes4, BalanceDelta) {
revert HookNotImplemented();
}

Expand All @@ -96,22 +97,22 @@ abstract contract BaseHook is IHooks, SafeCallback {
IPoolManager.ModifyLiquidityParams calldata,
BalanceDelta,
bytes calldata
) external virtual returns (bytes4) {
) external virtual returns (bytes4, BalanceDelta) {
revert HookNotImplemented();
}

function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata)
external
virtual
returns (bytes4)
returns (bytes4, BeforeSwapDelta, uint24)
{
revert HookNotImplemented();
}

function afterSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, BalanceDelta, bytes calldata)
external
virtual
returns (bytes4)
returns (bytes4, int128)
{
revert HookNotImplemented();
}
Expand Down
25 changes: 10 additions & 15 deletions contracts/SimpleBatchCall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {ImmutableState} from "./base/ImmutableState.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
import {CurrencySettler} from "@uniswap/v4-core/test/utils/CurrencySettler.sol";

/// @title SimpleBatchCall
/// @notice Implements a naive settle function to perform any arbitrary batch call under one lock to modifyPosition, donate, intitialize, or swap.
contract SimpleBatchCall is LockAndBatchCall {
using CurrencyLibrary for Currency;
using TransientStateLibrary for IPoolManager;
using CurrencySettler for Currency;

constructor(IPoolManager _poolManager) ImmutableState(_poolManager) {}

struct SettleConfig {
bool withdrawTokens; // If true, takes the underlying ERC20s.
bool settleUsingTransfer; // If true, sends the underlying ERC20s.
bool takeClaims;
bool settleUsingBurn; // If true, sends the underlying ERC20s.
}

/// @notice We naively settle all currencies that are touched by the batch call. This data is passed in intially to `execute`.
Expand All @@ -29,20 +33,11 @@ contract SimpleBatchCall is LockAndBatchCall {
Currency currency = currenciesTouched[i];
int256 delta = poolManager.currencyDelta(address(this), currenciesTouched[i]);

if (delta > 0) {
if (config.settleUsingTransfer) {
ERC20(Currency.unwrap(currency)).transferFrom(sender, address(poolManager), uint256(delta));
poolManager.settle(currency);
} else {
poolManager.transferFrom(address(poolManager), address(this), currency.toId(), uint256(delta));
}
}
if (delta < 0) {
if (config.withdrawTokens) {
poolManager.mint(address(this), currency.toId(), uint256(-delta));
} else {
poolManager.take(currency, address(this), uint256(-delta));
}
currency.settle(poolManager, sender, uint256(-delta), config.settleUsingBurn);
}
if (delta > 0) {
currency.take(poolManager, address(this), uint256(delta), config.takeClaims);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion contracts/base/CallsWithLock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {ImmutableState} from "./ImmutableState.sol";
import {ICallsWithLock} from "../interfaces/ICallsWithLock.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";

/// @title CallsWithLock
/// @notice Handles all the calls to the pool manager contract. Assumes the integrating contract has already acquired a lock.
Expand All @@ -29,7 +30,8 @@ abstract contract CallsWithLock is ICallsWithLock, ImmutableState {
IPoolManager.ModifyLiquidityParams calldata params,
bytes calldata hookData
) external onlyBySelf returns (bytes memory) {
return abi.encode(poolManager.modifyLiquidity(key, params, hookData));
(BalanceDelta delta, BalanceDelta feeDelta) = poolManager.modifyLiquidity(key, params, hookData);
return abi.encode(delta, feeDelta);
}

function swapWithLock(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
Expand Down
6 changes: 3 additions & 3 deletions contracts/base/LockAndBatchCall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ abstract contract LockAndBatchCall is CallsWithLock, SafeCallback {
/// @param executeData The function selectors and calldata for any of the function selectors in ICallsWithLock encoded as an array of bytes.
function execute(bytes memory executeData, bytes memory settleData) external {
(bytes memory lockReturnData) =
poolManager.lock(address(this), abi.encode(executeData, abi.encode(msg.sender, settleData)));
poolManager.unlock(abi.encode(executeData, abi.encode(msg.sender, settleData)));
(bytes memory executeReturnData, bytes memory settleReturnData) = abi.decode(lockReturnData, (bytes, bytes));
_handleAfterExecute(executeReturnData, settleReturnData);
}

/// @param data This data is passed from the top-level execute function to the internal _executeWithLockCalls and _settle function. It is decoded as two separate dynamic bytes parameters.
/// @dev _lockAcquired is responsible for executing the internal calls under the lock and settling open deltas left on the pool
function _lockAcquired(bytes calldata data) internal override returns (bytes memory) {
/// @dev _unlockCallback is responsible for executing the internal calls under the lock and settling open deltas left on the pool
function _unlockCallback(bytes calldata data) internal override returns (bytes memory) {
(bytes memory executeData, bytes memory settleDataWithSender) = abi.decode(data, (bytes, bytes));
(address sender, bytes memory settleData) = abi.decode(settleDataWithSender, (address, bytes));
return abi.encode(_executeWithLockCalls(executeData), _settle(sender, settleData));
Expand Down
10 changes: 5 additions & 5 deletions contracts/base/SafeCallback.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {ILockCallback} from "@uniswap/v4-core/src/interfaces/callback/ILockCallback.sol";
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, ILockCallback {
abstract contract SafeCallback is ImmutableState, IUnlockCallback {
error NotManager();

modifier onlyByManager() {
Expand All @@ -14,9 +14,9 @@ abstract contract SafeCallback is ImmutableState, ILockCallback {
}

/// @dev There is no way to force the onlyByManager modifier but for this callback to be safe, it MUST check that the msg.sender is the pool manager.
function lockAcquired(address, bytes calldata data) external onlyByManager returns (bytes memory) {
return _lockAcquired(data);
function unlockCallback(bytes calldata data) external onlyByManager returns (bytes memory) {
return _unlockCallback(data);
}

function _lockAcquired(bytes calldata data) internal virtual returns (bytes memory);
function _unlockCallback(bytes calldata data) internal virtual returns (bytes memory);
}
Loading

0 comments on commit 0f9936e

Please sign in to comment.