Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 31 additions & 26 deletions packages/indexer/abis/AsyncSwapCSMM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ export const AsyncSwapCSMMAbi = [
},
{
type: "function",
name: "asyncOrders",
name: "asyncOrder",
inputs: [
{
name: "poolId",
Expand All @@ -463,6 +463,30 @@ export const AsyncSwapCSMMAbi = [
],
stateMutability: "view",
},
{
type: "function",
name: "asyncOrders",
inputs: [
{
name: "poolId",
type: "bytes32",
internalType: "PoolId",
},
],
outputs: [
{
name: "poolManager",
type: "address",
internalType: "contract IPoolManager",
},
{
name: "algorithm",
type: "address",
internalType: "contract IAlgorithm",
},
],
stateMutability: "view",
},
{
type: "function",
name: "beforeAddLiquidity",
Expand Down Expand Up @@ -1116,7 +1140,12 @@ export const AsyncSwapCSMMAbi = [
name: "isExecutor",
inputs: [
{
name: "owner",
name: "poolId",
type: "bytes32",
internalType: "PoolId",
},
{
name: "user",
type: "address",
internalType: "address",
},
Expand Down Expand Up @@ -1148,30 +1177,6 @@ export const AsyncSwapCSMMAbi = [
],
stateMutability: "view",
},
{
type: "function",
name: "setExecutor",
inputs: [
{
name: "owner",
type: "address",
internalType: "address",
},
{
name: "executor",
type: "address",
internalType: "address",
},
],
outputs: [
{
name: "",
type: "bool",
internalType: "bool",
},
],
stateMutability: "view",
},
{
type: "event",
name: "AsyncOrderFilled",
Expand Down
29 changes: 16 additions & 13 deletions src/AsyncSwapCSMM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {
using SafeCast for *;
using CurrencySettler for Currency;
using PoolIdLibrary for PoolKey;
using AsyncFiller for AsyncOrder;

/// @notice Algorithm used for ordering transactions in our Async Swap AMM.
IAlgorithm public algorithm;
/// @notice Mapping to store async orders.
mapping(PoolId poolId => AsyncFiller.State) public asyncOrders;
/// @notice Mapping to store executor permissions for users.
mapping(address owner => mapping(address executor => bool)) public setExecutor;
/// Ordering algortim
IAlgorithm public immutable algorithm;

/// Event emitted when a swap is executed.
/// @param id The poolId of the pool where the swap occurred.
Expand Down Expand Up @@ -63,6 +62,9 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {
/// @inheritdoc BaseHook
function _beforeInitialize(address, PoolKey calldata key, uint160) internal virtual override returns (bytes4) {
require(key.fee == LPFeeLibrary.DYNAMIC_FEE_FLAG, "Dude use dynamic fees flag");
/// set algorithm for the pool being initialized
asyncOrders[key.toId()].algorithm = algorithm;
asyncOrders[key.toId()].poolManager = poolManager;
return this.beforeInitialize.selector;
}

Expand Down Expand Up @@ -96,13 +98,14 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {
revert UnsupportedLiquidity();
}

/// @inheritdoc IAsyncSwapOrder
function isExecutor(address owner, address executor) public view returns (bool) {
return setExecutor[owner][executor];
function asyncOrder(PoolId poolId, address user, bool zeroForOne) external view returns (uint256 claimable) {
AsyncFiller.State storage state = asyncOrders[poolId];
return state.asyncOrders[user][zeroForOne];
}

function asyncOrder(PoolId poolId, address user, bool zeroForOne) external view returns (uint256 claimable) {
return asyncOrders[poolId].asyncOrders[user][zeroForOne];
function isExecutor(PoolId poolId, address user, address executor) external view returns (bool) {
AsyncFiller.State storage state = asyncOrders[poolId];
return state.setExecutor[user][executor];
}

function calculateHookFee(uint256) public pure returns (uint256) {
Expand All @@ -120,7 +123,7 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {
for (uint8 i = 0; i < orders.length; i++) {
AsyncOrder calldata order = orders[i];
// Use transaction ordering algorithm to ensure correct execution order
algorithm.orderingRule(order.zeroForOne, uint256(order.amountIn));
asyncOrders[order.key.toId()].algorithm.orderingRule(order.zeroForOne, uint256(order.amountIn));
this.executeOrder(order, userParams);
}
}
Expand All @@ -138,10 +141,10 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {

/// TODO: Document what this does
uint256 amountToFill = uint256(amountIn);
// AsyncFiller.State storage _asyncOrders = asyncOrders[poolId];
uint256 claimableAmount = asyncOrders[poolId].asyncOrders[owner][zeroForOne];
require(amountToFill <= claimableAmount, "Max fill order limit exceed");
require(isExecutor(owner, msg.sender), "Caller is valid not excutor");
AsyncFiller.State storage state = asyncOrders[poolId];
require(order.isExecutor(state, msg.sender), "Caller is valid not excutor");

/// @dev Transfer currency of async order to user
Currency currencyTake;
Expand Down Expand Up @@ -190,7 +193,7 @@ contract AsyncSwapCSMM is BaseHook, IAsyncSwapAMM {
/// @dev Take pool fee for LP
uint256 feeAmount = calculatePoolFee(key.fee, amountTaken);
uint256 finalTaken = amountTaken - feeAmount;
setExecutor[hookData.user][hookData.executor] = true;
asyncOrders[poolId].setExecutor[hookData.user][hookData.executor] = true;
emit AsyncSwapOrder(poolId, hookData.user, params.zeroForOne, finalTaken.toInt256());

/// @dev Issue 1:1 claimableAmount - pool fee to user
Expand Down
3 changes: 2 additions & 1 deletion src/interfaces/IAsyncSwapOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ interface IAsyncSwapOrder {
function asyncOrder(PoolId poolId, address user, bool zeroForOne) external view returns (uint256 claimable);

/// @notice Checks if the given executor is valid for the async order.
/// @param poolId The poolId the executor is interacting with.
/// @param owner The async order owner be checked against.
/// @param executor The address of the executor to be checked.
/// @return isExecutor True if the executor is valid for the async order, false otherwise.
function isExecutor(address owner, address executor) external returns (bool);
function isExecutor(PoolId poolId, address owner, address executor) external returns (bool);

}
5 changes: 5 additions & 0 deletions src/libraries/AsyncFiller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ library AsyncFiller {
/// @notice Error thrown when an order is of zero amount.
error ZeroFillOrder();

/// @notice Checks if the given executor is valid for the async order.
/// @param order The async order to be filled.
/// @param self The storage slot that controls the state of orders.
/// @param executor The address of the executor to be checked.
/// @return isExecutor True if the executor is valid for the async order, false otherwise.
function isExecutor(AsyncOrder calldata order, State storage self, address executor) internal view returns (bool) {
return self.setExecutor[order.owner][executor];
}
Expand Down
3 changes: 3 additions & 0 deletions test/Algorithm2Test.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ contract Algorithm2Test is SetupHook {
algorithm = hook.algorithm();
}

/// this should test the intialized algoritm was selected
function testCheckSetAlgorithm() public { }

function testExecuteOrderBuy() public {
// Test setup for a buy order
bool zeroForOne = true;
Expand Down
6 changes: 4 additions & 2 deletions test/AsyncCSMM.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.13;
import { SetupHook } from "./SetupHook.sol";
import { AsyncSwapCSMM } from "@async-swap/AsyncSwapCSMM.sol";
import { IRouter } from "@async-swap/interfaces/IRouter.sol";
import { AsyncFiller } from "@async-swap/libraries/AsyncFiller.sol";
import { AsyncOrder } from "@async-swap/types/AsyncOrder.sol";
import { console } from "forge-std/Test.sol";
import { Currency, IHooks, IPoolManager } from "v4-core/interfaces/IPoolManager.sol";
Expand All @@ -15,6 +16,7 @@ import { PoolKey } from "v4-core/types/PoolKey.sol";
contract AsyncCsmmTest is SetupHook {

using CurrencyLibrary for Currency;
using AsyncFiller for AsyncOrder;

address asyncFiller = makeAddr("asyncFiller");
address user = makeAddr("user");
Expand Down Expand Up @@ -62,7 +64,7 @@ contract AsyncCsmmTest is SetupHook {

function testFuzzAsyncSwapAndFillOrder(address _user, uint256 amountIn, bool zeroForOne) public {
vm.assume(amountIn >= 1);
vm.assume(amountIn < 2 ** 96 / 2);
vm.assume(amountIn < 2 ** 96);
user = _user;
topUp(user, amountIn);
topUp(user2, amountIn);
Expand All @@ -87,7 +89,7 @@ contract AsyncCsmmTest is SetupHook {
assertEq(balance0Before, balance0After);
}
assertEq(hook.asyncOrder(poolId, user, zeroForOne), amountIn);
assertEq(hook.setExecutor(user, asyncFiller), true);
assertEq(hook.isExecutor(poolId, user, asyncFiller), true);

balance0Before = currency0.balanceOf(user2);
balance1Before = currency1.balanceOf(user2);
Expand Down