Skip to content

Commit

Permalink
Integer optimization (#6)
Browse files Browse the repository at this point in the history
* Working

* Add v4 tests

* Clean up V4Router

* Reorganize uint96

* Optimize with encodePacked

* Update Benchmark script

* Remove unnecessary casting

* Remove another unnecessary casting

* Change flags to uint8
  • Loading branch information
alexkeating authored Jun 6, 2023
1 parent a109f4c commit 6dad24f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 17 deletions.
8 changes: 6 additions & 2 deletions script/Benchmark.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ contract Benchmark is Script, OneInchContracts {
v5AggregationRouter.swap(v5AggregationExecutor, v5Desc, v5Permit, v5Data);

// Optimized router v5 swap call
(bool v5Ok,) = payable(v5Rtr).call(abi.encode(DAI, 100_000, v5Desc.minReturnAmount, v5Data, 0));
(bool v5Ok,) = payable(v5Rtr).call(
abi.encodePacked(DAI, uint96(100_000), uint96(v5Desc.minReturnAmount), uint256(0), v5Data)
);

if (!v5Ok) revert OptimizedV5RouterFailed();

Expand All @@ -78,7 +80,9 @@ contract Benchmark is Script, OneInchContracts {
v4AggregationRouter.swap(v4AggregationExecutor, v4Desc, v4Data);

// Optimized v4 swap call
(bool v4Ok,) = payable(v4Rtr).call(abi.encode(DAI, 100_000, v4Desc.minReturnAmount, v4Data, 0));
(bool v4Ok,) = payable(v4Rtr).call(
abi.encodePacked(DAI, uint96(100_000), uint96(v4Desc.minReturnAmount), uint256(0), v4Data)
);
if (!v4Ok) revert OptimizedV4RouterFailed();
}
}
10 changes: 7 additions & 3 deletions src/V4Router.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
pragma solidity ^0.8.0;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

Expand All @@ -22,8 +22,12 @@ contract V4Router is AggregationV4BaseRouter {

// Flags match specific constant masks. There is no documentation on these.
fallback() external payable {
(address dstToken, uint256 amount, uint256 minReturnAmount, bytes memory data, uint256 flags) =
abi.decode(msg.data, (address, uint256, uint256, bytes, uint256));
address dstToken = address(bytes20(msg.data[0:20]));
uint256 amount = uint256(uint96(bytes12(msg.data[20:32])));
uint256 minReturnAmount = uint256(uint96(bytes12(msg.data[32:44])));
uint256 flags = uint256(uint8(bytes1(msg.data[44:45])));
bytes memory data = bytes(msg.data[45:msg.data.length]);

IERC20(TOKEN).transferFrom(msg.sender, address(this), amount);
AGGREGATION_ROUTER.swap(
AGGREGATION_EXECUTOR,
Expand Down
8 changes: 6 additions & 2 deletions src/V5Router.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ contract V5Router is AggregationV5BaseRouter {

// Flags match specific constant masks. There is no documentation on these.
fallback() external payable {
(address dstToken, uint256 amount, uint256 minReturnAmount, bytes memory data, uint256 flags) =
abi.decode(msg.data, (address, uint256, uint256, bytes, uint256));
address dstToken = address(bytes20(msg.data[0:20]));
uint256 amount = uint256(uint96(bytes12(msg.data[20:32])));
uint256 minReturnAmount = uint256(uint96(bytes12(msg.data[32:44])));
uint256 flags = uint256(uint8(bytes1(msg.data[44:45])));
bytes memory data = bytes(msg.data[45:msg.data.length]);

IERC20(TOKEN).transferFrom(msg.sender, address(this), amount);
AGGREGATION_ROUTER.swap(
AGGREGATION_EXECUTOR,
Expand Down
14 changes: 9 additions & 5 deletions test/V4Router.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ contract Fallback is V4RouterTest {
assertEq(startingUNIBalance, 0, "Starting balance is incorrect");

// Optimized router call
(bool ok,) = payable(routerAddr).call(abi.encode(UNI, 100_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(UNI, uint96(100_000), uint96(desc.minReturnAmount), uint8(0), data)
);

assertTrue(ok, "Swap failed");

Expand Down Expand Up @@ -130,8 +132,9 @@ contract Fallback is V4RouterTest {
vm.startPrank(swapSenderAddress);
IERC20(USDC).approve(routerAddr, 10_000_000);
uint256 startingBalance = IERC20(USDC).balanceOf(swapSenderAddress);
(bool ok,) =
payable(routerAddr).call(abi.encode(UNI, 10_000_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(UNI, uint96(10_000_000), uint96(desc.minReturnAmount), uint8(0), data)
);
uint256 endingBalance = IERC20(USDC).balanceOf(swapSenderAddress);

assertTrue(!ok, "Swap succeeded");
Expand All @@ -142,8 +145,9 @@ contract Fallback is V4RouterTest {
(IV4AggregationRouter.SwapDescription memory desc, bytes memory data) = helper_apiParams();
IERC20(USDC).approve(routerAddr, 250_000);
uint256 startingBalance = IERC20(USDC).balanceOf(swapSenderAddress);
(bool ok,) =
payable(routerAddr).call(abi.encode(address(0), 250_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(address(0), uint96(250_000), uint96(desc.minReturnAmount), uint8(0), data)
);
uint256 endingBalance = IERC20(USDC).balanceOf(swapSenderAddress);

assertTrue(!ok, "Swap succeeded");
Expand Down
16 changes: 11 additions & 5 deletions test/V5Router.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ contract Fallback is V5RouterTest {
assertEq(startingUNIBalance, 0, "Starting balance is not 0");

// Optimized router call
(bool ok,) = payable(routerAddr).call(abi.encode(UNI, 100_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(UNI, uint96(100_000), uint96(desc.minReturnAmount), uint8(0), data)
);

assertTrue(ok, "Swap failed");

Expand Down Expand Up @@ -136,8 +138,9 @@ contract Fallback is V5RouterTest {
vm.startPrank(swapSenderAddress);
IERC20(USDC).approve(routerAddr, 10_000_000);
uint256 startingBalance = IERC20(USDC).balanceOf(swapSenderAddress);
(bool ok,) =
payable(routerAddr).call(abi.encode(UNI, 10_000_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(UNI, uint96(10_000_000), uint96(desc.minReturnAmount), uint8(0), data)
);
uint256 endingBalance = IERC20(USDC).balanceOf(swapSenderAddress);

assertTrue(!ok, "Swap succeeded");
Expand All @@ -148,8 +151,11 @@ contract Fallback is V5RouterTest {
(IV5AggregationRouter.SwapDescription memory desc,, bytes memory data) = helper_apiParams();
IERC20(USDC).approve(routerAddr, 250_000);
uint256 startingBalance = IERC20(USDC).balanceOf(swapSenderAddress);
(bool ok,) =
payable(routerAddr).call(abi.encode(address(0), 250_000, desc.minReturnAmount, data, 0));
(bool ok,) = payable(routerAddr).call(
abi.encodePacked(
address(0), uint96(250_000), uint96(desc.minReturnAmount), uint8(0), bytes(data)
)
);
uint256 endingBalance = IERC20(USDC).balanceOf(swapSenderAddress);
assertTrue(!ok, "Swap succeeded");
assertEq(startingBalance, endingBalance, "Funds were held by the router contract");
Expand Down

0 comments on commit 6dad24f

Please sign in to comment.