Comments (10)
cc @klkvr
from foundry.
expectRevert
expects the next frame to revert. delegatecalls to a library is a frame as well
In your case getNumeratorC512
is a public function thus it is getting dispatched as a delegatecall and expectRevert
works correctly.
However, calculate_c512
is an internal function which is getting inlined into a contract and no delegatecall is performed when it invoked (which can be seen in traces), thus the first frame seen by expectRevert
is invocation of mul512x256
This is interesting though as I would expect invocation of getNumeratorC512
in calculate_c512
to perform a delegatecall, but it seems that if public
library function is invoked in internal
function of the same library, it will cause public fn to get inlined as well, which is weird as it would cause duplicating bytecode being deployed in both library and contract using it
from foundry.
Hm. That's a good find because I had forgotten about the mixed visibilities I had there. However, the only reason I started to make the other functions public was because the issue was already there when there was only 1 function calculate_c512
, and I was not able to spot the problem thinking the error was in my code, so I made the other helper functions and made the library a regular contract at some point. Anyways, long story short, I tried making all the functions in library_A internal to test your point, so now getNumeratorC512
and calculate_c512
are both internal. I still have the same issue.
from foundry.
@oscarsernarosero mind sharing logs?
from foundry.
sure!
Traces:
[14421] CofN512FuzzTests::testEquations_CofN512_CalculateNumeratorFuzz(4136799322481705091955576 [4.136e24], 134193314344108 [1.341e14], 100000000000000000 [1e17], 0)
├─ [0] console::log("Bound Result", 4136799322481705091955576 [4.136e24]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound Result", 134193314344108 [1.341e14]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound Result", 100000000000000000 [1e17]) [staticcall]
│ └─ ← [Stop]
├─ [392] MathLibraryAbstractionLayer::mul256x256(4136799322481705091955576 [4.136e24], 4136799322481705091955576 [4.136e24]) [delegatecall]
│ └─ ← [Return] 17113108634485094279843588697454873929987957491776 [1.711e49], 0
├─ [505] MathLibraryAbstractionLayer::mul512x256(8556554317242547139921794348727436964993978745888 [8.556e48], 0, 134193314344108 [1.341e14]) [delegatecall]
│ └─ ← [Return] 1148232383196163535505025695706415258810544877106422631122027904 [1.148e63], 0
├─ [0] VM::expectRevert(ResultBelowPMin())
│ └─ ← [Return]
├─ [392] MathLibraryAbstractionLayer::mul256x256(4136799322481705091955576 [4.136e24], 4136799322481705091955576 [4.136e24]) [delegatecall]
│ └─ ← [Return] 17113108634485094279843588697454873929987957491776 [1.711e49], 0
└─ ← [Revert] call did not revert as expected
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.82s (2.81s CPU time)
This is calling getNumeratorC512
from foundry.
Traces:
[14456] CofN512FuzzTests::testEquations_CofN512_CalculateCFuzz(4136799322481705091955576 [4.136e24], 134193314344108 [1.341e14], 100000000000000000 [1e17], 0)
├─ [0] console::log("Bound Result", 4136799322481705091955576 [4.136e24]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound Result", 134193314344108 [1.341e14]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound Result", 100000000000000000 [1e17]) [staticcall]
│ └─ ← [Stop]
├─ [392] MathLibraryAbstractionLayer::mul256x256(4136799322481705091955576 [4.136e24], 4136799322481705091955576 [4.136e24]) [delegatecall]
│ └─ ← [Return] 17113108634485094279843588697454873929987957491776 [1.711e49], 0
├─ [505] MathLibraryAbstractionLayer::mul512x256(8556554317242547139921794348727436964993978745888 [8.556e48], 0, 134193314344108 [1.341e14]) [delegatecall]
│ └─ ← [Return] 1148232383196163535505025695706415258810544877106422631122027904 [1.148e63], 0
├─ [0] VM::expectRevert(ResultBelowPMin())
│ └─ ← [Return]
├─ [392] MathLibraryAbstractionLayer::mul256x256(4136799322481705091955576 [4.136e24], 4136799322481705091955576 [4.136e24]) [delegatecall]
│ └─ ← [Return] 17113108634485094279843588697454873929987957491776 [1.711e49], 0
└─ ← [Revert] call did not revert as expected
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.83s (2.82s CPU time)
This is calling calculate_c512
.
So it looks like you are into something here because now both calls fail. This is still not the desired behavior, but the function visibility definitely was causing one to fail the test and the other to pass. At least now both fail the test.
from foundry.
ah so right now when both functions are internal they are both getting inlined, thus first frame created with invocation of those fn is a MathLibraryAbstractionLayer
delegatecall which does not revert
to test this you can either make both functions public so that each of them creates a new frame when invoked
also you can create a wrapper around them for testing or just a helper function on a test contract
for example
function calculate_c512(uint256 Xn, uint256 Sn, uint256 DnL, uint256 DnH) internal pure returns (uint256 Cn) {
Xn.getNumeratorC512(Sn, DnL, DnH);
}
function test(....) public {
vm.expectRevert(...);
this.calculate_c512(...)
}
from foundry.
Yeah that would totally work. I do think Forge test should be smart enough to handle this tho.
from foundry.
unfortunately after compiler optimizations it is really hard to tell whether certain bytecode corresponds to an internal library, handling this is non-trivial just as handling reverts in internal contract functions for example
from foundry.
Ok I see. Thank you for your time @klkvr. This definitely helped me understand my issue even though it seems to be now in my hands to handle this kind of situations.
from foundry.
Related Issues (20)
- Contract verification failed with `create` command when library specified
- Smart app control has blocked part of this app.. no foundry for windows any more HOT 3
- Environment variable, ETH_RPC_URL, is not being picked up by forge script HOT 3
- Add serializeUintQuantity cheatcode HOT 6
- bug(cast): resolve-name and lookup-address ENS commands do not work HOT 1
- Support for foundry plugins written in Rust
- Support for flamegraph
- add `--background` and `stop` to allow anvil to run in the background HOT 2
- Regression: cast call results in execution reverted on local test network HOT 2
- anvil: problems with estimate gas - max fee per gas less than block base fee HOT 4
- Can't deploy contracts
- Anvil panic crash on eth_estimategas
- `vm.print` to replace `console.log` library
- Member "rpc" not found HOT 1
- Fee history ignores block count HOT 1
- deleteFork cheatcode HOT 3
- `forge coverage` produces incorrect output
- vm.expectRevert results in: panic: array out-of-bounds access (0x32) HOT 2
- Gas estimation when using the keystore is too high HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from foundry.