fix(fmt): don't break var assignments when callee fits (foundry-rs#12323) #219
Conversation
* Update transaction types to use constants * Update mod.rs * Update mod.rs
) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.33 to 2.62.39. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@e43a502...0ed4032) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.39 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](actions/download-artifact@v5...v6) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…e, allowance (#12258) * create new subcomands for erc20 * implement operations * Add deprecation warning on --erc20 usage * formatting * Add unit tests * Assert balance in test * Update crates/cast/src/args.rs Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> * Update crates/cast/src/cmd/erc20.rs Co-authored-by: onbjerg <onbjerg@users.noreply.github.com> * Nits: account -> owner, remove todo --------- Co-authored-by: grandizzy <grandizzy.the.egg@gmail.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: onbjerg <onbjerg@users.noreply.github.com>
…ne line (#12303) * add single_line_imports option to keep single imports on one line * update readme * add tests for single_line_imports feature + fmt * fix clippy and simplify the code * fix test failed * fix: simplify --------- Co-authored-by: 0xrusowsky <0xrusowsky@proton.me> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com>
fix(fmt): asm inline if stmt
Update state_snapshot.rs
* fix(fmt): only indent wrapped trailing cmnts which are line cmnts * style: flip --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com>
* ci: don't run most CI on push Merge group status checks are reported on push. I believe there is no point in re-running everything again after the merge group is committed. * ci: fix nested concurrency
* fix(fmt): don't break var assignments when callee fits * fix: deindent calls (exception)
We can't use GHA cache since it gets evicted every day
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
Reviewer's GuideThis PR implements ERC20 token operations in Sequence diagram for ERC20 token transfer CLI commandsequenceDiagram
actor User
participant CLI as "cast CLI"
participant Provider
participant Contract as "IERC20 contract"
User->>CLI: cast erc20 transfer <token> <to> <amount>
CLI->>Provider: Connect
CLI->>Contract: transfer(to, amount)
Contract-->>Provider: Transaction sent
Provider-->>CLI: Return TxHash
CLI-->>User: Print TxHash
Sequence diagram for ERC20 token balance CLI commandsequenceDiagram
actor User
participant CLI as "cast CLI"
participant Provider
participant Contract as "IERC20 contract"
User->>CLI: cast erc20 balance <token> <owner>
CLI->>Provider: Connect
CLI->>Contract: balanceOf(owner)
Contract-->>Provider: Return balance
Provider-->>CLI: Return balance
CLI-->>User: Print balance
Sequence diagram for ERC20 token approve CLI commandsequenceDiagram
actor User
participant CLI as "cast CLI"
participant Provider
participant Contract as "IERC20 contract"
User->>CLI: cast erc20 approve <token> <spender> <amount>
CLI->>Provider: Connect
CLI->>Contract: approve(spender, amount)
Contract-->>Provider: Transaction sent
Provider-->>CLI: Return TxHash
CLI-->>User: Print TxHash
Sequence diagram for ERC20 token allowance CLI commandsequenceDiagram
actor User
participant CLI as "cast CLI"
participant Provider
participant Contract as "IERC20 contract"
User->>CLI: cast erc20 allowance <token> <owner> <spender>
CLI->>Provider: Connect
CLI->>Contract: allowance(owner, spender)
Contract-->>Provider: Return allowance
Provider-->>CLI: Return allowance
CLI-->>User: Print allowance
Class diagram for new ERC20 CLI subcommands and provider methodsclassDiagram
class Cast {
+erc20_balance(token: Address, owner: Address, block: Option<BlockId>) Result<U256>
+erc20_allowance(token: Address, owner: Address, spender: Address, block: Option<BlockId>) Result<U256>
+erc20_transfer(token: Address, to: Address, amount: U256, signer: Option<WalletSigner>) Result<TxHash>
+erc20_approve(token: Address, spender: Address, amount: U256, signer: Option<WalletSigner>) Result<TxHash>
}
class Erc20Subcommand {
+Balance
+Transfer
+Approve
+Allowance
+run()
}
Cast <|-- Erc20Subcommand: uses
class WalletSigner
class Address
class BlockId
class U256
class TxHash
Erc20Subcommand --> WalletSigner
Erc20Subcommand --> Address
Erc20Subcommand --> BlockId
Erc20Subcommand --> U256
Erc20Subcommand --> TxHash
Class diagram for FormatterConfig with new single_line_imports optionclassDiagram
class FormatterConfig {
+single_line_imports: bool
+prefer_compact: PreferCompact
+docs_style: DocCommentStyle
...
}
FormatterConfig --> PreferCompact
FormatterConfig --> DocCommentStyle
Class diagram for updated Solidity/Yul formatter logicclassDiagram
class State {
+print_expr()
+print_yul_block(..., prefix_len)
+space_left()
+max_space_left(prefix_len)
+single_line_imports: bool
...
}
State --> FormatterConfig
class FormatterConfig {
+single_line_imports: bool
}
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
@DaniPopes is attempting to deploy a commit to the Foundry development Team on Vercel. A member of the Team first needs to authorize it. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Summary of ChangesHello @Dargon789, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces significant improvements to the Solidity formatter, addressing issues with line breaks in variable assignments and offering more control over import statement formatting. It also expands the Highlights
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Hey there - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `crates/fmt/src/state/sol.rs:217` </location>
<code_context>
}
ast::ImportItems::Aliases(aliases) => {
- self.s.cbox(self.ind);
- self.word("{");
</code_context>
<issue_to_address>
**issue (complexity):** Consider extracting complex closure logic into small helper methods to flatten match arms and improve readability.
```markdown
You’re right that most of the complexity comes from large nested blocks and closures. You can pull each into a small helper, flatten the `match` arms, and get rid of the closures. For example:
1) Extract the import‐alias logic:
```rust
// NEW HELPER
fn print_braced_aliases<I>(&mut self, aliases: I)
where
I: IntoIterator<Item = (&Ident, &Option<Ident>)>,
{
let single = self.config.single_line_imports && aliases.into_iter().count() == 1;
if single {
self.word("{");
if self.config.bracket_spacing { self.nbsp() }
} else {
self.s.cbox(self.ind);
self.word("{");
self.braces_break();
}
if self.config.sort_imports {
let mut sorted: Vec<_> = aliases.into_iter().collect();
sorted.sort_by_key(|(ident, _)| ident.name.as_str());
self.print_commasep_aliases(sorted.into_iter())
} else {
self.print_commasep_aliases(aliases.into_iter())
}
if single {
if self.config.bracket_spacing { self.nbsp() }
self.word("}");
} else {
self.braces_break();
self.s.offset(-self.ind);
self.word("}");
self.end();
}
}
```
Then in your `match items` arm:
```rust
ast::ImportItems::Aliases(aliases) => {
self.print_braced_aliases(aliases.iter());
self.word(" from ");
self.print_ast_str_lit(path);
}
```
2) Pull out binary‐expr printing into two small methods:
```rust
// NEW HELPERS
fn binary_inline(&mut self, rhs: &ast::Expr<'_>) {
self.print_sep(Separator::Nbsp);
self.neverbreak();
self.print_expr(rhs);
}
fn binary_break(&mut self, rhs: &ast::Expr<'_>, hard: bool) {
if !self.is_bol_or_only_ind() {
self.print_sep(if hard { Separator::Hardbreak } else { Separator::Space });
}
self.s.offset(self.ind);
self.s.ibox(self.ind);
self.print_expr(rhs);
self.end();
}
```
And simplify your match arm:
```rust
ast::ExprKind::Binary(lhs, op, _) => {
let size = self.estimate_lhs_size(rhs, op) + lhs_size;
let needs_break = force_break || size > space_left;
if needs_break {
self.binary_break(rhs, force_break);
} else {
self.binary_inline(rhs);
}
}
```
This keeps all behavior but removes closures and deep nesting.
</issue_to_address>
### Comment 2
<location> `crates/cast/src/lib.rs:1146` </location>
<code_context>
+ .await?)
+ }
+
+ pub async fn erc20_transfer(
+ &self,
+ token: Address,
</code_context>
<issue_to_address>
**issue (complexity):** Consider refactoring the duplicate signer and send logic into a helper function to simplify the transfer and approve methods.
Here’s one way to collapse the duplicate signer/`send()` logic into a small helper. It preserves 100% of the behavior, but cuts your two functions down to a one-liner each:
```rust
/// Helper: attach optional signer and `.send().await`, returning the hash.
async fn send_with_opt_signer<B>(
builder: B,
signer: Option<foundry_wallets::WalletSigner>
) -> eyre::Result<TxHash>
where
B: Into<alloy_provider::PendingTransactionBuilder> // or whatever your builder type is
{
// convert to the concrete builder type
let mut tx_builder = builder.into();
if let Some(wallet) = signer {
tx_builder = tx_builder.from(wallet.address());
}
let pending = tx_builder.send().await?;
Ok(*pending.tx_hash())
}
```
Then your two methods shrink to:
```rust
pub async fn erc20_transfer(
&self,
token: Address,
to: Address,
amount: U256,
signer: Option<foundry_wallets::WalletSigner>,
) -> Result<TxHash> {
let builder = IERC20::new(token, &self.provider).transfer(to, amount);
send_with_opt_signer(builder, signer).await
}
pub async fn erc20_approve(
&self,
token: Address,
spender: Address,
amount: U256,
signer: Option<foundry_wallets::WalletSigner>,
) -> Result<TxHash> {
let builder = IERC20::new(token, &self.provider).approve(spender, amount);
send_with_opt_signer(builder, signer).await
}
```
This removes all the duplication but keeps the exact same behavior.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Code Review
This pull request introduces several valuable changes, including new ERC20 subcommands for cast, a single_line_imports option for the formatter, and various bug fixes and enhancements. The code is generally well-structured and includes appropriate tests for the new functionality.
I've identified a couple of areas with code duplication in the new cast functionality. Refactoring these sections would improve the maintainability and readability of the code. My review includes specific suggestions for these improvements.
* chore: use drpc arb * Use other
…ation (#12309) * fix(cheats): correct impersonate() return semantics to match documentation * clean --------- Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>
Motivation
Solution
PR Checklist
Summary by Sourcery
Introduce ERC20 subcommands to cast and enhance the solidity formatter with a new single_line_imports option, refined formatting logic, and CI workflow updates, while fixing transaction type constants in anvil and RPC endpoint resolution
New Features:
Bug Fixes:
Enhancements:
Documentation:
Tests: