Skip to content

Commit 3f70474

Browse files
authored
feat: add initial gas snapshots (#91)
While the ci continuously checks gas usage via --gas-report, having isolated gas metering has some merit as it allows exact tracking for selected scenarios.
1 parent 9a6add7 commit 3f70474

13 files changed

+598
-0
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ lib
33
cache
44
node_modules
55
report
6+
snapshots

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ coverage :
3333
make coverage-report
3434
make coverage-badge
3535

36+
# Gas reports
37+
forge test --mp 'tests/gas/*.t.sol' --isolate
38+
3639
# Utilities
3740
download :; cast etherscan-source --chain ${chain} -d src/etherscan/${chain}_${address} ${address}
3841
git-diff :

snapshots/AToken.transfer.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"full amount; receiver: ->enableCollateral": "144837",
3+
"full amount; sender: ->disableCollateral;": "103274",
4+
"full amount; sender: ->disableCollateral; receiver: ->enableCollateral": "145016",
5+
"full amount; sender: ->disableCollateral; receiver: dirty, ->enableCollateral": "133059",
6+
"full amount; sender: collateralDisabled": "103095",
7+
"partial amount; sender: collateralDisabled;": "103095",
8+
"partial amount; sender: collateralDisabled; receiver: ->enableCollateral": "144837",
9+
"partial amount; sender: collateralEnabled;": "103303",
10+
"partial amount; sender: collateralEnabled; receiver: ->enableCollateral": "145045"
11+
}

snapshots/Pool.Getters.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"getEModeCategoryCollateralConfig": "8000",
3+
"getEModeCategoryData": "13430",
4+
"getLiquidationGracePeriod": "29197",
5+
"getReserveData": "34935",
6+
"getUserAccountData: supplies: 0, borrows: 0": "22641",
7+
"getUserAccountData: supplies: 1, borrows: 0": "34774",
8+
"getUserAccountData: supplies: 2, borrows: 0": "47296",
9+
"getUserAccountData: supplies: 2, borrows: 1": "28968"
10+
}

snapshots/Pool.Operations.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"borrow: first borrow->borrowingEnabled": "256189",
3+
"borrow: recurrent borrow": "248474",
4+
"liquidationCall: deficit on liquidated asset": "392266",
5+
"liquidationCall: deficit on liquidated asset + other asset": "422243",
6+
"liquidationCall: full liquidation": "392266",
7+
"liquidationCall: partial liquidation": "381149",
8+
"repay: full repay": "176547",
9+
"repay: partial repay": "189971",
10+
"supply: collateralDisabled": "146829",
11+
"supply: collateralEnabled": "146829",
12+
"supply: first supply->collateralEnabled": "176387",
13+
"withdraw: full withdraw": "165303",
14+
"withdraw: partial withdraw": "181992"
15+
}

snapshots/Pool.Setters.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"setUserEMode: enter eMode, 1 borrow, 1 supply": "140164",
3+
"setUserEMode: leave eMode, 1 borrow, 1 supply": "112199",
4+
"setUserUseReserveAsCollateral: disableCollateral, 1 supply": "93434",
5+
"setUserUseReserveAsCollateral: enableCollateral, 1 supply": "105145"
6+
}

snapshots/StataTokenV2.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"deposit": "284677",
3+
"depositATokens": "220136",
4+
"redeem": "205767",
5+
"redeemAToken": "153413"
6+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import 'forge-std/Test.sol';
5+
6+
import {IAToken} from '../../src/contracts/interfaces/IAToken.sol';
7+
import {Errors} from '../../src/contracts/protocol/libraries/helpers/Errors.sol';
8+
import {Testhelpers, IERC20} from './Testhelpers.sol';
9+
10+
/**
11+
* Scenario suite for transfer operations.
12+
*/
13+
contract ATokenTransfer_gas_Tests is Testhelpers {
14+
address token;
15+
IAToken aToken;
16+
address variableDebtToken;
17+
18+
address sender = makeAddr('sender');
19+
address receiver = makeAddr('receiver');
20+
21+
function setUp() public override {
22+
super.setUp();
23+
token = tokenList.usdx;
24+
(address aTokenAddress, , address variableDebtTokenAddress) = contracts
25+
.protocolDataProvider
26+
.getReserveTokensAddresses(tokenList.usdx);
27+
aToken = IAToken(aTokenAddress);
28+
variableDebtToken = variableDebtTokenAddress;
29+
}
30+
31+
function test_transfer_fullAmount() external {
32+
_supplyOnReserve(sender, 1 ether);
33+
vm.prank(sender);
34+
35+
_skip(100);
36+
37+
aToken.transfer(receiver, 1 ether);
38+
vm.snapshotGasLastCall(
39+
'AToken.transfer',
40+
'full amount; sender: ->disableCollateral; receiver: ->enableCollateral'
41+
);
42+
}
43+
44+
function test_transfer_fullAmount_dirtyReceiver() external {
45+
_supplyOnReserve(receiver, 1 ether, tokenList.weth);
46+
_supplyOnReserve(sender, 1 ether);
47+
vm.prank(sender);
48+
49+
_skip(100);
50+
51+
aToken.transfer(receiver, 1 ether);
52+
vm.snapshotGasLastCall(
53+
'AToken.transfer',
54+
'full amount; sender: ->disableCollateral; receiver: dirty, ->enableCollateral'
55+
);
56+
}
57+
58+
function test_transfer_fullAmount_senderCollateralDisabled() external {
59+
_supplyOnReserve(sender, 1 ether);
60+
vm.startPrank(sender);
61+
contracts.poolProxy.setUserUseReserveAsCollateral(token, false);
62+
63+
_skip(100);
64+
65+
aToken.transfer(receiver, 1 ether);
66+
vm.snapshotGasLastCall('AToken.transfer', 'full amount; receiver: ->enableCollateral');
67+
}
68+
69+
function test_transfer_fullAmount_senderCollateralDisabled_receiverNonZeroFunds2() external {
70+
_supplyOnReserve(sender, 1 ether);
71+
_supplyOnReserve(receiver, 1 ether);
72+
vm.startPrank(sender);
73+
74+
_skip(100);
75+
76+
aToken.transfer(receiver, 1 ether);
77+
vm.snapshotGasLastCall('AToken.transfer', 'full amount; sender: ->disableCollateral;');
78+
}
79+
80+
function test_transfer_fullAmount_senderCollateralDisabled_receiverNonZeroFunds() external {
81+
_supplyOnReserve(sender, 1 ether);
82+
_supplyOnReserve(receiver, 1 ether);
83+
vm.startPrank(sender);
84+
contracts.poolProxy.setUserUseReserveAsCollateral(token, false);
85+
86+
_skip(100);
87+
88+
aToken.transfer(receiver, 1 ether);
89+
vm.snapshotGasLastCall('AToken.transfer', 'full amount; sender: collateralDisabled');
90+
}
91+
92+
function test_transfer_partialAmount_senderCollateralEnabled() external {
93+
_supplyOnReserve(sender, 1 ether);
94+
vm.startPrank(sender);
95+
96+
_skip(100);
97+
98+
aToken.transfer(receiver, 0.5 ether);
99+
vm.snapshotGasLastCall(
100+
'AToken.transfer',
101+
'partial amount; sender: collateralEnabled; receiver: ->enableCollateral'
102+
);
103+
}
104+
105+
function test_transfer_partialAmount_senderCollateralEnabled_receiverNonZeroFunds() external {
106+
_supplyOnReserve(sender, 1 ether);
107+
_supplyOnReserve(receiver, 1 ether);
108+
vm.startPrank(sender);
109+
110+
_skip(100);
111+
112+
aToken.transfer(receiver, 0.5 ether);
113+
vm.snapshotGasLastCall('AToken.transfer', 'partial amount; sender: collateralEnabled;');
114+
}
115+
116+
function test_transfer_partialAmount_receiverNonZeroFunds() external {
117+
_supplyOnReserve(sender, 1 ether);
118+
_supplyOnReserve(receiver, 1 ether);
119+
vm.startPrank(sender);
120+
contracts.poolProxy.setUserUseReserveAsCollateral(token, false);
121+
122+
_skip(100);
123+
124+
aToken.transfer(receiver, 0.5 ether);
125+
vm.snapshotGasLastCall('AToken.transfer', 'partial amount; sender: collateralDisabled;');
126+
}
127+
128+
function test_transfer_partialAmount() external {
129+
_supplyOnReserve(sender, 1 ether);
130+
vm.startPrank(sender);
131+
contracts.poolProxy.setUserUseReserveAsCollateral(token, false);
132+
133+
_skip(100);
134+
135+
aToken.transfer(receiver, 0.5 ether);
136+
vm.snapshotGasLastCall(
137+
'AToken.transfer',
138+
'partial amount; sender: collateralDisabled; receiver: ->enableCollateral'
139+
);
140+
}
141+
142+
function _supplyOnReserve(address user, uint256 amount) internal {
143+
_supplyOnReserve(user, amount, token);
144+
}
145+
}

tests/gas/Pool.Getters.gas.t.sol

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import 'forge-std/Test.sol';
5+
6+
import {Errors} from '../../src/contracts/protocol/libraries/helpers/Errors.sol';
7+
import {UserConfiguration} from '../../src/contracts/protocol/libraries/configuration/UserConfiguration.sol';
8+
import {Testhelpers, IERC20} from './Testhelpers.sol';
9+
10+
/**
11+
* Scenario suite for pool getter operations.
12+
*/
13+
contract PoolGetters_gas_Tests is Testhelpers {
14+
// mock users to supply and borrow liquidity
15+
address user = makeAddr('user');
16+
17+
function test_getReserveData() external {
18+
contracts.poolProxy.getReserveData(tokenList.usdx);
19+
vm.snapshotGasLastCall('Pool.Getters', 'getReserveData');
20+
}
21+
22+
function test_getUserAccountData() external {
23+
contracts.poolProxy.getUserAccountData(user);
24+
vm.snapshotGasLastCall('Pool.Getters', 'getUserAccountData: supplies: 0, borrows: 0');
25+
}
26+
27+
function test_getUserAccountData_oneSupplies() external {
28+
_supplyOnReserve(user, 1 ether, tokenList.usdx);
29+
contracts.poolProxy.getUserAccountData(user);
30+
vm.snapshotGasLastCall('Pool.Getters', 'getUserAccountData: supplies: 1, borrows: 0');
31+
}
32+
33+
function test_getUserAccountData_twoSupplies() external {
34+
_supplyOnReserve(user, 1 ether, tokenList.usdx);
35+
_supplyOnReserve(user, 1 ether, tokenList.weth);
36+
37+
contracts.poolProxy.getUserAccountData(user);
38+
vm.snapshotGasLastCall('Pool.Getters', 'getUserAccountData: supplies: 2, borrows: 0');
39+
}
40+
41+
function test_getUserAccountData_twoSupplies_oneBorrows() external {
42+
_supplyOnReserve(user, 1 ether, tokenList.usdx);
43+
_supplyOnReserve(user, 1 ether, tokenList.weth);
44+
45+
_supplyOnReserve(address(1), 0.001e8, tokenList.wbtc);
46+
vm.prank(user);
47+
contracts.poolProxy.borrow(tokenList.wbtc, 0.001e8, 2, 0, user);
48+
49+
contracts.poolProxy.getUserAccountData(user);
50+
vm.snapshotGasLastCall('Pool.Getters', 'getUserAccountData: supplies: 2, borrows: 1');
51+
}
52+
53+
function test_getEModeCategoryData() external {
54+
contracts.poolProxy.getEModeCategoryData(1);
55+
vm.snapshotGasLastCall('Pool.Getters', 'getEModeCategoryData');
56+
}
57+
58+
function test_getEModeCategoryCollateralConfig() external {
59+
contracts.poolProxy.getEModeCategoryCollateralConfig(1);
60+
vm.snapshotGasLastCall('Pool.Getters', 'getEModeCategoryCollateralConfig');
61+
}
62+
63+
function test_getLiquidationGracePeriod() external {
64+
contracts.poolProxy.getLiquidationGracePeriod(tokenList.usdx);
65+
vm.snapshotGasLastCall('Pool.Getters', 'getLiquidationGracePeriod');
66+
}
67+
}

0 commit comments

Comments
 (0)