fix: rm callback fn
This commit is contained in:
@@ -2,27 +2,22 @@
|
|||||||
pragma solidity ^0.8.28;
|
pragma solidity ^0.8.28;
|
||||||
|
|
||||||
import "@interfaces/IExecutor.sol";
|
import "@interfaces/IExecutor.sol";
|
||||||
import {
|
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
IERC20,
|
|
||||||
SafeERC20
|
|
||||||
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
||||||
import {IPoolManager} from "@uniswap/v4-core/interfaces/IPoolManager.sol";
|
import {IPoolManager} from "@uniswap/v4-core/interfaces/IPoolManager.sol";
|
||||||
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/types/Currency.sol";
|
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/types/Currency.sol";
|
||||||
import {PoolKey} from "@uniswap/v4-core/types/PoolKey.sol";
|
import {PoolKey} from "@uniswap/v4-core/types/PoolKey.sol";
|
||||||
import {BalanceDelta} from "@uniswap/v4-core/types/BalanceDelta.sol";
|
import {BalanceDelta} from "@uniswap/v4-core/types/BalanceDelta.sol";
|
||||||
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
|
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
|
||||||
import {IHooks} from "@uniswap/v4-core/interfaces/IHooks.sol";
|
import {IHooks} from "@uniswap/v4-core/interfaces/IHooks.sol";
|
||||||
import {IUnlockCallback} from
|
import {IUnlockCallback} from "@uniswap/v4-core/interfaces/callback/IUnlockCallback.sol";
|
||||||
"@uniswap/v4-core/interfaces/callback/IUnlockCallback.sol";
|
import {TransientStateLibrary} from "@uniswap/v4-core/libraries/TransientStateLibrary.sol";
|
||||||
import {TransientStateLibrary} from
|
|
||||||
"@uniswap/v4-core/libraries/TransientStateLibrary.sol";
|
|
||||||
|
|
||||||
error UniswapV4Executor__InvalidDataLength();
|
error UniswapV4Executor__InvalidDataLength();
|
||||||
error UniswapV4Executor__SwapFailed();
|
error UniswapV4Executor__SwapFailed();
|
||||||
error UniswapV4Executor__InsufficientOutput();
|
error UniswapV4Executor__InsufficientOutput();
|
||||||
error UniswapV4Executor__ManagerMismatch();
|
error UniswapV4Executor__ManagerMismatch();
|
||||||
|
|
||||||
contract UniswapV4Executor is IExecutor, IUnlockCallback {
|
contract UniswapV4Executor is IExecutor {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
using CurrencyLibrary for Currency;
|
using CurrencyLibrary for Currency;
|
||||||
using SafeCast for int128;
|
using SafeCast for int128;
|
||||||
@@ -41,11 +36,10 @@ contract UniswapV4Executor is IExecutor, IUnlockCallback {
|
|||||||
address receiver;
|
address receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
function swap(uint256 amountIn, bytes calldata data)
|
function swap(
|
||||||
external
|
uint256 amountIn,
|
||||||
payable
|
bytes calldata data
|
||||||
returns (uint256 amountOut)
|
) external payable returns (uint256 amountOut) {
|
||||||
{
|
|
||||||
(
|
(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
@@ -71,10 +65,6 @@ contract UniswapV4Executor is IExecutor, IUnlockCallback {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Find a better place
|
|
||||||
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
|
|
||||||
IERC20(tokenIn).approve(target, amountIn);
|
|
||||||
|
|
||||||
SwapCallbackData memory callbackData = SwapCallbackData({
|
SwapCallbackData memory callbackData = SwapCallbackData({
|
||||||
key: key,
|
key: key,
|
||||||
params: params,
|
params: params,
|
||||||
@@ -101,124 +91,9 @@ contract UniswapV4Executor is IExecutor, IUnlockCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dev notes: This is inspired by the Uniswap V4 PoolSwapTest.sol
|
function _decodeData(
|
||||||
function unlockCallback(bytes calldata rawData)
|
bytes calldata data
|
||||||
external
|
)
|
||||||
returns (bytes memory)
|
|
||||||
{
|
|
||||||
SwapCallbackData memory data = abi.decode(rawData, (SwapCallbackData));
|
|
||||||
|
|
||||||
IPoolManager poolManager = IPoolManager(msg.sender);
|
|
||||||
|
|
||||||
// Check initial balances
|
|
||||||
(,, int256 deltaBefore0) = _fetchBalances(
|
|
||||||
data.key.currency0, data.receiver, address(this), poolManager
|
|
||||||
);
|
|
||||||
(,, int256 deltaBefore1) = _fetchBalances(
|
|
||||||
data.key.currency1, data.receiver, address(this), poolManager
|
|
||||||
);
|
|
||||||
|
|
||||||
require(deltaBefore0 == 0, "deltaBefore0 not zero");
|
|
||||||
require(deltaBefore1 == 0, "deltaBefore1 not zero");
|
|
||||||
|
|
||||||
BalanceDelta delta = poolManager.swap(data.key, data.params, "");
|
|
||||||
|
|
||||||
// Check final balances and validate based on swap direction
|
|
||||||
(,, int256 deltaAfter0) = _fetchBalances(
|
|
||||||
data.key.currency0, data.receiver, address(this), poolManager
|
|
||||||
);
|
|
||||||
(,, int256 deltaAfter1) = _fetchBalances(
|
|
||||||
data.key.currency1, data.receiver, address(this), poolManager
|
|
||||||
);
|
|
||||||
|
|
||||||
uint256 amountOut;
|
|
||||||
if (data.params.zeroForOne) {
|
|
||||||
if (data.params.amountSpecified < 0) {
|
|
||||||
// exact input, 0 for 1
|
|
||||||
require(
|
|
||||||
deltaAfter0 >= data.params.amountSpecified,
|
|
||||||
"insufficient input amount"
|
|
||||||
);
|
|
||||||
require(delta.amount0() == deltaAfter0, "delta mismatch");
|
|
||||||
require(deltaAfter1 >= 0, "negative output amount");
|
|
||||||
amountOut = deltaAfter1 > 0 ? uint256(deltaAfter1) : 0;
|
|
||||||
} else {
|
|
||||||
// exact output, 0 for 1
|
|
||||||
require(deltaAfter0 <= 0, "positive input amount");
|
|
||||||
require(delta.amount1() == deltaAfter1, "delta mismatch");
|
|
||||||
require(
|
|
||||||
deltaAfter1 <= data.params.amountSpecified,
|
|
||||||
"excessive output amount"
|
|
||||||
);
|
|
||||||
amountOut = uint256((-delta.amount1()).toUint256());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (data.params.amountSpecified < 0) {
|
|
||||||
// exact input, 1 for 0
|
|
||||||
require(
|
|
||||||
deltaAfter1 >= data.params.amountSpecified,
|
|
||||||
"insufficient input amount"
|
|
||||||
);
|
|
||||||
require(delta.amount1() == deltaAfter1, "delta mismatch");
|
|
||||||
require(deltaAfter0 >= 0, "negative output amount");
|
|
||||||
amountOut = deltaAfter0 > 0 ? uint256(deltaAfter0) : 0;
|
|
||||||
} else {
|
|
||||||
// exact output, 1 for 0
|
|
||||||
require(deltaAfter1 <= 0, "positive input amount");
|
|
||||||
require(delta.amount0() == deltaAfter0, "delta mismatch");
|
|
||||||
require(
|
|
||||||
deltaAfter0 <= data.params.amountSpecified,
|
|
||||||
"excessive output amount"
|
|
||||||
);
|
|
||||||
amountOut = uint256((-delta.amount0()).toUint256());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deltaAfter0 < 0) {
|
|
||||||
poolManager.settle{
|
|
||||||
value: data.key.currency0.isAddressZero()
|
|
||||||
? uint256(-deltaAfter0)
|
|
||||||
: 0
|
|
||||||
}();
|
|
||||||
if (!data.key.currency0.isAddressZero()) {
|
|
||||||
IERC20(Currency.unwrap(data.key.currency0)).transfer(
|
|
||||||
address(poolManager), uint256(-deltaAfter0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deltaAfter1 < 0) {
|
|
||||||
poolManager.settle{
|
|
||||||
value: data.key.currency1.isAddressZero()
|
|
||||||
? uint256(-deltaAfter1)
|
|
||||||
: 0
|
|
||||||
}();
|
|
||||||
if (!data.key.currency1.isAddressZero()) {
|
|
||||||
IERC20(Currency.unwrap(data.key.currency1)).transfer(
|
|
||||||
address(poolManager), uint256(-deltaAfter1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deltaAfter0 > 0) {
|
|
||||||
poolManager.take(
|
|
||||||
data.key.currency0, data.receiver, uint256(deltaAfter0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (deltaAfter1 > 0) {
|
|
||||||
poolManager.take(
|
|
||||||
data.key.currency1, data.receiver, uint256(deltaAfter1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle any remaining ETH balance
|
|
||||||
uint256 ethBalance = address(this).balance;
|
|
||||||
if (ethBalance > 0) {
|
|
||||||
CurrencyLibrary.ADDRESS_ZERO.transfer(data.receiver, ethBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return abi.encode(amountOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _decodeData(bytes calldata data)
|
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (
|
returns (
|
||||||
@@ -241,19 +116,4 @@ contract UniswapV4Executor is IExecutor, IUnlockCallback {
|
|||||||
target = address(bytes20(data[63:83]));
|
target = address(bytes20(data[63:83]));
|
||||||
zeroForOne = uint8(data[83]) > 0;
|
zeroForOne = uint8(data[83]) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _fetchBalances(
|
|
||||||
Currency currency,
|
|
||||||
address user,
|
|
||||||
address deltaHolder,
|
|
||||||
IPoolManager manager
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (uint256 userBalance, uint256 poolBalance, int256 delta)
|
|
||||||
{
|
|
||||||
userBalance = currency.balanceOf(user);
|
|
||||||
poolBalance = currency.balanceOf(address(manager));
|
|
||||||
delta = manager.currencyDelta(deltaHolder, currency);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user