Modularize forge-std - #126
Conversation
891cc2b to
5ba6127
Compare
|
In general some cleanup and modularity seems good to me. I haven't looked closely at this yet, but just commenting to say that if we're going to a big refactor like this there's some other things we should consider including. Namely, splitting I wrote up some of this this in #78, I'll need to review that to see if I still agree with it 😅 As a side note, thanks for all the recent issues/PRs to forge-std! 🙌 |
Yep, happy to move this to another bigger PR if appropriate. Alternatively, happy to split this PR into its constituent components so reviewing each proposal is easier.
That would be cool!
Very glad that I can help. |
|
fwiw this is how it used to be structured, but from a dev UX standpoint, it seemed monolithic was generally better. I am sympathetic to wanting to modularize, and as long as basically all normal users can still import a single test contract and it be clean (single inherit, no cc @gakonst |
My proposal would still be "monolithic" for the end user - it's just that we internally would maintain the
Yeah that wouldn't be cool. |
There was a problem hiding this comment.
I'm very supportive of making Forge Std modular to allow for maximal interoperability. It'd be great to standardize more things about testing in Solidity / frameworks, but that's out of scope of this PR, of course.
I just took a look at the changes and have a few questions.
One suggestion I have is to modularize every part of Forge Std (Std Errors, etc) and then just import them in Test.
Notes:
- We should make a new release before implementing these changes
- The
tipstd-cheat, which was deprecated, is removed
+1 for keeping naming simple with Cheats, Storage, etc!
| using stdStorage for StdStorage; | ||
|
|
||
| StdStorage private stdstore; | ||
| Vm private constant vm_cheats = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); |
There was a problem hiding this comment.
this should be inherited
| Vm private constant vm_cheats = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); | |
| Vm internal constant vm_cheats = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); |
There was a problem hiding this comment.
You mean inherited in Test?
The problem with marking it as internal is that there would be collisions with the third-party testing frameworks which need to also define vm such that that framework can used independently of forge-std (for example, I define vm in PRBTest).
I suggest leaving it as private. Forge Std already redeclares the vm in Test.
There was a problem hiding this comment.
I think a good approach to enabling composability long-term may be for individual components (Cheats, etc) to provide only the functionality they are made for.
E.g. Cheats should expose std-cheats; not vm because it's a Forge thing and not a feature of Cheats. This will also prevent collisions when composing, and some devs might come up with interesting combinations we cannot foresee.
Additionally, every component should be a self-contained unit, with its own private vm and stdstore if it needs it, so it does not depend on another component. I don't think that would be too much hassle.
Specifically made end-user contracts, such as Test and Script can expose vm and stdstore.
There was a problem hiding this comment.
Very much agree with @ZeroEkkusu's resolution here.
every component should be a self-contained unit, with its own private
vmandstdstore
+1
|
Hi @ZeroEkkusu, thanks very much for your review.
I'll work on this and push another commit to this PR.
yep!
Yeah well I have thought that since this introduces breaking changes anyway, we may just be able to delete the |
|
@ZeroEkkusu I have addressed all of your comments. Also, in my recent commit, I have created two new files |
There was a problem hiding this comment.
I left a couple of suggestions.
[Modularize] I'll work on this and push another commit to this PR.
Should we move out the assertions, as well?
The logs can stay inside Test because they are specific to Foundry, no need for a header.
As for bound, I thought we could add it and the utils from Script to Utils.sol, but haven't thought about this much.
Just did it!
Actually, no. I had to move the logs to the newly created
Hah, this was my 2nd proposal from #123. I just did this in the last commit. The only cost was the inability to use |
c92094b to
659cc68
Compare
|
Okay, this is starting to look good! @ZeroEkkusu, I have made the following final touches:
I will work on fixing the git conflicts tomorrow if this also LGT everyone else? |
ZeroEkkusu
left a comment
There was a problem hiding this comment.
It is starting to lg. Thank you for all the effort and patience.
I will work on fixing the git conflicts
I checked today, the conflicts are minimal.
|
Hey @mds1, thanks for your review.
@ZeroEkkusu and I have worked our way up to modularize the code base commit by commit .. besides the original proposals that I made in #122, #123, and #124, there's no central place where all changes are documented. What I will do now though is write a brief spec in my PR comment body at the top - let me know what you think. |
refactor: new category StdUtils refactor: unbundle Test from Script
Mark "vm_cheats" as "private" Instantiate a "vm" in "Test.sol"
refactor: rename "vm_cheats" to just "vm" refactor: rename "vm_std_store" to just "vm" refactor: delete "INT256_MAX" and "UINT256_MAX" revert: redeclare "stdstore" in "Test"
refactor: move "stdMath" to "Math.sol"
Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com>
chore: delete stale "using stdStorage for StdStorage"
refactor: delete "TestBase.sol" refactor: move TestBase in "Test.sol"
ZeroEkkusu
left a comment
There was a problem hiding this comment.
Team, this is the recap of the PR:
- No breaking changes besides the ones we've made deliberately
- The library is now modular
- One gotcha:
DSTestis not flexible and we could not separateIS_TESTfrom the assertions; we inheritedDSTestin bothTestandAssertions
Lgtm.
@mds1, we should consider merging into v0.3.
I will open an issue to track proposals for v0.3.
|
Thanks very much @ZeroEkkusu for your continuous guidance on this PR!
In case you're looking for a list of breaking changes, see my top comment. |
gakonst
left a comment
There was a problem hiding this comment.
Went through the code and the refactor LGTM. Trust you guys above that the user testing makes sense and that there's no critical breaking changes. Would be helpful to document if any.
|
Alright, we're merging this into If Matt finds something is missing, we can make changes in |
* Modularize forge-std (#126) * refactor: unbundle cheats from assertions refactor: new category StdUtils refactor: unbundle Test from Script * Rename "vm" to "vm_cheats" in "Cheats.sol" Mark "vm_cheats" as "private" Instantiate a "vm" in "Test.sol" * refactor: remove deprecated "lowLevelError" refactor: rename "vm_cheats" to just "vm" refactor: rename "vm_std_store" to just "vm" refactor: delete "INT256_MAX" and "UINT256_MAX" revert: redeclare "stdstore" in "Test" * refactor: move "stdErrors" to "Errors.sol" refactor: move "stdMath" to "Math.sol" * Add note about versions in "Errors.sol| Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> * chore: delete stale delineators in Errors and Math chore: delete stale "using stdStorage for StdStorage" * refactor: modularize assertions and utils docs: add NatSpec tag @dev in "console2" refactor: delete log from "bound" function refactor: move "addressFromLast20Bytes" to "Utils.sol" refactor: move "bound" to "Utils.sol" refactor: move "computeCreateAddress" to "Utils.sol" style: move brackets on same line with "if" and "else" in "bound" * Log bound result with static call to `console.log` Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> * fix: reintroduce "vm" in "Script.sol" chore: silence compiler warning in "bound" refactor: define console2.log address as constant in "Utils.sol" * test: move "testGenerateCorrectAddress" to "StdUtils.t.sol" * Nit: remove unnecessary "bytes20" casts * style: add white-spaces in "deal" * fix: readd "deployCode" functions with "val" * Add "computeCreate2Address" utility Rename "testGenerateCorrectAddress" to "testGenerateCreateAddress" * refactor: use "console2" in "Utils.sol" * style: end lines and white spaces * test: drop pragma to ">=0.8.0" in "StdError.t.sol" chore: remove comment about "v0.8.10" in "Errors.sol" * refactor: define "vm" and "stdStorage" in "TestBase" feat: add "Components.sol" file which re-exports everything * fix: inherit from DSTest in Test * feat: ScriptBase refactor: delete "TestBase.sol" refactor: move TestBase in "Test.sol" * ♻️ Make assertions virtual * ♻️ Make deployCode virtual * ✨ (Components) Export consoles * ♻️ (Script) Import Vm * ♻️ Import from Components * ♻️ Make bound view Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> * feat: make `Script` safer (#147) * feat: add `stdStorageSafe` * test(cheats): fix tests `deployCode` tests started failing after 01c60f9 * refactor: make components `abstract` * feat: add `CheatsSafe` * feat: add `VmSafe` * refactor: update `Script` * docs: add license info (#156) * feat: rebrand components (#157) * feat: rebrand components Rename to Std<Component> * fix: StdErrors -> StdError * chore: remove `.DS_Store` * fix: use `ABIEncoderV2` * test: correct test name * fix: add `CommonBase` * refactor: move test dir to root * Revert "refactor: move test dir to root" This reverts commit f21ef1a. * refactor: move test dir to root, update ci accordingly * style: configure and run forge fmt * ci: split into jobs and add fmt job * ci: update name and triggers * ci: remove name field * feat: better bound, ref #188 * fix: bound logs + remove unneeded line * fix: update require strings * refactor: clean up `Test` and `Script` - do not forge fmt Components import - do not import Safe Components in `Test` * fix: udpate bound to match forge's uint edge bias strategy * feat: add interfaces (#193) * chore: update function visibility * feat: add interfaces * fix: fix import * style: consistent spec style * chore: fix find/replace issue Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> * chore: update comments Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Co-authored-by: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> * feat: reimplement `bound` w/ even distribution * build: rename step * Add memory-safe notation so that compiling via-ir can optimize effectively (#196) * test(bound): add even distribution test (#197) * feat: add `assumeNoPrecompiles` (#195) * refactor: use fully-qualified paths instead of relative paths * chore: fix typo * feat: start adding StdChains * feat: start adding assumeNoPrecompiles * feat: add chains * feat: add precompiles/predeploys * Revert "refactor: use fully-qualified paths instead of relative paths" This reverts commit bb2579e. * refactor: use relative paths for compatibility with solc <0.6.9 (no --base-path flag) * refactor: make assumeNoPrecompiles virtual * refactor: no more constructor warning from StdChains * fix: move stdChains into StdCheats, fix constructor initalization order, move cheats into VmSafe that can be safely used * ♻️ update ds-test (#200) * ♻️ update ds-test Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch> * ♻️ use relative path for ds-test imports Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch> Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch> * refactor: move `UINT256_MAX` to `CommonBase` Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch> Co-authored-by: Paul Razvan Berg <hello@paulrberg.com> Co-authored-by: Matt Solomon <matt@mattsolomon.dev> Co-authored-by: Drake Evans <31104161+DrakeEvans@users.noreply.github.com> Co-authored-by: Pascal Marco Caversaccio <pcaversaccio@users.noreply.github.com>
Implements #122, #123, and #124.
Modularization
Assertions.solCheats.solstdErrorsmoved toErrors.solstdMathmoved toMath.solbound) moved toUtils.sol- also moved the utilities fromScript.soltoUtils.solTestnow inherits fromAssertions,CheatsandUtilsNew Features
createCompute2AddressutilityFixes
0.8.0inStdErrors.t.solBreaking Changes
lowLevelErrorcustom errortipcheatTestdoesn't inherit fromScriptanymoreI'm very much open to any feedback. Feel free to destroy this.