Skip to content

Commit c4b0140

Browse files
committed
perf: precompile contracts for faster test runs
1 parent 98bc1d7 commit c4b0140

15 files changed

+131
-103
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: ERC6900 RI Test CI
1+
name: ERC-6900 RI Test CI
22

33
on: [pull_request, workflow_dispatch]
44

@@ -45,7 +45,7 @@ jobs:
4545

4646
- name: "Lint the contracts"
4747
run: "pnpm lint"
48-
48+
4949
test:
5050
name: Run Forge Tests
5151
runs-on: ubuntu-latest
@@ -63,29 +63,7 @@ jobs:
6363
run: forge install
6464

6565
- name: Build project
66-
run: forge build
67-
68-
- name: Run tests
69-
run: FOUNDRY_PROFILE=deep forge test -vvv
70-
71-
test-lite:
72-
name: Run Forge Tests [lite build]
73-
runs-on: ubuntu-latest
74-
steps:
75-
- uses: actions/checkout@v3
76-
with:
77-
submodules: recursive
78-
79-
- name: Install Foundry
80-
uses: foundry-rs/foundry-toolchain@v1
81-
with:
82-
version: nightly
83-
84-
- name: Install forge dependencies
85-
run: forge install
86-
87-
- name: Build project
88-
run: FOUNDRY_PROFILE=lite forge build
66+
run: FOUNDRY_PROFILE=optimized-build forge build
8967

9068
- name: Run tests
91-
run: FOUNDRY_PROFILE=lite forge test -vvv
69+
run: FOUNDRY_PROFILE=optimized-test-deep forge test -vvv

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
# Foundry build and cache directories
22
out/
3+
out-optimized/
34
cache/
45
node_modules/
6+
7+
# Coverage
8+
report/
9+
lcov.info

README.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ERC-6900 Ref Implementation
1+
# ERC-6900 Reference Implementation
22

33
Reference implementation for [ERC-6900](https://eips.ethereum.org/EIPS/eip-6900). It is an early draft implementation.
44

@@ -13,20 +13,18 @@ The implementation includes an upgradable modular account with two plugins (`Sin
1313

1414
Anyone is welcome to submit feedback and/or PRs to improve code or add Plugins.
1515

16-
### Build
16+
### Testing
17+
18+
The default Foundry profile can be used to compile (without IR) and test the entire project. The default profile should be used when generating coverage and debugging.
1719

1820
```bash
1921
forge build
20-
21-
# or use the lite profile to reduce compilation time
22-
FOUNDRY_PROFILE=lite forge build
22+
forge test -vvv
2323
```
2424

25-
### Test
25+
Since IR compilation generates different bytecode, it's useful to test against the contracts compiled via IR. Since compiling the entire project (including the test suite) takes a long time, special profiles can be used to precompile just the source contracts, and have the tests deploy the relevant contracts using those artifacts.
2626

2727
```bash
28-
forge test -vvv
29-
30-
# or use the lite profile to reduce compilation time
31-
FOUNDRY_PROFILE=lite forge test -vvv
28+
FOUNDRY_PROFILE=optimized-build forge build
29+
FOUNDRY_PROFILE=optimized-test forge test -vvv
3230
```

foundry.toml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
[profile.default]
22
solc = '0.8.19'
3-
via_ir = true
3+
via_ir = false
44
src = 'src'
5-
out = 'out'
65
test = 'test'
76
libs = ['lib']
7+
out = 'out'
88
optimizer = true
99
optimizer_runs = 10_000
1010
ignored_error_codes = [3628]
11+
fs_permissions = [
12+
{ access = "read", path = "./out-optimized" }
13+
]
1114

1215
[fuzz]
1316
runs = 500
@@ -17,12 +20,24 @@ runs=500
1720
fail_on_revert = true
1821
depth = 10
1922

20-
[profile.lite]
21-
solc = '0.8.19'
22-
via_ir = false
23-
optimizer = true
24-
optimizer_runs = 10_000
25-
ignored_error_codes = [3628]
23+
[profile.optimized-build]
24+
via_ir = true
25+
test = 'src'
26+
out = 'out-optimized'
27+
bytecode_hash = 'none'
28+
29+
[profile.optimized-test]
30+
src = 'test'
31+
32+
[profile.optimized-test-deep]
33+
src = 'test'
34+
35+
[profile.optimized-test-deep.fuzz]
36+
runs = 10000
37+
38+
[profile.optimized-test-deep.invariant]
39+
runs = 5000
40+
depth = 32
2641

2742
[profile.deep.fuzz]
2843
runs = 10000
@@ -43,4 +58,4 @@ goerli = "${RPC_URL_GOERLI}"
4358
mainnet = { key = "${ETHERSCAN_API_KEY}" }
4459
goerli = { key = "${ETHERSCAN_API_KEY}" }
4560

46-
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
61+
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

test/TestUtils.sol

Lines changed: 0 additions & 21 deletions
This file was deleted.

test/account/AccountReturnData.t.sol

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.19;
33

4-
import {Test} from "forge-std/Test.sol";
5-
64
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
75

86
import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
@@ -17,9 +15,10 @@ import {
1715
ResultConsumerPlugin
1816
} from "../mocks/plugins/ReturnDataPluginMocks.sol";
1917
import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol";
18+
import {OptimizedTest} from "../utils/OptimizedTest.sol";
2019

2120
// Tests all the different ways that return data can be read from plugins through an account
22-
contract AccountReturnDataTest is Test {
21+
contract AccountReturnDataTest is OptimizedTest {
2322
EntryPoint public entryPoint; // Just to be able to construct the factory
2423
SingleOwnerPlugin public singleOwnerPlugin;
2524
MSCAFactoryFixture public factory;
@@ -32,7 +31,7 @@ contract AccountReturnDataTest is Test {
3231

3332
function setUp() public {
3433
entryPoint = new EntryPoint();
35-
singleOwnerPlugin = new SingleOwnerPlugin();
34+
singleOwnerPlugin = _deploySingleOwnerPlugin();
3635
factory = new MSCAFactoryFixture(entryPoint, singleOwnerPlugin);
3736

3837
regularResultContract = new RegularResultContract();

test/account/ExecuteFromPluginPermissions.t.sol

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.19;
33

4-
import {Test, console} from "forge-std/Test.sol";
4+
import {console} from "forge-std/Test.sol";
55

66
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
77

@@ -11,18 +11,17 @@ import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol";
1111
import {FunctionReference} from "../../src/libraries/FunctionReferenceLib.sol";
1212

1313
import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol";
14-
1514
import {Counter} from "../mocks/Counter.sol";
1615
import {ResultCreatorPlugin} from "../mocks/plugins/ReturnDataPluginMocks.sol";
17-
1816
import {
1917
EFPCallerPlugin,
2018
EFPCallerPluginAnyExternal,
2119
EFPPermittedCallHookPlugin,
2220
EFPExternalPermittedCallHookPlugin
2321
} from "../mocks/plugins/ExecFromPluginPermissionsMocks.sol";
22+
import {OptimizedTest} from "../utils/OptimizedTest.sol";
2423

25-
contract ExecuteFromPluginPermissionsTest is Test {
24+
contract ExecuteFromPluginPermissionsTest is OptimizedTest {
2625
Counter public counter1;
2726
Counter public counter2;
2827
Counter public counter3;
@@ -47,7 +46,7 @@ contract ExecuteFromPluginPermissionsTest is Test {
4746

4847
// Initialize the contracts needed to use the account.
4948
entryPoint = new EntryPoint();
50-
singleOwnerPlugin = new SingleOwnerPlugin();
49+
singleOwnerPlugin = _deploySingleOwnerPlugin();
5150
factory = new MSCAFactoryFixture(entryPoint, singleOwnerPlugin);
5251

5352
// Initialize the EFP caller plugins, which will attempt to use the permissions system to authorize calls.

test/account/ManifestValidity.t.sol

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.19;
33

4-
import {Test} from "forge-std/Test.sol";
5-
64
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
75

86
import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
@@ -22,8 +20,9 @@ import {
2220
BadHookMagicValue_RuntimeValidationFunction_Plugin,
2321
BadHookMagicValue_PostExecHook_Plugin
2422
} from "../mocks/plugins/ManifestValidityMocks.sol";
23+
import {OptimizedTest} from "../utils/OptimizedTest.sol";
2524

26-
contract ManifestValidityTest is Test {
25+
contract ManifestValidityTest is OptimizedTest {
2726
EntryPoint public entryPoint; // Just to be able to construct the factory
2827
SingleOwnerPlugin public singleOwnerPlugin;
2928
MSCAFactoryFixture public factory;
@@ -32,7 +31,7 @@ contract ManifestValidityTest is Test {
3231

3332
function setUp() public {
3433
entryPoint = new EntryPoint();
35-
singleOwnerPlugin = new SingleOwnerPlugin();
34+
singleOwnerPlugin = _deploySingleOwnerPlugin();
3635
factory = new MSCAFactoryFixture(entryPoint, singleOwnerPlugin);
3736

3837
// Create an account with "this" as the owner, so we can execute along the runtime path with regular

test/account/ModularAccountLoupe.t.sol

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.19;
33

4-
import {Test} from "forge-std/Test.sol";
5-
64
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
75
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
86

@@ -23,8 +21,9 @@ import {FunctionReference, FunctionReferenceLib} from "../../src/libraries/Funct
2321
import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol";
2422
import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol";
2523
import {MockPlugin} from "../mocks/MockPlugin.sol";
24+
import {OptimizedTest} from "../utils/OptimizedTest.sol";
2625

27-
contract ModularAccountLoupeTest is Test {
26+
contract ModularAccountLoupeTest is OptimizedTest {
2827
EntryPoint public entryPoint;
2928
SingleOwnerPlugin public singleOwnerPlugin;
3029
MSCAFactoryFixture public factory;
@@ -40,7 +39,7 @@ contract ModularAccountLoupeTest is Test {
4039
function setUp() public {
4140
entryPoint = new EntryPoint();
4241

43-
singleOwnerPlugin = new SingleOwnerPlugin();
42+
singleOwnerPlugin = _deploySingleOwnerPlugin();
4443
factory = new MSCAFactoryFixture(entryPoint, singleOwnerPlugin);
4544
comprehensivePlugin = new ComprehensivePlugin();
4645

test/account/UpgradeableModularAccount.t.sol

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.19;
33

4-
import {Test, console} from "forge-std/Test.sol";
4+
import {console} from "forge-std/Test.sol";
55

66
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
77
import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol";
@@ -23,8 +23,9 @@ import {Counter} from "../mocks/Counter.sol";
2323
import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol";
2424
import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol";
2525
import {MockPlugin} from "../mocks/MockPlugin.sol";
26+
import {OptimizedTest} from "../utils/OptimizedTest.sol";
2627

27-
contract UpgradeableModularAccountTest is Test {
28+
contract UpgradeableModularAccountTest is OptimizedTest {
2829
using ECDSA for bytes32;
2930

3031
EntryPoint public entryPoint;
@@ -63,8 +64,8 @@ contract UpgradeableModularAccountTest is Test {
6364
beneficiary = payable(makeAddr("beneficiary"));
6465
vm.deal(beneficiary, 1 wei);
6566

66-
singleOwnerPlugin = new SingleOwnerPlugin();
67-
tokenReceiverPlugin = new TokenReceiverPlugin();
67+
singleOwnerPlugin = _deploySingleOwnerPlugin();
68+
tokenReceiverPlugin = _deployTokenReceiverPlugin();
6869
factory = new MSCAFactoryFixture(entryPoint, singleOwnerPlugin);
6970

7071
// Compute counterfactual address

0 commit comments

Comments
 (0)