callback-style funding option
This commit is contained in:
@@ -279,7 +279,7 @@ contract DeploySepolia is Script {
|
|||||||
uint256 inputIndex = 0;
|
uint256 inputIndex = 0;
|
||||||
uint256 outputIndex = n > 1 ? n - 1 : 0;
|
uint256 outputIndex = n > 1 ? n - 1 : 0;
|
||||||
uint256 maxIn = 89 * 10**6; // varied
|
uint256 maxIn = 89 * 10**6; // varied
|
||||||
pool.swap(msg.sender, msg.sender, inputIndex, outputIndex, maxIn, int128(0), 0, false);
|
pool.swap(msg.sender, bytes4(0), msg.sender, inputIndex, outputIndex, maxIn, int128(0), 0, false);
|
||||||
|
|
||||||
// 6) Collect protocol fees now (after some swaps) so some will have been moved out
|
// 6) Collect protocol fees now (after some swaps) so some will have been moved out
|
||||||
pool.collectProtocolFees();
|
pool.collectProtocolFees();
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ interface IPartyPool is IERC20Metadata, IOwnable {
|
|||||||
/// @dev This function transfers the exact gross input (including fee) from payer and sends the computed output to receiver.
|
/// @dev This function transfers the exact gross input (including fee) from payer and sends the computed output to receiver.
|
||||||
/// Non-standard tokens (fee-on-transfer, rebasers) are rejected via balance checks.
|
/// Non-standard tokens (fee-on-transfer, rebasers) are rejected via balance checks.
|
||||||
/// @param payer address of the account that pays for the swap
|
/// @param payer address of the account that pays for the swap
|
||||||
|
/// @param selector If zero, then regular ERC20 approvals must be given by the payere to the pool to move the required input amount. If this selector is nonzero, then a callback style funding mechanism is used where the given selector is invoked on the payer, passing the arguments of (address inputToken, uint256 inputAmount). The callback function must send the given amount of input coin to the pool in ordr to continue the swap transaction, otherwise "Insufficient funds" is thrown.
|
||||||
/// @param receiver address that will receive the output tokens
|
/// @param receiver address that will receive the output tokens
|
||||||
/// @param inputTokenIndex index of input asset
|
/// @param inputTokenIndex index of input asset
|
||||||
/// @param outputTokenIndex index of output asset
|
/// @param outputTokenIndex index of output asset
|
||||||
@@ -187,6 +188,7 @@ interface IPartyPool is IERC20Metadata, IOwnable {
|
|||||||
/// @return amountIn actual input used (uint256), amountOut actual output sent (uint256), inFee fee taken from the input (uint256)
|
/// @return amountIn actual input used (uint256), amountOut actual output sent (uint256), inFee fee taken from the input (uint256)
|
||||||
function swap(
|
function swap(
|
||||||
address payer,
|
address payer,
|
||||||
|
bytes4 selector,
|
||||||
address receiver,
|
address receiver,
|
||||||
uint256 inputTokenIndex,
|
uint256 inputTokenIndex,
|
||||||
uint256 outputTokenIndex,
|
uint256 outputTokenIndex,
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
|||||||
/// @inheritdoc IPartyPool
|
/// @inheritdoc IPartyPool
|
||||||
function swap(
|
function swap(
|
||||||
address payer,
|
address payer,
|
||||||
|
bytes4 selector,
|
||||||
address receiver,
|
address receiver,
|
||||||
uint256 inputTokenIndex,
|
uint256 inputTokenIndex,
|
||||||
uint256 outputTokenIndex,
|
uint256 outputTokenIndex,
|
||||||
@@ -266,8 +267,18 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
|
|||||||
IERC20 tokenIn = _tokens[inputTokenIndex];
|
IERC20 tokenIn = _tokens[inputTokenIndex];
|
||||||
IERC20 tokenOut = _tokens[outputTokenIndex];
|
IERC20 tokenOut = _tokens[outputTokenIndex];
|
||||||
|
|
||||||
// Transfer _tokens in via centralized helper
|
if ( selector == bytes4(0) )
|
||||||
_receiveTokenFrom(payer, tokenIn, totalTransferAmount);
|
// Regular ERC20 permit of the pool to move the tokens
|
||||||
|
_receiveTokenFrom(payer, tokenIn, totalTransferAmount);
|
||||||
|
else {
|
||||||
|
// Callback-style funding mechanism
|
||||||
|
uint256 startingBalance = tokenIn.balanceOf(address(this));
|
||||||
|
bytes memory data = abi.encodeWithSelector(selector, tokenIn, totalTransferAmount);
|
||||||
|
// Invoke the payer callback; no return value expected (reverts on failure)
|
||||||
|
Address.functionCall(payer, data);
|
||||||
|
uint256 endingBalance = tokenIn.balanceOf(address(this));
|
||||||
|
require(endingBalance-startingBalance == totalTransferAmount, 'Insufficient funds');
|
||||||
|
}
|
||||||
|
|
||||||
// Compute on-chain balances as: onchain = cached + owed (+/- transfer)
|
// Compute on-chain balances as: onchain = cached + owed (+/- transfer)
|
||||||
uint256 balIAfter = _cachedUintBalances[inputTokenIndex] + _protocolFeesOwed[inputTokenIndex] + totalTransferAmount;
|
uint256 balIAfter = _cachedUintBalances[inputTokenIndex] + _protocolFeesOwed[inputTokenIndex] + totalTransferAmount;
|
||||||
|
|||||||
102
test/GasTest.sol
102
test/GasTest.sol
@@ -1,15 +1,25 @@
|
|||||||
// SPDX-License-Identifier: UNLICENSED
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
pragma solidity ^0.8.30;
|
pragma solidity ^0.8.30;
|
||||||
/* solhint-disable erc20-unchecked-transfer */
|
|
||||||
|
|
||||||
import "forge-std/Test.sol";
|
import {ABDKMath64x64} from "../lib/abdk-libraries-solidity/ABDKMath64x64.sol";
|
||||||
import "@abdk/ABDKMath64x64.sol";
|
import {CommonBase} from "../lib/forge-std/src/Base.sol";
|
||||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
import {StdAssertions} from "../lib/forge-std/src/StdAssertions.sol";
|
||||||
import "../src/LMSRStabilized.sol";
|
import {StdChains} from "../lib/forge-std/src/StdChains.sol";
|
||||||
import "../src/PartyPool.sol";
|
import {StdCheats, StdCheatsSafe} from "../lib/forge-std/src/StdCheats.sol";
|
||||||
import "../src/PartyPlanner.sol";
|
import {StdUtils} from "../lib/forge-std/src/StdUtils.sol";
|
||||||
import "../lib/openzeppelin-contracts/contracts/interfaces/IERC3156FlashBorrower.sol";
|
import {Test} from "../lib/forge-std/src/Test.sol";
|
||||||
|
import {IERC3156FlashBorrower} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC3156FlashBorrower.sol";
|
||||||
|
import {ERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
|
||||||
|
import {IERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
|
||||||
|
import {SafeERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
|
import {IPartyPool} from "../src/IPartyPool.sol";
|
||||||
|
import {LMSRStabilized} from "../src/LMSRStabilized.sol";
|
||||||
|
import {PartyPlanner} from "../src/PartyPlanner.sol";
|
||||||
|
import {PartyPool} from "../src/PartyPool.sol";
|
||||||
import {Deploy} from "./Deploy.sol";
|
import {Deploy} from "./Deploy.sol";
|
||||||
|
import {TestERC20, FlashBorrower} from "./GasTest.sol";
|
||||||
|
|
||||||
|
/* solhint-disable erc20-unchecked-transfer */
|
||||||
|
|
||||||
/// @notice Test contract that implements the flash callback for testing flash loans
|
/// @notice Test contract that implements the flash callback for testing flash loans
|
||||||
contract FlashBorrower is IERC3156FlashBorrower {
|
contract FlashBorrower is IERC3156FlashBorrower {
|
||||||
@@ -99,10 +109,10 @@ contract GasTest is Test {
|
|||||||
using SafeERC20 for TestERC20;
|
using SafeERC20 for TestERC20;
|
||||||
|
|
||||||
PartyPlanner internal planner;
|
PartyPlanner internal planner;
|
||||||
PartyPool internal pool2;
|
IPartyPool internal pool2;
|
||||||
PartyPool internal pool10;
|
IPartyPool internal pool10;
|
||||||
PartyPool internal pool20;
|
IPartyPool internal pool20;
|
||||||
PartyPool internal pool50;
|
IPartyPool internal pool50;
|
||||||
|
|
||||||
address internal alice;
|
address internal alice;
|
||||||
address internal bob;
|
address internal bob;
|
||||||
@@ -115,7 +125,7 @@ contract GasTest is Test {
|
|||||||
uint256 constant internal BASE = 1; // use base=1 so internal amounts correspond to raw integers (Q64.64 units)
|
uint256 constant internal BASE = 1; // use base=1 so internal amounts correspond to raw integers (Q64.64 units)
|
||||||
|
|
||||||
/// @notice Helper function to create a pool with the specified number of _tokens
|
/// @notice Helper function to create a pool with the specified number of _tokens
|
||||||
function createPool(uint256 numTokens) internal returns (PartyPool) {
|
function createPool(uint256 numTokens) internal returns (IPartyPool) {
|
||||||
// Deploy _tokens dynamically
|
// Deploy _tokens dynamically
|
||||||
address[] memory tokens = new address[](numTokens);
|
address[] memory tokens = new address[](numTokens);
|
||||||
uint256[] memory bases = new uint256[](numTokens);
|
uint256[] memory bases = new uint256[](numTokens);
|
||||||
@@ -141,21 +151,21 @@ contract GasTest is Test {
|
|||||||
}
|
}
|
||||||
// Compute kappa from slippage params and number of _tokens, then construct pool with kappa
|
// Compute kappa from slippage params and number of _tokens, then construct pool with kappa
|
||||||
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
|
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
|
||||||
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, false);
|
|
||||||
|
|
||||||
// Transfer initial deposit amounts into pool before initial mint
|
uint256[] memory initialBalances = new uint256[](numTokens);
|
||||||
for (uint256 i = 0; i < numTokens; i++) {
|
for (uint256 i = 0; i < numTokens; i++) {
|
||||||
TestERC20(tokens[i]).transfer(address(newPool), INIT_BAL);
|
initialBalances[i] = INIT_BAL;
|
||||||
|
ierc20Tokens[i].approve(address(planner), INIT_BAL);
|
||||||
}
|
}
|
||||||
|
vm.prank(planner.owner());
|
||||||
// Perform initial mint (initial deposit); receiver is this contract
|
(IPartyPool newPool, ) = planner.newPool(poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, false,
|
||||||
newPool.initialMint(address(this), 0);
|
address(this), address(this), initialBalances, 0, 0);
|
||||||
|
|
||||||
return newPool;
|
return newPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Helper to create a pool with the stable-pair optimization enabled
|
/// @notice Helper to create a pool with the stable-pair optimization enabled
|
||||||
function createPoolStable(uint256 numTokens) internal returns (PartyPool) {
|
function createPoolStable(uint256 numTokens) internal returns (IPartyPool) {
|
||||||
// Deploy _tokens dynamically
|
// Deploy _tokens dynamically
|
||||||
address[] memory tokens = new address[](numTokens);
|
address[] memory tokens = new address[](numTokens);
|
||||||
uint256[] memory bases = new uint256[](numTokens);
|
uint256[] memory bases = new uint256[](numTokens);
|
||||||
@@ -181,7 +191,7 @@ contract GasTest is Test {
|
|||||||
ierc20Tokens[i] = IERC20(tokens[i]);
|
ierc20Tokens[i] = IERC20(tokens[i]);
|
||||||
}
|
}
|
||||||
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
|
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
|
||||||
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, true);
|
IPartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, true);
|
||||||
|
|
||||||
// Transfer initial deposit amounts into pool before initial mint
|
// Transfer initial deposit amounts into pool before initial mint
|
||||||
for (uint256 i = 0; i < numTokens; i++) {
|
for (uint256 i = 0; i < numTokens; i++) {
|
||||||
@@ -227,15 +237,37 @@ contract GasTest is Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Helper function: perform 10 swaps back-and-forth between the first two _tokens.
|
/// @notice Helper function: perform 10 swaps back-and-forth between the first two _tokens.
|
||||||
function _performSwapGasTest(PartyPool testPool) internal {
|
function _performSwapGasTest(IPartyPool testPool) internal {
|
||||||
|
_performSwapGasTest(testPool, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendTokensCallback(IERC20 token, uint256 amount) external {
|
||||||
|
// verify the caller
|
||||||
|
require(planner.getPoolSupported(msg.sender), 'Not a LiqP pool');
|
||||||
|
token.transferFrom( alice, msg.sender, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _performSwapGasTest(IPartyPool testPool, bool useCallback) internal {
|
||||||
IERC20[] memory tokens = testPool.allTokens();
|
IERC20[] memory tokens = testPool.allTokens();
|
||||||
require(tokens.length >= 2, "Pool must have at least 2 tokens");
|
require(tokens.length >= 2, "Pool must have at least 2 tokens");
|
||||||
|
address payer;
|
||||||
|
address spender;
|
||||||
|
bytes4 selector;
|
||||||
|
|
||||||
// Ensure alice approves pool for both _tokens
|
if (useCallback) {
|
||||||
|
payer = address(this);
|
||||||
|
spender = address(this);
|
||||||
|
selector = this.sendTokensCallback.selector;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
payer = alice;
|
||||||
|
spender = address(testPool);
|
||||||
|
selector = bytes4(0);
|
||||||
|
}
|
||||||
vm.prank(alice);
|
vm.prank(alice);
|
||||||
TestERC20(address(tokens[0])).approve(address(testPool), type(uint256).max);
|
TestERC20(address(tokens[0])).approve(spender, type(uint256).max);
|
||||||
vm.prank(alice);
|
vm.prank(alice);
|
||||||
TestERC20(address(tokens[1])).approve(address(testPool), type(uint256).max);
|
TestERC20(address(tokens[1])).approve(spender, type(uint256).max);
|
||||||
|
|
||||||
uint256 maxIn = 10_000;
|
uint256 maxIn = 10_000;
|
||||||
|
|
||||||
@@ -244,10 +276,10 @@ contract GasTest is Test {
|
|||||||
vm.prank(alice);
|
vm.prank(alice);
|
||||||
if (i % 2 == 0) {
|
if (i % 2 == 0) {
|
||||||
// swap token0 -> token1
|
// swap token0 -> token1
|
||||||
testPool.swap(alice, alice, 0, 1, maxIn, 0, 0, false);
|
testPool.swap(payer, selector, alice, 0, 1, maxIn, 0, 0, false);
|
||||||
} else {
|
} else {
|
||||||
// swap token1 -> token0
|
// swap token1 -> token0
|
||||||
testPool.swap(alice, alice, 1, 0, maxIn, 0, 0, false);
|
testPool.swap(payer, selector, alice, 1, 0, maxIn, 0, 0, false);
|
||||||
}
|
}
|
||||||
// shake up the bits
|
// shake up the bits
|
||||||
maxIn *= 787;
|
maxIn *= 787;
|
||||||
@@ -265,6 +297,12 @@ contract GasTest is Test {
|
|||||||
_performSwapGasTest(pool10);
|
_performSwapGasTest(pool10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 10-token pool using the callback funding method.
|
||||||
|
function testSwapGasCallback() public {
|
||||||
|
_performSwapGasTest(pool10, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 20-token pool.
|
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 20-token pool.
|
||||||
function testSwapGasTwenty() public {
|
function testSwapGasTwenty() public {
|
||||||
_performSwapGasTest(pool20);
|
_performSwapGasTest(pool20);
|
||||||
@@ -277,24 +315,24 @@ contract GasTest is Test {
|
|||||||
|
|
||||||
/// @notice Gas measurement: perform 10 swaps back-and-forth on a 2-token stable pair (stable-path enabled)
|
/// @notice Gas measurement: perform 10 swaps back-and-forth on a 2-token stable pair (stable-path enabled)
|
||||||
function testSwapGasStablePair() public {
|
function testSwapGasStablePair() public {
|
||||||
PartyPool stablePair = createPoolStable(2);
|
IPartyPool stablePair = createPoolStable(2);
|
||||||
_performSwapGasTest(stablePair);
|
_performSwapGasTest(stablePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Gas-style test: alternate swapMint then burnSwap on a 2-token stable pair
|
/// @notice Gas-style test: alternate swapMint then burnSwap on a 2-token stable pair
|
||||||
function testSwapMintBurnSwapGasStablePair() public {
|
function testSwapMintBurnSwapGasStablePair() public {
|
||||||
PartyPool stablePair = createPoolStable(2);
|
IPartyPool stablePair = createPoolStable(2);
|
||||||
_performSwapMintBurnSwapGasTest(stablePair);
|
_performSwapMintBurnSwapGasTest(stablePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Combined gas test (mint then burn) on 2-token stable pair using mint() and burn().
|
/// @notice Combined gas test (mint then burn) on 2-token stable pair using mint() and burn().
|
||||||
function testMintBurnGasStablePair() public {
|
function testMintBurnGasStablePair() public {
|
||||||
PartyPool stablePair = createPoolStable(2);
|
IPartyPool stablePair = createPoolStable(2);
|
||||||
_performMintBurnGasTest(stablePair);
|
_performMintBurnGasTest(stablePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Helper function: alternate swapMint then burnSwap to keep pool size roughly stable.
|
/// @notice Helper function: alternate swapMint then burnSwap to keep pool size roughly stable.
|
||||||
function _performSwapMintBurnSwapGasTest(PartyPool testPool) internal {
|
function _performSwapMintBurnSwapGasTest(IPartyPool testPool) internal {
|
||||||
uint256 iterations = 10;
|
uint256 iterations = 10;
|
||||||
uint256 input = 1_000;
|
uint256 input = 1_000;
|
||||||
IERC20[] memory tokens = testPool.allTokens();
|
IERC20[] memory tokens = testPool.allTokens();
|
||||||
@@ -339,7 +377,7 @@ contract GasTest is Test {
|
|||||||
|
|
||||||
/// @notice Helper function: combined gas test (mint then burn) using mint() and burn().
|
/// @notice Helper function: combined gas test (mint then burn) using mint() and burn().
|
||||||
/// Alternates minting a tiny LP amount and immediately burning the actual minted LP back to avoid net pool depletion.
|
/// Alternates minting a tiny LP amount and immediately burning the actual minted LP back to avoid net pool depletion.
|
||||||
function _performMintBurnGasTest(PartyPool testPool) internal {
|
function _performMintBurnGasTest(IPartyPool testPool) internal {
|
||||||
uint256 iterations = 50;
|
uint256 iterations = 50;
|
||||||
uint256 input = 1_000;
|
uint256 input = 1_000;
|
||||||
IERC20[] memory poolTokens = testPool.allTokens();
|
IERC20[] memory poolTokens = testPool.allTokens();
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ contract NativeTest is Test {
|
|||||||
// Send native currency with {value: maxIn}
|
// Send native currency with {value: maxIn}
|
||||||
(uint256 amountIn, uint256 amountOut, ) = pool.swap{value: maxIn}(
|
(uint256 amountIn, uint256 amountOut, ) = pool.swap{value: maxIn}(
|
||||||
alice, // payer
|
alice, // payer
|
||||||
|
bytes4(0),
|
||||||
alice, // receiver
|
alice, // receiver
|
||||||
2, // inputTokenIndex (WETH)
|
2, // inputTokenIndex (WETH)
|
||||||
0, // outputTokenIndex (token0)
|
0, // outputTokenIndex (token0)
|
||||||
@@ -179,6 +180,7 @@ contract NativeTest is Test {
|
|||||||
// Execute swap: token0 (index 0) -> WETH (index 2) with unwrap=true
|
// Execute swap: token0 (index 0) -> WETH (index 2) with unwrap=true
|
||||||
(uint256 amountIn, uint256 amountOut, ) = pool.swap(
|
(uint256 amountIn, uint256 amountOut, ) = pool.swap(
|
||||||
alice, // payer
|
alice, // payer
|
||||||
|
bytes4(0), // no selector: use ERC20 approvals
|
||||||
alice, // receiver
|
alice, // receiver
|
||||||
0, // inputTokenIndex (token0)
|
0, // inputTokenIndex (token0)
|
||||||
2, // outputTokenIndex (WETH)
|
2, // outputTokenIndex (WETH)
|
||||||
@@ -214,6 +216,7 @@ contract NativeTest is Test {
|
|||||||
// Execute swap with excess native currency
|
// Execute swap with excess native currency
|
||||||
(uint256 amountIn, , ) = pool.swap{value: totalSent}(
|
(uint256 amountIn, , ) = pool.swap{value: totalSent}(
|
||||||
alice, // payer
|
alice, // payer
|
||||||
|
bytes4(0),
|
||||||
alice, // receiver
|
alice, // receiver
|
||||||
2, // inputTokenIndex (WETH)
|
2, // inputTokenIndex (WETH)
|
||||||
0, // outputTokenIndex (token0)
|
0, // outputTokenIndex (token0)
|
||||||
@@ -542,14 +545,14 @@ contract NativeTest is Test {
|
|||||||
// 2. Swap native currency for token0
|
// 2. Swap native currency for token0
|
||||||
uint256 swapAmount = 5_000;
|
uint256 swapAmount = 5_000;
|
||||||
(, uint256 amountOut, ) = pool.swap{value: swapAmount}(
|
(, uint256 amountOut, ) = pool.swap{value: swapAmount}(
|
||||||
alice, alice, 2, 0, swapAmount, 0, 0, false
|
alice,bytes4(0),alice, 2, 0, swapAmount, 0, 0, false
|
||||||
);
|
);
|
||||||
assertTrue(amountOut > 0, "Should receive token0");
|
assertTrue(amountOut > 0, "Should receive token0");
|
||||||
|
|
||||||
// 3. Swap token0 back to native currency
|
// 3. Swap token0 back to native currency
|
||||||
uint256 token0Balance = token0.balanceOf(alice);
|
uint256 token0Balance = token0.balanceOf(alice);
|
||||||
(, uint256 swapOut2, ) = pool.swap(
|
(, uint256 swapOut2, ) = pool.swap(
|
||||||
alice, alice, 0, 2, token0Balance / 2, 0, 0, true
|
alice, bytes4(0), alice, 0, 2, token0Balance / 2, 0, 0, true
|
||||||
);
|
);
|
||||||
assertTrue(swapOut2 > 0, "Should receive native currency");
|
assertTrue(swapOut2 > 0, "Should receive native currency");
|
||||||
|
|
||||||
@@ -576,7 +579,7 @@ contract NativeTest is Test {
|
|||||||
|
|
||||||
// Swap token0 -> WETH without unwrap
|
// Swap token0 -> WETH without unwrap
|
||||||
(, uint256 amountOut, ) = pool.swap(
|
(, uint256 amountOut, ) = pool.swap(
|
||||||
alice, alice, 0, 2, maxIn, 0, 0, false // unwrap=false
|
alice, bytes4(0), alice, 0, 2, maxIn, 0, 0, false // unwrap=false
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue(amountOut > 0, "Should receive WETH tokens");
|
assertTrue(amountOut > 0, "Should receive WETH tokens");
|
||||||
@@ -597,7 +600,7 @@ contract NativeTest is Test {
|
|||||||
// Try to swap token0 (not WETH) by sending native currency - should revert
|
// Try to swap token0 (not WETH) by sending native currency - should revert
|
||||||
vm.expectRevert();
|
vm.expectRevert();
|
||||||
pool.swap{value: 10_000}(
|
pool.swap{value: 10_000}(
|
||||||
alice, alice, 0, 1, 10_000, 0, 0, false
|
alice, bytes4(0), alice, 0, 1, 10_000, 0, 0, false
|
||||||
);
|
);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ contract PartyPoolTest is Test {
|
|||||||
|
|
||||||
// Execute swap: token0 -> token1
|
// Execute swap: token0 -> token1
|
||||||
vm.prank(alice);
|
vm.prank(alice);
|
||||||
(uint256 amountInUsed, uint256 amountOut, uint256 fee) = pool.swap(alice, bob, 0, 1, maxIn, 0, 0, false);
|
(uint256 amountInUsed, uint256 amountOut, uint256 fee) = pool.swap(alice, bytes4(0), bob, 0, 1, maxIn, 0, 0, false);
|
||||||
|
|
||||||
// Amounts should be positive and not exceed provided max
|
// Amounts should be positive and not exceed provided max
|
||||||
assertTrue(amountInUsed > 0, "expected some input used");
|
assertTrue(amountInUsed > 0, "expected some input used");
|
||||||
@@ -452,7 +452,7 @@ contract PartyPoolTest is Test {
|
|||||||
|
|
||||||
vm.prank(alice);
|
vm.prank(alice);
|
||||||
vm.expectRevert(bytes("LMSR: limitPrice <= current price"));
|
vm.expectRevert(bytes("LMSR: limitPrice <= current price"));
|
||||||
pool.swap(alice, alice, 0, 1, 1000, limitPrice, 0, false);
|
pool.swap(alice, bytes4(0), alice, 0, 1, 1000, limitPrice, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice swapToLimit should compute input needed to reach a slightly higher price and execute.
|
/// @notice swapToLimit should compute input needed to reach a slightly higher price and execute.
|
||||||
@@ -1024,8 +1024,8 @@ contract PartyPoolTest is Test {
|
|||||||
token0.approve(address(poolCustom), type(uint256).max);
|
token0.approve(address(poolCustom), type(uint256).max);
|
||||||
|
|
||||||
// Perform identical swaps: token0 -> token1
|
// Perform identical swaps: token0 -> token1
|
||||||
(uint256 amountInDefault, uint256 amountOutDefault, uint256 feeDefault) = poolDefault.swap(alice, alice, 0, 1, swapAmount, 0, 0, false);
|
(uint256 amountInDefault, uint256 amountOutDefault, uint256 feeDefault) = poolDefault.swap(alice, bytes4(0), alice, 0, 1, swapAmount, 0, 0, false);
|
||||||
(uint256 amountInCustom, uint256 amountOutCustom, uint256 feeCustom) = poolCustom.swap(alice, alice, 0, 1, swapAmount, 0, 0, false);
|
(uint256 amountInCustom, uint256 amountOutCustom, uint256 feeCustom) = poolCustom.swap(alice, bytes4(0), alice, 0, 1, swapAmount, 0, 0, false);
|
||||||
|
|
||||||
// Swap results should be identical
|
// Swap results should be identical
|
||||||
assertEq(amountInDefault, amountInCustom, "Swap input amounts should be identical");
|
assertEq(amountInDefault, amountInCustom, "Swap input amounts should be identical");
|
||||||
|
|||||||
Reference in New Issue
Block a user