-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
feat(coverage): library support #3128
Conversation
Taking the link references makes it impossible to link the object, which broke calls to external library functions
Attempt at collecting calls to libraries without using the strongly typed AST in ethers-rs until I find a less fragile way to implement that This *should* catch most library calls, but some edge cases need to be tested: - Referencing across files - Referencing with an alias - Calls to libraries that have been bound using `using for`
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.
lgtm!
@transmissions11 wanna give this a spin? |
Some feedbackI wanted to make a simple contract that exposes library functions for coverage to pick up. The following approaches do not work. The reported coverage for the library is 0%:
This approach works:
This also works, but is not useful in testing:
|
@onbjerg suspect we're not catching the typedef in the function sig? |
I think we're just not walking the expression on the right side of an assignment |
Should we track this in a separate ticket for followup? |
* fix(coverage): fix dummy linking Taking the link references makes it impossible to link the object, which broke calls to external library functions * feat(coverage): collect library calls Attempt at collecting calls to libraries without using the strongly typed AST in ethers-rs until I find a less fragile way to implement that This *should* catch most library calls, but some edge cases need to be tested: - Referencing across files - Referencing with an alias - Calls to libraries that have been bound using `using for` * fix(coverage): base contract determinism
## Summary * Deposit USDC into the Lending contract and create balance ## Details * Update to `handleAdjustment`: add manager check * the `deposit` function simply convert token amount => 18 decimals, and update that value in `Account`. * Add `DecimalMath` library that convert decimals for `uint256` * in `DecimalMathTest` test: it needs to setup a "helper contract" to let the forge coverage work properly with internal library. ([reference](foundry-rs/foundry#3128 (comment))) ## Todo - [x] decimal conversion for `deposit` - [x] Unit tests for `deposit` - [x] 100% coverage for `deposit` and `convertDecimals` ## Checklist Ensure you completed **all of the steps** below before submitting your pull request: - [x] Add [natspec](https://docs.soliditylang.org/en/latest/natspec-format.html) for all functions / parameters - [x] Ran `forge snapshot` - [x] Ran `forge fmt` - [x] Ran `forge test` - [x] [Triage Slither issues](../README.md#triage-issues), and post uncertain ones in the PR - [x] 100% test coverage on code changes ### Slither Issues (Optional) If you're unsure about a new issue reported by Slither, copy them here so others can verify as well.
Definitely. Opened an issue here: |
**Motivation:** Currently the coverage report for the Checkpoints Library shows up as 0%. We need to fix it by refactoring the Checkpoints Mock in `Checkpoints.t.sol` as stated in foundry-rs/foundry#3128 (comment) **Modifications:** * Refactoring Checkpoints Mock from: ``` contract LibHelper { function increment(uint256 a) external returns (uint256 r) { r = Lib.increment(a); } } ``` to ``` contract LibHelper { function increment(uint256 a) external returns (uint256) { uint256 r = Lib.increment(a); return r; } } ``` * Removing `using for` notation in Checkpoints Mock * Setting coverage threshold back to 80% **Result:** Increased code coverage for Checkpoints Library. Closes #184
**Motivation:** Currently the coverage report for the Checkpoints Library shows up as 0%. We need to fix it by refactoring the Checkpoints Mock in `Checkpoints.t.sol` as stated in foundry-rs/foundry#3128 (comment) **Modifications:** * Refactoring Checkpoints Mock from: ``` contract LibHelper { function increment(uint256 a) external returns (uint256 r) { r = Lib.increment(a); } } ``` to ``` contract LibHelper { function increment(uint256 a) external returns (uint256) { uint256 r = Lib.increment(a); return r; } } ``` * Removing `using for` notation in Checkpoints Mock * Setting coverage threshold back to 80% **Result:** Increased code coverage for Checkpoints Library. Closes #184
Motivation
Adds coverage support for libraries, of which there are two types:
delegatecall
operations from the user of the libraryOf course some libraries may be a mix.
For the first type of libraries, we were already kind of supporting it except we needed to replace all library address placeholders with a dummy address in order to produce a valid bytecode we can analyze. This was added previously but a minor error in the implementation made it non functional.
For internal libraries we need to walk through the AST of contracts that use them and find calls to the library. This is not super trivial to do since there are many ways to use libraries - calling them directly, importing them using an alias, using
using for
etc.At first I wanted to finish the strongly typed AST in ethers-rs, but I've become somewhat uncertain that it's a good idea for now since breaking changes in unrelated parts of the AST might render coverage completely unusable for new versions of Solidity, and I haven't found a good way around that yet.
Solution
FunctionCall
nodes where theexpression
attribute of those nodes are aMemberAccess
node.This does not currently handle cases where
using for
is used for internal libraries since it seems like we lose information on what libraries were bound to what types..Ref #2567
This PR can be validated with the updated tests I've added to https://github.com/onbjerg/forge-coverage-test (or the report can be viewed here https://f3128.tiiny.site/), note that the
using for
test case shows up as uncovered (InternalLibrary.subPlusOne
) even though it is covered (called from the contract inContract2.sol
).