Skip to content

Commit

Permalink
Gas measurements using snaps (#38)
Browse files Browse the repository at this point in the history
* gas measurements using snaps

* lint

* more lint

* Gas costs disclaimer

* mooooore lint

---------

Co-authored-by: alcueca <[email protected]>
  • Loading branch information
alcueca and alcueca authored Apr 16, 2024
1 parent ec746d4 commit 1ce8014
Show file tree
Hide file tree
Showing 35 changed files with 207 additions and 29 deletions.
1 change: 1 addition & 0 deletions .forge-snapshots/AaveV2.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
262190
1 change: 1 addition & 0 deletions .forge-snapshots/AaveV3.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
212569
1 change: 1 addition & 0 deletions .forge-snapshots/AlgebraCamelot.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
80679
1 change: 1 addition & 0 deletions .forge-snapshots/AlgebraPendleCamelot.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
506792
1 change: 1 addition & 0 deletions .forge-snapshots/Balancer.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
113032
1 change: 1 addition & 0 deletions .forge-snapshots/BalancerPendle.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
525422
1 change: 1 addition & 0 deletions .forge-snapshots/CompoundMoonwell.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1183309
1 change: 1 addition & 0 deletions .forge-snapshots/CompoundSonne.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1040313
1 change: 1 addition & 0 deletions .forge-snapshots/Dolomite.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
459815
1 change: 1 addition & 0 deletions .forge-snapshots/MorphoBlue.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
132114
1 change: 1 addition & 0 deletions .forge-snapshots/PermissionedAaveV3.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
229742
1 change: 1 addition & 0 deletions .forge-snapshots/Silo.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1025824
1 change: 1 addition & 0 deletions .forge-snapshots/Solidly.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
163919
1 change: 1 addition & 0 deletions .forge-snapshots/UniswapV3.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
94720
1 change: 1 addition & 0 deletions .forge-snapshots/UniswapV3Pendle.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
497567
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
[submodule "lib/forge-gas-snapshot"]
path = lib/forge-gas-snapshot
url = https://github.com/marktoda/forge-gas-snapshot
53 changes: 26 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,32 @@ sequenceDiagram
† For the BalancerWrapper and Uniswap v3 the borrower transfers the repayment to the lender and the wrapper skips the
repayment approval.

## Addresses

Contracts are deployed at the same address for all supported networks.

| Contract | Lender | Address | Networks |
| --------------------------------------------------------------- | ------------------- | ------------------------------------------ | ------------------------------------------------- |
| [AaveWrapper](src/aave/AaveWrapper.sol) | Aave v3 | 0x9D4D2C08b29A2Db1c614483cd8971734BFDCC9F2 | Arbitrum One, Optimism, Polygon |
| [AaveWrapper](src/aave/AaveWrapper.sol) | Aave v3 | 0x0c86c636ed5593705b5675d370c831972C787841 | Ethereum, Gnosis |
| [AaveWrapper](src/aave/AaveWrapper.sol) | Spark | 0x8cB701df93f2Dae295aE8D7beE5Aa7e4D40CB397 | Ethereum, Gnosis |
| [BalancerWrapper](src/balancer/BalancerWrapper.sol) | Balancer v2 | 0x9E092cb431e5F1aa70e47e052773711d2Ba4917E | Ethereum, Arbitrum One, Optimism, Polygon, Gnosis |
| [BalancerWrapper](src/balancer/BalancerWrapper.sol) | Balancer v2 | 0xD534400B0555F8441c5a3e0E9e585615B54fB2F4 | Base |
| [UniswapV3Wrapper](src/uniswapV3/UniswapV3Wrapper.sol) | Uniswap v3 | 0x319300462C37AD2D4f26B584C2b67De51F51f289 | Arbitrum One, Optimism, Polygon |
| [CompoundWrapper](src/compound/CompoundWrapper.sol) | Balancer + Moonwell | 0x6207ec38da68902CC60D3760c9fe3EB64B426207 | Base |
| [CompoundWrapper](src/compound/CompoundWrapper.sol) | Balancer + Sonne | 0x6412183C579a276f467ad38468D19CC8f1F2b5cb | Optimism |
| [SiloWrapper](src/silo/SiloWrapper.sol) | Balancer + Silo | 0x0F9104Fec1a5C91e63632E215e8F5c57C8f32c77 | Arbitrum One |
| [DolomiteWrapper](src/dolomite/DolomiteWrapper.sol) | Dolomite | 0x54F1ce5E6bdf027C9a6016C9F52fC5A445b77ed6 | Arbitrum One |
| [MorphoBlueWrapper](src/morpho/MorphoBlueWrapper.sol) | MorphoBlue | 0xa0Cb4e1222d813D6e4dE79f2A7A0B7759209588F | Ethereum |
| [AlgebraWrapper](src/algebra/DolomiteWrapper.sol) | Camelot | 0x5E8820B2832aD8451f65Fa2CCe2F3Cef29016D0d | Arbitrum One |
| [AlgebraPendleWrapper](src/pendle/AlgebraPendleWrapper.sol) | Camelot + Pendle | 0xC9d66F655b7B35A2B4958bE2FB58E472736Bbc47 | Arbitrum One |
| [BalancerPendleWrapper](src/pendle/BalancerPendleWrapper.sol) | Balancer + Pendle | 0xC1Ea6a6df39D991006b39706db7C51f5A1819da7 | Arbitrum One |
| [UniswapV3PendleWrapper](src/pendle/UniswapV3PendleWrapper.sol) | Uniswap v3 + Pendle | 0xa353Fd50210786F0E038ddD574A21d0CCefb3163 | Arbitrum One |
| [SolidlyWrapper](src/solidly/SolidlyWrapper.sol) | Aerodrome | 0x69b6E55f00d908018E2D745c524995bc231D762b | Base |
| [SolidlyWrapper](src/solidly/SolidlyWrapper.sol) | Velodrome | 0xcF13CDdbA3aEf757c52466deC310F221e06238d6 | Optimism |

When a contract requires constructor parameters which vary per network, these are supplied by the
[Registry](https://github.com/alcueca/registry) deployed at 0x1BFf8Eee6ECF1c8155E81dba8894CE9cF49a220c in each supported
network.
## Deployments

| Lender | Address | Networks | Gas | Fees | Contract |
| ---------------------- | ------------------------------------------ | ------------------------------------------------- | ------- | -------- | --------------------------------------------------------------- |
| Aave v3 | 0x9D4D2C08b29A2Db1c614483cd8971734BFDCC9F2 | Arbitrum One, Optimism, Polygon | 212569 | 0.05% | [AaveWrapper](src/aave/AaveWrapper.sol) |
| Aave v3 (Permissioned) | 0x0c86c636ed5593705b5675d370c831972C787841 | Ethereum, Gnosis | 229742 | 0 | [AaveWrapper](src/aave/AaveWrapper.sol) |
| Spark | 0x8cB701df93f2Dae295aE8D7beE5Aa7e4D40CB397 | Ethereum, Gnosis | 212569 | 0 | [AaveWrapper](src/aave/AaveWrapper.sol) |
| Balancer v2 | 0x9E092cb431e5F1aa70e47e052773711d2Ba4917E | Ethereum, Arbitrum One, Optimism, Polygon, Gnosis | 113032 | 0 | [BalancerWrapper](src/balancer/BalancerWrapper.sol) |
| Balancer v2 | 0xD534400B0555F8441c5a3e0E9e585615B54fB2F4 | Base | 113032 | 0 | [BalancerWrapper](src/balancer/BalancerWrapper.sol) |
| Uniswap v3 | 0x319300462C37AD2D4f26B584C2b67De51F51f289 | Arbitrum One, Optimism, Polygon | 94720 | Variable | [UniswapV3Wrapper](src/uniswapV3/UniswapV3Wrapper.sol) |
| Balancer + Moonwell | 0x6207ec38da68902CC60D3760c9fe3EB64B426207 | Base | 1183309 | 0 | [CompoundWrapper](src/compound/CompoundWrapper.sol) |
| Balancer + Sonne | 0x6412183C579a276f467ad38468D19CC8f1F2b5cb | Optimism | 1040313 | 0 | [CompoundWrapper](src/compound/CompoundWrapper.sol) |
| Balancer + Silo | 0x0F9104Fec1a5C91e63632E215e8F5c57C8f32c77 | Arbitrum One | 1025824 | 1 | [SiloWrapper](src/silo/SiloWrapper.sol) |
| Dolomite | 0x54F1ce5E6bdf027C9a6016C9F52fC5A445b77ed6 | Arbitrum One | 459815 | 0 | [DolomiteWrapper](src/dolomite/DolomiteWrapper.sol) |
| MorphoBlue | 0xa0Cb4e1222d813D6e4dE79f2A7A0B7759209588F | Ethereum | 132114 | 0 | [MorphoBlueWrapper](src/morpho/MorphoBlueWrapper.sol) |
| Camelot | 0x5E8820B2832aD8451f65Fa2CCe2F3Cef29016D0d | Arbitrum One | 80679 | 0.01% | [AlgebraWrapper](src/algebra/AlgebraWrapper.sol) |
| Camelot + Pendle | 0xC9d66F655b7B35A2B4958bE2FB58E472736Bbc47 | Arbitrum One | 506792 | 0.01% | [AlgebraPendleWrapper](src/pendle/AlgebraPendleWrapper.sol) |
| Balancer + Pendle | 0xC1Ea6a6df39D991006b39706db7C51f5A1819da7 | Arbitrum One | 525422 | 0 | [BalancerPendleWrapper](src/pendle/BalancerPendleWrapper.sol) |
| Uniswap v3 + Pendle | 0xa353Fd50210786F0E038ddD574A21d0CCefb3163 | Arbitrum One | 497567 | Variable | [UniswapV3PendleWrapper](src/pendle/UniswapV3PendleWrapper.sol) |
| Aerodrome | 0x69b6E55f00d908018E2D745c524995bc231D762b | Base | 163919 | Variable | [SolidlyWrapper](src/solidly/SolidlyWrapper.sol) |
| Velodrome | 0xcF13CDdbA3aEf757c52466deC310F221e06238d6 | Optimism | 163919 | Variable | [SolidlyWrapper](src/solidly/SolidlyWrapper.sol) |

Disclaimer: The gas costs are calculated for calling `flashLoan` on each wrapper for an arbitrarily chosen token and
loan amount. Calling the underlying flash lender directly may have larger gas savings in some instances than others.
Requesting loans for different tokens or amounts might have different gas costs. For AMMs the fees often vary according
to pool parameters and state.

## Flash Loans

Expand Down
4 changes: 3 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
cbor_metadata = false
evm_version = 'london'
ffi = true
fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}]
fuzz = { runs = 1_000 }
gas_reports = ["*"]
libs = ["lib"]
Expand All @@ -15,7 +18,6 @@
solc = "0.8.24"
src = "src"
test = "test"
evm_version = 'london'
verbosity = 2

[profile.ci]
Expand Down
1 change: 1 addition & 0 deletions lib/forge-gas-snapshot
Submodule forge-gas-snapshot added at 1a5804
8 changes: 8 additions & 0 deletions test/AaveWrapper.v2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,12 @@ contract AaveWrapperTest is Test {
params: ""
});
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(dai, loan);
IERC20(dai).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(dai, loan, "AaveV2");
}
}
8 changes: 8 additions & 0 deletions test/AaveWrapper.v3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,12 @@ contract AaveWrapperTest is Test {
params: ""
});
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(dai, loan);
IERC20(dai).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(dai, loan, "AaveV3");
}
}
8 changes: 8 additions & 0 deletions test/AlgebraPendleWrapper.Camelot.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,12 @@ contract AlgebraPendleWrapperCamelotTest is Test {
vm.expectRevert(AlgebraPendleWrapper.Unauthorized.selector);
wrapper.algebraFlashCallback({ fee0: 0, fee1: 0, params: abi.encode(underlying, weth, usdc, 0, "") });
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(token, loan);
IERC20(token).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "AlgebraPendleCamelot");
}
}
9 changes: 9 additions & 0 deletions test/AlgebraWrapper.Camelot.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,13 @@ contract AlgebraWrapperCamelotTest is Test {
vm.expectRevert(AlgebraWrapper.Unauthorized.selector);
wrapper.algebraFlashCallback({ fee0: 0, fee1: 0, params: abi.encode(weth, usdc, 0, "") });
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
address token = wsteth;
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(token, loan);
deal(address(token), address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "AlgebraCamelot");
}
}
8 changes: 8 additions & 0 deletions test/BalancerPendleWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,12 @@ contract BalancerPendleWrapperTest is Test {
vm.expectRevert(BalancerPendleWrapper.HashMismatch.selector);
wrapper.receiveFlashLoan(address(token).toArray(), uint256(1e18).toArray(), uint256(0).toArray(), "");
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 10e18;
uint256 fee = wrapper.flashFee(token, loan);
IERC20(token).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "BalancerPendle");
}
}
8 changes: 8 additions & 0 deletions test/BalancerWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,12 @@ contract BalancerWrapperTest is Test {
params: ""
});
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(dai, loan);
IERC20(dai).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(dai, loan, "Balancer");
}
}
8 changes: 8 additions & 0 deletions test/CompoundWrapper.Moonwell.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,12 @@ contract MoonwellWrapperTest is Test {

wrapper.setCToken(IERC20(dai), ICToken(address(0x628ff693426583D9a7FB391E54366292F509D457)));
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(dai, loan);
IERC20(dai).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(dai, loan, "CompoundMoonwell");
}
}
8 changes: 8 additions & 0 deletions test/CompoundWrapper.Sonne.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,12 @@ contract SonneWrapperTest is Test {

wrapper.setCToken(IERC20(snx), ICToken(address(0xD7dAabd899D1fAbbC3A9ac162568939CEc0393Cc)));
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(snx, loan);
IERC20(snx).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(snx, loan, "CompoundSonne");
}
}
8 changes: 8 additions & 0 deletions test/DolomiteWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,12 @@ contract DolomiteWrapperTest is Test {
vm.expectRevert(DolomiteWrapper.HashMismatch.selector);
wrapper.callFunction(address(wrapper), accountInfo, "");
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 10e8;
uint256 fee = wrapper.flashFee(wbtc, loan);
IERC20(wbtc).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(wbtc, loan, "Dolomite");
}
}
32 changes: 31 additions & 1 deletion test/MockBorrower.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.19;

import "erc7399/IERC7399.sol";
import "src/BaseWrapper.sol";
import { GasSnapshot } from "forge-gas-snapshot/GasSnapshot.sol";

contract LoanReceiver {
using SafeERC20 for IERC20;
Expand All @@ -13,7 +14,7 @@ contract LoanReceiver {
}

/// @dev Mock flash loan borrower. It allows to examine the state of the borrower during the callback.
contract MockBorrower {
contract MockBorrower is GasSnapshot {
using SafeERC20 for IERC20;

bytes32 public constant ERC3156PP_CALLBACK_SUCCESS = keccak256("ERC3156PP_CALLBACK_SUCCESS");
Expand Down Expand Up @@ -137,6 +138,22 @@ contract MockBorrower {
return "";
}

function onFlashLoanMeasureGas(
address,
address paymentReceiver,
address asset,
uint256 amount,
uint256 fee,
bytes calldata
)
external
returns (bytes memory)
{
IERC20(asset).safeTransfer(paymentReceiver, amount + fee);

return "";
}

function flashBorrow(address asset, uint256 amount) public returns (bytes memory) {
return lender.flash(address(loanReceiver), asset, amount, "", this.onFlashLoan);
}
Expand All @@ -158,4 +175,17 @@ contract MockBorrower {
function flashBorrowVoid(address asset, uint256 amount) public returns (bytes memory) {
return lender.flash(address(loanReceiver), asset, amount, "", this.onFlashLoanVoid);
}

function flashBorrowMeasureGas(
address asset,
uint256 amount,
string calldata tag
)
public
returns (bytes memory out)
{
snapStart(tag);
out = lender.flash(address(this), asset, amount, "", this.onFlashLoanMeasureGas);
snapEnd();
}
}
8 changes: 8 additions & 0 deletions test/MorphoBlueWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,12 @@ contract MorphoBlueWrapperTest is Test {
vm.expectRevert(MorphoBlueWrapper.NotMorpho.selector);
wrapper.onMorphoFlashLoan({ amount: 0, params: "" });
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 100e18;
uint256 fee = wrapper.flashFee(wstETH, loan);
IERC20(wstETH).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(wstETH, loan, "MorphoBlue");
}
}
13 changes: 13 additions & 0 deletions test/PermissionedAaveWrapper.v3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ contract PermissionedAaveWrapperTest is Test {
);
borrower.flashBorrow(dai, 1e18);
}

function test_measureFlashLoanGasPermissionedAaveV3() public {
console2.log("test_measureFlashLoanGas");
vm.mockCall(
provider.getACLManager(),
abi.encodeWithSelector(IACLManager.isFlashBorrower.selector, wrapper),
abi.encode(true)
);
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(dai, loan);
IERC20(dai).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(dai, loan, "PermissionedAaveV3");
}
}

interface IACLManager {
Expand Down
8 changes: 8 additions & 0 deletions test/SiloWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,12 @@ contract SiloWrapperTest is Test {
vm.expectRevert(SiloWrapper.HashMismatch.selector);
wrapper.receiveFlashLoan(address(token).toArray(), uint256(1e18).toArray(), uint256(0).toArray(), "");
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 10_999_999_999_999_999;
uint256 fee = wrapper.flashFee(token, loan);
IERC20(token).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "Silo");
}
}
9 changes: 9 additions & 0 deletions test/SolidlyWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,13 @@ contract SolidlyWrapperTest is Test {
vm.expectRevert(SolidlyWrapper.UnknownPool.selector);
wrapper.hook({ sender: address(wrapper), amount0: 0, amount1: 0, params: abi.encode(weth, usdc, 0, false, "") });
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
address token = weth;
uint256 fee = wrapper.flashFee(token, loan);
deal(address(token), address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "Solidly");
}
}
8 changes: 8 additions & 0 deletions test/UniswapV3PendleWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,12 @@ contract UniswapV3PendleWrapperTest is Test {
params: abi.encode(address(token), address(underlying), uint24(0.0005e6), uint256(0), "")
});
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(token, loan);
IERC20(token).safeTransfer(address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "UniswapV3Pendle");
}
}
9 changes: 9 additions & 0 deletions test/UniswapV3Wrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,13 @@ contract UniswapV3WrapperTest is Test {
params: abi.encode(address(usdc), address(usdt), uint24(0.0005e6), uint256(0), "")
});
}

function test_measureFlashLoanGas() public {
console2.log("test_measureFlashLoanGas");
address token = weth;
uint256 loan = 1e18;
uint256 fee = wrapper.flashFee(token, loan);
deal(address(token), address(borrower), fee);
borrower.flashBorrowMeasureGas(token, loan, "UniswapV3");
}
}

0 comments on commit 1ce8014

Please sign in to comment.