Skip to content
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

Improve test coverage action [@coderabbit ignore] #790

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e4c5947
Add Permit2Proxy
ezynda3 Aug 22, 2024
797e772
Add Permit2Proxy
ezynda3 Aug 22, 2024
48b9703
forge install: Permit2
ezynda3 Aug 22, 2024
9795b16
Get basic test working...
ezynda3 Aug 23, 2024
745c5c7
Add more basic tests
ezynda3 Aug 26, 2024
e186436
Remove superfluous receiver param
ezynda3 Aug 26, 2024
143d4c2
Add utility method for getting a valid and working msgHash to sign
ezynda3 Aug 26, 2024
779bd8b
Change name to be more specific
ezynda3 Aug 26, 2024
f36a67e
Add Permit "v1" functionality
ezynda3 Aug 26, 2024
48de477
Add Permit "v1" tests
ezynda3 Aug 26, 2024
d119ca9
Add missing comments
ezynda3 Aug 26, 2024
484c918
Flesh out demo script
ezynda3 Aug 26, 2024
f582cbc
Finish demo script
ezynda3 Aug 27, 2024
9785369
Cleanup and comments
ezynda3 Aug 27, 2024
4cd03e0
Fix log
ezynda3 Aug 27, 2024
f18dab6
Remove extra files
ezynda3 Aug 27, 2024
0eaa7c8
Remove extra remapping
ezynda3 Aug 27, 2024
a3e6f5d
Remove unneeded lib
ezynda3 Aug 27, 2024
cfd1977
Add official Permit2 addresses
ezynda3 Aug 27, 2024
db2f0ff
Merge branch 'main' into gasless-revisited
ezynda3 Aug 28, 2024
e7395b2
Allow only signer to call using EIP2612
ezynda3 Aug 29, 2024
8364ac7
Merge branch 'gasless-revisited' of github.com:lifinance/contracts in…
ezynda3 Aug 29, 2024
5d772b0
Bind Permit2Proxy to a single diamond
ezynda3 Aug 29, 2024
2f8e953
Update deploy script
ezynda3 Aug 29, 2024
3d39c31
Implement non-gasless Permit2 flow
ezynda3 Aug 29, 2024
af38e51
Redeploy to staging and update demo script
ezynda3 Aug 29, 2024
056a8c2
Update comments and remove unneeded events/errors
ezynda3 Aug 30, 2024
1755f86
Add utility methods for determining the next valid nonce
ezynda3 Aug 30, 2024
17e5da3
Redeploy and update demo script
ezynda3 Aug 30, 2024
476ba04
Add documentation
ezynda3 Aug 30, 2024
10b6204
Fixes
ezynda3 Sep 2, 2024
f5f566d
Change witness type to be consistent with the rest of the codebase
ezynda3 Sep 3, 2024
be50801
Remove unneeded whitelist
ezynda3 Sep 3, 2024
e40f49a
Merge branch 'main' of github.com:lifinance/contracts into gasless-re…
0xDEnYO Sep 6, 2024
2202a50
test
0xDEnYO Sep 6, 2024
6f86400
test
0xDEnYO Sep 6, 2024
1aa3287
test
0xDEnYO Sep 6, 2024
c75b982
test
0xDEnYO Sep 6, 2024
b27f938
test
0xDEnYO Sep 6, 2024
26fa4ea
test
0xDEnYO Sep 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 32 additions & 14 deletions .github/workflows/enforceTestCoverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: Enforce Min Test Coverage

on:
pull_request:
types: [opened, synchronize, reopened]
types: [opened, synchronize, reopened, ready_for_review]

jobs:
enforce-min-test-coverage:
Expand All @@ -27,6 +27,8 @@ jobs:
MIN_TEST_COVERAGE: 74 # = 74% line coverage
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0 ##### Fetch all history for all branches

- name: Set up Node.js
uses: actions/setup-node@v4
Expand Down Expand Up @@ -54,12 +56,20 @@ jobs:

echo "Coverage report successfully filtered"

- name: Generate Coverage Summary
# Step to get modified or added files in the src/ folder
- name: Get Modified Files
id: get_modified_files
run: |
# Get list of modified or added files in src directory
MODIFIED_FILES=$(git diff --name-only --diff-filter=AM origin/main | grep '^src/.*\.sol$')
echo "modified_files=$MODIFIED_FILES" >> "$GITHUB_ENV"
Comment on lines +59 to +65
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve the script for fetching modified files.

The script uses git diff to fetch modified or added Solidity files. However, it's crucial to ensure that the base branch (origin/main) is up-to-date to avoid missing any recent changes. Consider adding a git fetch step before this to ensure accuracy.

+ git fetch origin main
  MODIFIED_FILES=$(git diff --name-only --diff-filter=AM origin/main | grep '^src/.*\.sol$')

Committable suggestion was skipped due to low confidence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are checking out the repo in an earlier step in the same file, is it not automatically ensured that we have the latest version?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xDEnYO, the actions/checkout step does indeed clone the repository, but it doesn't automatically fetch the latest changes from the remote base branch (origin/main). By default, it only fetches the latest commit of the branch being checked out. Therefore, to ensure that the git diff command compares against the most up-to-date version of origin/main, it's recommended to add a git fetch step before running the git diff command. This will ensure that any recent changes to origin/main are included in the comparison.

Let me know if you need further clarification!


- name: Generate Coverage Summary
run: |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address shellcheck warnings in the script.

Static analysis has flagged several issues:

  • SC2206: Ensure that arrays are handled correctly to prevent word splitting.
  • SC2199 and SC2076: Improve regex handling in conditional checks.

These issues can lead to unexpected behavior and should be corrected.

- MODIFIED_FILES=(${MODIFIED_FILES})
+ read -r -a MODIFIED_FILES <<< "$MODIFIED_FILES"

- if [[ " ${MODIFIED_FILES[@]} " =~ "$FILE_NAME" ]]; then
+ if [[ " ${MODIFIED_FILES[*]} " =~ $FILE_NAME ]]; then

Committable suggestion was skipped due to low confidence.

Tools
actionlint

68-68: shellcheck reported issue in this script: SC2206:warning:4:17: Quote to prevent word splitting/globbing, or split robustly with mapfile or read -a

(shellcheck)


68-68: shellcheck reported issue in this script: SC2199:error:47:11: Arrays implicitly concatenate in [[ ]]. Use a loop (or explicit * instead of @)

(shellcheck)


68-68: shellcheck reported issue in this script: SC2076:warning:47:39: Remove quotes from right-hand side of =~ to match as a regex rather than literally

(shellcheck)


# Path to the lcov info file
LCOV_FILE="lcov-filtered.info"
MODIFIED_FILES=(${MODIFIED_FILES})

# Initialize counters
TOTAL_LINES_FOUND=0
Expand All @@ -69,14 +79,23 @@ jobs:
TOTAL_BRANCHES_FOUND=0
TOTAL_BRANCHES_HIT=0

# Clear the per-file coverage report file
echo "" > per_file_coverage_report.txt

# Read through the lcov file
while IFS= read -r line; do
case $line in
SF:*)
CURRENT_FILE=${line#SF:}
FILE_NAME=$(basename "$CURRENT_FILE")
;;
LF:*)
TOTAL_LINES_FOUND=$((TOTAL_LINES_FOUND + ${line#LF:}))
FILE_LINES_FOUND=${line#LF:}
;;
LH:*)
TOTAL_LINES_HIT=$((TOTAL_LINES_HIT + ${line#LH:}))
FILE_LINES_HIT=${line#LH:}
;;
FNF:*)
TOTAL_FUNCTIONS_FOUND=$((TOTAL_FUNCTIONS_FOUND + ${line#FNF:}))
Expand All @@ -91,6 +110,16 @@ jobs:
TOTAL_BRANCHES_HIT=$((TOTAL_BRANCHES_HIT + ${line#BRH:}))
;;
esac

# Check if the file is in the list of modified files
if [[ " ${MODIFIED_FILES[@]} " =~ " $FILE_NAME " ]]; then
# Calculate line coverage percentage for the current file
LINE_COVERAGE_PERCENTAGE=$(echo "scale=2; $FILE_LINES_HIT / $FILE_LINES_FOUND * 100" | bc)

# Append the per-file coverage to the report file
echo "File: $FILE_NAME - Line Coverage: $LINE_COVERAGE_PERCENTAGE% ($FILE_LINES_HIT / $FILE_LINES_FOUND)" >> per_file_coverage_report.txt
fi

done < "$LCOV_FILE"

# Calculate percentages with high precision
Expand Down Expand Up @@ -118,7 +147,7 @@ jobs:
exit 1
fi

# Output result_COVERAGE_REPORTs
# Output results
echo "$LINE_COVERAGE_REPORT"
echo "$FUNCTION_COVERAGE_REPORT"
echo "$BRANCH_COVERAGE_REPORT"
Expand All @@ -131,14 +160,3 @@ jobs:
echo "BRANCH_COVERAGE_REPORT=$BRANCH_COVERAGE_REPORT"
echo "RESULT_COVERAGE_REPORT=$RESULT_COVERAGE_REPORT"
} >> "$GITHUB_ENV"

- name: Comment with Coverage Summary in PR
uses: mshick/[email protected]
with:
repo-token: ${{ secrets.GIT_ACTIONS_BOT_PAT_CLASSIC }}
message: |
## Test Coverage Report
${{ env.LINE_COVERAGE_REPORT }}
${{ env.FUNCTION_COVERAGE_REPORT }}
${{ env.BRANCH_COVERAGE_REPORT }}
${{ env.RESULT_COVERAGE_REPORT }}
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
[submodule "lib/solady"]
path = lib/solady
url = https://github.com/Vectorized/solady
[submodule "lib/Permit2"]
path = lib/Permit2
url = https://github.com/Uniswap/Permit2
31 changes: 31 additions & 0 deletions config/permit2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"mainnet": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"arbitrum": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"aurora": "",
"avalanche": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"base": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"blast": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"boba": "",
"bsc": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"celo": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"fantom": "",
"fraxtal": "",
"fuse": "",
"gnosis": "",
"gravity": "",
"immutablezkevm": "",
"linea": "",
"mantle": "",
"metis": "",
"mode": "",
"moonbeam": "",
"moonriver": "",
"optimism": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"polygon": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"polygonzkevm": "",
"rootstock": "",
"scroll": "",
"sei": "",
"taiko": "",
"zksync": "0x0000000000225e31d15943971f47ad3022f714fa"
}
16 changes: 16 additions & 0 deletions deployments/_deployments_log_file.json
Original file line number Diff line number Diff line change
Expand Up @@ -22453,5 +22453,21 @@
]
}
}
},
"Permit2Proxy": {
"arbitrum": {
"staging": {
"1.0.0": [
{
"ADDRESS": "0xA3C7a31a2A97b847D967e0B755921D084C46a742",
"OPTIMIZER_RUNS": "1000000",
"TIMESTAMP": "2024-08-30 14:01:34",
"CONSTRUCTOR_ARGS": "0x000000000000000000000000d3b2b0ac0afdd0d166a495f5e9fca4ecc715a782000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3",
"SALT": "09072024",
"VERIFIED": "true"
}
]
}
}
}
}
3 changes: 2 additions & 1 deletion deployments/arbitrum.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@
"CircleBridgeFacet": "0xa73a8BC8d36472269138c3233e24D0Ee0c344bd8",
"HopFacetOptimized": "0xf82135385765f1324257ffF74489F16382EBBb8A",
"LiFuelFeeCollector": "0x94EA56D8049e93E0308B9c7d1418Baf6A7C68280",
"TokenWrapper": "0xF63b27AE2Dc887b88f82E2Cc597d07fBB2E78E70"
"TokenWrapper": "0xF63b27AE2Dc887b88f82E2Cc597d07fBB2E78E70",
"Permit2Proxy": "0xA3C7a31a2A97b847D967e0B755921D084C46a742"
}
126 changes: 126 additions & 0 deletions docs/Permit2Proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Permit2 Proxy

## Description

Periphery contract which enables gasless and semi-gasless transaction flows
enabled through ERC20 Permit and Uniswap's Permit2

## How To Use

The contract has a number of methods for making gasless and semi-gasless calls
as well as a few helpful utility methods.

The following methods are available:

This method is used to execute a transaction where the approval is granted
using an ERC20 Permit signature. It can only be called by the signer in order
to prevent front-running attacks.

```solidity
/// @notice Allows to bridge tokens through a LI.FI diamond contract using
/// an EIP2612 gasless permit (only works with tokenAddresses that
/// implement EIP2612) (in contrast to Permit2, calldata and diamondAddress
/// are not signed by the user and could therefore be replaced by the user)
/// Can only be called by the permit signer to prevent front-running.
/// @param tokenAddress Address of the token to be bridged
/// @param amount Amount of tokens to be bridged
/// @param deadline Transaction must be completed before this timestamp
/// @param v User signature (recovery ID)
/// @param r User signature (ECDSA output)
/// @param s User signature (ECDSA output)
/// @param diamondCalldata Address of the token to be bridged
function callDiamondWithEIP2612Signature(
address tokenAddress,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s,
bytes calldata diamondCalldata
) public payable
````

This method is used to execute a transaction where the approval is granted via
Uniswap's Permit2 contract. It can only be called by the signer in order to
prevent front-running attacks.

```solidity
/// @notice Allows to bridge tokens of one type through a LI.FI diamond
/// contract using Uniswap's Permit2 contract and a user signature
/// that verifies allowance. The calldata can be changed by the
/// user. Can only be called by the permit signer to prevent
/// front-running.
/// @param _diamondCalldata the calldata to execute
/// @param _permit the Uniswap Permit2 parameters
/// @param _signature the signature giving approval to transfer tokens
function callDiamondWithPermit2(
bytes calldata _diamondCalldata,
ISignatureTransfer.PermitTransferFrom calldata _permit,
bytes calldata _signature
) external payable
```

This method enables a gasless flow by allowing a user to sign a Uniswap Permit2
message hash which includes a "witness" type. This extra type restricts which
calldata can be called during execution and cannot be changed. Anyone with the
signature can execute the transaction on behalf of the signer.

```solidity
/// @notice Allows to bridge tokens of one type through a LI.FI diamond
/// contract using Uniswap's Permit2 contract and a user signature
/// that verifies allowance, diamondAddress and diamondCalldata
/// @param _diamondCalldata the calldata to execute
/// @param _signer the signer giving permission to transfer tokens
/// @param _permit the Uniswap Permit2 parameters
/// @param _signature the signature giving approval to transfer tokens
function callDiamondWithPermit2Witness(
bytes calldata _diamondCalldata,
address _signer,
ISignatureTransfer.PermitTransferFrom calldata _permit,
bytes calldata _signature
) external payable
```

There are a few utility methods to make it easier to generate the necessary
signature for the gasless flow.

Calling this method will return a valid message hash that can then be signed
in order to be executed later by another wallet.

```solidity
/// @notice utitlity method for constructing a valid Permit2 message hash
/// @param _diamondCalldata the calldata to execute
/// @param _assetId the address of the token to approve
/// @param _amount amount of tokens to approve
/// @param _nonce the nonce to use
/// @param _deadline the expiration deadline
function getPermit2MsgHash(
bytes calldata _diamondCalldata,
address _assetId,
uint256 _amount,
uint256 _nonce,
uint256 _deadline
) external view returns (bytes32 msgHash)
```

Permit2 nonces are non-sequential and are a bit complicated to work with. The
following utility methods allow you to fetch the next valid nonce or sequence
of nonces for use when generating Permit2 signatures.

```solidity
/// @notice Finds the next valid nonce for a user, starting from 0.
/// @param owner The owner of the nonces
/// @return nonce The first valid nonce starting from 0
function nextNonce(address owner) external view returns (uint256 nonce)

/// @notice Finds the next valid nonce for a user, after from a given nonce.
/// @dev This can be helpful if you're signing multiple nonces in a row and
/// need the next nonce to sign but the start one is still valid.
/// @param owner The owner of the nonces
/// @param start The nonce to start from
/// @return nonce The first valid nonce after the given nonce
function nextNonceAfter(
address owner,
uint256 start
) external view returns (uint256 nonce)
```
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@
- [FeeCollector](./FeeCollector.md)
- [Receiver](./Receiver.md)
- [RelayerCelerIM](./RelayerCelerIM.md)
- [Permit2Proxy](./Permit2Proxy.md)
1 change: 1 addition & 0 deletions lib/Permit2
Submodule Permit2 added at cc56ad
2 changes: 1 addition & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ celer-network/=lib/sgn-v2-contracts/
create3-factory/=lib/create3-factory/src/
solmate/=lib/solmate/src/
solady/=lib/solady/src/

permit2/=lib/Permit2/src/
ds-test/=lib/ds-test/src/
forge-std/=lib/forge-std/src/

Expand Down
Loading
Loading