solc artifact: error on a component the artifact does not carry - #290
Conversation
extract_artifact_component_json indexed the parsed artifact and returned Value::Null for an absent key, so `solc artifact -c abi` printed `null` and exited 0 on an artifact with no abi. Look the key up instead, so an absent key is an error naming it and a key present as explicit null still returns null. The three key names move into ArtifactComponent::artifact_key so the lookup and the error name one string. Closes #231 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 42 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment: S/M/L PR Classification Guidelines:This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed. Small (S)Characteristics:
Review Effort: Would have taken 5-10 minutes Examples:
Medium (M)Characteristics:
Review Effort: Would have taken 15-30 minutes Examples:
Large (L)Characteristics:
Review Effort: Would have taken 45+ minutes Examples:
Additional Factors to ConsiderWhen deciding between sizes, also consider:
Notes:
|
Closes #231
The defect
extract_artifact_component_jsonindexed the parsed artifact withjson["abi"]/json["bytecode"]/json["deployedBytecode"]. Indexing aserde_json::Valuewith a key it does not have yieldsValue::Null, so thefunction returned
Ok(Null)and the CLI printednullwith exit 0:Indistinguishable from an artifact whose component legitimately serialises as
null, and anything piping the output into ABI tooling getsnullrather thana failure.
The fix
Took the issue's first option: an absent component is an error, so the exit
code is nonzero and nothing reaches stdout.
The lookup is now
json.get(key), which separates the two cases indexingconflated -
Nonefor a key the artifact does not carry (also for an artifactthat is not a JSON object at all),
Some(Null)for a key present andexplicitly null. Absent errors; explicit null still returns
Value::Null, sothe distinction the issue names is preserved rather than collapsed the other
way.
The three key names moved into
ArtifactComponent::artifact_key, so the lookupand the error message name one string and cannot drift apart; the
per-component
matchis exhaustive, so a component variant added later is acompile error there rather than a silent
null.The function's doc comment said it "does not perform any checks on the returned
[Value] such as if it is null or not" - that was the accurate description of
the defect, and it now states the absent-vs-explicit-null contract instead.
solc artifactis the only caller.SolidityAbiMeta::from_artifactdoes itsown
["abi"]indexing but already errors, because deserialisingNullintoSolidityAbiMetafails; it is untouched.Relation to #266 (issue #181)
Same CLI output surface, adjacent but disjoint: #266 is
cli/schema- it madeschema lslist exactly the metasschema showcan produce, by routing boththrough one exhaustive
KnownMeta -> Option<RootSchema>map. This iscli/solcplussolc/mod.rs; no file, function or test overlaps, so the twomerge in either order.
The shape is deliberately the same one #266 established: a defect where a
lookup silently produced a non-answer is fixed by an exhaustive match feeding
an
Option, with the caller turningNoneinto the error. #266'sNonebecomes "Unsupported for {} meta"; this one's becomes
artifact has no "abi" component. Both make an added enum variant a compile error in one place.QA
test_dispatch_solc_artifact_missing_component(new,crates/cli/tests/cli_dispatch.rs) - the issue's own repro: asserts nonzeroexit, empty stdout, the missing key named on stderr, that
-owrites no fileon the failing path, and that an explicitly null component still succeeds and
prints
null.test_missing_component_errors,test_missing_component_errors_beside_present_siblings,test_explicit_null_component_is_returned,test_non_object_artifact_errors,test_artifact_key_per_component(all new,crates/cli/src/solc/mod.rs).Each fails on base, verified by restoring the pre-fix body
(
Ok(json[component.artifact_key()].clone())) and re-running: the fourabsent-key/non-object assertions fail with
Ok(Null)where anErrisexpected.
test_missing_component_returns_null, which pinned the oldbehaviour, is replaced by
test_missing_component_errorsrather than deletedsolc/mod.rs:36-38restore the pre-fix indexing body -> KILLED bytest_missing_component_errors,test_missing_component_errors_beside_present_siblings,test_non_object_artifact_errors,test_dispatch_solc_artifact_missing_component.solc/mod.rs:37insert.filter(|v| !v.is_null())before.cloned(), i.e.treat explicit null as absent -> KILLED by
test_explicit_null_component_is_returnedandtest_dispatch_solc_artifact_missing_component(this is the mutant provingthe fix did not just move the conflation).
solc/mod.rs:17Abi => "abi"->"bytecode"-> KILLED by 5 lib tests andboth dispatch tests.
solc/mod.rs:18Bytecode => "bytecode"->"abi"-> KILLED by 4 lib testsand
test_dispatch_solc_artifact.solc/mod.rs:19DeployedBytecode => "deployedBytecode"->"bytecode"->KILLED by 3 lib tests and
test_dispatch_solc_artifact.solc/mod.rs:38error text ->missing {}-> KILLED bytest_missing_component_errorsandtest_dispatch_solc_artifact_missing_component. (Scoped to the function body;applied file-wide it rewrites the lib test's expectation in lockstep and only
the dispatch test kills it, which is why the message is pinned from the other
test target too.)
No surviving mutant.
must not be reported as a value, and must be distinguishable from one that
legitimately serialises as
null. The absent/explicit-null split is derivedfrom the issue's own wording, not from the new code: the fix has to make those
two distinguishable, not error on both. The CLI test asserts process exit
status and stderr text, observable without reference to the implementation,
and the key names are checked against what solc writes into an artifact
(
abi,bytecode,deployedBytecode), not against the match being tested.(a) error with nonzero exit when the component key is absent, or (b) keep the
passthrough and document/flag it at the CLI layer. Covered by (a); (b) is the
alternative the issue offers, not an additional requirement, and (a) is the
one that fixes the piping hazard the issue describes rather than documenting
it. Nothing else in the issue.
Verification
Green locally:
cargo test -p rain-metadata --lib solc(7 passed),cargo test -p rain-metadata --test cli_dispatch --test cli(5 + 9 passed),cargo clippy -p rain-metadata --all-targetsclean,cargo fmt --all --checkclean. The full suite was not run locally.
Behaviour change
extract_artifact_component_jsonandArtifactComponentare re-exported fromthe crate root (
pub use solc::*), so this is a library-visible change: a callthat previously got
Ok(Value::Null)for a missing key now getsErr(Error::InvalidInput(..)), rendered asinvalid input: artifact has no "abi" component. That is the point of theissue. No new
Errorvariant, so the public error enum's match surface isunchanged.
solc artifactis the only in-repo caller.🤖 Generated with Claude Code