-
Notifications
You must be signed in to change notification settings - Fork 0
tests: add solver delegate coverage #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/setup
Are you sure you want to change the base?
Changes from all commits
cf9c6c6
0f099e3
3f02a52
4d3ca32
c0e4aa2
7e00d57
6dd4735
6014b9e
d5f4220
7377c12
d0db7b4
626efad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| ETH_MAINNET_RPC_URL= | ||
| GNOSIS_RPC_URL= | ||
| ARBITRUM_ONE_RPC_URL= | ||
| BASE_RPC_URL= | ||
| OPTIMISM_RPC_URL= | ||
| POLYGON_RPC_URL= | ||
| BNB_MAINNET_RPC_URL= | ||
| PLASMA_RPC_URL= | ||
| AVALANCHE_RPC_URL= | ||
| INK_RPC_URL= | ||
| LINEA_RPC_URL= |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,13 +67,25 @@ jobs: | |
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| env: | ||
| ETH_MAINNET_RPC_URL: ${{ secrets.ETH_MAINNET_RPC_URL }} | ||
| GNOSIS_RPC_URL: ${{ secrets.GNOSIS_RPC_URL }} | ||
| ARBITRUM_ONE_RPC_URL: ${{ secrets.ARBITRUM_ONE_RPC_URL }} | ||
| BASE_RPC_URL: ${{ secrets.BASE_RPC_URL }} | ||
| OPTIMISM_RPC_URL: ${{ secrets.OPTIMISM_RPC_URL }} | ||
| POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }} | ||
| BNB_MAINNET_RPC_URL: ${{ secrets.BNB_MAINNET_RPC_URL }} | ||
| PLASMA_RPC_URL: ${{ secrets.PLASMA_RPC_URL }} | ||
| AVALANCHE_RPC_URL: ${{ secrets.AVALANCHE_RPC_URL }} | ||
| INK_RPC_URL: ${{ secrets.INK_RPC_URL }} | ||
| LINEA_RPC_URL: ${{ secrets.LINEA_RPC_URL }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # action v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
| submodules: recursive | ||
| - uses: ./.github/actions/setup | ||
| - name: Test | ||
| run: just test | ||
| run: just test --gas-snapshot-check true | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment below on Justfile |
||
| - name: Coverage | ||
| run: just coverage-check | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| [submodule "lib/forge-std"] | ||
| path = lib/forge-std | ||
| url = https://github.com/foundry-rs/forge-std | ||
| [submodule "lib/openzeppelin-contracts"] | ||
| path = lib/openzeppelin-contracts | ||
| url = https://github.com/OpenZeppelin/openzeppelin-contracts |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,16 +59,16 @@ slither: | |
| PATH="$PWD/{{NPM_BIN}}:$PATH" uv run --project dev slither src --config-file slither.config.json | ||
|
|
||
| # Run tests | ||
| test: | ||
| {{FORGE}} test -vvv --show-progress --gas-snapshot-check true | ||
| test *args: | ||
| {{FORGE}} test -vvv --show-progress {{args}} | ||
|
|
||
| # Print coverage summary | ||
| coverage-summary: | ||
| {{FORGE}} coverage --no-match-coverage "^(test|script)/" --report summary | ||
| {{FORGE}} coverage --no-match-coverage "^(test|script|lib)/" --report summary | ||
|
|
||
| # Generate lcov coverage report | ||
| coverage-lcov: | ||
| {{FORGE}} coverage --no-match-coverage "^(test|script)/" --report lcov | ||
| {{FORGE}} coverage --no-match-coverage "^(test|script|lib)/" --report lcov | ||
|
Comment on lines
-62
to
+71
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added these modifications to the Basically:
|
||
|
|
||
| # Fail if the minimum of all four coverage metrics (lines/statements/branches/funcs) on the `Total` row is below `COVERAGE_MIN` (default `100`) | ||
| coverage-check: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,11 @@ | ||
| { | ||
| "lib/forge-std": { | ||
| "rev": "1801b0541f4fda118a10798fd3486bb7051c5dd6" | ||
| }, | ||
| "lib/openzeppelin-contracts": { | ||
| "tag": { | ||
| "name": "v5.6.1", | ||
| "rev": "5fd1781b1454fd1ef8e722282f86f9293cacf256" | ||
| } | ||
| } | ||
| } |
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added for mocks and possibly other utilities for testing. Isn't used in |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| { | ||
| "arbitrum - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "arbitrum - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "avalanche - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "avalanche - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "base - delegated call - simple WETH -> USDC order attempt": "15434", | ||
| "base - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "bnb - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "bnb - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "ethereum - delegated call - simple WETH -> USDC order attempt": "15439", | ||
| "ethereum - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "gnosis - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "gnosis - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "historical order - USDC -> EURA - delegated call": "190277", | ||
| "historical order - USDC -> EURA - direct call": "186425", | ||
| "historical order - USDC permit -> MOG - delegated call": "446922", | ||
| "historical order - USDC permit -> MOG - direct call": "443150", | ||
| "historical order - USDT -> AAVE - delegated call": "783333", | ||
| "historical order - USDT -> AAVE - direct call": "779746", | ||
| "historical order - WETH -> USDC - delegated call": "253798", | ||
| "historical order - WETH -> USDC - direct call": "249951", | ||
| "historical order - YFI -> USDC - delegated call": "814481", | ||
| "historical order - YFI -> USDC - direct call": "811173", | ||
| "ink - delegated call - simple WETH -> USDC order attempt": "15434", | ||
| "ink - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "linea - delegated call - simple WETH -> USDC order attempt": "15434", | ||
| "linea - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "optimism - delegated call - simple WETH -> USDC order attempt": "15439", | ||
| "optimism - direct call - simple WETH -> USDC order attempt": "11449", | ||
| "plasma - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "plasma - direct call - simple WETH -> USDC order attempt": "11450", | ||
| "polygon - delegated call - simple WETH -> USDC order attempt": "15438", | ||
| "polygon - direct call - simple WETH -> USDC order attempt": "11450" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "delegated submission - reverts - UnauthorizedCaller": "460", | ||
| "delegated submission - success - interactions across phases": "44663", | ||
| "delegated submission - success - large settlement with interactions": "114609", | ||
| "delegated submission - success - small settlement": "24071", | ||
| "direct submission - success - interactions across phases": "155237", | ||
| "direct submission - success - large settlement with interactions": "222656", | ||
| "direct submission - success - small settlement": "115158" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "constructor - success - distinct callers": "1212494", | ||
| "constructor - success - duplicate callers": "1212494", | ||
| "constructor - success - zero address callers": "1212494", | ||
| "delegate fallback - reverts - custom error": "4398", | ||
| "delegate fallback - reverts - empty revert data": "3753", | ||
| "delegate fallback - reverts - non-empty revert data": "3828", | ||
| "delegate fallback - reverts - panic": "3405", | ||
| "delegate fallback - reverts - sending ETH to nonpayable target": "9875", | ||
| "delegate fallback - reverts - string error": "4057", | ||
| "delegate fallback - reverts - unauthorized caller": "460", | ||
| "delegate fallback - success - approved caller slot 0 forwards payload": "21184", | ||
| "delegate fallback - success - approved caller slot 1 forwards payload": "23430", | ||
| "delegate fallback - success - approved caller slot 2 forwards payload": "23490", | ||
| "delegate fallback - success - approved caller slot 3 forwards payload": "23550", | ||
| "delegate fallback - success - approved caller slot 4 forwards payload": "23576", | ||
| "delegate fallback - success - packed calldata bubbles return data": "3767", | ||
| "delegate fallback - success - packed calldata forwards zero ETH": "23749", | ||
| "delegate fallback - success - target has no code": "3131", | ||
| "delegate fallback - success - target is zero address": "631" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| { | ||
| "rules": { | ||
| "func-name-mixedcase": "off", | ||
| "gas-strict-inequalities": "off", | ||
| "no-empty-blocks": "off", | ||
| "use-natspec": "off" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| // SPDX-License-Identifier: MIT OR Apache-2.0 | ||
| pragma solidity ^0.8.34; | ||
|
igorroncevic marked this conversation as resolved.
|
||
|
|
||
| import {Test} from "forge-std/Test.sol"; | ||
|
|
||
| import {Solver7702Delegate} from "src/Solver7702Delegate.sol"; | ||
|
|
||
| struct ApprovedCallers { | ||
| /// @notice First approved caller slot. | ||
| address first; | ||
| /// @notice Second approved caller slot. | ||
| address second; | ||
| /// @notice Third approved caller slot. | ||
| address third; | ||
| /// @notice Fourth approved caller slot. | ||
| address fourth; | ||
| /// @notice Fifth approved caller slot. | ||
| address fifth; | ||
| } | ||
|
|
||
| /// @notice Shared setup and helpers for Solver7702Delegate tests. | ||
| abstract contract BaseTest is Test { | ||
| /// @notice Private key for the EOA that gets EIP-7702 delegation attached. | ||
| uint256 internal constant SOLVER_PRIVATE_KEY = uint256(keccak256("SOLVER_PRIVATE_KEY")); | ||
| /// @notice ETH value used by tests that forward native token value. | ||
| uint256 internal constant MSG_VALUE = 1 ether; | ||
| /// @notice Number of bytes used to encode the packed target address. | ||
| uint256 internal constant PACKED_TARGET_LENGTH = 20; | ||
| /// @notice Shared token and mock settlement amount. | ||
| uint256 internal constant TEST_AMOUNT = 100 ether; | ||
| /// @notice Shared order UID used by mock settlement tests. | ||
| bytes32 internal constant TEST_ORDER_UID = keccak256("TEST_ORDER_UID"); | ||
| /// @notice Selector for RawRevert(uint256,string). | ||
| bytes4 internal constant RAW_REVERT_SELECTOR = bytes4(keccak256("RawRevert(uint256,string)")); | ||
|
|
||
| /// @notice Shared solver address. | ||
| address internal solver; | ||
| /// @notice Shared recipient address. | ||
| address internal recipient; | ||
| /// @notice Shared unauthorized caller address. | ||
| address internal unauthorizedCaller; | ||
| /// @notice Shared approved callers. | ||
| ApprovedCallers internal approvedCallers; | ||
| /// @notice Shared delegate contract. | ||
| Solver7702Delegate internal delegateContract; | ||
|
|
||
| /// @notice Creates the default solver, approved callers, and delegate contract. | ||
| function setUp() public virtual { | ||
| solver = vm.addr(SOLVER_PRIVATE_KEY); | ||
| recipient = makeAddr("RECIPIENT"); | ||
| unauthorizedCaller = makeAddr("UNAUTHORIZED_CALLER"); | ||
| approvedCallers = ApprovedCallers({ | ||
| first: makeAddr("APPROVED_CALLER_0"), | ||
| second: makeAddr("APPROVED_CALLER_1"), | ||
| third: makeAddr("APPROVED_CALLER_2"), | ||
| fourth: makeAddr("APPROVED_CALLER_3"), | ||
| fifth: makeAddr("APPROVED_CALLER_4") | ||
| }); | ||
|
|
||
| delegateContract = new Solver7702Delegate( | ||
| [ | ||
| approvedCallers.first, | ||
| approvedCallers.second, | ||
| approvedCallers.third, | ||
| approvedCallers.fourth, | ||
| approvedCallers.fifth | ||
| ] | ||
| ); | ||
| } | ||
|
|
||
| /// @notice Encodes the delegate fallback calldata as a 20-byte target followed by payload. | ||
| function _packedCalldata(address target, bytes memory payload) internal pure returns (bytes memory) { | ||
| return abi.encodePacked(bytes20(target), payload); | ||
| } | ||
|
|
||
| /// @notice Attaches the delegate code to the solver EOA. | ||
| function _attachDelegation(uint256 solverPrivateKey) internal { | ||
| vm.signAndAttachDelegation(address(delegateContract), solverPrivateKey); | ||
| } | ||
|
|
||
| /// @notice Decodes and checks the return data from PayableFallbackTarget. | ||
| function _assertFallbackReturn( | ||
| bytes memory returnData, | ||
| address expectedSender, | ||
| uint256 expectedValue, | ||
| bytes memory expectedPayload, | ||
| uint256 expectedBalance | ||
| ) internal pure { | ||
| (address sender, uint256 value, bytes memory payload, uint256 balance) = | ||
| abi.decode(returnData, (address, uint256, bytes, uint256)); | ||
|
|
||
| assertEq(sender, expectedSender); | ||
| assertEq(value, expectedValue); | ||
| assertEq(payload, expectedPayload); | ||
| assertEq(balance, expectedBalance); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Supported sample tests for all networks just to be sure ERC-7702 is present on all of them and generally as a sanity check.