SMTChecker: writeStateVars retains function->annotation().contract at CHC.cpp:1149 — sibling of PR #17151
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 55/100
Research direction
Start in libsolidity/formal/CHC.cpp, in externalFunctionCallToTrustedCode: compare the pre-call readStateVars(*targetContract, ...) with the post-call writeStateVars(*function->annotation().contract, ...) near line 1149. Confirm the only remaining function->annotation().contract site with grep in libsolidity/formal/. Done means the write uses targetContract and an SMTChecker test for inherited external this calls still passes. The soundness impact is unverified, so check whether a test shows a difference.
Written by the indexing model from the issue text.
Description
Summary
PR #17151 (2026-10-27, 185246c4) explicitly passes targetContract to predicate(...) so SMTChecker accounts for inheritance across external this calls. The fix updated readStateVars at CHC.cpp:1109 (pre-call block in externalFunctionCallToTrustedCode) to use *targetContract instead of *function->annotation().contract.
The paired writeStateVars call in the post-call block of the same function (currently line 1149 on main) still uses the pre-fix pattern:
state().writeStateVars(*function->annotation().contract, contractAddressValue(_funCall));
grep -rn "function->annotation()\.contract" libsolidity/formal/ returns this as the only remaining instance in the whole directory. Every other site was updated by PR #17151.
Why it may matter
In externalFunctionCallToTrustedCode, state tracking becomes asymmetric for external this calls across inheritance:
- pre-call
readStateVars(*targetContract, ...)reads from the correct inherited contract - post-call
writeStateVars(*function->annotation().contract, ...)writes to a potentially different contract scope
For the exact scenario PR #17151 flags (external this.foo() where foo is inherited), the read side was fixed but the write side was not — the SMT state model may track reads and writes on different contracts.
Caveats / honest state
- Two attempted CHC
assert-level repros on brewsolc 0.8.38(which pre-dates PR #17151) did not produce a demonstrable false-negative at the assertion level. The soundness consequence is theoretical from inspection; no observable mis-verification demonstrated so far. - Review-history scan via GitHub API: PR #17151 has 2 reviews, 0 inline comments, 0 issue comments — no reviewer dispatched this specific line, which supports oversight rather than an informed design decision.
Suggested fix (one-line symmetry)
state().writeStateVars(*targetContract, contractAddressValue(_funCall));
(Hoist the targetContract local above both the pre-call and post-call blocks so both sides use the resolved contract.)
References
- Fix PR: #17151 (
185246c4), merged 2026-10-27 - Current
mainreference:libsolidity/formal/CHC.cpp:1149 - Grep witness: single remaining
function->annotation().contractcallsite inlibsolidity/formal/
Reporter: symposia-gi (General Imperative). Code-review observation only; no bounty claim.
- Dominant language
- C++
- Stars
- 25.8k
- Forks
- 6.2k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 43
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from argotorg/solidity
-
AI tool policy: add AGENTS.mdMay be free again @cameel claimed this 47 days ago, and no pull request is open. Opendocumentation :book:
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
argotorg/solidity#16996 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
`fitsPrecisionExp` charges the base's bit *length* per multiplication instead of its bit *position*, so valid constant powers such as `2 ** 2049` are rejectedPossibly taken @clonker claimed this 54 days ago. Openbug :bug:
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
argotorg/solidity#16984 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
`0 ** (-1)` is silently evaluated to `0` in a constant expression instead of being rejected as division by zeroMay be free again @matheusaaguiar claimed this 54 days ago, and no pull request is open. Openbug :bug: low impact
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
argotorg/solidity#16982 · 3 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
AssemblyItem AssemblyItem::toSubAssemblyTag assumes size_t is at least 64bPossibly taken @riba2534 claimed this 67 days ago. Openbug :bug: low impact
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
FileReader: Duplicate search paths cause false ambiguous importsPossibly taken @zjuncal claimed this 3 days ago. Openbug :bug:
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
Maintainers usually reply within 1 day
All issues in argotorg/solidity
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
KLayout/klayout#2554 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
LaneDibello/Kotor-Patch-Manager#375 ·
Maintainers usually reply within 2 days